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

Revision 2337, 12.5 KB checked in by curtis, 13 years ago (diff)

Formatting tweaks.

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