//
// ImageWriter.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.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import loci.common.Region;
import loci.formats.codec.CodecOptions;
import loci.formats.meta.MetadataRetrieve;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 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="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/bio-formats/src/loci/formats/ImageWriter.java">Trac</a>,
* <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/bio-formats/src/loci/formats/ImageWriter.java;hb=HEAD">Gitweb</a></dd></dl>
*
* @author Curtis Rueden ctrueden at wisc.edu
*/
public class ImageWriter implements IFormatWriter {
// -- Constants --
private static final Logger LOGGER =
LoggerFactory.getLogger(ImageWriter.class);
// -- Static fields --
/** Default list of writer classes, for use with noargs constructor. */
private static ClassList<IFormatWriter> defaultClasses;
// -- Static utility methods --
public static ClassList<IFormatWriter> getDefaultWriterClasses() {
if (defaultClasses == null) {
// load built-in writer classes from writers.txt file
try {
defaultClasses =
new ClassList<IFormatWriter>("writers.txt", IFormatWriter.class);
}
catch (IOException exc) {
defaultClasses = new ClassList<IFormatWriter>(IFormatWriter.class);
LOGGER.info("Could not parse class list; using default classes", 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<IFormatWriter> classList) {
// add writers to the list
List<IFormatWriter> list = new ArrayList<IFormatWriter>();
Class<? extends IFormatWriter>[] c = classList.getClasses();
for (int i=0; i<c.length; i++) {
IFormatWriter writer = null;
try {
writer = c[i].newInstance();
}
catch (IllegalAccessException exc) { }
catch (InstantiationException exc) { }
if (writer == null) {
LOGGER.error("{} cannot be instantiated.", c[i].getName());
continue;
}
list.add(writer);
}
writers = new IFormatWriter[list.size()];
list.toArray(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 UnknownFormatException("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<? extends IFormatWriter> 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#changeOutputFile(String) */
public void changeOutputFile(String id) throws FormatException, IOException {
getWriter().changeOutputFile(id);
}
/* @see IFormatWriter#saveBytes(int, byte[]) */
public void saveBytes(int no, byte[] buf) throws FormatException, IOException
{
getWriter().saveBytes(no, buf);
}
/* @see IFormatWriter#saveBytes(int, byte[], int, int, int, int) */
public void saveBytes(int no, byte[] buf, int x, int y, int w, int h)
throws FormatException, IOException
{
getWriter().saveBytes(no, buf, x, y, w, h);
}
/* @see IFormatWriter#saveBytes(int, byte[], Region) */
public void saveBytes(int no, byte[] buf, Region tile)
throws FormatException, IOException
{
getWriter().saveBytes(no, buf, tile);
}
/* @see IFormatWriter#savePlane(int, Object) */
public void savePlane(int no, Object plane)
throws FormatException, IOException
{
getWriter().savePlane(no, plane);
}
/* @see IFormatWriter#savePlane(int, Object, int, int, int, int) */
public void savePlane(int no, Object plane, int x, int y, int w, int h)
throws FormatException, IOException
{
getWriter().savePlane(no, plane, x, y, w, h);
}
/* @see IFormatWriter#savePlane(int, Object, Region) */
public void savePlane(int no, Object plane, Region tile)
throws FormatException, IOException
{
getWriter().savePlane(no, plane, tile);
}
/* @see IFormatWriter#setSeries(int) */
public void setSeries(int series) throws FormatException {
getWriter().setSeries(series);
}
/* @see IFormatWriter#getSeries() */
public int getSeries() {
return getWriter().getSeries();
}
/* @see IFormatWriter#setInterleaved(boolean) */
public void setInterleaved(boolean interleaved) {
for (int i=0; i<writers.length; i++) writers[i].setInterleaved(interleaved);
}
/* @see IFormatWriter#isInterleaved() */
public boolean isInterleaved() {
// NB: all writers should have the same interleaved status
return writers[0].isInterleaved();
}
/* @see IFormatWriter#setValidBitsPerPixel(int) */
public void setValidBitsPerPixel(int bits) {
for (IFormatWriter writer : writers) {
writer.setValidBitsPerPixel(bits);
}
}
/* @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<String> set = new HashSet<String>();
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#getPixelTypes(String) */
public int[] getPixelTypes(String codec) {
return getWriter().getPixelTypes(codec);
}
/* @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();
if (s == null) continue;
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);
}
/* @see IFormatWriter#getCompression() */
public String getCompression() {
return getWriter().getCompression();
}
/* @see IFormatWriter#setWriteSequentially(boolean) */
public void setWriteSequentially(boolean sequential) {
for (IFormatWriter writer : writers) {
writer.setWriteSequentially(sequential);
}
}
/* @see IFormatWriter#setCodecOptions(CodecOptions) */
public void setCodecOptions(CodecOptions options) {
getWriter().setCodecOptions(options);
}
// -- Deprecated IFormatWriter API methods --
/**
* @deprecated
* @see IFormatWriter#saveBytes(byte[], boolean)
*/
public void saveBytes(byte[] bytes, boolean last)
throws FormatException, IOException
{
getWriter().saveBytes(bytes, last);
}
/**
* @deprecated
* @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);
}
/**
* @deprecated
* @see IFormatWriter#savePlane(Object, boolean)
*/
public void savePlane(Object plane, boolean last)
throws FormatException, IOException
{
getWriter().savePlane(plane, last);
}
/**
* @deprecated
* @see IFormatWriter#savePlane(Object, int, boolean, boolean)
*/
public void savePlane(Object plane, int series, boolean lastInSeries,
boolean last) throws FormatException, IOException
{
getWriter().savePlane(plane, series, lastInSeries, last);
}
// -- IFormatHandler API methods --
/* @see IFormatHandler#isThisType(String) */
public boolean isThisType(String name) {
for (int i=0; i<writers.length; i++) {
if (writers[i].isThisType(name)) return true;
}
return false;
}
/* @see IFormatHandler#getFormat() */
public String getFormat() { return getWriter().getFormat(); }
/* @see IFormatHandler#getSuffixes() */
public String[] getSuffixes() {
if (suffixes == null) {
HashSet<String> suffixSet = new HashSet<String>();
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#getNativeDataType() */
public Class<?> getNativeDataType() {
return getWriter().getNativeDataType();
}
/* @see IFormatHandler#setId(String) */
public void setId(String id) throws FormatException, IOException {
getWriter(id).setId(id);
}
/* @see IFormatHandler#close() */
public void close() throws IOException {
getWriter().close();
}
}