Example: TIFF File Writer

This example creates a file writer to write TIFF format files.

Example Code
The code for this example file writer is included in the file example1_writetiff__define.pro in the examples/doc/itools subdirectory of the IDL distribution. Run the example procedure by entering example1_writetiff__define at the IDL command prompt or view the file in an IDL Editor window by entering .EDIT example1_writetiff__define.pro.

Note
The standard TIFF file writer included with the iTools contains additional features not included in this example. In most cases, if a file writer is included in the standard iTool distribution, there is no need to create your own writer for files of the same type.

Class Definition File

The class definition for example1_writetiff consists of an Init method, a SetData method, and a class structure definition routine. As with all object class definition files, the class structure definition routine is the last routine in the file, and the file is given the same name as the class definition routine (with the suffix .pro appended).

Class Definition Discussion

PRO example1_writetiff__Define 
 
   struct = {example1_writetiff,       $ 
             inherits IDLitWriter  $ 
           } 
END 

Discussion

Our class definition routine is very simple. We create an IDL structure variable with the name example1_writetiff, specifying that the structure inherits from the IDLitWriter class. The object has no instance data, and thus no instance data fields.

Init Method

FUNCTION example1_writetiff::Init, _REF_EXTRA = _extra 
 
   IF (self->IDLitWriter::Init('tiff', $ 
      TYPES=['IDLIMAGE', 'IDLIMAGEPIXELS', 'IDLARRAY2D'], $ 
      NAME="Tag Image File Format", $ 
      DESCRIPTION="Tag Image File Format (TIFF)", $ 
      _EXTRA = _extra) EQ 0) THEN $ 
      RETURN, 0 
 
   RETURN, 1 
 
END 

Discussion

The first item in our class definition file is the Init method. The Init method's function signature is defined first, using the class name example1_writetiff. Note the use of the _REF_EXTRA keyword inheritance mechanism; this allows any keywords specified in a call to the Init method to be passed through to routines that are called within the Init method even if we do not know the names of those keywords in advance.

Next, we call the Init method of the superclass. In this case, we are creating a subclass of the IDLitWriter class; this provides us with all of the standard iTool file writer functionality automatically. Any "extra" keywords specified in the call to our Init method are passed to the IDLitWriter::Init method via the keyword inheritance mechanism.

We specify a list of accepted filename extensions (tiff, in this case) via the Extensions argument, and set the TYPES keyword equal to the iTool data type of data that can be written using this file writer. (The iTool data types specified by the TYPES keyword must match the iTool data type of the data selected in the iTool Export Wizard in order for the file writer to be available for selection.)

We specify a value for the NAME property of the writer object (this is displayed in the system preferences dialog) and include a description of the writer via the DESCRIPTION keyword. Finally, we use the _EXTRA keyword inheritance mechanism to pass through any keywords provided when the Init method is called.

Finally, we return the value 1 to indicate successful initialization.

SetData Method

FUNCTION example1_writetiff::SetData, oImageData 
 
   ; We need a filename for the file we are about to write. 
   strFilename = self->GetFilename() 
   IF (strFilename EQ '') THEN $ 
      RETURN, 0 ; failure 
 
   ; Make sure that the object passed to this method is valid. 
   IF (~ OBJ_VALID(oImageData)) THEN BEGIN 
      MESSAGE, 'Invalid image data object.', /CONTINUE 
      RETURN, 0 ; failure 
   ENDIF 
 
   ; First, we look for some image data. 
   oData = (oImageData->GetByType('IDLIMAGEPIXELS'))[0] 
 
   ; If we did not get any image data, try retrieving a 
   ; 2D array. 
   IF (~ OBJ_VALID(oData)) THEN BEGIN 
      oData = (oImageData->GetByType('IDLARRAY2D'))[0] 
      IF (~ OBJ_VALID(oData)) THEN RETURN, 0 
   ENDIF 
 
   ; If we got neither image data nor a 2D array,  
   ; exit with a failure code. 
   IF (~ oData->GetData(image)) THEN BEGIN 
      MESSAGE, 'Error retrieving image data.', /CONTINUE 
      RETURN, 0 ; failure 
   ENDIF 
 
   ; Next, try to retrieve a palette object from the selected 
   ; object. 
   oPalette = (oImageData->GetByType('IDLPALETTE'))[0] 
 
   ; If we got a palette object, retrive the palette data 
   ; and store the information in the variables red, green, 
   ; and blue. 
   IF (OBJ_VALID(oPalette)) THEN BEGIN 
      success = oPalette->GetData(palette) 
      IF (N_ELEMENTS(palette) GT 0) THEN BEGIN 
         red = REFORM(palette[0,*]) 
         green = REFORM(palette[1,*]) 
         blue = REFORM(palette[2,*]) 
      ENDIF 
   ENDIF 
 
   ; Retrieve the number of dimensions in our image. 
   ndim = SIZE(image, /N_DIMENSIONS) 
 
   ; Write the file. The REVERSE ensures that other 
   ; applications will read the image in right side up. 
   WRITE_TIFF, strFilename, REVERSE(image, ndim), $ 
      RED = red, GREEN = green, BLUE = blue 
 
   RETURN, 1  ; success 
 
END 

Discussion

The SetData method accepts an IDLitData object (oImageData) as its input parameter. Before processing the input data, the method prompts the user for a file in which to save the image, using the GetFilename method of the IDLitWriter object.

After securing a filename, the method proceeds to check the input data object. First it checks to make sure that the input object is valid. Then it attempts to retrieve a data object of the iTool data type IDLIMAGEPIXELS from the data object, using the GetByType method. If this fails, it attempts to retrieve a data object of the iTool data type IDLARRAY2D from the data object, again using the GetByType method. If this second attempt fails, we exit, returning 0.

Next, we use the GetData method to retrieve the image data from the data object. The method then checks the return value from the GetData method to determine whether the returned value is valid, and exits if it is not.

The method next attempts to retrieve a object of the data type IDLPALETTE from the input object. If a palette is retrieved, the palette data is reformed to suit the needs of the WRITE_TIFF procedure.

Finally, the method uses the WRITE_TIFF procedure to create an image file. The image data must be processed by the REVERSE function in order to make it appear in the output file with the correct orientation.