Importing and Exporting Graphics

QuickTime offers many components whose job is to import from and export to different graphics formats. As you might expect, these components are wrapped by classes called GraphicsImporter and GraphicsExporter.

The GraphicImportExport example application (shown in Example 4-3) uses both of these classes to illustrate the dynamic lookup of importers and exporters.

Note

Compile and run this example with ant run-ch04-graphicimport-export..

Example 4-3. Graphics import and export

package com.oreilly.qtjnotebook.ch04;
 
import quicktime.*;
import quicktime.io.*;
import quicktime.std.*;
import quicktime.std.comp.*;
import quicktime.std.image.*;
import quicktime.app.view.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Vector;
import java.io.*;
 
import com.oreilly.qtjnotebook.ch01.QTSessionCheck;
 
public class GraphicImportExport extends Object {
 
  Button exportButton;
  Frame frame;
  GraphicsImporter importer;
 
  static final int[  ] imagetypes =
       { StdQTConstants.kQTFileTypeQuickTimeImage};
  /* other interesting values:
      StdQTConstants.kQTFileTypeGIF,
      StdQTConstants.kQTFileTypeJPEG,
      StdQTConstants4.kQTFileTypePNG,
      StdQTConstants4.kQTFileTypeTIFF
      StdQTConstants.kQTFileTypeMacPaint,
      StdQTConstants.kQTFileTypePhotoShop,
      StdQTConstants.kQTFileTypePICS,
      StdQTConstants.kQTFileTypePicture,
  */
 
  public static void main (String[  ] args) {
      new GraphicImportExport( );
  }
 
  public GraphicImportExport( ) {
      try {
          QTSessionCheck.check( );
          QTFile inFile =  QTFile.standardGetFilePreview (imagetypes);
          importer = new GraphicsImporter (inFile);
          // put image onscreen
          QTComponent qtc = QTFactory.makeQTComponent (importer);
          java.awt.Component c = qtc.asComponent( );
          frame = new Frame ("Imported image");
          frame.setLayout (new BorderLayout( ));
          frame.add (c, BorderLayout.CENTER);
          exportButton = new Button ("Export");
          exportButton.addActionListener (new ActionListener( ) {
              public void actionPerformed (ActionEvent ae) {
                  try {
                      doExport( );
                  } catch (QTException qte) {
                      qte.printStackTrace( );
                  }
              }
          });
          frame.add (exportButton, BorderLayout.SOUTH);
          frame.pack( );
          frame.setVisible(true);
      } catch (QTException qte) {
          qte.printStackTrace( );
      }
  }
  
  public void doExport( ) throws QTException {
      // build list of GraphicExporters
      Vector choices = new Vector( );
      ComponentDescription cd =
          new ComponentDescription (
              StdQTConstants.graphicsExporterComponentType);
      ComponentIdentifier ci = null;
      while ( (ci = ComponentIdentifier.find(ci, cd)) != null) {
          choices.add (new ExportChoice (ci.getInfo( ).getName( ),
                                         ci.getInfo( ).getSubType( )));
      }
 
      // offer a choice of movie exporters
      JComboBox exportCombo = new JComboBox (choices);
      JOptionPane.showMessageDialog (frame,
                                     exportCombo,
                                     "Choose exporter",
                                     JOptionPane.PLAIN_MESSAGE);
      ExportChoice choice = 
          (ExportChoice) exportCombo.getSelectedItem( );
      System.out.println ("chose " + choice.name);
 
      // build a GE, wire up to the GraphicsImporter
      GraphicsExporter exporter =
          new GraphicsExporter (choice.subtype);
      exporter.setInputGraphicsImporter (importer);
 
      // ask for destination, settings
      FileDialog fd =
          new FileDialog (frame, "Save As", 
                          FileDialog.SAVE);
      fd.setVisible(true);
      String filename = fd.getFile( );
      if (filename.indexOf('.') =  = -1)
          filename = filename + "." +
              exporter.getDefaultFileNameExtension( );
      File file = new File (fd.getDirectory( ), filename);
      exporter.setOutputFile (new QTFile(file));
      exporter.requestSettings( );
 
      // export
      exporter.doExport( );
 
      // need to explicitly quit (since awt is running)
      System.exit(0);
  }
 
