// // WriterWrapper.java // /* OME Bio-Formats package for reading and converting biological file formats. Copyright (C) 2005-@year@ UW-Madison LOCI and Glencoe Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU 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.ColorModel; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import loci.common.Region; import loci.formats.codec.CodecOptions; import loci.formats.meta.MetadataRetrieve; /** * Abstract superclass of writer logic that wraps other writers. * All methods are simply delegated to the wrapped writer. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/bio-formats/src/loci/formats/WriterWrapper.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/bio-formats/src/loci/formats/WriterWrapper.java;hb=HEAD">Gitweb</a></dd></dl> */ public abstract class WriterWrapper implements IFormatWriter { // -- Fields -- /** FormatWriter used to write the file. */ protected IFormatWriter writer; // -- Constructors -- /** Constructs a writer wrapper around a new image writer. */ public WriterWrapper() { this(new ImageWriter()); } /** Constructs a writer wrapper around the given writer. */ public WriterWrapper(IFormatWriter w) { if (w == null) { throw new IllegalArgumentException("Format writer cannot be null"); } writer = w; } // -- WriterWrapper API methods -- /** Gets the wrapped writer. */ public IFormatWriter getWriter() { return writer; } /** * Unwraps nested wrapped writers until the core writer (i.e., not * a {@link WriterWrapper} or {@link ImageWriter}) is found. */ public IFormatWriter unwrap() throws FormatException, IOException { return unwrap(null, null); } /** * Unwraps nested wrapped writers until the core writer (i.e., not * a {@link WriterWrapper} or {@link ImageWriter}) is found. * * @param id Id to use as a basis when unwrapping any nested * {@link ImageWriter}s. If null, the current id is used. */ public IFormatWriter unwrap(String id) throws FormatException, IOException { return unwrap(null, id); } /** * Unwraps nested wrapped writers until the given writer class is found. * * @param writerClass Class of the desired nested writer. If null, the * core writer (i.e., deepest wrapped writer) will be returned. * @param id Id to use as a basis when unwrapping any nested * {@link ImageWriter}s. If null, the current id is used. */ public IFormatWriter unwrap(Class<? extends IFormatWriter> writerClass, String id) throws FormatException, IOException { IFormatWriter w = this; while (w instanceof WriterWrapper || w instanceof ImageWriter) { if (writerClass != null && writerClass.isInstance(w)) break; if (w instanceof ImageWriter) { ImageWriter iw = (ImageWriter) w; w = id == null ? iw.getWriter() : iw.getWriter(id); } else w = ((WriterWrapper) w).getWriter(); } if (writerClass != null && !writerClass.isInstance(w)) return null; return w; } /** * Performs a deep copy of the writer, including nested wrapped writers. * Most of the writer state is preserved as well, including:<ul> * <li>{@link #isInterleaved()}</li> * <li>{@link #getColorModel()}</li> * <li>{@link #getFramesPerSecond()}</li> * <li>{@link #getCompression()}</li> * </ul> * * @param imageWriterClass If non-null, any {@link ImageWriter}s in the * writer stack will be replaced with instances of the given class. * @throws FormatException If something goes wrong during the duplication. */ public WriterWrapper duplicate( Class<? extends IFormatWriter> imageWriterClass) throws FormatException { WriterWrapper wrapperCopy = duplicateRecurse(imageWriterClass); // sync top-level configuration with original writer boolean interleaved = isInterleaved(); ColorModel cm = getColorModel(); int rate = getFramesPerSecond(); String compress = getCompression(); wrapperCopy.setInterleaved(interleaved); wrapperCopy.setColorModel(cm); wrapperCopy.setFramesPerSecond(rate); wrapperCopy.setCompression(compress); return wrapperCopy; } // -- IFormatWriter API methods -- public void changeOutputFile(String id) throws FormatException, IOException { writer.changeOutputFile(id); } public void saveBytes(int no, byte[] buf) throws FormatException, IOException { writer.saveBytes(no, buf); } public void saveBytes(int no, byte[] buf, int x, int y, int w, int h) throws FormatException, IOException { writer.saveBytes(no, buf, x, y, w, h); } public void saveBytes(int no, byte[] buf, Region tile) throws FormatException, IOException { writer.saveBytes(no, buf, tile); } public void savePlane(int no, Object plane) throws FormatException, IOException { writer.savePlane(no, plane); } public void savePlane(int no, Object plane, int x, int y, int w, int h) throws FormatException, IOException { writer.savePlane(no, plane, x, y, w, h); } public void savePlane(int no, Object plane, Region tile) throws FormatException, IOException { writer.savePlane(no, plane, tile); } public void setSeries(int series) throws FormatException { writer.setSeries(series); } public int getSeries() { return writer.getSeries(); } public void setInterleaved(boolean interleaved) { writer.setInterleaved(interleaved); } public boolean isInterleaved() { return writer.isInterleaved(); } public void setValidBitsPerPixel(int bits) { writer.setValidBitsPerPixel(bits); } public boolean canDoStacks() { return writer.canDoStacks(); } public void setMetadataRetrieve(MetadataRetrieve r) { writer.setMetadataRetrieve(r); } public MetadataRetrieve getMetadataRetrieve() { return writer.getMetadataRetrieve(); } public void setColorModel(ColorModel cm) { writer.setColorModel(cm); } public ColorModel getColorModel() { return writer.getColorModel(); } public void setFramesPerSecond(int rate) { writer.setFramesPerSecond(rate); } public int getFramesPerSecond() { return writer.getFramesPerSecond(); } public String[] getCompressionTypes() { return writer.getCompressionTypes(); } public int[] getPixelTypes() { return writer.getPixelTypes(); } public int[] getPixelTypes(String codec) { return writer.getPixelTypes(codec); } public boolean isSupportedType(int type) { return writer.isSupportedType(type); } public void setCompression(String compress) throws FormatException { writer.setCompression(compress); } /* @see IFormatWriter#setCodecOptions(CodecOptions) */ public void setCodecOptions(CodecOptions options) { writer.setCodecOptions(options); } public String getCompression() { return writer.getCompression(); } public void setWriteSequentially(boolean sequential) { writer.setWriteSequentially(sequential); } // -- Deprecated IFormatWriter methods -- /** @deprecated */ public void saveBytes(byte[] bytes, boolean last) throws FormatException, IOException { writer.saveBytes(bytes, last); } /** @deprecated */ public void saveBytes(byte[] bytes, int series, boolean lastInSeries, boolean last) throws FormatException, IOException { writer.saveBytes(bytes, series, lastInSeries, last); } /** @deprecated */ public void savePlane(Object plane, boolean last) throws FormatException, IOException { writer.savePlane(plane, last); } /** @deprecated */ public void savePlane(Object plane, int series, boolean lastInSeries, boolean last) throws FormatException, IOException { writer.savePlane(plane, series, lastInSeries, last); } // -- IFormatHandler API methods -- public boolean isThisType(String name) { return writer.isThisType(name); } public String getFormat() { return writer.getFormat(); } public String[] getSuffixes() { return writer.getSuffixes(); } public Class<?> getNativeDataType() { return writer.getNativeDataType(); } public void setId(String id) throws FormatException, IOException { writer.setId(id); } public void close() throws IOException { writer.close(); } // -- Helper methods -- private WriterWrapper duplicateRecurse( Class<? extends IFormatWriter> imageWriterClass) throws FormatException { IFormatWriter childCopy = null; if (writer instanceof WriterWrapper) { // found a nested writer layer; duplicate via recursion childCopy = ((WriterWrapper) writer).duplicateRecurse(imageWriterClass); } else { Class<? extends IFormatWriter> c = null; if (writer instanceof ImageWriter) { // found an image writer; if given, substitute the writer class c = imageWriterClass == null ? ImageWriter.class : imageWriterClass; } else { // bottom of the writer stack; duplicate the core writer c = writer.getClass(); } try { childCopy = (IFormatWriter) c.newInstance(); } catch (IllegalAccessException exc) { throw new FormatException(exc); } catch (InstantiationException exc) { throw new FormatException(exc); } } // use crazy reflection to instantiate a writer of the proper type Class<? extends WriterWrapper> wrapperClass = getClass(); WriterWrapper wrapperCopy = null; try { wrapperCopy = wrapperClass.getConstructor(new Class[] {IFormatWriter.class}).newInstance(new Object[] {childCopy}); } catch (InstantiationException exc) { throw new FormatException(exc); } catch (IllegalAccessException exc) { throw new FormatException(exc); } catch (NoSuchMethodException exc) { throw new FormatException(exc); } catch (InvocationTargetException exc) { throw new FormatException(exc); } return wrapperCopy; } }