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
MetadataStore metadata;
try {
ServiceFactory factory = new ServiceFactory();
OMEXMLService service = factory.getInstance(OMEXMLService.class);
metadata = service.createOMEXMLMetadata();
}
catch (DependencyException exc) {
throw new FormatException("Could not create OME-XML store.", exc);
}
catch (ServiceException exc) {
throw new FormatException("Could not create OME-XML store.", exc);
}
reader.setMetadataStore(metadata);
// initialize the dataset
reader.setId("/path/to/file");
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)
OMEXMLService service = factory.getInstance(OMEXMLService.class);
writer.setMetadataRetrieve(service.asRetrieve(reader.getMetadataStore()));
// initialize the writer
writer.setId("/path/to/output/file");
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++) {
reader.setSeries(series);
writer.setSeries(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:
reader.close();
writer.close();
Converting to multiple files
The recommended method of converting to multiple files is to use a single IFormatWriter, like so:
// you should have set up a reader as in the first example
ImageWriter writer = new ImageWriter();
OMEXMLService service = factory.getInstance(OMEXMLService.class);
writer.setMetadataRetrieve(service.asRetrieve(reader.getMetadataStore()));
// replace this with your own filename definitions
// in this example, we're going to write half of the planes to one file
// and half of the planes to another file
String[] outputFiles =
new String[] {"/path/to/file/1.tiff", "/path/to/file/2.tiff"};
writer.setId(outputFiles[0]);
int planesPerFile = reader.getImageCount() / outputFiles.length;
for (int file=0; file<outputFiles.length; file++) {
writer.changeOutputFile(outputFiles[file]);
for (int image=0; image<planesPerFile; image++) {
int index = file * planesPerFile + image;
writer.saveBytes(image, reader.openBytes(index));
}
}
reader.close();
writer.close();
The advantage here is that the relationship between the files is preserved when converting to formats that support multi-file datasets internally (namely OME-TIFF). If you are only converting to graphics formats (e.g. JPEG, AVI, MOV), then you could also use a separate IFormatWriter for each file, like this:
OMEXMLService service = factory.getInstance(OMEXMLService.class);
// again, you should have set up a reader already
String[] outputFiles = new String[] {"/path/to/file/1.avi", "/path/to/file/2.avi"};
int planesPerFile = reader.getImageCount() / outputFiles.length;
for (int file=0; file<outputFiles.length; file++) {
ImageWriter writer = new ImageWriter();
writer.setMetadataRetrieve(service.asRetrieve(reader.getMetadataStore()));
writer.setId(outputFiles[file]);
for (int image=0; image<planesPerFile; image++) {
int index = file * planesPerFile + image;
writer.saveBytes(image, reader.openBytes(index));
}
writer.close();
}