  public class ExportChoice {
      String name;
      int subtype;
      public ExportChoice (String n, int st) {
          name = n;
          subtype = st;
      }
      public String toString( ) {
          return name;
      }
  }
 
}

When run, the program shows a dialog to select a graphic to be imported. On Windows, the “file type” in this dialog is QuickTime Image. Once an image is selected, it appears in a window with an “export” button. When the user clicks the button, she is asked for an export type, as shown in Figure 4-6.

Note

GraphicsImporter and GraphicsExporter are in quicktime.std.image, not quicktime.std.qtcomponents like most other components.

Selecting a GraphicsExporter

Figure 4-6. Selecting a GraphicsExporter

After this, the program displays a configuration dialog specific to the type of exporter selected—at a minimum, this dialog usually offers a choice of color depths (256 colors, 256 grays, millions of colors, etc.). Next, a save dialog requests the location of the exported file. Once approved, the program converts the image to the specified format and saves it to the supplied location.

What just happened?

Notice the QTFile.standardGetFilePreview() . This shows a file-open dialog and takes an array of up to four ints, representing FOUR_CHAR_CODE s of various file format constants, which are used as a filter of what file types to make selectable. You can use kQTFileTypeQuickTimeImage as a convenient wildcard that matches any kind of image QuickTime can open, though it seems to work only on Windows (on the Mac, any file can be selected).

Tip

If you want to specify formats, interesting constants in StdQTConstants include kQTFileTypeGIF, kQTFileTypeJPEG, and kQTFileTypePhotoShop. The StdQTConstants4 class adds similarly named constants for PNG and TIFF. Unfortunately, you can send only four.

Given a file, you can construct a GraphicsImporter object to load it into QuickTime. To put the imported image on-screen, pass the importer to QTFactory.makeQTComponent() , which returns a QTComponent that you can either cast to an AWT Component or, to be type-safe, convert with the asComponent( ) method.

Warning

java.awt and quicktime.std.comp both define a class called Component . If you’re casually importing every class from these packages, you’re probably headed for a compile-time error. You’ll have to make your imports more selective or use a fully qualified class name for one of the Components, like this example does.

To export an image to another format, you can search for graphics exporter subtypes by creating a ComponentDescription template to match components of the graphicsExporterComponentType. In the example, the names of matching components are shown in a JComboBox. With a subtype selected, create the GraphicsExporter by passing the subtype to its constructor.

Note

This method of looking up exporter components was shown in the previous lab.

A GraphicsExporter needs to be wired up to some kind of source image. With a GraphicsImporter, you wire the two together with setInputGraphicsImporter() . The exporter also needs a destination. If writing to a file (as opposed to, say, memory), you set this with setOutputFile( ) —just to be safe, it’s wise to sanity-check the user-provided filename extension against the value returned by the exporter’s getDefaultFileNameExtension() .

The user probably wants some say in the color depth, image quality, and other settings for the export, a dialog for which is provided with a requestSettings() .

After all that, you finally can do the export with...doExport( ).

What about...

...other sources for the export? The Javadoc for GraphicsExporter shows a bunch of setInputXXX( ) methods. True enough, and in the next chapter, we’ll explore some of these, including Picts, QDGraphics, and PixMaps.

And what about setting export parameters programmatically? QTJ exposes some methods that could be used instead of the user dialog, such as setDepth() and setCompressionMethod( ). One interesting method, setTargetDataSize( ) , lets exporters with a “quality” option (like JPEG) find a value that will result in a file of the given size in bytes.

Note

GraphicsExporters have an AtomContainer-based settings scheme that’s just as painful as the MovieExporter equivalent from the last lab.

Get QuickTime for Java: A Developer's Notebook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.