source: trunk/loci/formats/reader-guide.txt @ 2588

Revision 2588, 10.1 KB checked in by melissa, 13 years ago (diff)

Updated documentation to reflect recent API changes.

Line 
1            Bio-Formats File Format Reader Guide by Melissa Linkert
2
3This document is a brief guide to writing new Bio-Formats file format readers.
4
5All format readers should extend either loci.formats.FormatReader or a reader
6in loci.formats.in.
7
8                              Methods to Override
9                             ---------------------
10
11boolean isThisType(byte[]) :
12  Check the first few bytes of a file to determine if the file can be read by
13  this reader.  You can assume that the first byte of the array corresponds to
14  the first byte of the file.  Return true if the file can be read; false if
15  not (or if there is no way of checking).
16
17int getImageCount() throws FormatException, IOException :
18  Return the number of image planes in the file. 
19
20boolean isRGB() throws FormatException, IOException :
21  This should only return true if the file's image planes are stored as RGB
22  or indexed color.  All other cases return false.
23
24boolean isLittleEndian() throws FormatException, IOException :
25  Return the byte ordering of the pixel data.  Note that in some cases, this
26  is different from the file's native ordering.  If the pixel data is
27  guaranteed to have 8 bits per pixel, then isLittleEndian can return
28  anything.
29
30boolean isInterleaved() throws FormatException, IOException :
31  This is only relevant if the file's image planes are stored as RGB or
32  indexed color; however, it should always be implemented.  If the image
33  planes are RGB, and the pixel data is stored as "RRR...GGG...BBB", then
34  return false.  Otherwise, if the pixel data is stored as "RGBRGBRGB..."
35  return true.
36
37String[] getUsedFiles() throws FormatException, IOException :
38  You only need to override this if your format uses multiple files in a single
39  dataset.  This method should return a list of all the files associated with
40  the given file name (i.e. every file needed to display the current dataset).
41  For an example of how this works, see loci.formats.in.PerkinElmerReader.
42
43byte[] openBytes(int) throws FormatException, IOException :
44  Returns a byte array containing the pixel data for the specified image from
45  the given file.  Should throw a FormatException if the image number is invalid
46  (less than 0 or >= the number of images).  The ordering of the array
47  returned by openBytes should correspond to the values returned by
48  isLittleEndian() and isInterleaved().  Also, the length of the
49  byte array should be [image width * image height * bytes per pixel].  Extra
50  bytes will generally be truncated.
51
52BufferedImage openImage(int) throws FormatException, IOException :
53  Basically the same as openBytes, but returns a java.awt.image.BufferedImage
54  instead of a byte array.  In general, the easiest way to implement this is
55  by getting the corresponding byte array from openBytes, then returning
56  loci.formats.ImageTools.makeImage(byte[], int width, int height, int
57  numberOfChannels, boolean isInterleaved, int bytesPerPixel, boolean
58  isLittleEndian).
59
60void close() throws FormatException, IOException :
61  Close the stream used to read the file, and set the stream and file name to
62  null.  It is also very important to free any resources initialized elsewhere
63  in the reader.  After calling close on a reader, any additional calls to
64  that reader should result in a call to initFile(String).
65
66void close(boolean) throws FormatException, IOException :
67  If the flag is set, just close the stream used to read the file (the reader
68  should remain initialized).  Otherwise, should be equivalent to calling
69  close().
70
71protected void initFile(String) throws FormatException, IOException :
72  The majority of the file parsing logic should be placed in this method.  The
73  idea is to call this method once (and only once!) when the file is first
74  opened.  Generally, you will want to start by calling
75  super.initFile(String).  You will also need to set up the stream for reading
76  the file, as well as initializing any dimension information and metadata.
77  Most of this logic is up to you; however, you should populate the 'core'
78  variable (see loci.formats.CoreMetadata).
79
80  Note that each variable is initialized to 0 or null when
81  super.initFile(String) is called.
82  Also, super.initFile(String) constructs a Hashtable called "metadata" where
83  you should store any relevant metadata.
84
85Note that if the new format is a variant of a format currently supported by
86Bio-Formats, it is more efficient to make the new reader a subclass of the
87existing reader (rather than subclassing FormatReader).  In this case, it is
88usually sufficient to override initFile(String) and isThisType(byte[]).
89
90
91If you read from a file using something other than RandomAccessStream or
92Location, you *must* use the file name returned by Location.getMappedId(String),
93not the file name passed to the reader.
94Thus, a stub for initFile(String) might look like this:
95
96  protected void initFile(String id) throws FormatException, IOException {
97    super.initFile(id);
98
99    RandomAccessStream in = new RandomAccessStream(id);
100    // alternatively,
101    //FileInputStream in = new FileInputStream(Location.getMappedId(id));
102
103    // read basic file structure and metadata from stream
104  }
105
106For more details, see the javadoc for Location.mapId(String, String)
107and Location.getMappedId(String).
108
109                              Other Useful Things
110                             ---------------------
111
112- loci.formats.RandomAccessStream is a hybrid RandomAccessFile/InputStream
113  class that is generally more efficient than either RandomAccessFile or
114  InputStream, and implements the DataInput interface.  It also keeps track
115  of open files, and will automatically close and re-open files as needed
116  to ensure that there aren't too many files open at one time.
117  It is recommended that you use this for reading binary files.
118
119- loci.formats.Location provides an API similar to java.io.File, and supports
120  File-like operations on URLs.  It is highly recommended that you use this
121  instead of File.  See the javadoc for additional information.
122
123- loci.formats.DataTools provides a number of methods for converting bytes to
124  shorts, ints, longs, etc.  It also supports reading most primitive types
125  directly from a RandomAccessStream (or other DataInput implementation).
126
127- loci.formats.ImageTools provides several methods for manipulating
128  java.awt.image.BufferedImage objects.  In particular, it can create
129  BufferedImages from primitive type arrays, resize images, split RGB images
130  into 3 grayscale images, and so on.  Consult the source or javadoc for more
131  information.
132
133- If your reader relies on third-party code which may not be available to all
134  users, it is strongly suggested that you access this code only through a
135  loci.formats.ReflectedUniverse object.  For an example of how this works,
136  see loci.formats.in.ZeissZVIReader.
137
138- Several common image compression types are supported through subclasses of
139  loci.formats.BaseCompressor.  These include LZW, LZO, Base64, ZIP and
140  RLE (PackBits).
141
142- Debugging statements can be added using FormatReader.debug(String).
143
144- If you wish to convert a file's metadata to OME-XML (strongly encouraged),
145  loci.formats.ome.OMEXMLMetadataStore provides methods for creating OME-XML
146  from metadata values.  Note that OMEXMLMetadataStore is a subclass of
147  loci.formats.MetadataStore (every subclass of FormatReader keeps an instance
148  of MetadataStore by default); so to add OME-XML support is as simple as
149  calling getMetadataStore() on a format reader instance, and then
150  calling the appropriate "set" methods as documented in OMEXMLMetadataStore.
151
152- Utility methods for reading and writing individual bits from a byte array
153  can be found in loci.formats.BitBuffer and loci.formats.BitWriter
154
155- Once you have written your file format reader, add a line to the readers.txt
156  file with the fully qualified name of the reader, followed by a '#' and the
157  file extensions associated with the file format. Note that ImageReader,
158  the master file format reader, tries to identify which format reader to use
159  according to the order given in readers.txt, so be sure to place your reader
160  in an appropriate position within the list.
161
162- The easiest way to test your new reader is by calling "java
163  loci.formats.ImageReader <file name>".  If all goes well, you should see
164  all of the metadata and dimension information, along with a window showing
165  the images in the file.  ImageReader can take additional parameters; a
166  brief listing is provided for reference, but it is recommended that you
167  take a look at the contents of FormatReader.testRead to see exactly what
168  each one does.
169
170    Argument            Action
171    --------------------------
172    -nopix              Read metadata only; don't display images.
173    -nometa             Output only core metadata (dimension information).
174    -thumbs             Read thumbnails instead of regular images.
175    -merge              Combine separate channels into a set of RGB images.
176    -stitch             Open all files with a similar name.
177    -separate           Force RGB images to be split into separate channels.
178    -omexml             Output the OME-XML for the file.
179    -normalize          Normalize floating point images.
180    -fast               Display RGB images as quickly as possible.
181    -debug              Turn on debugging output.
182    -range              Specify a range of images to open.
183    -series             Set the series number (for container file formats).
184    -map                Specify file on disk to which name should be mapped.
185
186- If you wish to test using JUnit, loci.formats.test.ReaderTest provides seven
187  basic tests that work with all Bio-Formats readers.  To run the test suite,
188  use "java loci.formats.test.ReaderTest <path to data folder>".  See the
189  ReaderTest source code for additional information.
190
191- For more details, please look at the source code and javadocs.  Studying
192  existing readers is probably the best way to get a feel for the API; I would
193  recommend first looking at loci.formats.in.ImarisReader (this is the most
194  straightforward one).  loci.formats.in.LIFReader and ZeissZVIReader are also
195  good references that show off some of the nicer features of Bio-Formats.
196
197If you have questions about Bio-Formats, please contact:
198  Curtis Rueden <ctrueden@wisc.edu>
199  Melissa Linkert <linkert@wisc.edu>
Note: See TracBrowser for help on using the repository browser.