source: trunk/loci/formats/getting-started.txt @ 2292

Revision 2292, 12.4 KB checked in by melissa, 13 years ago (diff)

Fixed channel min/max for multi-series formats; added a note about new min/max
methods to "getting started" file.

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