source: tags/loci-tools-2007-Feb-7/getting-started.txt @ 2221

Revision 2221, 11.6 KB checked in by melissa, 13 years ago (diff)

Added note about new RandomAccessStream feature.

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