86
• numberofactualchannelsinthecurrentseries(getSizeC()
13
)
• numberofchannelsperimage(getRGBChannelCount()
14
)
• theorderingoftheimageswithinthecurrentseries(getDimensionOrder()15)
• whethereachimageisRGB(isRGB()16)
• whetherthepixelbytesareinlittle-endianorder(isLittleEndian()
17
)
• whetherthechannelsinanimageareinterleaved(isInterleaved()
18
)
• thetypeofpixeldatainthisfile(getPixelType()
19
)
Allfileformatsareguaranteedtoaccuratelyreportcoremetadata.
Format-specificmetadatareferstoanyotherdataspecifiedinthefile-thisincludesacquisitionandhardwareparameters,among
otherthings. Thisdataisstoredinternallyinajava.util.Hashtable,andcanbeaccessedinoneoftwoways:individualvalues
canberetrievedbycallinggetMetadataValue(String)
20
,whichgetsthevalueofthespecifiedkey.Alternatively,getMetadata()
21
willreturntheentireHashtable.NotethatthekeysinthisHashtablearedifferentforeachformat,hencethename“format-specific
metadata”.
SeeBio-FormatsmetadataprocessingformoreinformationonthemetadatacapabilitiesthatBio-Formatsprovides.
11.1.3 Filereadingextras
Theprevioussectiondescribedhowtoreadpixelsastheyarestoredinthefile. However,thenativeformatisnotnecessarily
convenient,soBio-Formatsprovidesafewextrastomakefilereadingmoreflexible.
• Thereareafew“wrapper”readers(thatimplementIFormatReader)thattakeareaderintheconstructor,andmanipulate
theresultssomehow,forconvenience. Usingthemissimilartothejava.ioInputStream/OutputStreammodel: justlayer
whicheverfunctionalityyouneedbynestingthewrappers.
– BufferedImageReader
22
extendsIFormatReader,andallowspixeldatatobereturnedasBufferedImagesinsteadof
rawbytearrays.
– FileStitcher
23
extendsIFormatReader,andusesadvancedpatternmatchingheuristicstogroupfilesthatbelongtothe
samedataset.
– ChannelSeparator
24
extendsIFormatReader,andmakessurethatallplanesaregrayscale-RGBimagesaresplitinto
3separategrayscaleimages.
– ChannelMerger25extendsIFormatReader,andmergesgrayscaleimagestoRGBifthenumberofchannelsisgreater
than1.
– ChannelFiller
26
extendsIFormatReader,andconvertsindexedcolorimagestoRGBimages.
– MinMaxCalculator
27
extendsIFormatReader,andprovidesanAPIforretrievingtheminimumandmaximumpixel
valuesforeachchannel.
– DimensionSwapper
28
extendsIFormatReader,andprovidesanAPIforchangingthedimensionorderofafile.
13
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#getSizeC()
14
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#getRGBChannelCount()
15
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#getDimensionOrder()
16
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#isRGB()
17
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#isLittleEndian()
18
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#isInterleaved()
19
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#getPixelType()
20
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#getMetadataValue(java.lang.String)
21
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/loci/formats/IFormatReader.html#getMetadata()
22
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/gui/BufferedImageReader.java
23https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/FileStitcher.java
24https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/ChannelSeparator.java
25https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/ChannelMerger.java
26https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/ChannelFiller.java
27https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/MinMaxCalculator.java
28
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/DimensionSwapper.java
11.1. Anin-depthguidetousingBio-Formats
56
48
• ImageTools
29
andloci.formats.gui.AWTImageTools
30
provideanumberofmethodsformanipulatingBufferedImagesand
primitivetypearrays. Inparticular,therearemethodstosplitandmergechannelsinaBufferedImage/array,aswellas
convertingtoaspecificdatatype(e.g.convertshortdatatobytedata).
11.1.4 Writingfiles
ThefollowingfileformatscanbewrittenusingBio-Formats:
• TIFF(uncompressed,LZW,JPEG,orJPEG-2000)
• OME-TIFF(uncompressed,LZW,JPEG,orJPEG-2000)
• JPEG
• PNG
• AVI(uncompressed)
• QuickTime(uncompressedissupportednatively;additionalcodecsuseQTJava)
• EncapsulatedPostScript(EPS)
• OME-XML(notrecommended)
ThewriterAPI(seeloci.formats.IFormatWriter31)isverysimilartothereaderAPI,inthatfilesarewrittenoneplaneattime
(ratherthanallatonce).
Allwritersallowtheoutputfiletobechangedbeforethelastplanehasbeenwritten. Thisallowsyoutowritetoanynumberof
outputfilesusingthesamewriterandoutputsettings(compression,framespersecond,etc.),andisespeciallyusefulforformats
thatdonotsupportmultipleimagesperfile.
Pleaseseeloci.formats.tools.ImageConverter
32
andthisguidetoexportingtoOME-TIFFfilesforexamplesofhowtowritefiles.
11.1.5 Arcanenotesandimplementationdetails
Knownoddities:
• Importingmulti-fileformats(LeicaLEI,PerkinElmer,FV1000OIF,ICS,andPrairieTIFF,tonameafew)canfailifany
ofthefilesarerenamed.Thereare“bestguess”heuristicsinthesereaders,buttheyarenotguaranteedtoworkingeneral.
Sopleasedonotrenamefilesintheseformats.
• IfyouareworkingonaMacintosh,makesurethatthedataandresourceforksofyourimagefilesarestoredtogether.
Bio-Formatsdoesnothandleseparatedforks(thenativeQuickTimereadertries,butusuallyfails).
11.2 Generatingtestimages
Sometimesitisnicetohaveafileofaspecificsizeorpixeltypefortesting.Togenerateafile(thatcontainsgradientimages):
touch ”my-special-test-file&pixelType=uint8&sizeX=8192&sizeY=8192.fake”
Whateverisbeforethe&istheimagename;remainingkeyvaluepairsshouldbeprettyself-explanatory.Justreplacethevalues
withwhateveryouneedfortesting.
Thereareafewotherkeysthatcanbeaddedaswell:
29
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/ImageTools.java
30
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/gui/AWTImageTools.java
31
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio/src/loci/formats/IFormatWriter.java
32
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio-tools/src/loci/formats/tools/ImageConverter.java
11.2. Generatingtestimages
57
37
Key
Value
sizeZ
numberofZsections
sizeC
numberofchannels
sizeT
numberoftimepoints
bitsPerPixel
numberofvalidbits(<=numberofbitsimpliedbypixeltype)
rgb
numberofchannelsthataremergedtogether
dimOrder
dimensionorder(e.g.XYZCT)
little
whetherornotthepixeldatashouldbelittle-endian
interleaved
whetherornotmergedchannelsareinterleaved
indexed
whetherornotacolorlookuptableispresent
falseColor
whetherornotthecolorlookuptableisjustformakingtheimagelookpretty
series
numberofseries(Images)
lutLength
numberofentriesinthecolorlookuptable
Youcanoftenworkwiththe.fakefiledirectly,butinsomecasessupportforthosefilesisdisabledandsoyouwillneedtoconvert
thefiletosomethingelse.MakesurethatyouhaveBio-FormatsbuiltandtheJARsinyourCLASSPATH(individualJARsorjust
loci_tools.jar):
bfconvert test&pixelType=uint8&sizeX=8192&sizeY=8192.fake test.tiff
Ifyoudonothavethecommandlinetoolsinstalled,substituteloci.formats.tools.ImageConverter
33
forbfconvert.
33
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio-tools/src/loci/formats/tools/ImageConverter.java
11.2. Generatingtestimages
58
94
CHAPTER
TWELVE
BIO-FORMATS AS A JAVA LIBRARY
12.1 APIdocumentation
12.1.1 UsingBio-FormatsasaJavalibrary
IfyouwishtomakeuseofBio-Formatswithinyourownsoftware,youcandownloadbio-formats.jar
1
touseitasalibrary.
Justaddbio-formats.jartoyourCLASSPATHorbuildpath. Youwillalsoneedloci-common.jarforcommonI/Ofunctions,
ome-xml.jarformetadatastandardization,andSLF4J
2
forlogging.
Therearealsocertainpackagesthatifpresentwillbeutilizedtoprovideadditionalfunctionality.Toincludeone,justplaceitin
thesamefolder.
Package
Filename
License
Notes
ApacheJakartaPOI
3
library,LOCI
fork
poi-loci.jar
4
Apache
For OLE-based formats (zvi, oib,
ipw,cxd)
MDB Tools project5 Java port,
LOCIfork
mdbtools-java.jar6
LGPL
ForOlympusCellRandZeissLSM
metadata(mdb)
JAIImageI/OTools
7
pureJavaim-
plementation,LOCIfork
jai_imageio.jar
8
BSD
ForJPEG2000-basedformats(nd2,
jp2)
NetCDFJavalibrary
9
netcdf-4.0.jar
10
LGPL
For HDF5-based formats (Imaris
5.5,MINCMRI)
QuickTimeforJava
11
QTJava.zip
Commercial
ForadditionalQuickTimecodecs
SeethelistintheBio-Formatstoplevelbuildfile12 foracompleteandup-to-datelistofalloptionallibraries,whichcanallbe
foundinourGitrepository13.
Examplesofusage
ImageConverter14-Asimplecommandlinetoolforconvertingbetweenformats.
ImageInfo
15
-Amoreinvolvedcommandlineutilityforthoroughlyreadinganinputfile,printingsomeinformationaboutit,and
displayingthepixelsonscreenusingtheBio-Formatsviewer.
MinimumWriter
16
-Acommandlineutilitydemonstratingtheminimumamountofmetadataneededtowriteafile.
1
http://downloads.openmicroscopy.org/bio-formats/
2
http://slf4j.org/
3
http://jakarta.apache.org/poi/
4
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/lastSuccessfulBuild/artifact/artifacts/poi-loci.jar
5
http://sourceforge.net/projects/mdbtools
6
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/lastSuccessfulBuild/artifact/artifacts/mdbtools-java.jar
7
http://java.net/projects/jai-imageio
8
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/lastSuccessfulBuild/artifact/artifacts/jai_imageio.jar
9
http://www.unidata.ucar.edu/software/netcdf-java/
10http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/lastSuccessfulBuild/artifact/artifacts/netcdf-4.0.jar
11http://www.apple.com/quicktime/download/standalone.html
12https://github.com/openmicroscopy/bioformats/blob/develop/build.xml
13https://github.com/openmicroscopy/bioformats/blob/develop/jar
14
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio-tools/src/loci/formats/tools/ImageConverter.java
15
https://github.com/openmicroscopy/bioformats/blob/develop/components/scifio-tools/src/loci/formats/tools/ImageInfo.java
16
https://github.com/openmicroscopy/bioformats/blob/develop/components/bio-formats/utils/MinimumWriter.java
59
61
PrintTimestamps
17
-Acommandlineexampledemonstratinghowtoextracttimestampsfromafile.
Simple_Read
18
-AsimpleImageJplugindemonstratinghowtouseBio-FormatstoreadfilesintoImageJ(seeImageJ).
Read_Image19-AnImageJpluginthatusesBio-Formatstobuildupanimagestack,readingimageplanesonebyone(seeImageJ).
Mass_Importer20 -AsimplepluginforImageJthatdemonstrateshowtoopenallimagefilesinadirectoryusingBio-Formats,
groupingfileswithsimilarnamestoavoidingopeningthesamedatasetmorethanonce(seeImageJ).
ANoteonJavaWebStart(loci_tools.jarvs.bio-formats.jar)
TouseBio-FormatswithyourJavaWebStartapplication,werecommendusingbio-formats.jarratherthanloci_tools.jar—the
latterismerelyabundleofbio-formats.jarplusallitsoptionaldependencies.
Theloci_tools.jarbundleisintendedasaconvenience(e.g.tosimplifyinstallationasanImageJplugin),butisbynomeansthe
onlysolutionfordevelopers.Werecommendusingbio-formats.jarasaseparateentitydependingonyourneedsasadeveloper.
Thebundleisquitelargebecausewehaveaddedsupportforseveralformatsthatneedlargehelperlibraries(e.g. Imaris’HDF-
basedformat). However,theseadditionallibrariesareoptional;Bio-Formatshasbeencodedusingreflectionsothatitcanboth
compileandrunwithoutthem.
WhendeployingaJNLP-basedapplication,usingloci_tools.jardirectlyisnotthebestapproach,sinceeverytimeBio-Formats
isupdated,theserverwouldneedtofeedanother8+MBJARfiletotheclient. Rather,WebStartisacasewhereyoushould
keeptheJARsseparate,sinceJNLPwasdesignedtomakemanagementofJARdependenciestrivialfortheenduser.Bykeeping
bio-formats.jarandtheoptionaldependenciesseparate,onlya<1MBJARneedstobeupdatedwhenbio-formats.jarchanges.
Asadeveloper,youhavetheoptionofpackagingbio-formats.jarwithasmanyorasfewoptionallibrariesasyouwish,tocut
downonfilesizeasneeded.Youarefreetomakewhateverkindof“strippeddown”versionyourequire.Youcouldevenbuilda
custombio-formats.jarthatexcludescertainclasses,ifyoulike.
Foranexplicitenumerationofalltheoptionallibrariesincludedinloci_tools.jar,seetheloci-tools.librariesvariable
oftheant/toplevel.properties
21
fileofthedistribution. Youcanalsoreadournotesabouteachinthesourcedistribution’sAnt
build.xml
22
script.
AlsoseeBio-FormatsJavadocs
23
12.2 Examples
12.2.1 ExportingfilesusingBio-Formats
Thisguidepertainstoversion4.2andlater.
Basicconversion
Thefirstthingweneedtodoissetupareader:
// 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
reader.setMetadataStore(MetadataTools.createOMEXMLMetadata());
// initialize the dataset
reader.setId(”/path/to/file”);
Now,wesetupourwriter:
17
https://github.com/openmicroscopy/bioformats/blob/develop/components/bio-formats/utils/PrintTimestamps.java
18
https://github.com/openmicroscopy/bioformats/blob/develop/components/loci-plugins/utils/Simple_Read.java
19
https://github.com/openmicroscopy/bioformats/blob/develop/components/loci-plugins/utils/Read_Image.java
20
https://github.com/openmicroscopy/bioformats/blob/develop/components/loci-plugins/utils/Mass_Importer.java
21
https://github.com/openmicroscopy/bioformats/blob/develop/ant/toplevel.properties
22
https://github.com/openmicroscopy/bioformats/blob/develop/build.xml#L240
23
http://hudson.openmicroscopy.org.uk/job/BIOFORMATS-trunk/javadoc/
12.2. Examples
60
44
// 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)
writer.setMetadataRetrieve(MetadataTools.asRetrieve(reader.getMetadataStore()));
// initialize the writer
writer.setId(”/path/to/output/file”);
Notethattheextensionofthefilenamepassedto‘writer.setId(...)’determinesthefileformatoftheexportedfile.
Nowthateverythingissetup,wecanstartwritingplanes:
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,makesuretocloseboththereaderandthewriter.Failuretodosocancause:
• filehandleleaks
• memoryleaks
• truncatedoutputfiles
Fortunately,closingthefilesisveryeasy:
reader.close();
writer.close();
Convertinglargeimages
Theflawinthepreviousexampleisthatitrequiresanimageplanetobefullyreadintomemorybeforeitcanbesaved.Inmany
casesthisisfine,butifyouareworkingwithverylargeimages(especially>4GB)thisisproblematic.Thesolutionistobreak
eachimageplaneintoasetofreasonably-sizedtilesandsaveeachtileseparately-thussubstantiallyreducingtheamountof
memoryrequiredforconversion.
Fornow,we’llassumethatyourtilesizeis1024x1024,thoughinpracticeyouwilllikelywanttoadjustthis.Assumingyouhave
anIFormatReaderandIFormatWritersetupasinthepreviousexample,let’sstartwritingplanes:
int tileWidth = 1024;
int tileHeight = 1024;
for (int series=0; series<reader.getSeriesCount(); series++) {
reader.setSeries(series);
writer.setSeries(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++) {
12.2. Examples
61
52
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
int xCoordinate = col * tileWidth;
int yCoordinate = row * tileHeight;
byte[] tile =
reader.openBytes(image, xCoordinate, yCoordinate, tileWidth, tileHeight);
writer.saveBytes(
image, tile, xCoordinate, yCoordinate, tileWidth, tileHeight);
}
}
}
}
Asnoted,theexampleassumesthatthewidthandheightoftheimagearemultiplesofthetiledimensions.Becareful,asthisis
notalwaysthecase;thelastcolumnand/orrowmaybesmallerthanprecedingcolumns/rows.Anexceptionwillbethrownifyou
attempttoreadorwriteatilethatisnotcompletelycontainedbytheoriginalimageplane. Mostwritersperformbestifthetile
widthisequaltotheimagewidth,althoughspecifyinganyvalidwidthshouldwork.
Asbefore,youneedtoclosethereaderandwriter.
Convertingtomultiplefiles
TherecommendedmethodofconvertingtomultiplefilesistouseasingleIFormatWriter,likeso:
// you should have set up a reader as in the first example
ImageWriter writer = new ImageWriter();
writer.setMetadataRetrieve(MetadataTools.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();
Theadvantagehereisthattherelationshipbetweenthefilesispreservedwhenconvertingtoformatsthatsupportmulti-filedatasets
internally(namelyOME-TIFF).Ifyouareonlyconvertingtographicsformats(e.g.JPEG,AVI,MOV),thenyoucouldalsouse
aseparateIFormatWriterforeachfile,likethis:
// 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(MetadataTools.asRetrieve(reader.getMetadataStore()));
writer.setId(outputFiles[file]);
12.2. Examples
62
46
for (int image=0; image<planesPerFile; image++) {
int index = file * planesPerFile + image;
writer.saveBytes(image, reader.openBytes(index));
}
writer.close();
}
Knownissues
ListofTractickets
24
12.2.2 FurtherdetailsonexportingrawpixeldatatoOME-TIFFfiles
ThisdocumentexplainshowtoexportpixeldatatoOME-TIFFusingBio-Formatsversion4.2andlater.
ThefirstthingthatmusthappeniswemustcreatetheobjectthatstoresOME-XMLmetadata.Thisisdoneasfollows:
ServiceFactory factory = new ServiceFactory();
OMEXMLService service = factory.getInstance(OMEXMLService.class);
IMetadata omexml = service.createOMEXMLMetadata();
The‘omexml’objectcannowbeusedinourcodetostoreOME-XMLmetadata,andbythefileformatwritertoretrieveOME-
XMLmetadata.
Nowthatwehavesomewheretoputmetadata,weneedtopopulateasmuchmetadataaswecan. Theminimumamountof
metadatarequiredis:
• endiannessofthepixeldata
• theorderinwhichdimensionsarestored
• thebitdepthofthepixeldata
• thenumberofchannels
• thenumberoftimepoints
• thenumberofZsections
• thewidth(inpixels)ofanimage
• theheight(inpixels)ofanimage
• thenumberofsamplesperchannel(3forRGBimages,1otherwise)
Wepopulatethatmetadataasfollows:
omexml.setImageID(”Image:0”, 0);
omexml.setPixelsID(”Pixels:0”, 0);
// specify that the pixel data is stored in big-endian order
// replace ’TRUE’ with ’FALSE’ to specify little-endian order
omexml.setPixelsBinDataBigEndian(Boolean.TRUE, 0, 0);
omexml.setPixelsDimensionOrder(DimensionOrder.XYCZT, 0);
omexml.setPixelsType(PixelType.UINT16, 0);
omexml.setPixelsSizeX(new PositiveInteger(width), 0);
omexml.setPixelsSizeY(new PositiveInteger(height), 0);
omexml.setPixelsSizeZ(new PositiveInteger(zSectionCount), 0);
omexml.setPixelsSizeC(new PositiveInteger(channelCount *
24
http://trac.openmicroscopy.org.uk/ome/query?status=accepted&status=new&status=reopened&keywords=
export&component=Bio-
Formats&col=id&col=summary&col=status&col=type&col=priority&col=milestone&col=component&order=priority
12.2. Examples
63
Documents you may be interested
Documents you may be interested