Version 3 (modified by melissa, 10 years ago) (diff)


Exporting files using Bio-Formats

This guide pertains to version 4.2 and later.

Basic conversion

The first thing we need to do is set up a reader:

  // create a reader that will automatically handle any supported format
  IFormatReader reader = new ImageReader();
  // tell the reader where to store the metadata from the dataset
  // initialize the dataset

Now, we set up our writer:

  // create a writer that will automatically handle any supported output format
  IFormatWriter writer = new ImageWriter();
  // give the writer a MetadataRetrieve object, which encapsulates all of the
  // dimension information for the dataset (among many other things)
  // initialize the writer

Note that the extension of the file name passed to 'writer.setId(...)' determines the file format of the exported file.

Now that everything is set up, we can start writing planes:

  for (int series=0; series<reader.getSeriesCount(); series++) {

    for (int image=0; image<reader.getImageCount(); image++) {
      writer.saveBytes(image, reader.openBytes(image));

Finally, make sure to close both the reader and the writer. Failure to do so can cause:

  • file handle leaks
  • memory leaks
  • truncated output files

Fortunately, closing the files is very easy:


Converting large images

The flaw in the previous example is that it requires an image plane to be fully read into memory before it can be saved. In many cases this is fine, but if you are working with very large images (especially > 4 GB) this is problematic. The solution is to break each image plane into a set of reasonably-sized tiles and save each tile separately - thus substantially reducing the amount of memory required for conversion.

For now, we'll assume that your tile size is 1024 x 1024, though in practice you will likely want to adjust this. Assuming you have an IFormatReader and IFormatWriter set up as in the previous example, let's start writing planes:

  int tileWidth = 1024;
  int tileHeight = 1024;

  for (int series=0; series<reader.getSeriesCount(); series++) {
    // determine how many tiles are in each image plane
    // for simplicity, we'll assume that the image width and height are multiples of 1024
    int tileRows = reader.getSizeY() / tileHeight;
    int tileColumns = reader.getSizeX() / tileWidth;

    for (int image=0; image<reader.getImageCount(); image++) {
      for (int row=0; row<tileRows; row++) {
        for (int col=0; col<tileColumns; col++) {
          // open a tile - in addition to the image index, we need to specify
          // the (x, y) coordinate of the upper left corner of the tile, along with the
          // width and height of the tile
          byte[] tile = reader.openBytes(image, col * tileWidth, row * tileHeight, tileWidth, tileHeight);
          writer.saveBytes(image, tile, col * tileWidth, row * tileHeight, tileWidth, tileHeight);

As noted, the example assumes that the width and height of the image are multiples of the tile dimensions. Be careful, as this is not always the case; the last column and/or row may be smaller than preceding columns/rows. An exception will be thrown if you attempt to read or write a tile that is not completely contained by the original image plane. Most writers perform best if the tile width is equal to the image width, although specifying any valid width should work.

As before, you need to close the reader and writer.

Converting to multiple files

Known issues (r6306)

  • exporting multiple OME-TIFF files does not work correctly
  • several writers do not support writing image tiles:
    • APNG
    • AVI
    • Java
    • JPEG-2000
    • JPEG
    • OME-XML