// // ImageWriter.java // /* LOCI Bio-Formats package for reading and converting biological file formats. Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden, Chris Allan, Eric Kjellman and Brian Loranger. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package loci.formats; import java.awt.Image; import java.awt.image.ColorModel; import java.io.IOException; import java.util.*; /** * ImageWriter is the master file format writer for all supported formats. * It uses one instance of each writer subclass (specified in writers.txt, * or other class list source) to identify file formats and write data. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/loci/formats/ImageWriter.java">Trac</a>, * <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/formats/ImageWriter.java">SVN</a></dd></dl> * * @author Curtis Rueden ctrueden at wisc.edu */ public class ImageWriter implements IFormatWriter { // -- Static fields -- /** Default list of writer classes, for use with noargs constructor. */ private static ClassList defaultClasses; // -- Static helper methods -- private static ClassList getDefaultWriterClasses() { if (defaultClasses == null) { // load built-in writer classes from writers.txt file try { defaultClasses = new ClassList("writers.txt", IFormatWriter.class); } catch (IOException exc) { defaultClasses = new ClassList(IFormatWriter.class); LogTools.trace(exc); } } return defaultClasses; } // -- Fields -- /** List of supported file format writers. */ protected IFormatWriter[] writers; /** * Valid suffixes for all file format writers. * Populated the first time getSuffixes() is called. */ private String[] suffixes; /** * Compression types for all file format writers. * Populated the first time getCompressionTypes() is called. */ protected String[] compressionTypes; /** Name of current file. */ protected String currentId; /** Current form index. */ protected int current; // -- Constructor -- /** * Constructs a new ImageWriter with the default * list of writer classes from writers.txt. */ public ImageWriter() { this(getDefaultWriterClasses()); } /** Constructs a new ImageWriter from the given list of writer classes. */ public ImageWriter(ClassList classList) { // add writers to the list Vector v = new Vector(); Class[] c = classList.getClasses(); for (int i=0; i<c.length; i++) { IFormatWriter writer = null; try { writer = (IFormatWriter) c[i].newInstance(); } catch (IllegalAccessException exc) { } catch (InstantiationException exc) { } if (writer == null) { LogTools.println("Error: " + c[i].getName() + " cannot be instantiated."); continue; } v.add(writer); } writers = new IFormatWriter[v.size()]; v.copyInto(writers); } // -- ImageWriter API methods -- /** Gets a string describing the file format for the given file. */ public String getFormat(String id) throws FormatException, IOException { return getWriter(id).getFormat(); } /** Gets the writer used to save the given file. */ public IFormatWriter getWriter(String id) throws FormatException { if (!id.equals(currentId)) { // initialize file boolean success = false; for (int i=0; i<writers.length; i++) { if (writers[i].isThisType(id)) { current = i; currentId = id; success = true; break; } } if (!success) throw new FormatException("Unknown file format: " + id); } return writers[current]; } /** Gets the writer used to save the current file. */ public IFormatWriter getWriter() { return writers[current]; } /** Gets the file format writer instance matching the given class. */ public IFormatWriter getWriter(Class c) { for (int i=0; i<writers.length; i++) { if (writers[i].getClass().equals(c)) return writers[i]; } return null; } /** Gets all constituent file format writers. */ public IFormatWriter[] getWriters() { IFormatWriter[] w = new IFormatWriter[writers.length]; System.arraycopy(writers, 0, w, 0, writers.length); return w; } // -- IFormatWriter API methods -- /* @see IFormatWriter#saveBytes(byte[], boolean) */ public void saveBytes(byte[] bytes, boolean last) throws FormatException, IOException { getWriter().saveBytes(bytes, last); } /* @see IFormatWriter#saveBytes(byte[], int, boolean, boolean) */ public void saveBytes(byte[] bytes, int series, boolean lastInSeries, boolean last) throws FormatException, IOException { getWriter().saveBytes(bytes, series, lastInSeries, last); } /* @see IFormatWriter#saveImage(Image, boolean) */ public void saveImage(Image image, boolean last) throws FormatException, IOException { getWriter().saveImage(image, last); } /* @see IFormatWriter#saveImage(Image, int, boolean, boolean) */ public void saveImage(Image image, int series, boolean lastInSeries, boolean last) throws FormatException, IOException { getWriter().saveImage(image, series, lastInSeries, last); } /* @see IFormatWriter#canDoStacks() */ public boolean canDoStacks() { return getWriter().canDoStacks(); } /* @see IFormatWriter#setMetadataRetrieve(MetadataRetrieve) */ public void setMetadataRetrieve(MetadataRetrieve r) { for (int i=0; i<writers.length; i++) writers[i].setMetadataRetrieve(r); } /* @see IFormatReader#getMetadataStore() */ public MetadataRetrieve getMetadataRetrieve() { return getWriter().getMetadataRetrieve(); } /* @see IFormatWriter#setColorModel(ColorModel) */ public void setColorModel(ColorModel cm) { for (int i=0; i<writers.length; i++) writers[i].setColorModel(cm); } /* @see IFormatWriter#getColorModel() */ public ColorModel getColorModel() { // NB: all writers should have the same color model return writers[0].getColorModel(); } /* @see IFormatWriter#setFramesPerSecond(int) */ public void setFramesPerSecond(int rate) { for (int i=0; i<writers.length; i++) writers[i].setFramesPerSecond(rate); } /* @see IFormatWriter#getFramesPerSecond() */ public int getFramesPerSecond() { // NB: all writers should have the same frames per second return writers[0].getFramesPerSecond(); } /* @see IFormatWriter#getCompressionTypes() */ public String[] getCompressionTypes() { if (compressionTypes == null) { HashSet set = new HashSet(); for (int i=0; i<writers.length; i++) { String[] s = writers[i].getCompressionTypes(); if (s != null) { for (int j=0; j<s.length; j++) set.add(s[j]); } } compressionTypes = new String[set.size()]; set.toArray(compressionTypes); Arrays.sort(compressionTypes); } return compressionTypes; } /* @see IFormatWriter#getPixelTypes() */ public int[] getPixelTypes() { return getWriter().getPixelTypes(); } /* @see IFormatWriter#isSupportedType(int) */ public boolean isSupportedType(int type) { return getWriter().isSupportedType(type); } /* @see IFormatWriter#setCompression(String) */ public void setCompression(String compress) throws FormatException { boolean ok = false; for (int i=0; i<writers.length; i++) { String[] s = writers[i].getCompressionTypes(); for (int j=0; j<s.length; j++) { if (s[j].equals(compress)) { // valid compression type for this format writers[i].setCompression(compress); ok = true; } } } if (!ok) throw new FormatException("Invalid compression type: " + compress); } // -- IFormatHandler API methods -- /* @see IFormatHandler#isThisType(String) */ public boolean isThisType(String name) { // NB: Unlike individual format writers, ImageWriter defaults to *not* // allowing files to be opened to analyze type, because doing so is // quite slow with the large number of supported formats. return isThisType(name, false); } /* @see IFormatHandler#isThisType(String, boolean) */ public boolean isThisType(String name, boolean open) { for (int i=0; i<writers.length; i++) { if (writers[i].isThisType(name, open)) return true; } return false; } /* @see IFormatHandler#getFormat() */ public String getFormat() { return getWriter().getFormat(); } /* @see IFormatHandler#getSuffixes() */ public String[] getSuffixes() { if (suffixes == null) { HashSet suffixSet = new HashSet(); for (int i=0; i<writers.length; i++) { String[] suf = writers[i].getSuffixes(); for (int j=0; j<suf.length; j++) suffixSet.add(suf[j]); } suffixes = new String[suffixSet.size()]; suffixSet.toArray(suffixes); Arrays.sort(suffixes); } return suffixes; } /* @see IFormatHandler#setId(String) */ public void setId(String id) throws FormatException, IOException { getWriter(id).setId(id); } /* @see IFormatHandler#setId(String, boolean) */ public void setId(String id, boolean force) throws FormatException, IOException { getWriter(id).setId(id, force); } /* @see IFormatHandler#close() */ public void close() throws IOException { for (int i=0; i<writers.length; i++) writers[i].close(); } // -- StatusReporter API methods -- /* @see IFormatHandler#addStatusListener(StatusListener) */ public void addStatusListener(StatusListener l) { for (int i=0; i<writers.length; i++) writers[i].addStatusListener(l); } /* @see IFormatHandler#removeStatusListener(StatusListener) */ public void removeStatusListener(StatusListener l) { for (int i=0; i<writers.length; i++) writers[i].removeStatusListener(l); } /* @see IFormatHandler#getStatusListeners() */ public StatusListener[] getStatusListeners() { // NB: all writers should have the same status listeners return writers[0].getStatusListeners(); } // -- Deprecated IFormatWriter API methods -- /** @deprecated Replaced by {@link #canDoStacks()} */ public boolean canDoStacks(String id) throws FormatException { try { setId(id); } catch (IOException exc) { // NB: should never happen throw new FormatException(exc); } return canDoStacks(id); } /** @deprecated Replaced by {@link #getPixelTypes()} */ public int[] getPixelTypes(String id) throws FormatException, IOException { setId(id); return getPixelTypes(id); } /** @deprecated Replaced by {@link #isSupportedType(int type)} */ public boolean isSupportedType(String id, int type) throws FormatException, IOException { setId(id); return isSupportedType(type); } /** @deprecated Replaced by {@link #saveImage(Image, boolean)} */ public void save(String id, Image image, boolean last) throws FormatException, IOException { setId(id); saveImage(image, last); } }