![]() |
Home · Pages · Index · Overviews |
Tiff Class ReferenceDirect I/O of individual multi-channel Tiff Image File Descriptors (IFDs). More... #include <image.h> Enumerated Scalars
Descriptive Types
Routines
Detailed DescriptionWhile the Image I/O module provides the simplist possible interface to get images and stacks into and out of tiff-encoded files, the Tiff class provides more flexibility, at the expense of somewhat greater complexity, by (a) realizing routines that give serial access to the individual IFDs of the file, (b) removing the restriction that all IFDs have to be of the same dimensions, and (c) not automatically mapping color-mapped channels. Before introducing the routines, we describe the aspects of a tiff encoding that need to be understood by a user of the class. A Tiff-encoded file contains a sequence of one or more image file descriptors (IFDs) each of which contains any number of channels each of which is a 2D array, all of the same shape. Each channel's array can contain signed or unsigned integers of some specific number of bits, or a 32-bit floating point number. Each channel also has a photometric interpretation which in effect can be one of RED, GREEN, BLUE, ALPHA, MAPPED, or PLAIN, with the restriction that the only channel that can be MAPPED is the first. (Tiff actually uses a somewhat baroque and complicated set of tags to encode these interpretations, but in effect the list just given is the information that is present.) Note carefully, that unlike the Image I/O module, the IFDs in this context do *not* have to have the same dimensions or number and types of channels/layers as other IFDs in the tif file. This can be useful if you want to store something more complicated in a tiff. For example, every even-numbered IFD could be a thumbnail of the previous odd-numbered IFD. What is in the sequence of IFDs could even be encoded in the text field of the first channel of the first IFD, which is put into or taken from the JF_ANO_BLOCK tag of the tiff (there is only one per file, see 2. below). If the first channel is MAPPED then the IFD also contains a 16-bit rgb-color map, presumably for mapping the values of that channel. Unfortunately, the tiff format is not general enough to associate color maps with different channels, there is at most one map and its presence is always contingent on the first channel being designated as MAPPED. However, there is nothing to prevent the application of this map to other channels if it suites your purpose, and there is generally no reason why the application can't arrange the channels so the first one is a color-mapped one. The Tiff class, unlike the routines of the Image I/O module, does not use the concept of layers, but works directly with the channels in each IFD. One should further note the following subtleties:
A Tiff object manages either the reading or writing of a tiff file. It has the concept of a current IFD, which for reading is one in the sequence of IFDs in the file or none if the Tiff is at the end of the file. For writing, the current IFD is always the next one to be written to the file's sequence of IFDs and this IFD, immediately after the previous one has been written, is empty in that it has no channels. A Tiff is opened for either reading ("r") or writing ("w") with Open_Tiff and must be closed with Close_Tiff when all I/O involving the Tiff is complete. To clearly distinguish between Tiffs open for reading versus those open for writing, the descriptive type names RTiff and WTiff are introduced. One can advance an RTiff to the next IFD in the file's sequence with Advance_Tiff and query as to whether or not the end of the sequence has been reached with Tiff_EOF. An RTiff can also be rewound with Rewind_Tiff which sets the current IFD to the first IFD in the associated file. For example, a simple code to count the number of IFDs in a tiff file is: int nifd; Tiff t; Open_Tiff("foo.tif","r"); nifd = 0; while ( ! Tiff_EOF(t)) { nifd += 1; Advance_Tiff(t); } Close_Tiff(t); printf("There are %d IFD's in foo.tif\n",nifd); An RTiff object gives one finer control over reading the contents of the current IFD of a tiff file. Get_IFD_Shape returns the width, height, and number of channels in the current IFD. Get_IFD_Channel_Kind and Get_IFD_Channel_Type return the Channel_Kind and Value_Type of any given channel in the current IFD. These routines allow a user to know what kind of Array container might hold the channel images of the IFD and whether or not it has a color map and how big it is. Get_IFD_Channel fetches the contents of a given channel into an Array supplied by the caller, and Get_IFD_Map fetches the color map (if there is one) into an Array supplied by the caller. It is frequently the case that these Arrays are actually Array_Bundles into a slice of a larger array that contains the entire stack encoded in the file. For example, suppose it is known that a tiff file contains an RGB_KIND stack as might be interpreted by the routines of the Image I/O module. The following code would read such a stack into the Array stack: int width, height, depth, nchan; Array *stack; Open_Tiff("RGB_3D_Stack.tif","r"); depth = 0; while ( ! Tiff_EOF(t)) { depth += 1; Advance_Tiff(t); } Rewind_Tiff(t); Get_IFD_Shape(&width,&height,&nchan); stack = Make_Array_With_Shape(RGB_KIND,UINT8_TYPE,Coord3(depth,height,width)); depth = 0; while ( ! Tiff_EOF(t)) { for (j = 0; j < nchan; j++) { Array_Bundle plane = *stack; Get_IFD_Channel(t,j,Get_Array_Plane(Get_Array_Plane(&plane,j),depth)); } depth += 1; Advance_Tiff(t); } Close_Tiff(t); A more careful code would check the return values of all the calls for error conditions and would further check that indeed all the IFD's have the same shape, that nchan = 3, and that the Channel_Kinds are RED_CHAN, GREEN_CHAN, and BLUE_CHAN in that order. Writing a tiff file is simply a matter of building up the current IFD by adding channels to it with Add_IFD_Channel, and possibly adding a color map with Set_IFD_Map (if the first channel added is a MAPPED_CHAN), and then appending it to the sequence of IFDs already written with Update_Tiff. The routine below presents a more complex example involving Tiff objects and specifically illustrates how to write a tiff file. The routine take a file named input and looks to see if a color thumbnail is encoded in the even IFDs of the file's IFD sequence, as is the case for most Zeiss LSM files. If so, then it extracts and outputs this thumbnail to the file output. In this example, care was taken to at least protect every call, returning true if there was an error of any kind. Note also the care that is taken to clean up any open objects regardless of how the routine terminates. boolean Extract_Thumbnail(string input, string output) { Tiff *R, *W; Array *P; int w1[2], h1[2], n1[2]; int w, h, d, n, i, c; int status = 1; if ((R = Open_Tiff(input,"r")) == NULL) return (1); if ((W = Open_Tiff(output,"w")) == NULL) goto exit1; for (d = 0; ! Tiff_EOF(R); d++) { if (d < 2) { if (Get_IFD_Shape(R,w1+d,h1+d,n1+d)) goto exit2; } else { if (Get_IFD_Shape(R,&w,&h,&n)) goto exit2; if (w1[d%2] != w || h1[d%2] != h || n1[d%2] != n) goto exit2; if (d%2) { if (n != 3) goto exit2; for (c = 0; c < n; c++) if (Get_IFD_Channel_Kind(R,c) != RED_CHAN+c || Get_IFD_Channel_Type(R,c) != UINT8_TYPE) goto exit2; } } Advance_Tiff(R); } Rewind_Tiff(R); P = Make_Array_With_Shape(RGB_KIND,UINT8_TYPE,Coord2(h1[1],w1[1])); for (d = 0; ! Tiff_EOF(R); d++) { if (d%2) { for (c = 0; c < 3; c++) { Array_Bundle p = *P; if (Get_IFD_Channel(R,c,Get_Array_Plane(&p,c))) goto exit3; if (Add_IFD_Channel(W,&p,RED_CHAN+c)) goto exit3; } Update_Tiff(W,DONT_PRESS); } Advance_Tiff(R); } status = 0; exit3: Free_Array(P); exit2: Close_Tiff(W); exit1: Close_Tiff(R); return (status); } Enumerated Scalars Documentation
The possible photometric interpretations for a channel. As noted in the detailed description the only channel in an IFD that can have Channel_Kind MAPPED_CHAN is the first. Even if you ask Add_IFD_Channel to add a MAPPED_CHAN it will end up being PLAIN_CHAN if it is not the first. If it is the first, then you should supply the expected color map with Set_IFD_Map. Routine Documentation
Open file_name for reading if mode = "r", or for writing if mode = "w" as a tiff-encoded file return a Tiff object that models the current state of the I/O. The Tiff is setup so that its current IFD is the first in the sequence. NULL is returned if there are any problems and if so the nature of the problem can be diagnosed with Image_Error.
Close the tif I/O object. This routine must be called to properly complete the writing of a tiff file. It frees the tif object.
Set the width, height, and number of channels in the current IFD of the readable Tiff tif at the locations pointed at by width, height, and num_chan, respectively. True is returned if any I/O or decoding errors occur in attempting to get the shape of the IFD, and if so the nature of the problem can be diagnosed with Image_Error.
Return the Value_Type of channel channel in the current IFD of the readable Tiff tif. If there is any error in accessing the current IFD or the parameter channel is out of range, then -1 is returned and the nature of the problem can be diagnosed with Image_Error.
Return the Channel_Kind of channel channel in the current IFD of the readable Tiff tif. If there is any error in accessing the current IFD or the parameter channel is out of range, then -1 is returned and the nature of the problem can be diagnosed with Image_Error.
Read channel channel from the current IFD of readable Tiff tif into the data vector of array plane. The array plane must be a PLAIN_KIND 2D array whose dimensions match those of the channels of the IFD and whose type must be consistent with the Value_Type of the channel (i.e. Get_IFD_Channel_Type(tif,channel)). True is returned if any I/O or decoding errors occur in attempting to fetch the channel, and if so the nature of the problem can be diagnosed with Image_Error.
Return a pointer to the text of the JF_ANO_BLOCK tag of the current IFD of the readable Tiff tif if it is present. If it is not present than a pointer to an empty string is returned, and if there is an error than NULL is returned.
Place the value of the color map of the current IFD of the readable Tiff tif in the array map. The array map must be an RGB_KIND 1D array whose size is 2scale where scale is the number of bits in the first channel that must further be of kind CHAN_MAPPED. If it is not, or any other I/O or decoding error occurs then true is returned and the nature of the problem can be diagnosed with Image_Error.
The readable Tiff tif, has its current IFD updated to the next one in sequence within the underlying tiff file.
The readable Tiff tif, has its current IFD reset to the first one in the sequence of IFDs within the underlying tiff file.
Returns true only if the tif, that must be opened for reading, is at the end of the file, i.e. it has advanced beyond the last IFD.
Add a new channel to the current IFD of the writeable Tiff tif. The contents of the channel will be those of plane when the Tiff is updated and plane must be a PLAIN_KIND 2D array. If it is the first channel added, then its dimensions set the dimensions of the channels of the current IFD, otherwise its dimensions must match those of the previously added channels. The setting of the parameter kind determines the photometric interpretation or Channel_Kind for the channel. NB: All the arrays added as channels to a current IFD must not be modified until after the Tiff is updated with a call to Update_Tiff as their data is copied directly from the array to the underlying file at the time of the update and not before. If there are any errors then true is returned and the problem can be diagnosed with a call to Image_Error.
Set the value of the colormap of the writeable Tiff tif to the value in the array map. Unlike Add_IFD_Channel, the values of map are copied immediately so there is no requirement for map to remain untouched until the Tiff is updated. However, at least the first channel must have been added to the current IFD and it must be of kind MAPPED_CHAN. Moreover, the array map must be an RGB_KIND 1D array whose size is 2scale where scale is the number of bits in the first channel. If there are any errors then true is returned and the problem can be diagnosed with a call to Image_Error.
Write the contents of the current IFD of the writeable Tiff tif as the next IFD in the underlying tiff file's sequence (as long as it is not empty), and reset the current IFD to be empty. |