Image I/O Module Reference
I/O of Tiff-encoded multi-channel images and stacks.
More...
#include <image.h>
Structures
Enumerated Scalars
Routines
Array * |
Read_ImageG
(string file_name, int layer) |
Layer_Bundle * |
Read_Images
(string file_name, Layer_Bundle *images RM) |
boolean |
Write_Image
(string file_name, Array *array, Image_Compress comp) |
boolean |
Write_Images
(string file_name, Layer_Bundle *images, Image_Compress comp) |
Array * |
Read_SeriesG
(Series_Bundle *files M, int layer) |
Layer_Bundle * |
Read_All_Series
(Series_Bundle *files M, Layer_Bundle *images RM) |
boolean |
Write_Series
(Series_Bundle *files, Array *image, Image_Compress comp) |
boolean |
Write_All_Series
(Series_Bundle *files, Layer_Bundle *images, Image_Compress comp) |
Detailed Description
A Tiff-encoded file contains a sequence of one or more image file descriptors (IFD's) each of
which contains any number of channels each of which is a 2D array, all of the same shape.
A 3D stack is not explicitly supported but the common convention is that if a tiff file
contains a sequence of IFD's all of which encode the same channels and arrays of the
same dimensions and types, then the sequence of IFD's gives each successive z-plane of
a 3D stack in each channel. 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 (or not) these interpretations, but in effect the list just given is the information
that is present.)
We divide the sequence of channels in an IFD into layers as follows:
4 channels in sequence that together constitute a RED, GREEN,
BLUE, and ALPHA channel (the order is not important), form an RGBA layer, 3 channels in
sequence that consitute a RED, GREEN, and BLUE channel, form an RGB layer, and any
other channel is a PLAIN layer. The layers are read off in sequence, always taking
RGBA over RGB over PLAIN as the next layer. For example, if an IFD has a sequence "RABGRA"
then it has 3 layers, the first is RGBA, and the second and third are considered PLAIN
despite having interpretations RED and ALPHA. As another example, "MGBRG", has 3 layers,
the second is RGB, the third is PLAIN, and the first will be RGB as it will be the result
of applying the color map to the first channel.
The examples are convoluted in order to clarify how channels are grouped into layers,
in most cases the channel sequences are straightforward, e.g. PRGBP.
The routines in the Image module, read and write the 2D or 3D layers of a tiff-encoded file
into or from an Array of the corresponding kind, type, and scale. One should be
aware of the following subtleties:
-
The scale of an array is actually operative here: the values of a 12-bit UINT16_TYPE array will be
written as 12-bit numbers to the tiff file, which in turn, when read, will produce an array
with a scale of 12.
-
The text field of the first layer array is written to a JF_ANO_BLOCK tag upon a write and
this tag is loaded into the text field of the first layer array when read. There is no
limitation on the size of a text field, so one can in principle encode arbitrarily complex
meta-data about an image in this field in an ASCII-oriented format such as XML.
-
The software will also read LSM files produced by Zeiss microscopes. The format is a small
variation on the tiff format. LSM's frequently contain thumbnails as well as the primary
image. These are ignored so that just the "primary" stack is read.
-
All the read routines may return NULL if they can't open a file or if the tiff
contents are improperly formated. Similarly, the write routines will return true if they
cannot open a file for writing. In such an error event, one may
get a descriptive string of the problem by calling Image_Error, right after the
error occurs. In order for this to be thread-safe, if multiple threads encounter an
error, only one of the threads (which is unspecified) records a descriptive string.
One must subsequently "release" the recorded error (with Image_Error_Release) in order
for a thread to record a new error, if one occurs. So an error message must be released even
when one's application is not threaded.
Read_Image reads a single specified layer from a specified file and returns the result
as a 2D or 3D array of either PLAIN_KIND, RGB_KIND, or RGBA_KIND according to the number
of IFDs in the file and the series of channel kinds in each IFD. Read_Images reads all
the layers in a file and returns them in a Layer_Bundle structure. Write_Image writes
a single 2D or 3D array as a Tiff file compressing it according to the Image_Compress
value passed to it. Write_Images writes a set of either 2D or 3D arrays as supplied
in a Layer_Bundle to a single file, compressing them as indicated.
Occasionally, especially with older data sets, the individual planes of a 3D stack are
recorded as separate files with a number series in their names. To facilitate this situation
Mylib provides the "(Read/Write)_(All_)Series" routines (Read_Series,
Read_All_Series, Write_Series, Write_All_Series) that are analogous
to the "(Read/Write)_Image(s)" routines above save that they read or write a numbered series of
files. The key is the routine Parse_Series_Name which parses the first name in such a series and
fills in a Series_Bundle structure that can then be given to the IO routines to read or
write the series.
Structure Documentation
• |
num_layers | : int |
• |
layers | : Array *[] |
Used to encode a set of 2D or 3D arrays that can be read from or written to a tiff file as
a series of layers. num_layers is the number of arrays or layers in the set, and
layers[i] is a pointer to the
ith array in the set, where i ∈ [0,num_layers-1]. All the
arrays are either 2D or 3D and have the same dimensions. The arrays can be of any kind
except COMPLEX_KIND and are of any type except FLOAT64_TYPE. The arrays in the set
do not need to be of the same kind, type, or scale.
• |
prefix | : string |
• |
suffix | : string |
• |
padded | : boolean |
• |
num_width | : int |
• |
first_num | : int |
Used to repesent an unbounded series of file names that is most easily explained with a couple
of examples. Suppose prefix = "x", suffix = ".tif", and first_num = 8. If
padded is false, then the sequence of names modeled is: "x8.tif", "x9.tif", "x10.tif", ....
On the otherhand, if padded is true and num_width = 3, then the sequence of names modeled
is: "x008.tif", "x009.tif", "x010.tif", ...
Enumerated Scalars Documentation
Image_Compress | : { DONT_PRESS LZW_PRESS PACKBITS_PRESS } |
Values that indicate what kind of compression should be applied to a data being written in
the tiff format. DONT_PRESS indicates no compression. PACKBITS_PRESS indicates
Packbits
compression which is a lossless run-length encoding scheme. Lastly, LZW_PRESS indicates
Lempel-Ziv-Welch
compression which is a very effective lossless repeat compression scheme.
Routine Documentation
string |
Image_Error () |
void |
Image_Error_Release () |
All the routines that read layers may return NULL if they can't open a file or if the tiff
contents are improperly formated. Similarly, the write routines will return true if they
cannot open a file for writing. In such an error event, one may
get a descriptive string of the problem by calling Image_Error, right after the
error occurs. In order for this to be thread-safe, if multiple threads encounter an
error, only one of the threads (which is unspecified) records a descriptive string.
One must subsequently "release" the recorded error with Image_Error_Release in order
for a thread to record a new error, if one occurs. So an error message must be released even
when one's application is not threaded.
Array * |
Read_ImageG (string file_name, int layer) |
Read layer layer from file file_name returning a newly generated 2D array if the file
contains a single IFD, and a newly generated 3D array otherwise. The layer is color mapped
if the tiff channel kind indicates it should be.
Read all the layers from file file_name and return the result in images.
The bundle images should be a semantically valid Layer_Bundle on input, i.e. if
num_layers > 0 then layers should be a vector of at least num_layers pointers to
arrays, and exactly the first num_layers of these pointers should be to valid
Array objects. The simplist way to establish a semantically valid bundle is to set
num_layers to 0 and layers to NULL. This routine will take the bundle and modify it
so that it reflects the number of layers in the file and so that layers points at an
array for each layer read, where arrays are freed, created, and or modified as necessary
to produce the result. The user is responsible for managing the array objects in the bundle
and the vector layers that points at the arrays.
Write array to a file file_name in the tiff format. The array must be 2D or 3D and
cannot be of COMPLEX_KIND or FLOAT64_TYPE. The file is compressed (or not) according
to the value of comp. Writing an LZW compressed file takes almost 3 times longer than
an uncompressed file, but does result in the file being 30-50% of the uncompressed size.
Packbits compression is faster run-length compression, but does not compress as effectively.
Write the arrays in images to the file file_name in tiff format. The arrays in
images must all be either 2D or 3D, and all have the same dimensions. The arrays can
be of different kinds and types, but may not be of COMPLEX_KIND or FLOAT64_TYPE.
The data in the file is compressed according to the value of the parameter comp.
Parse the string file_name assuming it is of the form "<prefix><first_num><suffix>"
and fills in the supplied Series_Bundle files with the constituent parts where num_width
is the length of the string matched to first_num and padded is true if the number
begins with a 0.
Read the specified layer from the series of 2D tiff images specified by the Series_Bundle
files into a newly generated 3D Array that is returned as the result. The routine will
look for a series of files as specified by files, with the field padded set to both true
and false, and it will load the longer series. For example, if files has
prefix = "x",
suffix = ".tif", num_first = 8, and num_width = 3, then the routine will look for the
series "x8.tif", "x9.tif", ... and for the series "x008.tif", "x009.tif" ... in the file system
and create the image corresponding to the longer of the two series, setting padded
accordingly (which incidentally is the only way in which files is modified by the routine).
Read all the layers from the series of 2D tiff images specified by files, filling
images with the array read exactly as for Read_Images. The identification of the
series of images to read according to files is as for Read_Series immediately above.
Write the supplied array to the seres of 2D tiff images specified by files,
compressed according to the value of comp. Unlike the read analog of this
routine, the padded field of files is operative and determines whether the
number sequence is 0-padded or not.
Write the arrays in images to the series of 2D tiff images specified by files, compressed
according to the value of comp. The arrays in
images must all be either 2D or 3D, and all have the same dimensions. The arrays can
be of different kinds and types, but may not be of COMPLEX_KIND or FLOAT64_TYPE.
|