diff --git a/pom.xml b/pom.xml index 546ffda0a..1cf037b53 100644 --- a/pom.xml +++ b/pom.xml @@ -207,6 +207,11 @@ 2.4 test + + org.apache.ant + ant + 1.9.4 + diff --git a/src/main/java/org/apache/commons/imaging/ImageConverter.java b/src/main/java/org/apache/commons/imaging/ImageConverter.java new file mode 100644 index 000000000..ad2dd110a --- /dev/null +++ b/src/main/java/org/apache/commons/imaging/ImageConverter.java @@ -0,0 +1,342 @@ +package org.apache.commons.imaging; + +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import org.apache.commons.imaging.formats.dcx.DcxImageParser; +import org.apache.commons.imaging.formats.icns.IcnsImageParser; +import org.apache.commons.imaging.formats.ico.IcoImageParser; +import org.apache.commons.imaging.formats.tiff.TiffImageParser; + +/** + * Image converter + * + */ +public class ImageConverter { + + /** + * index of the source image to use during the conversion when the + * destination format supports a single image per data source, ignored when + * an hint to compute this index dynamically is enabled + */ + private int sourceImageIndex; + + private boolean indexOfSmallestSourceImageComputationEnabled; + + private boolean indexOfBiggestSourceImageComputationEnabled; + + /** + * indicates whether several images should be computed from one source image + * when the destination format supports more than one image per data source. + * The source image is then copied and rescaled several times. Ignored when + * the destination format is not ICNS + */ + private boolean sourceImageDuplicationAndRescaleEnabled; + + public ImageConverter() { + super(); + this.sourceImageIndex = 0; + } + + public int getSourceImageIndex() { + return sourceImageIndex; + } + + public void setSourceImageIndex(final int sourceImageIndex) { + this.sourceImageIndex = sourceImageIndex; + } + + public boolean isIndexOfSmallestSourceImageComputationEnabled() { + return indexOfSmallestSourceImageComputationEnabled; + } + + public void setIndexOfSmallestSourceImageComputationEnabled( + boolean indexOfSmallestSourceImageComputationEnabled) { + this.indexOfSmallestSourceImageComputationEnabled = indexOfSmallestSourceImageComputationEnabled; + } + + public boolean isIndexOfBiggestSourceImageComputationEnabled() { + return indexOfBiggestSourceImageComputationEnabled; + } + + public void setIndexOfBiggestSourceImageComputationEnabled( + boolean indexOfBiggestSourceImageComputationEnabled) { + this.indexOfBiggestSourceImageComputationEnabled = indexOfBiggestSourceImageComputationEnabled; + } + + public boolean isSourceImageDuplicationAndRescaleEnabled() { + return sourceImageDuplicationAndRescaleEnabled; + } + + public void setSourceImageDuplicationAndRescaleEnabled( + boolean sourceImageDuplicationAndRescaleEnabled) { + this.sourceImageDuplicationAndRescaleEnabled = sourceImageDuplicationAndRescaleEnabled; + } + + /** + * Converts the source image file into the format of the destination image + * file + * + * @param srcFile + * source image file + * @param dstFile + * destination image file + * @throws IOException + * In the event that the destination file cannot be (re)created + * or an I/O error occurs + * @throws ImageReadException + * In the event that the source image file cannot be read + * @throws ImageWriteException + * In the event that the destination image file cannot be + * written (for example if the destination format does not + * support the size or the palette of the source image) + * @throws IllegalArgumentException + * In the event that at least one extension is invalid, when the + * source file does not exist + */ + public void convertImage(final File srcFile, final File dstFile) + throws IOException, ImageReadException, ImageWriteException, + IllegalArgumentException { + if (!srcFile.exists()) { + throw new IllegalArgumentException("The source file " + + srcFile.getAbsolutePath() + " does not exist"); + } + final int srcFileExtIndex = srcFile.getName().lastIndexOf('.'); + final String srcFileExt; + if (srcFileExtIndex != -1 + && srcFileExtIndex + 1 < srcFile.getName().length()) { + srcFileExt = srcFile.getName().substring(srcFileExtIndex); + } else { + srcFileExt = null; + } + final int dstFileExtIndex = dstFile.getName().lastIndexOf('.'); + final String dstFileExt; + if (dstFileExtIndex != -1 + && dstFileExtIndex + 1 < dstFile.getName().length()) { + dstFileExt = dstFile.getName().substring(dstFileExtIndex); + } else { + dstFileExt = null; + } + + checkExtensionsValidity(srcFileExt, dstFileExt); + + List srcImgs = Imaging.getAllBufferedImages(srcFile); + if (dstFile.exists() && !dstFile.delete()) { + throw new IllegalArgumentException("The destination file " + + dstFile.getAbsolutePath() + + " already exists and cannot be deleted"); + } + dstFile.createNewFile(); + if (srcImgs != null && !srcImgs.isEmpty()) { + BufferedOutputStream bos = null; + try { + bos = new BufferedOutputStream(new FileOutputStream(dstFile)); + doConvertImage(srcImgs, bos, dstFileExt); + } finally { + if (bos != null) { + bos.close(); + } + } + } + } + + protected void doConvertImage(final List srcImgs, + final OutputStream os, final String dstExt) + throws ImageWriteException, IOException, IllegalArgumentException { + final ImageParser dstParser = getImageParser(dstExt); + if (srcImgs.size() == 1) { + if (supportsMultipleImagesWithinSingleDataSource(dstParser)) { + if (sourceImageDuplicationAndRescaleEnabled + && dstParser.getClass() == IcnsImageParser.class) { + BufferedImage srcImg = srcImgs.get(0); + List altSrcImgs = new ArrayList(); + final int[] sizes = new int[]{16, 32, 48, 128}; + for (int size : sizes) { + if (srcImg.getWidth() == size && srcImg.getHeight() == size) { + altSrcImgs.add(srcImg); + } else { + BufferedImage rescaledImg = new BufferedImage(size, + size, BufferedImage.TYPE_INT_ARGB); + AffineTransform transform = new AffineTransform(); + transform.scale(size / (double) srcImg.getWidth(), + size / (double) srcImg.getHeight()); + AffineTransformOp scaleOp = new AffineTransformOp( + transform, AffineTransformOp.TYPE_BICUBIC); + scaleOp.filter(srcImg, rescaledImg); + altSrcImgs.add(rescaledImg); + } + } + dstParser.writeImages(altSrcImgs, os, null); + } else { + dstParser.writeImage(srcImgs.get(0), os, null); + } + } else { + dstParser.writeImage(srcImgs.get(0), os, null); + } + } else { + if (supportsMultipleImagesWithinSingleDataSource(dstParser)) { + dstParser.writeImages(srcImgs, os, null); + } else { + if (indexOfSmallestSourceImageComputationEnabled) { + int indexOfSmallestSourceImage = 0; + int areaOfSmallestSourceImage = srcImgs.get(0).getWidth() + * srcImgs.get(0).getHeight(); + for (int srcIndex = 1; srcIndex < srcImgs.size(); srcIndex++) { + int areaOfSourceImage = srcImgs.get(srcIndex) + .getWidth() * srcImgs.get(srcIndex).getHeight(); + if (areaOfSourceImage < areaOfSmallestSourceImage) { + areaOfSmallestSourceImage = areaOfSourceImage; + indexOfSmallestSourceImage = srcIndex; + } + } + dstParser.writeImage( + srcImgs.get(indexOfSmallestSourceImage), os, null); + } else { + if (indexOfBiggestSourceImageComputationEnabled) { + int indexOfBiggestSourceImage = 0; + int areaOfBiggestSourceImage = srcImgs.get(0) + .getWidth() * srcImgs.get(0).getHeight(); + for (int srcIndex = 1; srcIndex < srcImgs.size(); srcIndex++) { + int areaOfSourceImage = srcImgs.get(srcIndex) + .getWidth() + * srcImgs.get(srcIndex).getHeight(); + if (areaOfSourceImage > areaOfBiggestSourceImage) { + areaOfBiggestSourceImage = areaOfSourceImage; + indexOfBiggestSourceImage = srcIndex; + } + } + dstParser.writeImage( + srcImgs.get(indexOfBiggestSourceImage), os, + null); + } else { + if (sourceImageIndex < 0 + || srcImgs.size() <= sourceImageIndex) { + throw new IllegalArgumentException( + "Impossible to read an image at index " + + sourceImageIndex); + } else { + dstParser.writeImage(srcImgs.get(sourceImageIndex), + os, null); + } + } + } + } + } + } + + /** + * Checks whether the extension of the source and the extension of the + * destination are valid and distinct + * + * @param srcExt + * extension of the source + * @param dstExt + * extension of the destination + * @throws IllegalArgumentException + * In the event that one of them is invalid or both are two + * extensions of the same format + */ + protected void checkExtensionsValidity(final String srcExt, + final String dstExt) throws IllegalArgumentException { + if (srcExt == null || srcExt.length() == 0) { + throw new IllegalArgumentException("The source has no extension"); + } + if (!Imaging.hasImageFileExtension(srcExt)) { + throw new IllegalArgumentException(srcExt + + " is not an image file extension"); + } + if (dstExt == null || dstExt.length() == 0) { + throw new IllegalArgumentException( + "The destination has no extension"); + } + if (!Imaging.hasImageFileExtension(dstExt)) { + throw new IllegalArgumentException(dstExt + + " is not an image file extension"); + } + final ImageParser srcParser = getImageParser(srcExt); + final ImageParser dstParser = getImageParser(dstExt); + if (srcParser.getClass() == dstParser.getClass()) { + throw new IllegalArgumentException("No conversion needed"); + } + } + + /** + * Converts the source image stream into the format of the destination image + * stream + * + * @param is + * source image stream + * @param srcExt + * extension of the source image + * @param os + * destination image stream + * @param dstExt + * extension of the destination image + * @throws IOException + * In the event of an I/O error + * @throws ImageReadException + * In the event that the source image stream cannot be read + * @throws ImageWriteException + * In the event that the destination image stream cannot be + * written (for example if the destination format does not + * support the size or the palette of the source image) + * @throws IllegalArgumentException + * In the event that at least one extension is invalid + */ + public void convertImage(final InputStream is, final String srcExt, + final OutputStream os, final String dstExt) throws IOException, + ImageReadException, ImageWriteException, IllegalArgumentException { + checkExtensionsValidity(srcExt, dstExt); + List srcImgs = Imaging.getAllBufferedImages(is, srcExt); + if (srcImgs != null && !srcImgs.isEmpty()) { + doConvertImage(srcImgs, os, dstExt); + } + } + + private boolean supportsMultipleImagesWithinSingleDataSource( + final ImageParser imageParser) { + final Class imageParserClass = imageParser.getClass(); + return /*imageParserClass == DcxImageParser.class + || */imageParserClass == IcnsImageParser.class/* + || imageParserClass == IcoImageParser.class + || imageParserClass == TiffImageParser.class*/; + } + + /** + * Returns the image parser of the file + * + * @param filename + * image filename + * @return image parser of the image if any, otherwise null + */ + private ImageParser getImageParser(String filename) { + if (filename == null) { + return null; + } + + filename = filename.toLowerCase(Locale.ENGLISH); + + final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); + for (final ImageParser imageParser : imageParsers) { + final String[] exts = imageParser.getAcceptedExtensions(); + + for (final String ext : exts) { + if (filename.endsWith(ext.toLowerCase(Locale.ENGLISH))) { + return imageParser; + } + } + } + + return null; + } +} diff --git a/src/main/java/org/apache/commons/imaging/ImageConverterTask.java b/src/main/java/org/apache/commons/imaging/ImageConverterTask.java new file mode 100644 index 000000000..b0496eddb --- /dev/null +++ b/src/main/java/org/apache/commons/imaging/ImageConverterTask.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.imaging; + +import java.io.File; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +/** + * Ant task of image conversion + * + */ +public class ImageConverterTask extends Task { + + /**path of the source image*/ + private String src; + + /**path of the destination image*/ + private String dst; + + /**image converter*/ + private final ImageConverter delegate; + + /** + * Constructor + */ + public ImageConverterTask() { + super(); + this.delegate = new ImageConverter(); + } + + @Override + public void execute() throws BuildException { + if (src == null) { + throw new BuildException("The src attribute cannot be null"); + } + if (dst == null) { + throw new BuildException("The dst attribute cannot be null"); + } + final File srcFile = new File(getProject().getBaseDir(), src); + final File dstFile = new File(getProject().getBaseDir(), dst); + try { + this.delegate.convertImage(srcFile, dstFile); + } catch (Throwable t) { + throw new BuildException("The conversion of the image file " + src + + " failed", t, getLocation()); + } + } + + /** + * Sets the path of the destination image + * + * @param dst + */ + public void setDst(String dst) { + this.dst = dst; + } + + /** + * Sets the path of the source image + * + * @param src + */ + public void setSrc(String src) { + this.src = src; + } + + public void setSourceImageIndex(final int sourceImageIndex) { + this.delegate.setSourceImageIndex(sourceImageIndex); + } + + public void setIndexOfSmallestSourceImageComputationEnabled( + boolean indexOfSmallestSourceImageComputationEnabled) { + this.delegate.setIndexOfSmallestSourceImageComputationEnabled(indexOfSmallestSourceImageComputationEnabled); + } + + public void setIndexOfBiggestSourceImageComputationEnabled( + boolean indexOfBiggestSourceImageComputationEnabled) { + this.delegate.setIndexOfBiggestSourceImageComputationEnabled(indexOfBiggestSourceImageComputationEnabled); + } + + public void setSourceImageDuplicationAndRescaleEnabled( + boolean sourceImageDuplicationAndRescaleEnabled) { + this.delegate.setSourceImageDuplicationAndRescaleEnabled(sourceImageDuplicationAndRescaleEnabled); + } +} diff --git a/src/main/java/org/apache/commons/imaging/ImageParser.java b/src/main/java/org/apache/commons/imaging/ImageParser.java index 164f9b06f..54efe1f17 100644 --- a/src/main/java/org/apache/commons/imaging/ImageParser.java +++ b/src/main/java/org/apache/commons/imaging/ImageParser.java @@ -24,6 +24,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -52,936 +53,1103 @@ import org.apache.commons.imaging.formats.xpm.XpmImageParser; /** - * Provides the abstract base class for all image reading and writing - * utilities. ImageParser implementations are expected to extend this - * class providing logic for identifying and processing data in their - * own specific format. Specific implementations are found - * under the com.apache.commons.imaging.formats package. + * Provides the abstract base class for all image reading and writing utilities. + * ImageParser implementations are expected to extend this class providing logic + * for identifying and processing data in their own specific format. Specific + * implementations are found under the com.apache.commons.imaging.formats + * package. * *

Application Notes

* *

Format support

* - * For the most recent information on format support for the - * Apache Commons Imaging package, refer to - * Format Support - * at the main project development web site. + * For the most recent information on format support for the Apache Commons + * Imaging package, refer to Format + * Support at the main project development web site. * *

On the accuracy of this Javadoc

* - * The original authors of this class did not supply documentation. - * The Javadoc for this class is based on inspection of the - * source code. In some cases, the purpose and usage for particular - * methods was deduced from the source and may not perfectly reflect - * the intentions of the original. Therefore, you should not assume - * that the documentation is perfect, especially in the more obscure + * The original authors of this class did not supply documentation. The Javadoc + * for this class is based on inspection of the source code. In some cases, the + * purpose and usage for particular methods was deduced from the source and may + * not perfectly reflect the intentions of the original. Therefore, you should + * not assume that the documentation is perfect, especially in the more obscure * and specialized areas of implementation. * *

The "Map params" argument

* - * Many of the methods specified by this class accept an argument of - * type Map giving a list of parameters to be used when processing an - * image. For example, some of the output formats permit the specification - * of different kinds of image compression or color models. Some of the - * reading methods permit the calling application to require strict - * format compliance. In many cases, however, an application will not - * require the use of this argument. While some of the ImageParser - * implementations check for (and ignore) null arguments for this parameter, - * not all of them do (at least not at the time these notes were written). - * Therefore, a prudent programmer will always supply an valid, though - * empty instance of a Map implementation when calling such methods. - * Generally, the java HashMap class is useful for this purpose. + * Many of the methods specified by this class accept an argument of type Map + * giving a list of parameters to be used when processing an image. For example, + * some of the output formats permit the specification of different kinds of + * image compression or color models. Some of the reading methods permit the + * calling application to require strict format compliance. In many cases, + * however, an application will not require the use of this argument. While some + * of the ImageParser implementations check for (and ignore) null arguments for + * this parameter, not all of them do (at least not at the time these notes were + * written). Therefore, a prudent programmer will always supply an valid, though + * empty instance of a Map implementation when calling such methods. Generally, + * the java HashMap class is useful for this purpose. * - *

Additionally, developers creating or enhancing classes derived - * from ImageParser are encouraged to include such checks in their code. + *

+ * Additionally, developers creating or enhancing classes derived from + * ImageParser are encouraged to include such checks in their code. */ public abstract class ImageParser extends BinaryFileParser { - /** - * Gets an array of new instances of all image parsers. - * - * @return A valid array of image parsers - */ - public static ImageParser[] getAllImageParsers() { - - return new ImageParser[]{ - new BmpImageParser(), - new DcxImageParser(), - new GifImageParser(), - new IcnsImageParser(), - new IcoImageParser(), - new JpegImageParser(), - new PcxImageParser(), - new PngImageParser(), - new PnmImageParser(), - new PsdImageParser(), - new RgbeImageParser(), - new TiffImageParser(), - new WbmpImageParser(), - new XbmImageParser(), - new XpmImageParser(), - // new JBig2ImageParser(), - // new TgaImageParser(), - }; - } - - /** - * Get image metadata from the specified byte source. Format-specific - * ImageParser implementations are expected to return a valid - * IImageMetadata object or to throw an ImageReadException if unable - * to process the specified byte source. - * - * @param byteSource A valid byte source. - * @return A valid, potentially subject-matter-specific implementation of - * the IImageMetadata interface describing the content extracted - * from the source content. - * @throws ImageReadException In the event that the the ByteSource - * content does not conform to the format of the specific parser - * implementation. - * @throws IOException In the event of unsuccessful data read operation. - */ - public final IImageMetadata getMetadata(final ByteSource byteSource) throws ImageReadException, IOException { - return getMetadata(byteSource, null); - } - - /** - * Get image metadata from the specified byte source. Format-specific - * ImageParser implementations are expected to return a valid - * IImageMetadata object or to throw an ImageReadException if unable - * to process the specified byte source. - * - *

The params argument provides a mechanism for individual - * implementations to pass optional information into the parser. - * Not all formats will require this capability. Because the - * base class may call this method with a null params argument, - * implementations should always include logic - * for ignoring null input. - * - * @param byteSource A valid byte source. - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid, potentially subject-matter-specific implementation of - * the IImageMetadata interface describing the content extracted - * from the source content. - * @throws ImageReadException In the event that the the ByteSource - * content does not conform to the format of the specific parser - * implementation. - * @throws IOException In the event of unsuccessful data read operation. - */ - public abstract IImageMetadata getMetadata(ByteSource byteSource, Map params) - throws ImageReadException, IOException; - - /** - * Get image metadata from the specified array of bytes. Format-specific - * ImageParser implementations are expected to return a valid - * IImageMetadata object or to throw an ImageReadException if unable - * to process the specified data. - * - * @param bytes A valid array of bytes - * @return A valid, potentially subject-matter-specific implementation of - * the IImageMetadata interface describing the content extracted - * from the source content. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful data read operation. - */ - public final IImageMetadata getMetadata(final byte[] bytes) throws ImageReadException, IOException { - return getMetadata(bytes, null); - } - - /** - * Get image metadata from the specified array of bytes. Format-specific - * ImageParser implementations are expected to return a valid - * IImageMetadata object or to throw an ImageReadException if unable - * to process the specified data. - * - *

The params argument provides a mechanism for individual - * implementations to pass optional information into the parser. - * Not all formats will require this capability. Because the - * base class may call this method with a null params argument, - * implementations should always include logic - * for ignoring null input. - * - * @param bytes A valid array of bytes - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid image metadata object describing the content extracted - * from the specified content. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful data read operation. - */ - public final IImageMetadata getMetadata(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getMetadata(new ByteSourceArray(bytes), params); - } - - /** - * Get image metadata from the specified file. Format-specific - * ImageParser implementations are expected to return a valid - * IImageMetadata object or to throw an ImageReadException if unable - * to process the specified data. - * - * @param file A valid reference to a file. - * @return A valid image metadata object describing the content extracted - * from the specified content. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful file read or - * access operation. - */ - public final IImageMetadata getMetadata(final File file) throws ImageReadException, IOException { - return getMetadata(file, null); - } - - /** - * Get image metadata from the specified file. Format-specific - * ImageParser implementations are expected to return a valid - * IImageMetadata object or to throw an ImageReadException if unable - * to process the specified data. - * - *

The params argument provides a mechanism for individual - * implementations to pass optional information into the parser. - * Not all formats will require this capability. Because the - * base class may call this method with a null params argument, - * implementations should always include logic - * for ignoring null input. - * - * @param file A valid reference to a file. - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid image metadata object describing the content extracted - * from the specified content. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful file read or - * access operation. - */ - public final IImageMetadata getMetadata(final File file, final Map params) - throws ImageReadException, IOException { - if (getDebug()) { - System.out.println(getName() + ".getMetadata" + ": " - + file.getName()); + /** + * Gets an array of new instances of all image parsers. + * + * @return A valid array of image parsers + */ + public static ImageParser[] getAllImageParsers() { + + return new ImageParser[] { new BmpImageParser(), new DcxImageParser(), + new GifImageParser(), new IcnsImageParser(), + new IcoImageParser(), new JpegImageParser(), + new PcxImageParser(), new PngImageParser(), + new PnmImageParser(), new PsdImageParser(), + new RgbeImageParser(), new TiffImageParser(), + new WbmpImageParser(), new XbmImageParser(), + new XpmImageParser(), + // new JBig2ImageParser(), + // new TgaImageParser(), + }; + } + + /** + * Get image metadata from the specified byte source. Format-specific + * ImageParser implementations are expected to return a valid IImageMetadata + * object or to throw an ImageReadException if unable to process the + * specified byte source. + * + * @param byteSource + * A valid byte source. + * @return A valid, potentially subject-matter-specific implementation of + * the IImageMetadata interface describing the content extracted + * from the source content. + * @throws ImageReadException + * In the event that the the ByteSource content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful data read operation. + */ + public final IImageMetadata getMetadata(final ByteSource byteSource) + throws ImageReadException, IOException { + return getMetadata(byteSource, null); + } + + /** + * Get image metadata from the specified byte source. Format-specific + * ImageParser implementations are expected to return a valid IImageMetadata + * object or to throw an ImageReadException if unable to process the + * specified byte source. + * + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * require this capability. Because the base class may call this method with + * a null params argument, implementations should always + * include logic for ignoring null input. + * + * @param byteSource + * A valid byte source. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid, potentially subject-matter-specific implementation of + * the IImageMetadata interface describing the content extracted + * from the source content. + * @throws ImageReadException + * In the event that the the ByteSource content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful data read operation. + */ + public abstract IImageMetadata getMetadata(ByteSource byteSource, + Map params) throws ImageReadException, IOException; + + /** + * Get image metadata from the specified array of bytes. Format-specific + * ImageParser implementations are expected to return a valid IImageMetadata + * object or to throw an ImageReadException if unable to process the + * specified data. + * + * @param bytes + * A valid array of bytes + * @return A valid, potentially subject-matter-specific implementation of + * the IImageMetadata interface describing the content extracted + * from the source content. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful data read operation. + */ + public final IImageMetadata getMetadata(final byte[] bytes) + throws ImageReadException, IOException { + return getMetadata(bytes, null); + } + + /** + * Get image metadata from the specified array of bytes. Format-specific + * ImageParser implementations are expected to return a valid IImageMetadata + * object or to throw an ImageReadException if unable to process the + * specified data. + * + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * require this capability. Because the base class may call this method with + * a null params argument, implementations should always + * include logic for ignoring null input. + * + * @param bytes + * A valid array of bytes + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid image metadata object describing the content extracted + * from the specified content. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful data read operation. + */ + public final IImageMetadata getMetadata(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getMetadata(new ByteSourceArray(bytes), params); + } + + /** + * Get image metadata from the specified file. Format-specific ImageParser + * implementations are expected to return a valid IImageMetadata object or + * to throw an ImageReadException if unable to process the specified data. + * + * @param file + * A valid reference to a file. + * @return A valid image metadata object describing the content extracted + * from the specified content. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful file read or access operation. + */ + public final IImageMetadata getMetadata(final File file) + throws ImageReadException, IOException { + return getMetadata(file, null); + } + + /** + * Get image metadata from the specified file. Format-specific ImageParser + * implementations are expected to return a valid IImageMetadata object or + * to throw an ImageReadException if unable to process the specified data. + * + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * require this capability. Because the base class may call this method with + * a null params argument, implementations should always + * include logic for ignoring null input. + * + * @param file + * A valid reference to a file. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid image metadata object describing the content extracted + * from the specified content. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful file read or access operation. + */ + public final IImageMetadata getMetadata(final File file, + final Map params) throws ImageReadException, + IOException { + if (getDebug()) { + System.out.println(getName() + ".getMetadata" + ": " + + file.getName()); + } + + if (!canAcceptExtension(file)) { + return null; + } + + return getMetadata(new ByteSourceFile(file), params); + } + + /** + * Get image information from the specified ByteSource. Format-specific + * ImageParser implementations are expected to return a valid ImageInfo + * object or to throw an ImageReadException if unable to process the + * specified data. + * + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * require this capability. Because the base class may call this method with + * a null params argument, implementations should always + * include logic for ignoring null input. + * + * @param byteSource + * A valid ByteSource object + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid image information object describing the content extracted + * from the specified data. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful data access operation. + */ + public abstract ImageInfo getImageInfo(ByteSource byteSource, + Map params) throws ImageReadException, IOException; + + /** + * Get image information from the specified ByteSource. Format-specific + * ImageParser implementations are expected to return a valid ImageInfo + * object or to throw an ImageReadException if unable to process the + * specified data. + * + * @param byteSource + * A valid ByteSource object + * @return A valid image information object describing the content extracted + * from the specified data. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful data access operation. + */ + public final ImageInfo getImageInfo(final ByteSource byteSource) + throws ImageReadException, IOException { + return getImageInfo(byteSource, null); + } + + /** + * Get image information from the specified array of bytes. Format-specific + * ImageParser implementations are expected to return a valid ImageInfo + * object or to throw an ImageReadException if unable to process the + * specified data. + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * require this capability. Because the base class may call this method with + * a null params argument, implementations should always + * include logic for ignoring null input. + * + * @param bytes + * A valid array of bytes + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid image information object describing the content extracted + * from the specified data. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful data access operation. + */ + public final ImageInfo getImageInfo(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getImageInfo(new ByteSourceArray(bytes), params); + } + + /** + * Get image information from the specified file Format-specific ImageParser + * implementations are expected to return a valid ImageInfo object or to + * throw an ImageReadException if unable to process the specified data. + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * require this capability. Because the base class may call this method with + * a null params argument, implementations should always + * include logic for ignoring null input. + * + * @param file + * A valid File object + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid image information object describing the content extracted + * from the specified data. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful file read or access operation. + */ + public final ImageInfo getImageInfo(final File file, + final Map params) throws ImageReadException, + IOException { + if (!canAcceptExtension(file)) { + return null; + } + + return getImageInfo(new ByteSourceFile(file), params); + } + + /** + * Determines the format compliance of the content of the supplied byte + * source based on rules provided by a specific implementation. + * + * @param byteSource + * A valid instance of ByteSource + * @return true if the content is format-compliant; otherwise, false + * @throws ImageReadException + * may be thrown by sub-classes + * @throws IOException + * may be thrown by sub-classes + */ + public FormatCompliance getFormatCompliance(final ByteSource byteSource) + throws ImageReadException, IOException { + return null; + } + + /** + * Determines the format compliance of the content of the supplied byte + * array based on rules provided by a specific implementation. + * + * @param bytes + * A valid byte array. + * @return A valid FormatCompliance object. + * @throws ImageReadException + * may be thrown by sub-classes + * @throws IOException + * may be thrown by sub-classes + */ + public final FormatCompliance getFormatCompliance(final byte[] bytes) + throws ImageReadException, IOException { + return getFormatCompliance(new ByteSourceArray(bytes)); + } + + /** + * Determines the format compliance of the specified file based on rules + * provided by a specific implementation. + * + * @param file + * A valid reference to a file. + * @return A valid format compliance object. + * @throws ImageReadException + * may be thrown by sub-classes + * @throws IOException + * may be thrown by sub-classes + */ + public final FormatCompliance getFormatCompliance(final File file) + throws ImageReadException, IOException { + if (!canAcceptExtension(file)) { + return null; + } + + return getFormatCompliance(new ByteSourceFile(file)); + } + + /** + * Gets all images specified by the byte source (some formats may include + * multiple images within a single data source). + * + * @param byteSource + * A valid instance of ByteSource. + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public List getAllBufferedImages(final ByteSource byteSource) + throws ImageReadException, IOException { + return getAllBufferedImages(byteSource, null); + } + + /** + * Gets all images specified by the byte source (some formats may include + * multiple images within a single data source). + * + * @param byteSource + * A valid instance of ByteSource. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public List getAllBufferedImages( + final ByteSource byteSource, Map params) + throws ImageReadException, IOException { + if (null == params) { + params = new HashMap(); } - - if (!canAcceptExtension(file)) { - return null; - } - - return getMetadata(new ByteSourceFile(file), params); - } - - /** - * Get image information from the specified ByteSource. Format-specific - * ImageParser implementations are expected to return a valid - * ImageInfo object or to throw an ImageReadException if unable - * to process the specified data. - * - *

The params argument provides a mechanism for individual - * implementations to pass optional information into the parser. - * Not all formats will require this capability. Because the - * base class may call this method with a null params argument, - * implementations should always include logic - * for ignoring null input. - * - * @param byteSource A valid ByteSource object - * @param params Optional instructions for special-handling or interpretation - * of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid image information object describing the content extracted - * from the specified data. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful data access operation. - */ - public abstract ImageInfo getImageInfo(ByteSource byteSource, Map params) - throws ImageReadException, IOException; - - /** - * Get image information from the specified ByteSource. Format-specific - * ImageParser implementations are expected to return a valid - * ImageInfo object or to throw an ImageReadException if unable - * to process the specified data. - * - * @param byteSource A valid ByteSource object - * @return A valid image information object describing the content extracted - * from the specified data. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful data - * access operation. - */ - public final ImageInfo getImageInfo(final ByteSource byteSource) throws ImageReadException, IOException { - return getImageInfo(byteSource, null); - } - - /** - * Get image information from the specified array of bytes. Format-specific - * ImageParser implementations are expected to return a valid - * ImageInfo object or to throw an ImageReadException if unable - * to process the specified data. - *

The params argument provides a mechanism for individual - * implementations to pass optional information into the parser. - * Not all formats will require this capability. Because the - * base class may call this method with a null params argument, - * implementations should always include logic - * for ignoring null input. - * - * @param bytes A valid array of bytes - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid image information object describing the content extracted - * from the specified data. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful data - * access operation. - */ - public final ImageInfo getImageInfo(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getImageInfo(new ByteSourceArray(bytes), params); - } - - /** - * Get image information from the specified file Format-specific - * ImageParser implementations are expected to return a valid - * ImageInfo object or to throw an ImageReadException if unable - * to process the specified data. - *

The params argument provides a mechanism for individual - * implementations to pass optional information into the parser. - * Not all formats will require this capability. Because the - * base class may call this method with a null params argument, - * implementations should always include logic - * for ignoring null input. - * - * @param file A valid File object - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid image information object describing the content extracted - * from the specified data. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful file read or - * access operation. - */ - public final ImageInfo getImageInfo(final File file, final Map params) - throws ImageReadException, IOException { - if (!canAcceptExtension(file)) { - return null; - } - - return getImageInfo(new ByteSourceFile(file), params); - } - - /** - * Determines the format compliance of the content of the supplied byte - * source based on rules provided by a specific implementation. - * - * @param byteSource A valid instance of ByteSource - * @return true if the content is format-compliant; otherwise, false - * @throws ImageReadException may be thrown by sub-classes - * @throws IOException may be thrown by sub-classes - */ - public FormatCompliance getFormatCompliance(final ByteSource byteSource) - throws ImageReadException, IOException { - return null; - } - - /** - * Determines the format compliance of the content of the supplied byte - * array based on rules provided by a specific implementation. - * - * @param bytes A valid byte array. - * @return A valid FormatCompliance object. - * @throws ImageReadException may be thrown by sub-classes - * @throws IOException may be thrown by sub-classes - */ - public final FormatCompliance getFormatCompliance(final byte[] bytes) - throws ImageReadException, IOException { - return getFormatCompliance(new ByteSourceArray(bytes)); - } - - /** - * Determines the format compliance of the specified file based on - * rules provided by a specific implementation. - * - * @param file A valid reference to a file. - * @return A valid format compliance object. - * @throws ImageReadException may be thrown by sub-classes - * @throws IOException may be thrown by sub-classes - */ - public final FormatCompliance getFormatCompliance(final File file) - throws ImageReadException, IOException { - if (!canAcceptExtension(file)) { - return null; - } - - return getFormatCompliance(new ByteSourceFile(file)); - } - - /** - * Gets all images specified by the byte source (some - * formats may include multiple images within a single data source). - * - * @param byteSource A valid instance of ByteSource. - * @return A valid (potentially empty) list of BufferedImage objects. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public List getAllBufferedImages(final ByteSource byteSource) - throws ImageReadException, IOException { - final BufferedImage bi = getBufferedImage(byteSource, null); - - final List result = new ArrayList(); - - result.add(bi); - - return result; - } - - /** - * Gets all images specified by the byte array (some - * formats may include multiple images within a single data source). - * - * @param bytes A valid byte array - * @return A valid (potentially empty) list of BufferedImage objects. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final List getAllBufferedImages(final byte[] bytes) - throws ImageReadException, IOException { - return getAllBufferedImages(new ByteSourceArray(bytes)); - } - - /** - * Gets all images specified by indicated file (some - * formats may include multiple images within a single data source). - * - * @param file A valid reference to a file. - * @return A valid (potentially empty) list of BufferedImage objects. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final List getAllBufferedImages(final File file) throws ImageReadException, IOException { - if (!canAcceptExtension(file)) { - return null; - } - - return getAllBufferedImages(new ByteSourceFile(file)); - } - - /** - * Gets a buffered image specified by the byte source (for - * sources that specify multiple images, choice of which image - * is returned is implementation dependent). - * - * @param byteSource A valid instance of ByteSource - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid instance of BufferedImage. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public abstract BufferedImage getBufferedImage(ByteSource byteSource, Map params) - throws ImageReadException, IOException; - - /** - * Gets a buffered image specified by the byte array (for - * sources that specify multiple images, choice of which image - * is returned is implementation dependent). - * - * @param bytes A valid byte array - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid instance of BufferedImage. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final BufferedImage getBufferedImage(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getBufferedImage(new ByteSourceArray(bytes), params); - } - - /** - * Gets a buffered image specified by the indicated file (for - * sources that specify multiple images, choice of which image - * is returned is implementation dependent). - * - * @param file A valid file reference. - * @param params Optional instructions for special-handling or - * interpretation of the input data (null objects are permitted and - * must be supported by implementations). - * @return A valid instance of BufferedImage. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final BufferedImage getBufferedImage(final File file, final Map params) - throws ImageReadException, IOException { - if (!canAcceptExtension(file)) { - return null; - } - - return getBufferedImage(new ByteSourceFile(file), params); - } - - - /** - * Writes the content of a BufferedImage to the specified output - * stream. - * - *

The params argument provides a mechanism for individual - * implementations to pass optional information into the parser. - * Not all formats will support this capability. Currently, - * some of the parsers do not check for null arguments. So in cases - * where no optional specifications are supported, application - * code should pass in an empty instance of an implementation of - * the map interface (i.e. an empty HashMap). - * - * @param src An image giving the source content for output - * @param os A valid output stream for storing the formatted image - * @param params A non-null Map implementation supplying optional, - * format-specific instructions for output - * (such as selections for data compression, color models, etc.) - * @throws ImageWriteException In the event that the output format - * cannot handle the input image or invalid params are specified. - * @throws IOException In the event of an write error from - * the output stream. - */ - public void writeImage(final BufferedImage src, final OutputStream os, final Map params) - throws ImageWriteException, IOException { - os.close(); // we are obligated to close stream. - - throw new ImageWriteException("This image format (" + getName() - + ") cannot be written."); - } - - /** - * Get the size of the image described by the specified byte array. - * - * @param bytes A valid byte array. - * @return A valid instance of Dimension. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final Dimension getImageSize(final byte[] bytes) throws ImageReadException, IOException { - return getImageSize(bytes, null); - } - - /** - * Get the size of the image described by the specified byte array. - * - * @param bytes A valid byte array. - * @param params Optional instructions for special-handling or - * interpretation of the input data. - * @return A valid instance of Dimension. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final Dimension getImageSize(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getImageSize(new ByteSourceArray(bytes), params); - } - - /** - * Get the size of the image described by the specified file. - * - * @param file A valid reference to a file. - * @return A valid instance of Dimension. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final Dimension getImageSize(final File file) throws ImageReadException, IOException { - return getImageSize(file, null); - } - - /** - * Get the size of the image described by the specified file. - * - * @param file A valid reference to a file. - * @param params Optional instructions for special-handling or - * interpretation of the input data. - * @return A valid instance of Dimension. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final Dimension getImageSize(final File file, final Map params) - throws ImageReadException, IOException { - - if (!canAcceptExtension(file)) { - return null; - } - - return getImageSize(new ByteSourceFile(file), params); - } - - /** - * Get the size of the image described by the specified ByteSource. - * - * @param byteSource A valid reference to a ByteSource. - * @param params Optional instructions for special-handling or - * interpretation of the input data. - * @return A valid instance of Dimension. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public abstract Dimension getImageSize(ByteSource byteSource, Map params) - throws ImageReadException, IOException; - - /** - * Get a string containing XML-formatted text conforming to the Extensible - * Metadata Platform (EXP) standard for representing information about - * image content. Not all image formats support EXP infomation and - * even for those that do, there is no guarantee that such information - * will be present in an image. - * - * @param byteSource A valid reference to a ByteSource. - * @param params Optional instructions for special-handling or - * interpretation of the input data. - * @return If XMP metadata is present, a valid string; - * if it is not present, a null. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public abstract String getXmpXml(ByteSource byteSource, Map params) - throws ImageReadException, IOException; - - /** - * Get an array of bytes describing the International Color Consortium (ICC) - * specification for the color space of the image contained in the - * input byte array. Not all formats support ICC profiles. - * - * @param bytes A valid array of bytes. - * @return If available, a valid array of bytes; otherwise, a null - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final byte[] getICCProfileBytes(final byte[] bytes) throws ImageReadException, IOException { - return getICCProfileBytes(bytes, null); - } - - /** - * Get an array of bytes describing the International Color Consortium (ICC) - * specification for the color space of the image contained in the - * input byte array. Not all formats support ICC profiles. - * - * @param bytes A valid array of bytes. - * @param params Optional instructions for special-handling or - * interpretation of the input data. - * @return If available, a valid array of bytes; otherwise, a null - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final byte[] getICCProfileBytes(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getICCProfileBytes(new ByteSourceArray(bytes), params); - } - - /** - * Get an array of bytes describing the International Color Consortium (ICC) - * specification for the color space of the image contained in the - * input file. Not all formats support ICC profiles. - * - * @param file A valid file reference. - * @return If available, a valid array of bytes; otherwise, a null - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final byte[] getICCProfileBytes(final File file) throws ImageReadException, IOException { - return getICCProfileBytes(file, null); - } - - /** - * Get an array of bytes describing the International Color Consortium (ICC) - * specification for the color space of the image contained in the - * input file. Not all formats support ICC profiles. - * - * @param file A valid file reference. - * @param params Optional instructions for special-handling or - * interpretation of the input data. - * @return If available, a valid array of bytes; otherwise, a null - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final byte[] getICCProfileBytes(final File file, final Map params) - throws ImageReadException, IOException { - if (!canAcceptExtension(file)) { - return null; - } - - if (getDebug()) { - System.out.println(getName() + ": " + file.getName()); - } - - return getICCProfileBytes(new ByteSourceFile(file), params); - } - - /** - * Get an array of bytes describing the International Color Consortium (ICC) - * specification for the color space of the image contained in the - * input byteSoruce. Not all formats support ICC profiles. - * - * @param byteSource A valid ByteSource. - * @param params Optional instructions for special-handling or - * interpretation of the input data. - * @return If available, a valid array of bytes; otherwise, a null - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public abstract byte[] getICCProfileBytes(ByteSource byteSource, Map params) - throws ImageReadException, IOException; - - /** - * Write the ImageInfo and format-specific information for the image - * content of the specified byte array to a string. - * - * @param bytes A valid array of bytes. - * @return A valid string. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final String dumpImageFile(final byte[] bytes) throws ImageReadException, IOException { - return dumpImageFile(new ByteSourceArray(bytes)); - } - - - /** - * Write the ImageInfo and format-specific information for the image - * content of the specified file to a string. - * - * @param file A valid file reference. - * @return A valid string. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final String dumpImageFile(final File file) throws ImageReadException, IOException { - if (!canAcceptExtension(file)) { - return null; - } - - if (getDebug()) { - System.out.println(getName() + ": " + file.getName()); - } - - return dumpImageFile(new ByteSourceFile(file)); - } - - /** - * Write the ImageInfo and format-specific information for the image - * content of the specified byte source to a string. - * - * @param byteSource A valid byte source. - * @return A valid string. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public final String dumpImageFile(final ByteSource byteSource) - throws ImageReadException, IOException { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw); - - dumpImageFile(pw, byteSource); - - pw.flush(); - - return sw.toString(); - } - - /** - * Write the ImageInfo and format-specific information for the image - * content of the specified byte source to a PrintWriter - * - * @param byteSource A valid byte source. - * @return A valid PrintWriter. - * @throws ImageReadException In the event that the the specified content - * does not conform to the format of the specific - * parser implementation. - * @throws IOException In the event of unsuccessful read or access operation. - */ - public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource) - throws ImageReadException, IOException { - return false; - } - - - /** - * Get a descriptive name for the implementation of an ImageParser. - * - * @return a valid, subject-matter-specific string. - */ - public abstract String getName(); - - /** - * Get the default extension for the format specified by an implementation - * of ImageParser. Some parsers can support more than one extension - * (i.e. .JPEG, .JPG; .TIF, .TIFF, etc.). - * - * @return A valid string. - */ - public abstract String getDefaultExtension(); - - /** - * Get an array of all accepted extensions - * - * @return A valid array of one or more elements. - */ - protected abstract String[] getAcceptedExtensions(); - - /** - * Get an array of ImageFormat objects describing all accepted types - * - * @return A valid array of one or more elements. - */ - protected abstract ImageFormat[] getAcceptedTypes(); - - /** - * Indicates whether the ImageParser implementation can accept - * the specified format - * - * @param type An instance of ImageFormat. - * @return If the parser can accept the format, true; otherwise, false. - */ - public boolean canAcceptType(final ImageFormat type) { - final ImageFormat[] types = getAcceptedTypes(); - - for (final ImageFormat type2 : types) { - if (type2.equals(type)) { - return true; - } - } - return false; - } - - /** - * Indicates whether the ImageParser implementation can accept - * the specified file based on its extension. - * - * @param file An valid file reference. - * @return If the parser can accept the format, true; otherwise, false. - */ - protected final boolean canAcceptExtension(final File file) { - return canAcceptExtension(file.getName()); - } - - /** - * Indicates whether the ImageParser implementation can accept - * the specified file name based on its extension. - * - * @param filename An valid string giving a file name or file path. - * @return If the parser can accept the format, true; otherwise, false. - */ - protected final boolean canAcceptExtension(final String filename) { - final String[] exts = getAcceptedExtensions(); - if (exts == null) { - return true; - } - - final int index = filename.lastIndexOf('.'); - if (index >= 0) { - String ext = filename.substring(index); - ext = ext.toLowerCase(Locale.ENGLISH); - - for (final String ext2 : exts) { - final String ext2Lower = ext2.toLowerCase(Locale.ENGLISH); - if (ext2Lower.equals(ext)) { - return true; - } - } - } - return false; - } - - /** - * Get an instance of IBufferedImageFactory based on the presence - * of a specification for ImagingConstants..BUFFERED_IMAGE_FACTORY - * within the supplied params. - * - * @param params A valid Map object, or a null. - * @return A valid instance of an implementation of a IBufferedImageFactory. - */ - protected IBufferedImageFactory getBufferedImageFactory(final Map params) { - if (params == null) { - return new SimpleBufferedImageFactory(); - } - - final IBufferedImageFactory result = (IBufferedImageFactory) params - .get(ImagingConstants.BUFFERED_IMAGE_FACTORY); - - if (null != result) { - return result; - } - - return new SimpleBufferedImageFactory(); - } - - /** - * A utility method to search a params specification and determine - * whether it contains the ImagingConstants.PARAM_KEY_STRICT - * specification. Intended - * for internal use by ImageParser implementations. - * - * @param params A valid Map object (or a null). - * @return If the params specify strict format compliance, true; - * otherwise, false. - */ - public static boolean isStrict(final Map params) { - if (params == null || !params.containsKey(ImagingConstants.PARAM_KEY_STRICT)) { - return false; - } - return ((Boolean) params.get(ImagingConstants.PARAM_KEY_STRICT)).booleanValue(); - } + final BufferedImage bi = getBufferedImage(byteSource, params); + + final List result = new ArrayList(); + + result.add(bi); + + return result; + } + + /** + * Gets all images specified by the byte array (some formats may include + * multiple images within a single data source). + * + * @param bytes + * A valid byte array + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final List getAllBufferedImages(final byte[] bytes) + throws ImageReadException, IOException { + return getAllBufferedImages(new ByteSourceArray(bytes)); + } + + /** + * Gets all images specified by indicated file (some formats may include + * multiple images within a single data source). + * + * @param file + * A valid reference to a file. + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final List getAllBufferedImages(final File file) + throws ImageReadException, IOException { + if (!canAcceptExtension(file)) { + return null; + } + + return getAllBufferedImages(new ByteSourceFile(file)); + } + + /** + * Gets a buffered image specified by the byte source (for sources that + * specify multiple images, choice of which image is returned is + * implementation dependent). + * + * @param byteSource + * A valid instance of ByteSource + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid instance of BufferedImage. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public abstract BufferedImage getBufferedImage(ByteSource byteSource, + Map params) throws ImageReadException, IOException; + + /** + * Gets a buffered image specified by the byte array (for sources that + * specify multiple images, choice of which image is returned is + * implementation dependent). + * + * @param bytes + * A valid byte array + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid instance of BufferedImage. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final BufferedImage getBufferedImage(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getBufferedImage(new ByteSourceArray(bytes), params); + } + + /** + * Gets a buffered image specified by the indicated file (for sources that + * specify multiple images, choice of which image is returned is + * implementation dependent). + * + * @param file + * A valid file reference. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data (null objects are permitted and must be + * supported by implementations). + * @return A valid instance of BufferedImage. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final BufferedImage getBufferedImage(final File file, + final Map params) throws ImageReadException, + IOException { + if (!canAcceptExtension(file)) { + return null; + } + + return getBufferedImage(new ByteSourceFile(file), params); + } + + /** + * Writes the content of a BufferedImage to the specified output stream. + * + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * support this capability. Currently, some of the parsers do not check for + * null arguments. So in cases where no optional specifications are + * supported, application code should pass in an empty instance of an + * implementation of the map interface (i.e. an empty HashMap). + * + * @param src + * An image giving the source content for output + * @param os + * A valid output stream for storing the formatted image + * @param params + * A non-null Map implementation supplying optional, + * format-specific instructions for output (such as selections + * for data compression, color models, etc.) + * @throws ImageWriteException + * In the event that the output format cannot handle the input + * image or invalid params are specified. + * @throws IOException + * In the event of an write error from the output stream. + */ + public void writeImage(final BufferedImage src, final OutputStream os, + final Map params) throws ImageWriteException, + IOException { + os.close(); // we are obligated to close stream. + + throw new ImageWriteException("This image format (" + getName() + + ") cannot be written."); + } + + /** + * Writes the content of several images to the specified output stream. + * + *

+ * The params argument provides a mechanism for individual implementations + * to pass optional information into the parser. Not all formats will + * support this capability. Currently, some of the parsers do not check for + * null arguments. So in cases where no optional specifications are + * supported, application code should pass in an empty instance of an + * implementation of the map interface (i.e. an empty HashMap). + * + * @param srcs + * Some images giving the source content for output + * @param os + * A valid output stream for storing the formatted image + * @param params + * A non-null Map implementation supplying optional, + * format-specific instructions for output (such as selections + * for data compression, color models, etc.) + * @throws ImageWriteException + * In the event that the output format cannot handle the input + * image or invalid params are specified. + * @throws IOException + * In the event of an write error from the output stream. + */ + public void writeImages(final List srcs, + final OutputStream os, final Map params) + throws ImageWriteException, IOException { + if (!srcs.isEmpty()) { + if (srcs.size() == 1) { + writeImage(srcs.get(0), os, params); + } else { + os.close(); // we are obligated to close stream. + + throw new ImageWriteException( + "This image format (" + + getName() + + ") does not support writing multiple images to the same data source."); + } + } + } + + /** + * Get the size of the image described by the specified byte array. + * + * @param bytes + * A valid byte array. + * @return A valid instance of Dimension. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final Dimension getImageSize(final byte[] bytes) + throws ImageReadException, IOException { + return getImageSize(bytes, null); + } + + /** + * Get the size of the image described by the specified byte array. + * + * @param bytes + * A valid byte array. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data. + * @return A valid instance of Dimension. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final Dimension getImageSize(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getImageSize(new ByteSourceArray(bytes), params); + } + + /** + * Get the size of the image described by the specified file. + * + * @param file + * A valid reference to a file. + * @return A valid instance of Dimension. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final Dimension getImageSize(final File file) + throws ImageReadException, IOException { + return getImageSize(file, null); + } + + /** + * Get the size of the image described by the specified file. + * + * @param file + * A valid reference to a file. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data. + * @return A valid instance of Dimension. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final Dimension getImageSize(final File file, + final Map params) throws ImageReadException, + IOException { + + if (!canAcceptExtension(file)) { + return null; + } + + return getImageSize(new ByteSourceFile(file), params); + } + + /** + * Get the size of the image described by the specified ByteSource. + * + * @param byteSource + * A valid reference to a ByteSource. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data. + * @return A valid instance of Dimension. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public abstract Dimension getImageSize(ByteSource byteSource, + Map params) throws ImageReadException, IOException; + + /** + * Get a string containing XML-formatted text conforming to the Extensible + * Metadata Platform (EXP) standard for representing information about image + * content. Not all image formats support EXP infomation and even for those + * that do, there is no guarantee that such information will be present in + * an image. + * + * @param byteSource + * A valid reference to a ByteSource. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data. + * @return If XMP metadata is present, a valid string; if it is not present, + * a null. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public abstract String getXmpXml(ByteSource byteSource, + Map params) throws ImageReadException, IOException; + + /** + * Get an array of bytes describing the International Color Consortium (ICC) + * specification for the color space of the image contained in the input + * byte array. Not all formats support ICC profiles. + * + * @param bytes + * A valid array of bytes. + * @return If available, a valid array of bytes; otherwise, a null + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final byte[] getICCProfileBytes(final byte[] bytes) + throws ImageReadException, IOException { + return getICCProfileBytes(bytes, null); + } + + /** + * Get an array of bytes describing the International Color Consortium (ICC) + * specification for the color space of the image contained in the input + * byte array. Not all formats support ICC profiles. + * + * @param bytes + * A valid array of bytes. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data. + * @return If available, a valid array of bytes; otherwise, a null + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final byte[] getICCProfileBytes(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getICCProfileBytes(new ByteSourceArray(bytes), params); + } + + /** + * Get an array of bytes describing the International Color Consortium (ICC) + * specification for the color space of the image contained in the input + * file. Not all formats support ICC profiles. + * + * @param file + * A valid file reference. + * @return If available, a valid array of bytes; otherwise, a null + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final byte[] getICCProfileBytes(final File file) + throws ImageReadException, IOException { + return getICCProfileBytes(file, null); + } + + /** + * Get an array of bytes describing the International Color Consortium (ICC) + * specification for the color space of the image contained in the input + * file. Not all formats support ICC profiles. + * + * @param file + * A valid file reference. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data. + * @return If available, a valid array of bytes; otherwise, a null + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final byte[] getICCProfileBytes(final File file, + final Map params) throws ImageReadException, + IOException { + if (!canAcceptExtension(file)) { + return null; + } + + if (getDebug()) { + System.out.println(getName() + ": " + file.getName()); + } + + return getICCProfileBytes(new ByteSourceFile(file), params); + } + + /** + * Get an array of bytes describing the International Color Consortium (ICC) + * specification for the color space of the image contained in the input + * byteSoruce. Not all formats support ICC profiles. + * + * @param byteSource + * A valid ByteSource. + * @param params + * Optional instructions for special-handling or interpretation + * of the input data. + * @return If available, a valid array of bytes; otherwise, a null + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public abstract byte[] getICCProfileBytes(ByteSource byteSource, + Map params) throws ImageReadException, IOException; + + /** + * Write the ImageInfo and format-specific information for the image content + * of the specified byte array to a string. + * + * @param bytes + * A valid array of bytes. + * @return A valid string. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final String dumpImageFile(final byte[] bytes) + throws ImageReadException, IOException { + return dumpImageFile(new ByteSourceArray(bytes)); + } + + /** + * Write the ImageInfo and format-specific information for the image content + * of the specified file to a string. + * + * @param file + * A valid file reference. + * @return A valid string. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final String dumpImageFile(final File file) + throws ImageReadException, IOException { + if (!canAcceptExtension(file)) { + return null; + } + + if (getDebug()) { + System.out.println(getName() + ": " + file.getName()); + } + + return dumpImageFile(new ByteSourceFile(file)); + } + + /** + * Write the ImageInfo and format-specific information for the image content + * of the specified byte source to a string. + * + * @param byteSource + * A valid byte source. + * @return A valid string. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public final String dumpImageFile(final ByteSource byteSource) + throws ImageReadException, IOException { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + + dumpImageFile(pw, byteSource); + + pw.flush(); + + return sw.toString(); + } + + /** + * Write the ImageInfo and format-specific information for the image content + * of the specified byte source to a PrintWriter + * + * @param byteSource + * A valid byte source. + * @return A valid PrintWriter. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public boolean dumpImageFile(final PrintWriter pw, + final ByteSource byteSource) throws ImageReadException, IOException { + return false; + } + + /** + * Get a descriptive name for the implementation of an ImageParser. + * + * @return a valid, subject-matter-specific string. + */ + public abstract String getName(); + + /** + * Get the default extension for the format specified by an implementation + * of ImageParser. Some parsers can support more than one extension (i.e. + * .JPEG, .JPG; .TIF, .TIFF, etc.). + * + * @return A valid string. + */ + public abstract String getDefaultExtension(); + + /** + * Get an array of all accepted extensions + * + * @return A valid array of one or more elements. + */ + protected abstract String[] getAcceptedExtensions(); + + /** + * Get an array of ImageFormat objects describing all accepted types + * + * @return A valid array of one or more elements. + */ + protected abstract ImageFormat[] getAcceptedTypes(); + + /** + * Indicates whether the ImageParser implementation can accept the specified + * format + * + * @param type + * An instance of ImageFormat. + * @return If the parser can accept the format, true; otherwise, false. + */ + public boolean canAcceptType(final ImageFormat type) { + final ImageFormat[] types = getAcceptedTypes(); + + for (final ImageFormat type2 : types) { + if (type2.equals(type)) { + return true; + } + } + return false; + } + + /** + * Indicates whether the ImageParser implementation can accept the specified + * file based on its extension. + * + * @param file + * An valid file reference. + * @return If the parser can accept the format, true; otherwise, false. + */ + protected final boolean canAcceptExtension(final File file) { + return canAcceptExtension(file.getName()); + } + + /** + * Indicates whether the ImageParser implementation can accept the specified + * file name based on its extension. + * + * @param filename + * An valid string giving a file name or file path. + * @return If the parser can accept the format, true; otherwise, false. + */ + protected final boolean canAcceptExtension(final String filename) { + final String[] exts = getAcceptedExtensions(); + if (exts == null) { + return true; + } + + final int index = filename.lastIndexOf('.'); + if (index >= 0) { + String ext = filename.substring(index); + ext = ext.toLowerCase(Locale.ENGLISH); + + for (final String ext2 : exts) { + final String ext2Lower = ext2.toLowerCase(Locale.ENGLISH); + if (ext2Lower.equals(ext)) { + return true; + } + } + } + return false; + } + + /** + * Get an instance of IBufferedImageFactory based on the presence of a + * specification for ImagingConstants..BUFFERED_IMAGE_FACTORY within the + * supplied params. + * + * @param params + * A valid Map object, or a null. + * @return A valid instance of an implementation of a IBufferedImageFactory. + */ + protected IBufferedImageFactory getBufferedImageFactory( + final Map params) { + if (params == null) { + return new SimpleBufferedImageFactory(); + } + + final IBufferedImageFactory result = (IBufferedImageFactory) params + .get(ImagingConstants.BUFFERED_IMAGE_FACTORY); + + if (null != result) { + return result; + } + + return new SimpleBufferedImageFactory(); + } + + /** + * A utility method to search a params specification and determine whether + * it contains the ImagingConstants.PARAM_KEY_STRICT specification. + * Intended for internal use by ImageParser implementations. + * + * @param params + * A valid Map object (or a null). + * @return If the params specify strict format compliance, true; otherwise, + * false. + */ + public static boolean isStrict(final Map params) { + if (params == null + || !params.containsKey(ImagingConstants.PARAM_KEY_STRICT)) { + return false; + } + return ((Boolean) params.get(ImagingConstants.PARAM_KEY_STRICT)) + .booleanValue(); + } } diff --git a/src/main/java/org/apache/commons/imaging/Imaging.java b/src/main/java/org/apache/commons/imaging/Imaging.java index 5bb31df10..b8b0481e9 100644 --- a/src/main/java/org/apache/commons/imaging/Imaging.java +++ b/src/main/java/org/apache/commons/imaging/Imaging.java @@ -45,1460 +45,1615 @@ /** * The primary application programming interface (API) to the Imaging library. *

- + * *

Application Notes

*

Using this class

- * Almost all of the Apache Commons Imaging library's core functionality can - * be accessed through the methods provided by this class. - * The use of the Imaging class is similar to the Java API's ImageIO class, - * though Imaging supports formats and options not included in the standard - * Java API. - *

All of methods provided by the Imaging class are declared static. - *

The Apache Commons Imaging package is a pure Java implementation. + * Almost all of the Apache Commons Imaging library's core functionality can be + * accessed through the methods provided by this class. The use of the Imaging + * class is similar to the Java API's ImageIO class, though Imaging supports + * formats and options not included in the standard Java API. + *

+ * All of methods provided by the Imaging class are declared static. + *

+ * The Apache Commons Imaging package is a pure Java implementation. *

Format support

- * While the Apache Commons Imaging package handles a number of different - * graphics formats, support for some formats is not yet complete. - * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. + * While the Apache Commons Imaging package handles a number of different + * graphics formats, support for some formats is not yet complete. For the most + * recent information on support for specific formats, refer to Format + * Support at the main project development web site. *

Optional parameters for image reading and writing

- * Some of the methods provided by this class accept an optional + * Some of the methods provided by this class accept an optional * params argument that permits the application to specify - * elements for special handling. If these specifications are not required by - * the application, the params argument may be omitted (as appropriate) or - * a null argument may be provided. In image-writing operations, the option - * parameters may include options such as data-compression type (if any), - * color model, or other format-specific data representations. The parameters - * map may also be used to provide EXIF Tags and other metadata to those - * formats that support them. In image-reading operations, - * the parameters may include information about special handling in reading - * the image data. - *

Optional parameters are specified using a Map object (typically, - * a Java HashMap) to specify a set of keys and values for input. - * The specification for support keys is provided by the ImagingConstants - * interface as well as by format-specific interfaces such as - * JpegContants or TiffConstants. + * elements for special handling. If these specifications are not required by + * the application, the params argument may be omitted (as appropriate) or a + * null argument may be provided. In image-writing operations, the option + * parameters may include options such as data-compression type (if any), color + * model, or other format-specific data representations. The parameters map may + * also be used to provide EXIF Tags and other metadata to those formats that + * support them. In image-reading operations, the parameters may include + * information about special handling in reading the image data. + *

+ * Optional parameters are specified using a Map object (typically, a Java + * HashMap) to specify a set of keys and values for input. The specification for + * support keys is provided by the ImagingConstants interface as well as by + * format-specific interfaces such as JpegContants or TiffConstants. *

Example code

* See the source of the SampleUsage class and other classes in the * org.apache.commons.imaging.examples package for examples. * * @see org.apache.commons.imaging.examples.SampleUsage - * @see Format Support + * @see Format + * Support */ public abstract class Imaging { - private static final int[] MAGIC_NUMBERS_GIF = { 0x47, 0x49, }; - private static final int[] MAGIC_NUMBERS_PNG = { 0x89, 0x50, }; - private static final int[] MAGIC_NUMBERS_JPEG = { 0xff, 0xd8, }; - private static final int[] MAGIC_NUMBERS_BMP = { 0x42, 0x4d, }; - private static final int[] MAGIC_NUMBERS_TIFF_MOTOROLA = { 0x4D, 0x4D, }; - private static final int[] MAGIC_NUMBERS_TIFF_INTEL = { 0x49, 0x49, }; - private static final int[] MAGIC_NUMBERS_PAM = { 0x50, 0x37, }; - private static final int[] MAGIC_NUMBERS_PSD = { 0x38, 0x42, }; - private static final int[] MAGIC_NUMBERS_PBM_A = { 0x50, 0x31, }; - private static final int[] MAGIC_NUMBERS_PBM_B = { 0x50, 0x34, }; - private static final int[] MAGIC_NUMBERS_PGM_A = { 0x50, 0x32, }; - private static final int[] MAGIC_NUMBERS_PGM_B = { 0x50, 0x35, }; - private static final int[] MAGIC_NUMBERS_PPM_A = { 0x50, 0x33, }; - private static final int[] MAGIC_NUMBERS_PPM_B = { 0x50, 0x36, }; - private static final int[] MAGIC_NUMBERS_JBIG2_1 = { 0x97, 0x4A, }; - private static final int[] MAGIC_NUMBERS_JBIG2_2 = { 0x42, 0x32, }; - private static final int[] MAGIC_NUMBERS_ICNS = { 0x69, 0x63, }; - private static final int[] MAGIC_NUMBERS_DCX = { 0xB1, 0x68, }; - private static final int[] MAGIC_NUMBERS_RGBE = { 0x23, 0x3F, }; - - /** - * Attempts to determine if a file contains an image recorded in - * a supported graphics format based on its file-name extension - * (for example ".jpg", ".gif", ".png", etc.). - * - * @param file A valid File object providing a reference to - * a file that may contain an image. - * @return true if the file-name includes a supported image - * format file extension; otherwise, false. - */ - public static boolean hasImageFileExtension(final File file) { - if (file == null || !file.isFile()) { - return false; - } - return hasImageFileExtension(file.getName()); - } - - /** - * Attempts to determine if a file contains an image recorded in - * a supported graphics format based on its file-name extension - * (for example ".jpg", ".gif", ".png", etc.). - * - * @param filename A valid string representing name of file - * which may contain an image. - * @return true if the filename has an image format file extension. - */ - public static boolean hasImageFileExtension(String filename) { - if (filename == null) { - return false; - } - - filename = filename.toLowerCase(Locale.ENGLISH); - - final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); - for (final ImageParser imageParser : imageParsers) { - final String[] exts = imageParser.getAcceptedExtensions(); - - for (final String ext : exts) { - if (filename.endsWith(ext.toLowerCase(Locale.ENGLISH))) { - return true; - } - } - } - - return false; - } - - /** - * Attempts to determine the image format of a file based on its - * "magic numbers," the first bytes of the data. - *

Many graphics format specify identifying byte - * values that appear at the beginning of the data file. This method - * checks for such identifying elements and returns a ImageFormat - * enumeration indicating what it detects. Note that this - * method can return "false positives" in cases where non-image files - * begin with the specified byte values. - * - * @param bytes Byte array containing an image file. - * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns - * ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be - * determined. - */ - public static ImageFormat guessFormat(final byte[] bytes) - throws ImageReadException, IOException { - return guessFormat(new ByteSourceArray(bytes)); - } - - /** - * Attempts to determine the image format of a file based on its - * "magic numbers," the first bytes of the data. - *

Many graphics formats specify identifying byte - * values that appear at the beginning of the data file. This method - * checks for such identifying elements and returns a ImageFormat - * enumeration indicating what it detects. Note that this - * method can return "false positives" in cases where non-image files - * begin with the specified byte values. - * - * @param file File containing image data. - * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns - * ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be - * determined. - */ - public static ImageFormat guessFormat(final File file) throws ImageReadException, - IOException { - return guessFormat(new ByteSourceFile(file)); - } - - private static boolean compareBytePair(final int[] a, final int[] b) { - if (a.length != 2 && b.length != 2) { - throw new RuntimeException("Invalid Byte Pair."); - } - return (a[0] == b[0]) && (a[1] == b[1]); - } - - - /** - * Attempts to determine the image format of a file based on its - * "magic numbers," the first bytes of the data. - *

Many graphics formats specify identifying byte - * values that appear at the beginning of the data file. This method - * checks for such identifying elements and returns a ImageFormat - * enumeration indicating what it detects. Note that this - * method can return "false positives" in cases where non-image files - * begin with the specified byte values. - * - * @param byteSource a valid ByteSource object potentially supplying - * data for an image. - * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns - * ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be - * determined. - * @throws ImageReadException in the event of an unsuccessful - * attempt to read the image data - * @throws IOException in the event of an unrecoverable I/O condition. - */ - public static ImageFormat guessFormat(final ByteSource byteSource) - throws ImageReadException, IOException { - - if (byteSource == null) { - return ImageFormats.UNKNOWN; - } - - InputStream is = null; - boolean canThrow = false; - try { - is = byteSource.getInputStream(); - - final int i1 = is.read(); - final int i2 = is.read(); - if ((i1 < 0) || (i2 < 0)) { - throw new ImageReadException( - "Couldn't read magic numbers to guess format."); - } - - final int b1 = i1 & 0xff; - final int b2 = i2 & 0xff; - final int[] bytePair = { b1, b2, }; - - if (compareBytePair(MAGIC_NUMBERS_GIF, bytePair)) { - canThrow = true; - return ImageFormats.GIF; - } - // else if (b1 == 0x00 && b2 == 0x00) // too similar to TGA - // { - // return ImageFormat.IMAGE_FORMAT_ICO; - // } - else if (compareBytePair(MAGIC_NUMBERS_PNG, bytePair)) { - canThrow = true; - return ImageFormats.PNG; - } else if (compareBytePair(MAGIC_NUMBERS_JPEG, bytePair)) { - canThrow = true; - return ImageFormats.JPEG; - } else if (compareBytePair(MAGIC_NUMBERS_BMP, bytePair)) { - canThrow = true; - return ImageFormats.BMP; - } else if (compareBytePair(MAGIC_NUMBERS_TIFF_MOTOROLA, bytePair)) { - canThrow = true; - return ImageFormats.TIFF; - } else if (compareBytePair(MAGIC_NUMBERS_TIFF_INTEL, bytePair)) { - canThrow = true; - return ImageFormats.TIFF; - } else if (compareBytePair(MAGIC_NUMBERS_PSD, bytePair)) { - canThrow = true; - return ImageFormats.PSD; - } else if (compareBytePair(MAGIC_NUMBERS_PAM, bytePair)) { - canThrow = true; - return ImageFormats.PAM; - } else if (compareBytePair(MAGIC_NUMBERS_PBM_A, bytePair)) { - canThrow = true; - return ImageFormats.PBM; - } else if (compareBytePair(MAGIC_NUMBERS_PBM_B, bytePair)) { - canThrow = true; - return ImageFormats.PBM; - } else if (compareBytePair(MAGIC_NUMBERS_PGM_A, bytePair)) { - canThrow = true; - return ImageFormats.PGM; - } else if (compareBytePair(MAGIC_NUMBERS_PGM_B, bytePair)) { - canThrow = true; - return ImageFormats.PGM; - } else if (compareBytePair(MAGIC_NUMBERS_PPM_A, bytePair)) { - canThrow = true; - return ImageFormats.PPM; - } else if (compareBytePair(MAGIC_NUMBERS_PPM_B, bytePair)) { - canThrow = true; - return ImageFormats.PPM; - } else if (compareBytePair(MAGIC_NUMBERS_JBIG2_1, bytePair)) { - final int i3 = is.read(); - final int i4 = is.read(); - if ((i3 < 0) || (i4 < 0)) { - throw new ImageReadException( - "Couldn't read magic numbers to guess format."); - } - - final int b3 = i3 & 0xff; - final int b4 = i4 & 0xff; - final int[] bytePair2 = { b3, b4, }; - if (compareBytePair(MAGIC_NUMBERS_JBIG2_2, bytePair2)) { - canThrow = true; - return ImageFormats.JBIG2; - } - } else if (compareBytePair(MAGIC_NUMBERS_ICNS, bytePair)) { - canThrow = true; - return ImageFormats.ICNS; - } else if (compareBytePair(MAGIC_NUMBERS_DCX, bytePair)) { - canThrow = true; - return ImageFormats.DCX; - } else if (compareBytePair(MAGIC_NUMBERS_RGBE, bytePair)) { - canThrow = true; - return ImageFormats.RGBE; - } - canThrow = true; - return ImageFormats.UNKNOWN; - } finally { - IoUtils.closeQuietly(canThrow, is); - } - } - - /** - * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and - * TIFF images. - *

- * - * @param bytes - * Byte array containing an image file. - * @return An instance of ICC_Profile or null if the image contains no ICC - * profile. - */ - public static ICC_Profile getICCProfile(final byte[] bytes) - throws ImageReadException, IOException { - return getICCProfile(bytes, null); - } - - /** - * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and - * TIFF images. - *

- * - * @param bytes - * Byte array containing an image file. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of ICC_Profile or null if the image contains no ICC - * profile.. - */ - public static ICC_Profile getICCProfile(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getICCProfile(new ByteSourceArray(bytes), params); - } - - /** - * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and - * TIFF images. - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @return An instance of ICC_Profile or null if the image contains no ICC - * profile.. - */ - public static ICC_Profile getICCProfile(final InputStream is, final String filename) - throws ImageReadException, IOException { - return getICCProfile(is, filename, null); - } - - /** - * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and - * TIFF images. - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of ICC_Profile or null if the image contains no ICC - * profile.. - */ - public static ICC_Profile getICCProfile(final InputStream is, final String filename, - final Map params) throws ImageReadException, IOException { - return getICCProfile(new ByteSourceInputStream(is, filename), params); - } - - /** - * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and - * TIFF images. - *

- * - * @param file - * File containing image data. - * @return An instance of ICC_Profile or null if the image contains no ICC - * profile.. - */ - public static ICC_Profile getICCProfile(final File file) - throws ImageReadException, IOException { - return getICCProfile(file, null); - } - - /** - * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and - * TIFF images. - *

- * - * @param file - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of ICC_Profile or null if the image contains no ICC - * profile.. - */ - public static ICC_Profile getICCProfile(final File file, final Map params) - throws ImageReadException, IOException { - return getICCProfile(new ByteSourceFile(file), params); - } - - protected static ICC_Profile getICCProfile(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { - final byte[] bytes = getICCProfileBytes(byteSource, params); - if (bytes == null) { - return null; - } - - final IccProfileParser parser = new IccProfileParser(); - final IccProfileInfo info = parser.getICCProfileInfo(bytes); - if (info == null) { - return null; - } - if (info.issRGB()) { - return null; - } - - return ICC_Profile.getInstance(bytes); - } - - /** - * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD - * (Photoshop) and TIFF images. - *

- * To parse the result use IccProfileParser or - * ICC_Profile.getInstance(bytes). - *

- * - * @param bytes - * Byte array containing an image file. - * @return A byte array. - * @see IccProfileParser - * @see ICC_Profile - */ - public static byte[] getICCProfileBytes(final byte[] bytes) - throws ImageReadException, IOException { - return getICCProfileBytes(bytes, null); - } - - /** - * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD - * (Photoshop) and TIFF images. - *

- * To parse the result use IccProfileParser or - * ICC_Profile.getInstance(bytes). - *

- * - * @param bytes - * Byte array containing an image file. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return A byte array. - * @see IccProfileParser - * @see ICC_Profile - */ - public static byte[] getICCProfileBytes(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getICCProfileBytes(new ByteSourceArray(bytes), params); - } - - /** - * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD - * (Photoshop) and TIFF images. - *

- * To parse the result use IccProfileParser or - * ICC_Profile.getInstance(bytes). - *

- * - * @param file - * File containing image data. - * @return A byte array. - * @see IccProfileParser - * @see ICC_Profile - */ - public static byte[] getICCProfileBytes(final File file) - throws ImageReadException, IOException { - return getICCProfileBytes(file, null); - } - - /** - * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD - * (Photoshop) and TIFF images. - *

- * To parse the result use IccProfileParser or - * ICC_Profile.getInstance(bytes). - *

- * - * @param file - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return A byte array. - * @see IccProfileParser - * @see ICC_Profile - */ - public static byte[] getICCProfileBytes(final File file, final Map params) - throws ImageReadException, IOException { - return getICCProfileBytes(new ByteSourceFile(file), params); - } - - private static byte[] getICCProfileBytes(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.getICCProfileBytes(byteSource, params); - } - - /** - * Parses the "image info" of an image. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param filename - * String. - * @param bytes - * Byte array containing an image file. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final String filename, final byte[] bytes, - final Map params) throws ImageReadException, IOException { - return getImageInfo(new ByteSourceArray(filename, bytes), params); - } - - /** - * Parses the "image info" of an image. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param filename - * String. - * @param bytes - * Byte array containing an image file. - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final String filename, final byte[] bytes) - throws ImageReadException, IOException { - return getImageInfo(new ByteSourceArray(filename, bytes), null); - } - - /** - * Parses the "image info" of an image. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final InputStream is, final String filename) - throws ImageReadException, IOException { - return getImageInfo(new ByteSourceInputStream(is, filename), null); - } - - /** - * Parses the "image info" of an image. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final InputStream is, final String filename, - final Map params) throws ImageReadException, IOException { - return getImageInfo(new ByteSourceInputStream(is, filename), params); - } - - /** - * Parses the "image info" of an image. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param bytes - * Byte array containing an image file. - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final byte[] bytes) - throws ImageReadException, IOException { - return getImageInfo(new ByteSourceArray(bytes), null); - } - - /** - * Parses the "image info" of an image. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param bytes - * Byte array containing an image file. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getImageInfo(new ByteSourceArray(bytes), params); - } - - /** - * Parses the "image info" of an image file. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param file - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final File file, final Map params) - throws ImageReadException, IOException { - return getImageInfo(new ByteSourceFile(file), params); - } - - /** - * Parses the "image info" of an image file. - *

- * "Image info" is a summary of basic information about the image such as: - * width, height, file format, bit depth, color type, etc. - *

- * Not to be confused with "image metadata." - *

- * - * @param file - * File containing image data. - * @return An instance of ImageInfo. - * @see ImageInfo - */ - public static ImageInfo getImageInfo(final File file) throws ImageReadException, - IOException { - return getImageInfo(file, null); - } - - private static ImageInfo getImageInfo(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.getImageInfo(byteSource, params); - } - - private static ImageParser getImageParser(final ByteSource byteSource) - throws ImageReadException, IOException { - final ImageFormat format = guessFormat(byteSource); - if (!format.equals(ImageFormats.UNKNOWN)) { - - final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); - - for (final ImageParser imageParser : imageParsers) { - if (imageParser.canAcceptType(format)) { - return imageParser; - } - } - } - - final String filename = byteSource.getFilename(); - if (filename != null) { - final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); - - for (final ImageParser imageParser : imageParsers) { - if (imageParser.canAcceptExtension(filename)) { - return imageParser; - } - } - } - - throw new ImageReadException("Can't parse this format."); - } - - /** - * Determines the width and height of an image. - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @return The width and height of the image. - */ - public static Dimension getImageSize(final InputStream is, final String filename) - throws ImageReadException, IOException { - return getImageSize(is, filename, null); - } - - /** - * Determines the width and height of an image. - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return The width and height of the image. - */ - public static Dimension getImageSize(final InputStream is, final String filename, - final Map params) throws ImageReadException, IOException { - return getImageSize(new ByteSourceInputStream(is, filename), params); - } - - /** - * Determines the width and height of an image. - *

- * - * @param bytes - * Byte array containing an image file. - * @return The width and height of the image. - */ - public static Dimension getImageSize(final byte[] bytes) - throws ImageReadException, IOException { - return getImageSize(bytes, null); - } - - /** - * Determines the width and height of an image. - *

- * - * @param bytes - * Byte array containing an image file. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return The width and height of the image. - */ - public static Dimension getImageSize(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getImageSize(new ByteSourceArray(bytes), params); - } - - /** - * Determines the width and height of an image file. - *

- * - * @param file - * File containing image data. - * @return The width and height of the image. - */ - public static Dimension getImageSize(final File file) throws ImageReadException, - IOException { - return getImageSize(file, null); - } - - /** - * Determines the width and height of an image file. - *

- * - * @param file - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return The width and height of the image. - */ - public static Dimension getImageSize(final File file, final Map params) - throws ImageReadException, IOException { - return getImageSize(new ByteSourceFile(file), params); - } - - public static Dimension getImageSize(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.getImageSize(byteSource, params); - } - - /** - * Extracts the embedded XML metadata as an XML string. - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @return Xmp Xml as String, if present. Otherwise, returns null. - */ - public static String getXmpXml(final InputStream is, final String filename) - throws ImageReadException, IOException { - return getXmpXml(is, filename, null); - } - - /** - * Extracts the embedded XML metadata as an XML string. - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return Xmp Xml as String, if present. Otherwise, returns null. - */ - public static String getXmpXml(final InputStream is, final String filename, final Map params) - throws ImageReadException, IOException { - return getXmpXml(new ByteSourceInputStream(is, filename), params); - } - - /** - * Extracts the embedded XML metadata as an XML string. - *

- * - * @param bytes - * Byte array containing an image file. - * @return Xmp Xml as String, if present. Otherwise, returns null. - */ - public static String getXmpXml(final byte[] bytes) throws ImageReadException, - IOException { - return getXmpXml(bytes, null); - } - - /** - * Extracts the embedded XML metadata as an XML string. - *

- * - * @param bytes - * Byte array containing an image file. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return Xmp Xml as String, if present. Otherwise, returns null. - */ - public static String getXmpXml(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getXmpXml(new ByteSourceArray(bytes), params); - } - - /** - * Extracts the embedded XML metadata as an XML string. - *

- * - * @param file - * File containing image data. - * @return Xmp Xml as String, if present. Otherwise, returns null. - */ - public static String getXmpXml(final File file) throws ImageReadException, - IOException { - return getXmpXml(file, null); - } - - /** - * Extracts the embedded XML metadata as an XML string. - *

- * - * @param file - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return Xmp Xml as String, if present. Otherwise, returns null. - */ - public static String getXmpXml(final File file, final Map params) - throws ImageReadException, IOException { - return getXmpXml(new ByteSourceFile(file), params); - } - - /** - * Extracts the embedded XML metadata as an XML string. - *

- * - * @param byteSource - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return Xmp Xml as String, if present. Otherwise, returns null. - */ - public static String getXmpXml(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.getXmpXml(byteSource, params); - } - - /** - * Parses the metadata of an image. This metadata depends on the format of - * the image. - *

- * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may - * contain comments. TIFF files may contain metadata. - *

- * The instance of IImageMetadata returned by getMetadata() should be upcast - * (depending on image format). - *

- * Not to be confused with "image info." - *

- * - * @param bytes - * Byte array containing an image file. - * @return An instance of IImageMetadata. - * @see IImageMetadata - */ - public static IImageMetadata getMetadata(final byte[] bytes) - throws ImageReadException, IOException { - return getMetadata(bytes, null); - } - - /** - * Parses the metadata of an image. This metadata depends on the format of - * the image. - *

- * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may - * contain comments. TIFF files may contain metadata. - *

- * The instance of IImageMetadata returned by getMetadata() should be upcast - * (depending on image format). - *

- * Not to be confused with "image info." - *

- * - * @param bytes - * Byte array containing an image file. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of IImageMetadata. - * @see IImageMetadata - */ - public static IImageMetadata getMetadata(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getMetadata(new ByteSourceArray(bytes), params); - } - - /** - * Parses the metadata of an image file. This metadata depends on the format - * of the image. - *

- * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may - * contain comments. TIFF files may contain metadata. - *

- * The instance of IImageMetadata returned by getMetadata() should be upcast - * (depending on image format). - *

- * Not to be confused with "image info." - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @return An instance of IImageMetadata. - * @see IImageMetadata - */ - public static IImageMetadata getMetadata(final InputStream is, final String filename) - throws ImageReadException, IOException { - return getMetadata(is, filename, null); - } - - /** - * Parses the metadata of an image file. This metadata depends on the format - * of the image. - *

- * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may - * contain comments. TIFF files may contain metadata. - *

- * The instance of IImageMetadata returned by getMetadata() should be upcast - * (depending on image format). - *

- * Not to be confused with "image info." - *

- * - * @param is - * InputStream from which to read image data. - * @param filename - * Filename associated with image data (optional). - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of IImageMetadata. - * @see IImageMetadata - */ - public static IImageMetadata getMetadata(final InputStream is, final String filename, - final Map params) throws ImageReadException, IOException { - return getMetadata(new ByteSourceInputStream(is, filename), params); - } - - /** - * Parses the metadata of an image file. This metadata depends on the format - * of the image. - *

- * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may - * contain comments. TIFF files may contain metadata. - *

- * The instance of IImageMetadata returned by getMetadata() should be upcast - * (depending on image format). - *

- * Not to be confused with "image info." - *

- * - * @param file - * File containing image data. - * @return An instance of IImageMetadata. - * @see IImageMetadata - */ - public static IImageMetadata getMetadata(final File file) - throws ImageReadException, IOException { - return getMetadata(file, null); - } - - /** - * Parses the metadata of an image file. This metadata depends on the format - * of the image. - *

- * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may - * contain comments. TIFF files may contain metadata. - *

- * The instance of IImageMetadata returned by getMetadata() should be upcast - * (depending on image format). - *

- * Not to be confused with "image info." - *

- * - * @param file - * File containing image data. - * @param params - * Map of optional parameters, defined in ImagingConstants. - * @return An instance of IImageMetadata. - * @see IImageMetadata - */ - public static IImageMetadata getMetadata(final File file, final Map params) - throws ImageReadException, IOException { - return getMetadata(new ByteSourceFile(file), params); - } - - private static IImageMetadata getMetadata(final ByteSource byteSource, final Map params) - throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.getMetadata(byteSource, params); - } - - /** - * Write the ImageInfo and format-specific information for the image - * content of the specified byte array to a string. - * @param bytes A valid array of bytes. - * @return A valid string. - * @throws ImageReadException In the event that the the specified - * content does not conform to the format of the specific parser - * implementation. - * @throws IOException In the event of unsuccessful read or - * access operation. - */ - public static String dumpImageFile(final byte[] bytes) throws ImageReadException, - IOException { - return dumpImageFile(new ByteSourceArray(bytes)); - } - - /** - * Write the ImageInfo and format-specific information for the image - * content of the specified file to a string. - * @param file A valid file reference. - * @return A valid string. - * @throws ImageReadException In the event that the the specified - * content does not conform to the format of the specific parser - * implementation. - * @throws IOException In the event of unsuccessful read or - * access operation. - */ - public static String dumpImageFile(final File file) throws ImageReadException, - IOException { - return dumpImageFile(new ByteSourceFile(file)); - } - - private static String dumpImageFile(final ByteSource byteSource) - throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.dumpImageFile(byteSource); - } - - /** - * Attempts to determine the image format of the specified data and - * evaluates its format compliance. This method - * returns a FormatCompliance object which includes information - * about the data's compliance to a specific format. - * @param bytes a valid array of bytes containing image data. - * @return if successful, a valid FormatCompliance object. - * @throws ImageReadException in the event of unreadable data. - * @throws IOException in the event of an unrecoverable I/O condition. - */ - public static FormatCompliance getFormatCompliance(final byte[] bytes) - throws ImageReadException, IOException { - return getFormatCompliance(new ByteSourceArray(bytes)); - } - - /** - * Attempts to determine the image format of the specified data and - * evaluates its format compliance. This method - * returns a FormatCompliance object which includes information - * about the data's compliance to a specific format. - * @param file valid file containing image data - * @return if successful, a valid FormatCompliance object. - * @throws ImageReadException in the event of unreadable data. - * @throws IOException in the event of an unrecoverable I/O condition. - */ - public static FormatCompliance getFormatCompliance(final File file) - throws ImageReadException, IOException { - return getFormatCompliance(new ByteSourceFile(file)); - } - - private static FormatCompliance getFormatCompliance(final ByteSource byteSource) - throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.getFormatCompliance(byteSource); - } - - /** - * Gets all images specified by the InputStream (some - * formats may include multiple images within a single data source). - * @param is A valid InputStream - * @return A valid (potentially empty) list of BufferedImage objects. - * @throws ImageReadException In the event that the the specified - * content does not conform to the format of the specific parser - * implementation. - * @throws IOException In the event of unsuccessful read or - * access operation. - */ - public static List getAllBufferedImages(final InputStream is, - final String filename) throws ImageReadException, IOException { - return getAllBufferedImages(new ByteSourceInputStream(is, filename)); - } - - /** - * Gets all images specified by the byte array (some - * formats may include multiple images within a single data source). - * @param bytes a valid array of bytes - * @return A valid (potentially empty) list of BufferedImage objects. - * @throws ImageReadException In the event that the the specified - * content does not conform to the format of the specific parser - * implementation. - * @throws IOException In the event of unsuccessful read or - * access operation. - */ - public static List getAllBufferedImages(final byte[] bytes) - throws ImageReadException, IOException { - return getAllBufferedImages(new ByteSourceArray(bytes)); - } - - /** - * Gets all images specified by the file (some - * formats may include multiple images within a single data source). - * @param file A reference to a valid data file. - * @return A valid (potentially empty) list of BufferedImage objects. - * @throws ImageReadException In the event that the the specified - * content does not conform to the format of the specific parser - * implementation. - * @throws IOException In the event of unsuccessful read or - * access operation. - */ - public static List getAllBufferedImages(final File file) - throws ImageReadException, IOException { - return getAllBufferedImages(new ByteSourceFile(file)); - } - - - private static List getAllBufferedImages( - final ByteSource byteSource) throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - - return imageParser.getAllBufferedImages(byteSource); - } - - - /** - * Reads the first image from an InputStream. - *

- * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param is a valid ImageStream from which to read data. - * @return if successful, a valid buffered image - * @throws ImageReadException in the event of a processing error - * while reading an image (i.e. a format violation, etc.). - * @throws IOException in the event of an unrecoverable I/O exception. - */ - - public static BufferedImage getBufferedImage(final InputStream is) - throws ImageReadException, IOException { - return getBufferedImage(is, null); - } - - - - /** - * Reads the first image from an InputStream - * using data-processing options specified through a parameters - * map. Options may be configured using the ImagingContants - * interface or the various format-specific implementations provided - * by this package. - *

- * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param is a valid ImageStream from which to read data. - * @param params an optional parameters map specifying options - * @return if successful, a valid buffered image - * @throws ImageReadException in the event of a processing error - * while reading an image (i.e. a format violation, etc.). - * @throws IOException in the event of an unrecoverable I/O exception. - */ - public static BufferedImage getBufferedImage(final InputStream is, final Map params) - throws ImageReadException, IOException { - String filename = null; - if (params != null && params.containsKey(PARAM_KEY_FILENAME)) { - filename = (String) params.get(PARAM_KEY_FILENAME); - } - return getBufferedImage(new ByteSourceInputStream(is, filename), params); - } - - /** - * Reads the first image from a byte array. - *

- * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param bytes a valid array of bytes from which to read data. - * @return if successful, a valid buffered image - * @throws ImageReadException in the event of a processing error - * while reading an image (i.e. a format violation, etc.). - * @throws IOException in the event of an unrecoverable I/O exception. - */ - public static BufferedImage getBufferedImage(final byte[] bytes) - throws ImageReadException, IOException { - return getBufferedImage(new ByteSourceArray(bytes), null); - } - - - /** - * Reads the first image from a byte array - * using data-processing options specified through a parameters - * map. Options may be configured using the ImagingContants - * interface or the various format-specific implementations provided - * by this package. - *

- * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param bytes a valid array of bytes from which to read data. - * @param params an optional parameters map specifying options. - * @return if successful, a valid buffered image - * @throws ImageReadException in the event of a processing error - * while reading an image (i.e. a format violation, etc.). - * @throws IOException in the event of an unrecoverable I/O exception. - */ - public static BufferedImage getBufferedImage(final byte[] bytes, final Map params) - throws ImageReadException, IOException { - return getBufferedImage(new ByteSourceArray(bytes), params); - } - - - - - /** - * Reads the first image from a file. - *

- * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param file a valid reference to a file containing image data. - * @return if successful, a valid buffered image - * @throws ImageReadException in the event of a processing error - * while reading an image (i.e. a format violation, etc.). - * @throws IOException in the event of an unrecoverable I/O exception. - */ - public static BufferedImage getBufferedImage(final File file) - throws ImageReadException, IOException { - return getBufferedImage(new ByteSourceFile(file), null); - } - - - /** - * Reads the first image from a file - * using data-processing options specified through a parameters - * map. Options may be configured using the ImagingContants - * interface or the various format-specific implementations provided - * by this package. - *

- * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param file a valid reference to a file containing image data. - * @return if successful, a valid buffered image - * @throws ImageReadException in the event of a processing error - * while reading an image (i.e. a format violation, etc.). - * @throws IOException in the event of an unrecoverable I/O exception. - */ - public static BufferedImage getBufferedImage(final File file, final Map params) - throws ImageReadException, IOException { - return getBufferedImage(new ByteSourceFile(file), params); - } - - - - private static BufferedImage getBufferedImage(final ByteSource byteSource, - Map params) throws ImageReadException, IOException { - final ImageParser imageParser = getImageParser(byteSource); - if (null == params) { - params = new HashMap(); - } - - return imageParser.getBufferedImage(byteSource, params); - } - - /** - * Writes the content of a BufferedImage to a file using the specified - * image format. Specifications for storing the file (such as data compression, - * color models, metadata tags, etc.) may be specified using an optional - * parameters map. These specifications are defined in the ImagingConstants - * interface or in various format-specific implementations. - *

- * Image writing is not supported for all graphics formats. - * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param src a valid BufferedImage object - * @param file the file to which the output image is to be written - * @param format the format in which the output image is to be written - * @param params an optional parameters map (nulls permitted) - * @throws ImageWriteException in the event of a format violation, - * unsupported image format, etc. - * @throws IOException in the event of an unrecoverable I/O exception. - * @see ImagingConstants - */ - public static void writeImage(final BufferedImage src, final File file, - final ImageFormat format, final Map params) throws ImageWriteException, - IOException { - OutputStream os = null; - boolean canThrow = false; - try { - os = new FileOutputStream(file); - os = new BufferedOutputStream(os); - - writeImage(src, os, format, params); - canThrow = true; - } finally { - IoUtils.closeQuietly(canThrow, os); - } - } - - - /** - * Writes the content of a BufferedImage to a byte array using the specified - * image format. Specifications for storing the file (such as data compression, - * color models, metadata tags, etc.) may be specified using an optional - * parameters map. These specifications are defined in the ImagingConstants - * interface or in various format-specific implementations. - *

- * Image writing is not supported for all graphics formats. - * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param src a valid BufferedImage object - * @param format the format in which the output image is to be written - * @param params an optional parameters map (nulls permitted) - * @return if successful, a valid array of bytes. - * @throws ImageWriteException in the event of a format violation, - * unsupported image format, etc. - * @throws IOException in the event of an unrecoverable I/O exception. - * @see ImagingConstants - */ - public static byte[] writeImageToBytes(final BufferedImage src, - final ImageFormat format, final Map params) throws ImageWriteException, - IOException { - final ByteArrayOutputStream os = new ByteArrayOutputStream(); - - writeImage(src, os, format, params); - - return os.toByteArray(); - } - - - /** - * Writes the content of a BufferedImage to an OutputStream using the specified - * image format. Specifications for storing the file (such as data compression, - * color models, metadata tags, etc.) may be specified using an optional - * parameters map. These specifications are defined in the ImagingConstants - * interface or in various format-specific implementations. - *

- * Image writing is not supported for all graphics formats. - * For the most recent information on support for specific formats, refer to - * Format Support - * at the main project development web site. While the Apache Commons - * Imaging package does not fully support all formats, it can read - * image info, metadata and ICC profiles from all image formats that - * provide this data. - * @param src a valid BufferedImage object - * @param os the OutputStream to which the output image is to be written - * @param format the format in which the output image is to be written - * @param params an optional parameters map (nulls permitted) - * @throws ImageWriteException in the event of a format violation, - * unsupported image format, etc. - * @throws IOException in the event of an unrecoverable I/O exception. - * @see ImagingConstants - */ - public static void writeImage(final BufferedImage src, final OutputStream os, - final ImageFormat format, Map params) throws ImageWriteException, - IOException { - final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); - - // make sure params are non-null - if (params == null) { - params = new HashMap(); - } - - params.put(PARAM_KEY_FORMAT, format); - - ImageParser imageParser = null; - for (final ImageParser imageParser2 : imageParsers) { - if (imageParser2.canAcceptType(format)) { - imageParser = imageParser2; - break; - } - } - if (imageParser != null) { - imageParser.writeImage(src, os, params); - } else { - throw new ImageWriteException("Unknown Format: " + format); - } - } + private static final int[] MAGIC_NUMBERS_GIF = { 0x47, 0x49, }; + private static final int[] MAGIC_NUMBERS_PNG = { 0x89, 0x50, }; + private static final int[] MAGIC_NUMBERS_JPEG = { 0xff, 0xd8, }; + private static final int[] MAGIC_NUMBERS_BMP = { 0x42, 0x4d, }; + private static final int[] MAGIC_NUMBERS_TIFF_MOTOROLA = { 0x4D, 0x4D, }; + private static final int[] MAGIC_NUMBERS_TIFF_INTEL = { 0x49, 0x49, }; + private static final int[] MAGIC_NUMBERS_PAM = { 0x50, 0x37, }; + private static final int[] MAGIC_NUMBERS_PSD = { 0x38, 0x42, }; + private static final int[] MAGIC_NUMBERS_PBM_A = { 0x50, 0x31, }; + private static final int[] MAGIC_NUMBERS_PBM_B = { 0x50, 0x34, }; + private static final int[] MAGIC_NUMBERS_PGM_A = { 0x50, 0x32, }; + private static final int[] MAGIC_NUMBERS_PGM_B = { 0x50, 0x35, }; + private static final int[] MAGIC_NUMBERS_PPM_A = { 0x50, 0x33, }; + private static final int[] MAGIC_NUMBERS_PPM_B = { 0x50, 0x36, }; + private static final int[] MAGIC_NUMBERS_JBIG2_1 = { 0x97, 0x4A, }; + private static final int[] MAGIC_NUMBERS_JBIG2_2 = { 0x42, 0x32, }; + private static final int[] MAGIC_NUMBERS_ICNS = { 0x69, 0x63, }; + private static final int[] MAGIC_NUMBERS_DCX = { 0xB1, 0x68, }; + private static final int[] MAGIC_NUMBERS_RGBE = { 0x23, 0x3F, }; + + /** + * Attempts to determine if a file contains an image recorded in a supported + * graphics format based on its file-name extension (for example ".jpg", + * ".gif", ".png", etc.). + * + * @param file + * A valid File object providing a reference to a file that may + * contain an image. + * @return true if the file-name includes a supported image format file + * extension; otherwise, false. + */ + public static boolean hasImageFileExtension(final File file) { + if (file == null || !file.isFile()) { + return false; + } + return hasImageFileExtension(file.getName()); + } + + /** + * Attempts to determine if a file contains an image recorded in a supported + * graphics format based on its file-name extension (for example ".jpg", + * ".gif", ".png", etc.). + * + * @param filename + * A valid string representing name of file which may contain an + * image. + * @return true if the filename has an image format file extension. + */ + public static boolean hasImageFileExtension(String filename) { + if (filename == null) { + return false; + } + + filename = filename.toLowerCase(Locale.ENGLISH); + + final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); + for (final ImageParser imageParser : imageParsers) { + final String[] exts = imageParser.getAcceptedExtensions(); + + for (final String ext : exts) { + if (filename.endsWith(ext.toLowerCase(Locale.ENGLISH))) { + return true; + } + } + } + + return false; + } + + /** + * Attempts to determine the image format of a file based on its + * "magic numbers," the first bytes of the data. + *

+ * Many graphics format specify identifying byte values that appear at the + * beginning of the data file. This method checks for such identifying + * elements and returns a ImageFormat enumeration indicating what it + * detects. Note that this method can return "false positives" in cases + * where non-image files begin with the specified byte values. + * + * @param bytes + * Byte array containing an image file. + * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns + * ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be + * determined. + */ + public static ImageFormat guessFormat(final byte[] bytes) + throws ImageReadException, IOException { + return guessFormat(new ByteSourceArray(bytes)); + } + + /** + * Attempts to determine the image format of a file based on its + * "magic numbers," the first bytes of the data. + *

+ * Many graphics formats specify identifying byte values that appear at the + * beginning of the data file. This method checks for such identifying + * elements and returns a ImageFormat enumeration indicating what it + * detects. Note that this method can return "false positives" in cases + * where non-image files begin with the specified byte values. + * + * @param file + * File containing image data. + * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns + * ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be + * determined. + */ + public static ImageFormat guessFormat(final File file) + throws ImageReadException, IOException { + return guessFormat(new ByteSourceFile(file)); + } + + private static boolean compareBytePair(final int[] a, final int[] b) { + if (a.length != 2 && b.length != 2) { + throw new RuntimeException("Invalid Byte Pair."); + } + return (a[0] == b[0]) && (a[1] == b[1]); + } + + /** + * Attempts to determine the image format of a file based on its + * "magic numbers," the first bytes of the data. + *

+ * Many graphics formats specify identifying byte values that appear at the + * beginning of the data file. This method checks for such identifying + * elements and returns a ImageFormat enumeration indicating what it + * detects. Note that this method can return "false positives" in cases + * where non-image files begin with the specified byte values. + * + * @param byteSource + * a valid ByteSource object potentially supplying data for an + * image. + * @return An ImageFormat, such as ImageFormat.IMAGE_FORMAT_JPEG. Returns + * ImageFormat.IMAGE_FORMAT_UNKNOWN if the image type cannot be + * determined. + * @throws ImageReadException + * in the event of an unsuccessful attempt to read the image + * data + * @throws IOException + * in the event of an unrecoverable I/O condition. + */ + public static ImageFormat guessFormat(final ByteSource byteSource) + throws ImageReadException, IOException { + + if (byteSource == null) { + return ImageFormats.UNKNOWN; + } + + InputStream is = null; + boolean canThrow = false; + try { + is = byteSource.getInputStream(); + + final int i1 = is.read(); + final int i2 = is.read(); + if ((i1 < 0) || (i2 < 0)) { + throw new ImageReadException( + "Couldn't read magic numbers to guess format."); + } + + final int b1 = i1 & 0xff; + final int b2 = i2 & 0xff; + final int[] bytePair = { b1, b2, }; + + if (compareBytePair(MAGIC_NUMBERS_GIF, bytePair)) { + canThrow = true; + return ImageFormats.GIF; + } + // else if (b1 == 0x00 && b2 == 0x00) // too similar to TGA + // { + // return ImageFormat.IMAGE_FORMAT_ICO; + // } + else if (compareBytePair(MAGIC_NUMBERS_PNG, bytePair)) { + canThrow = true; + return ImageFormats.PNG; + } else if (compareBytePair(MAGIC_NUMBERS_JPEG, bytePair)) { + canThrow = true; + return ImageFormats.JPEG; + } else if (compareBytePair(MAGIC_NUMBERS_BMP, bytePair)) { + canThrow = true; + return ImageFormats.BMP; + } else if (compareBytePair(MAGIC_NUMBERS_TIFF_MOTOROLA, bytePair)) { + canThrow = true; + return ImageFormats.TIFF; + } else if (compareBytePair(MAGIC_NUMBERS_TIFF_INTEL, bytePair)) { + canThrow = true; + return ImageFormats.TIFF; + } else if (compareBytePair(MAGIC_NUMBERS_PSD, bytePair)) { + canThrow = true; + return ImageFormats.PSD; + } else if (compareBytePair(MAGIC_NUMBERS_PAM, bytePair)) { + canThrow = true; + return ImageFormats.PAM; + } else if (compareBytePair(MAGIC_NUMBERS_PBM_A, bytePair)) { + canThrow = true; + return ImageFormats.PBM; + } else if (compareBytePair(MAGIC_NUMBERS_PBM_B, bytePair)) { + canThrow = true; + return ImageFormats.PBM; + } else if (compareBytePair(MAGIC_NUMBERS_PGM_A, bytePair)) { + canThrow = true; + return ImageFormats.PGM; + } else if (compareBytePair(MAGIC_NUMBERS_PGM_B, bytePair)) { + canThrow = true; + return ImageFormats.PGM; + } else if (compareBytePair(MAGIC_NUMBERS_PPM_A, bytePair)) { + canThrow = true; + return ImageFormats.PPM; + } else if (compareBytePair(MAGIC_NUMBERS_PPM_B, bytePair)) { + canThrow = true; + return ImageFormats.PPM; + } else if (compareBytePair(MAGIC_NUMBERS_JBIG2_1, bytePair)) { + final int i3 = is.read(); + final int i4 = is.read(); + if ((i3 < 0) || (i4 < 0)) { + throw new ImageReadException( + "Couldn't read magic numbers to guess format."); + } + + final int b3 = i3 & 0xff; + final int b4 = i4 & 0xff; + final int[] bytePair2 = { b3, b4, }; + if (compareBytePair(MAGIC_NUMBERS_JBIG2_2, bytePair2)) { + canThrow = true; + return ImageFormats.JBIG2; + } + } else if (compareBytePair(MAGIC_NUMBERS_ICNS, bytePair)) { + canThrow = true; + return ImageFormats.ICNS; + } else if (compareBytePair(MAGIC_NUMBERS_DCX, bytePair)) { + canThrow = true; + return ImageFormats.DCX; + } else if (compareBytePair(MAGIC_NUMBERS_RGBE, bytePair)) { + canThrow = true; + return ImageFormats.RGBE; + } + canThrow = true; + return ImageFormats.UNKNOWN; + } finally { + IoUtils.closeQuietly(canThrow, is); + } + } + + /** + * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and + * TIFF images. + *

+ * + * @param bytes + * Byte array containing an image file. + * @return An instance of ICC_Profile or null if the image contains no ICC + * profile. + */ + public static ICC_Profile getICCProfile(final byte[] bytes) + throws ImageReadException, IOException { + return getICCProfile(bytes, null); + } + + /** + * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and + * TIFF images. + *

+ * + * @param bytes + * Byte array containing an image file. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of ICC_Profile or null if the image contains no ICC + * profile.. + */ + public static ICC_Profile getICCProfile(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getICCProfile(new ByteSourceArray(bytes), params); + } + + /** + * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and + * TIFF images. + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @return An instance of ICC_Profile or null if the image contains no ICC + * profile.. + */ + public static ICC_Profile getICCProfile(final InputStream is, + final String filename) throws ImageReadException, IOException { + return getICCProfile(is, filename, null); + } + + /** + * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and + * TIFF images. + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of ICC_Profile or null if the image contains no ICC + * profile.. + */ + public static ICC_Profile getICCProfile(final InputStream is, + final String filename, final Map params) + throws ImageReadException, IOException { + return getICCProfile(new ByteSourceInputStream(is, filename), params); + } + + /** + * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and + * TIFF images. + *

+ * + * @param file + * File containing image data. + * @return An instance of ICC_Profile or null if the image contains no ICC + * profile.. + */ + public static ICC_Profile getICCProfile(final File file) + throws ImageReadException, IOException { + return getICCProfile(file, null); + } + + /** + * Extracts an ICC Profile (if present) from JPEG, PNG, PSD (Photoshop) and + * TIFF images. + *

+ * + * @param file + * File containing image data. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of ICC_Profile or null if the image contains no ICC + * profile.. + */ + public static ICC_Profile getICCProfile(final File file, + final Map params) throws ImageReadException, + IOException { + return getICCProfile(new ByteSourceFile(file), params); + } + + protected static ICC_Profile getICCProfile(final ByteSource byteSource, + final Map params) throws ImageReadException, + IOException { + final byte[] bytes = getICCProfileBytes(byteSource, params); + if (bytes == null) { + return null; + } + + final IccProfileParser parser = new IccProfileParser(); + final IccProfileInfo info = parser.getICCProfileInfo(bytes); + if (info == null) { + return null; + } + if (info.issRGB()) { + return null; + } + + return ICC_Profile.getInstance(bytes); + } + + /** + * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD + * (Photoshop) and TIFF images. + *

+ * To parse the result use IccProfileParser or + * ICC_Profile.getInstance(bytes). + *

+ * + * @param bytes + * Byte array containing an image file. + * @return A byte array. + * @see IccProfileParser + * @see ICC_Profile + */ + public static byte[] getICCProfileBytes(final byte[] bytes) + throws ImageReadException, IOException { + return getICCProfileBytes(bytes, null); + } + + /** + * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD + * (Photoshop) and TIFF images. + *

+ * To parse the result use IccProfileParser or + * ICC_Profile.getInstance(bytes). + *

+ * + * @param bytes + * Byte array containing an image file. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return A byte array. + * @see IccProfileParser + * @see ICC_Profile + */ + public static byte[] getICCProfileBytes(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getICCProfileBytes(new ByteSourceArray(bytes), params); + } + + /** + * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD + * (Photoshop) and TIFF images. + *

+ * To parse the result use IccProfileParser or + * ICC_Profile.getInstance(bytes). + *

+ * + * @param file + * File containing image data. + * @return A byte array. + * @see IccProfileParser + * @see ICC_Profile + */ + public static byte[] getICCProfileBytes(final File file) + throws ImageReadException, IOException { + return getICCProfileBytes(file, null); + } + + /** + * Extracts the raw bytes of an ICC Profile (if present) from JPEG, PNG, PSD + * (Photoshop) and TIFF images. + *

+ * To parse the result use IccProfileParser or + * ICC_Profile.getInstance(bytes). + *

+ * + * @param file + * File containing image data. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return A byte array. + * @see IccProfileParser + * @see ICC_Profile + */ + public static byte[] getICCProfileBytes(final File file, + final Map params) throws ImageReadException, + IOException { + return getICCProfileBytes(new ByteSourceFile(file), params); + } + + private static byte[] getICCProfileBytes(final ByteSource byteSource, + final Map params) throws ImageReadException, + IOException { + final ImageParser imageParser = getImageParser(byteSource); + + return imageParser.getICCProfileBytes(byteSource, params); + } + + /** + * Parses the "image info" of an image. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param filename + * String. + * @param bytes + * Byte array containing an image file. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final String filename, + final byte[] bytes, final Map params) + throws ImageReadException, IOException { + return getImageInfo(new ByteSourceArray(filename, bytes), params); + } + + /** + * Parses the "image info" of an image. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param filename + * String. + * @param bytes + * Byte array containing an image file. + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final String filename, + final byte[] bytes) throws ImageReadException, IOException { + return getImageInfo(new ByteSourceArray(filename, bytes), null); + } + + /** + * Parses the "image info" of an image. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final InputStream is, + final String filename) throws ImageReadException, IOException { + return getImageInfo(new ByteSourceInputStream(is, filename), null); + } + + /** + * Parses the "image info" of an image. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final InputStream is, + final String filename, final Map params) + throws ImageReadException, IOException { + return getImageInfo(new ByteSourceInputStream(is, filename), params); + } + + /** + * Parses the "image info" of an image. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param bytes + * Byte array containing an image file. + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final byte[] bytes) + throws ImageReadException, IOException { + return getImageInfo(new ByteSourceArray(bytes), null); + } + + /** + * Parses the "image info" of an image. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param bytes + * Byte array containing an image file. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getImageInfo(new ByteSourceArray(bytes), params); + } + + /** + * Parses the "image info" of an image file. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param file + * File containing image data. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final File file, + final Map params) throws ImageReadException, + IOException { + return getImageInfo(new ByteSourceFile(file), params); + } + + /** + * Parses the "image info" of an image file. + *

+ * "Image info" is a summary of basic information about the image such as: + * width, height, file format, bit depth, color type, etc. + *

+ * Not to be confused with "image metadata." + *

+ * + * @param file + * File containing image data. + * @return An instance of ImageInfo. + * @see ImageInfo + */ + public static ImageInfo getImageInfo(final File file) + throws ImageReadException, IOException { + return getImageInfo(file, null); + } + + private static ImageInfo getImageInfo(final ByteSource byteSource, + final Map params) throws ImageReadException, + IOException { + final ImageParser imageParser = getImageParser(byteSource); + + return imageParser.getImageInfo(byteSource, params); + } + + private static ImageParser getImageParser(final ByteSource byteSource) + throws ImageReadException, IOException { + final ImageFormat format = guessFormat(byteSource); + if (!format.equals(ImageFormats.UNKNOWN)) { + + final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); + + for (final ImageParser imageParser : imageParsers) { + if (imageParser.canAcceptType(format)) { + return imageParser; + } + } + } + + final String filename = byteSource.getFilename(); + if (filename != null) { + final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); + + for (final ImageParser imageParser : imageParsers) { + if (imageParser.canAcceptExtension(filename)) { + return imageParser; + } + } + } + + throw new ImageReadException("Can't parse this format."); + } + + /** + * Determines the width and height of an image. + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @return The width and height of the image. + */ + public static Dimension getImageSize(final InputStream is, + final String filename) throws ImageReadException, IOException { + return getImageSize(is, filename, null); + } + + /** + * Determines the width and height of an image. + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return The width and height of the image. + */ + public static Dimension getImageSize(final InputStream is, + final String filename, final Map params) + throws ImageReadException, IOException { + return getImageSize(new ByteSourceInputStream(is, filename), params); + } + + /** + * Determines the width and height of an image. + *

+ * + * @param bytes + * Byte array containing an image file. + * @return The width and height of the image. + */ + public static Dimension getImageSize(final byte[] bytes) + throws ImageReadException, IOException { + return getImageSize(bytes, null); + } + + /** + * Determines the width and height of an image. + *

+ * + * @param bytes + * Byte array containing an image file. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return The width and height of the image. + */ + public static Dimension getImageSize(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getImageSize(new ByteSourceArray(bytes), params); + } + + /** + * Determines the width and height of an image file. + *

+ * + * @param file + * File containing image data. + * @return The width and height of the image. + */ + public static Dimension getImageSize(final File file) + throws ImageReadException, IOException { + return getImageSize(file, null); + } + + /** + * Determines the width and height of an image file. + *

+ * + * @param file + * File containing image data. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return The width and height of the image. + */ + public static Dimension getImageSize(final File file, + final Map params) throws ImageReadException, + IOException { + return getImageSize(new ByteSourceFile(file), params); + } + + public static Dimension getImageSize(final ByteSource byteSource, + final Map params) throws ImageReadException, + IOException { + final ImageParser imageParser = getImageParser(byteSource); + + return imageParser.getImageSize(byteSource, params); + } + + /** + * Extracts the embedded XML metadata as an XML string. + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @return Xmp Xml as String, if present. Otherwise, returns null. + */ + public static String getXmpXml(final InputStream is, final String filename) + throws ImageReadException, IOException { + return getXmpXml(is, filename, null); + } + + /** + * Extracts the embedded XML metadata as an XML string. + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return Xmp Xml as String, if present. Otherwise, returns null. + */ + public static String getXmpXml(final InputStream is, final String filename, + final Map params) throws ImageReadException, + IOException { + return getXmpXml(new ByteSourceInputStream(is, filename), params); + } + + /** + * Extracts the embedded XML metadata as an XML string. + *

+ * + * @param bytes + * Byte array containing an image file. + * @return Xmp Xml as String, if present. Otherwise, returns null. + */ + public static String getXmpXml(final byte[] bytes) + throws ImageReadException, IOException { + return getXmpXml(bytes, null); + } + + /** + * Extracts the embedded XML metadata as an XML string. + *

+ * + * @param bytes + * Byte array containing an image file. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return Xmp Xml as String, if present. Otherwise, returns null. + */ + public static String getXmpXml(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getXmpXml(new ByteSourceArray(bytes), params); + } + + /** + * Extracts the embedded XML metadata as an XML string. + *

+ * + * @param file + * File containing image data. + * @return Xmp Xml as String, if present. Otherwise, returns null. + */ + public static String getXmpXml(final File file) throws ImageReadException, + IOException { + return getXmpXml(file, null); + } + + /** + * Extracts the embedded XML metadata as an XML string. + *

+ * + * @param file + * File containing image data. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return Xmp Xml as String, if present. Otherwise, returns null. + */ + public static String getXmpXml(final File file, + final Map params) throws ImageReadException, + IOException { + return getXmpXml(new ByteSourceFile(file), params); + } + + /** + * Extracts the embedded XML metadata as an XML string. + *

+ * + * @param byteSource + * File containing image data. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return Xmp Xml as String, if present. Otherwise, returns null. + */ + public static String getXmpXml(final ByteSource byteSource, + final Map params) throws ImageReadException, + IOException { + final ImageParser imageParser = getImageParser(byteSource); + + return imageParser.getXmpXml(byteSource, params); + } + + /** + * Parses the metadata of an image. This metadata depends on the format of + * the image. + *

+ * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may + * contain comments. TIFF files may contain metadata. + *

+ * The instance of IImageMetadata returned by getMetadata() should be upcast + * (depending on image format). + *

+ * Not to be confused with "image info." + *

+ * + * @param bytes + * Byte array containing an image file. + * @return An instance of IImageMetadata. + * @see IImageMetadata + */ + public static IImageMetadata getMetadata(final byte[] bytes) + throws ImageReadException, IOException { + return getMetadata(bytes, null); + } + + /** + * Parses the metadata of an image. This metadata depends on the format of + * the image. + *

+ * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may + * contain comments. TIFF files may contain metadata. + *

+ * The instance of IImageMetadata returned by getMetadata() should be upcast + * (depending on image format). + *

+ * Not to be confused with "image info." + *

+ * + * @param bytes + * Byte array containing an image file. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of IImageMetadata. + * @see IImageMetadata + */ + public static IImageMetadata getMetadata(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getMetadata(new ByteSourceArray(bytes), params); + } + + /** + * Parses the metadata of an image file. This metadata depends on the format + * of the image. + *

+ * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may + * contain comments. TIFF files may contain metadata. + *

+ * The instance of IImageMetadata returned by getMetadata() should be upcast + * (depending on image format). + *

+ * Not to be confused with "image info." + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @return An instance of IImageMetadata. + * @see IImageMetadata + */ + public static IImageMetadata getMetadata(final InputStream is, + final String filename) throws ImageReadException, IOException { + return getMetadata(is, filename, null); + } + + /** + * Parses the metadata of an image file. This metadata depends on the format + * of the image. + *

+ * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may + * contain comments. TIFF files may contain metadata. + *

+ * The instance of IImageMetadata returned by getMetadata() should be upcast + * (depending on image format). + *

+ * Not to be confused with "image info." + *

+ * + * @param is + * InputStream from which to read image data. + * @param filename + * Filename associated with image data (optional). + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of IImageMetadata. + * @see IImageMetadata + */ + public static IImageMetadata getMetadata(final InputStream is, + final String filename, final Map params) + throws ImageReadException, IOException { + return getMetadata(new ByteSourceInputStream(is, filename), params); + } + + /** + * Parses the metadata of an image file. This metadata depends on the format + * of the image. + *

+ * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may + * contain comments. TIFF files may contain metadata. + *

+ * The instance of IImageMetadata returned by getMetadata() should be upcast + * (depending on image format). + *

+ * Not to be confused with "image info." + *

+ * + * @param file + * File containing image data. + * @return An instance of IImageMetadata. + * @see IImageMetadata + */ + public static IImageMetadata getMetadata(final File file) + throws ImageReadException, IOException { + return getMetadata(file, null); + } + + /** + * Parses the metadata of an image file. This metadata depends on the format + * of the image. + *

+ * JPEG/JFIF files may contain EXIF and/or IPTC metadata. PNG files may + * contain comments. TIFF files may contain metadata. + *

+ * The instance of IImageMetadata returned by getMetadata() should be upcast + * (depending on image format). + *

+ * Not to be confused with "image info." + *

+ * + * @param file + * File containing image data. + * @param params + * Map of optional parameters, defined in ImagingConstants. + * @return An instance of IImageMetadata. + * @see IImageMetadata + */ + public static IImageMetadata getMetadata(final File file, + final Map params) throws ImageReadException, + IOException { + return getMetadata(new ByteSourceFile(file), params); + } + + private static IImageMetadata getMetadata(final ByteSource byteSource, + final Map params) throws ImageReadException, + IOException { + final ImageParser imageParser = getImageParser(byteSource); + + return imageParser.getMetadata(byteSource, params); + } + + /** + * Write the ImageInfo and format-specific information for the image content + * of the specified byte array to a string. + * + * @param bytes + * A valid array of bytes. + * @return A valid string. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static String dumpImageFile(final byte[] bytes) + throws ImageReadException, IOException { + return dumpImageFile(new ByteSourceArray(bytes)); + } + + /** + * Write the ImageInfo and format-specific information for the image content + * of the specified file to a string. + * + * @param file + * A valid file reference. + * @return A valid string. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static String dumpImageFile(final File file) + throws ImageReadException, IOException { + return dumpImageFile(new ByteSourceFile(file)); + } + + private static String dumpImageFile(final ByteSource byteSource) + throws ImageReadException, IOException { + final ImageParser imageParser = getImageParser(byteSource); + + return imageParser.dumpImageFile(byteSource); + } + + /** + * Attempts to determine the image format of the specified data and + * evaluates its format compliance. This method returns a FormatCompliance + * object which includes information about the data's compliance to a + * specific format. + * + * @param bytes + * a valid array of bytes containing image data. + * @return if successful, a valid FormatCompliance object. + * @throws ImageReadException + * in the event of unreadable data. + * @throws IOException + * in the event of an unrecoverable I/O condition. + */ + public static FormatCompliance getFormatCompliance(final byte[] bytes) + throws ImageReadException, IOException { + return getFormatCompliance(new ByteSourceArray(bytes)); + } + + /** + * Attempts to determine the image format of the specified data and + * evaluates its format compliance. This method returns a FormatCompliance + * object which includes information about the data's compliance to a + * specific format. + * + * @param file + * valid file containing image data + * @return if successful, a valid FormatCompliance object. + * @throws ImageReadException + * in the event of unreadable data. + * @throws IOException + * in the event of an unrecoverable I/O condition. + */ + public static FormatCompliance getFormatCompliance(final File file) + throws ImageReadException, IOException { + return getFormatCompliance(new ByteSourceFile(file)); + } + + private static FormatCompliance getFormatCompliance( + final ByteSource byteSource) throws ImageReadException, IOException { + final ImageParser imageParser = getImageParser(byteSource); + + return imageParser.getFormatCompliance(byteSource); + } + + /** + * Gets all images specified by the InputStream (some formats may include + * multiple images within a single data source). + * + * @param is + * A valid InputStream + * @param filename + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static List getAllBufferedImages( + final InputStream is, final String filename) + throws ImageReadException, IOException { + return getAllBufferedImages(new ByteSourceInputStream(is, filename), + null); + } + + /** + * Gets all images specified by the InputStream (some formats may include + * multiple images within a single data source). + * + * @param is + * A valid InputStream + * @param filename + * @param params + * an optional parameters map specifying options. + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static List getAllBufferedImages( + final InputStream is, final String filename, + final Map params) throws ImageReadException, + IOException { + return getAllBufferedImages(new ByteSourceInputStream(is, filename), + params); + } + + /** + * Gets all images specified by the byte array (some formats may include + * multiple images within a single data source). + * + * @param bytes + * a valid array of bytes + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static List getAllBufferedImages(final byte[] bytes) + throws ImageReadException, IOException { + return getAllBufferedImages(new ByteSourceArray(bytes), null); + } + + /** + * Gets all images specified by the byte array (some formats may include + * multiple images within a single data source). + * + * @param bytes + * a valid array of bytes + * @param params + * an optional parameters map specifying options. + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static List getAllBufferedImages(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getAllBufferedImages(new ByteSourceArray(bytes), params); + } + + /** + * Gets all images specified by the file (some formats may include multiple + * images within a single data source). + * + * @param file + * A reference to a valid data file. + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static List getAllBufferedImages(final File file) + throws ImageReadException, IOException { + return getAllBufferedImages(new ByteSourceFile(file), null); + } + + /** + * Gets all images specified by the file (some formats may include multiple + * images within a single data source). + * + * @param file + * A reference to a valid data file. + * @param params + * an optional parameters map specifying options. + * @return A valid (potentially empty) list of BufferedImage objects. + * @throws ImageReadException + * In the event that the the specified content does not conform + * to the format of the specific parser implementation. + * @throws IOException + * In the event of unsuccessful read or access operation. + */ + public static List getAllBufferedImages(final File file, + final Map params) throws ImageReadException, + IOException { + return getAllBufferedImages(new ByteSourceFile(file), params); + } + + private static List getAllBufferedImages( + final ByteSource byteSource, Map params) + throws ImageReadException, IOException { + final ImageParser imageParser = getImageParser(byteSource); + if (null == params) { + params = new HashMap(); + } + + return imageParser.getAllBufferedImages(byteSource, params); + } + + /** + * Reads the first image from an InputStream. + *

+ * For the most recent information on support for specific formats, refer to + * Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param is + * a valid ImageStream from which to read data. + * @return if successful, a valid buffered image + * @throws ImageReadException + * in the event of a processing error while reading an image + * (i.e. a format violation, etc.). + * @throws IOException + * in the event of an unrecoverable I/O exception. + */ + + public static BufferedImage getBufferedImage(final InputStream is) + throws ImageReadException, IOException { + return getBufferedImage(is, null); + } + + /** + * Reads the first image from an InputStream using data-processing options + * specified through a parameters map. Options may be configured using the + * ImagingContants interface or the various format-specific implementations + * provided by this package. + *

+ * For the most recent information on support for specific formats, refer to + * Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param is + * a valid ImageStream from which to read data. + * @param params + * an optional parameters map specifying options + * @return if successful, a valid buffered image + * @throws ImageReadException + * in the event of a processing error while reading an image + * (i.e. a format violation, etc.). + * @throws IOException + * in the event of an unrecoverable I/O exception. + */ + public static BufferedImage getBufferedImage(final InputStream is, + final Map params) throws ImageReadException, + IOException { + String filename = null; + if (params != null && params.containsKey(PARAM_KEY_FILENAME)) { + filename = (String) params.get(PARAM_KEY_FILENAME); + } + return getBufferedImage(new ByteSourceInputStream(is, filename), params); + } + + /** + * Reads the first image from a byte array. + *

+ * For the most recent information on support for specific formats, refer to + * Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param bytes + * a valid array of bytes from which to read data. + * @return if successful, a valid buffered image + * @throws ImageReadException + * in the event of a processing error while reading an image + * (i.e. a format violation, etc.). + * @throws IOException + * in the event of an unrecoverable I/O exception. + */ + public static BufferedImage getBufferedImage(final byte[] bytes) + throws ImageReadException, IOException { + return getBufferedImage(new ByteSourceArray(bytes), null); + } + + /** + * Reads the first image from a byte array using data-processing options + * specified through a parameters map. Options may be configured using the + * ImagingContants interface or the various format-specific implementations + * provided by this package. + *

+ * For the most recent information on support for specific formats, refer to + * Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param bytes + * a valid array of bytes from which to read data. + * @param params + * an optional parameters map specifying options. + * @return if successful, a valid buffered image + * @throws ImageReadException + * in the event of a processing error while reading an image + * (i.e. a format violation, etc.). + * @throws IOException + * in the event of an unrecoverable I/O exception. + */ + public static BufferedImage getBufferedImage(final byte[] bytes, + final Map params) throws ImageReadException, + IOException { + return getBufferedImage(new ByteSourceArray(bytes), params); + } + + /** + * Reads the first image from a file. + *

+ * For the most recent information on support for specific formats, refer to + * Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param file + * a valid reference to a file containing image data. + * @return if successful, a valid buffered image + * @throws ImageReadException + * in the event of a processing error while reading an image + * (i.e. a format violation, etc.). + * @throws IOException + * in the event of an unrecoverable I/O exception. + */ + public static BufferedImage getBufferedImage(final File file) + throws ImageReadException, IOException { + return getBufferedImage(new ByteSourceFile(file), null); + } + + /** + * Reads the first image from a file using data-processing options specified + * through a parameters map. Options may be configured using the + * ImagingContants interface or the various format-specific implementations + * provided by this package. + *

+ * For the most recent information on support for specific formats, refer to + * Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param file + * a valid reference to a file containing image data. + * @return if successful, a valid buffered image + * @throws ImageReadException + * in the event of a processing error while reading an image + * (i.e. a format violation, etc.). + * @throws IOException + * in the event of an unrecoverable I/O exception. + */ + public static BufferedImage getBufferedImage(final File file, + final Map params) throws ImageReadException, + IOException { + return getBufferedImage(new ByteSourceFile(file), params); + } + + private static BufferedImage getBufferedImage(final ByteSource byteSource, + Map params) throws ImageReadException, IOException { + final ImageParser imageParser = getImageParser(byteSource); + if (null == params) { + params = new HashMap(); + } + + return imageParser.getBufferedImage(byteSource, params); + } + + /** + * Writes the content of a BufferedImage to a file using the specified image + * format. Specifications for storing the file (such as data compression, + * color models, metadata tags, etc.) may be specified using an optional + * parameters map. These specifications are defined in the ImagingConstants + * interface or in various format-specific implementations. + *

+ * Image writing is not supported for all graphics formats. For the most + * recent information on support for specific formats, refer to Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param src + * a valid BufferedImage object + * @param file + * the file to which the output image is to be written + * @param format + * the format in which the output image is to be written + * @param params + * an optional parameters map (nulls permitted) + * @throws ImageWriteException + * in the event of a format violation, unsupported image format, + * etc. + * @throws IOException + * in the event of an unrecoverable I/O exception. + * @see ImagingConstants + */ + public static void writeImage(final BufferedImage src, final File file, + final ImageFormat format, final Map params) + throws ImageWriteException, IOException { + OutputStream os = null; + boolean canThrow = false; + try { + os = new FileOutputStream(file); + os = new BufferedOutputStream(os); + + writeImage(src, os, format, params); + canThrow = true; + } finally { + IoUtils.closeQuietly(canThrow, os); + } + } + + /** + * Writes the content of a BufferedImage to a byte array using the specified + * image format. Specifications for storing the file (such as data + * compression, color models, metadata tags, etc.) may be specified using an + * optional parameters map. These specifications are defined in the + * ImagingConstants interface or in various format-specific implementations. + *

+ * Image writing is not supported for all graphics formats. For the most + * recent information on support for specific formats, refer to Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param src + * a valid BufferedImage object + * @param format + * the format in which the output image is to be written + * @param params + * an optional parameters map (nulls permitted) + * @return if successful, a valid array of bytes. + * @throws ImageWriteException + * in the event of a format violation, unsupported image format, + * etc. + * @throws IOException + * in the event of an unrecoverable I/O exception. + * @see ImagingConstants + */ + public static byte[] writeImageToBytes(final BufferedImage src, + final ImageFormat format, final Map params) + throws ImageWriteException, IOException { + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + + writeImage(src, os, format, params); + + return os.toByteArray(); + } + + /** + * Writes the content of a BufferedImage to an OutputStream using the + * specified image format. Specifications for storing the file (such as data + * compression, color models, metadata tags, etc.) may be specified using an + * optional parameters map. These specifications are defined in the + * ImagingConstants interface or in various format-specific implementations. + *

+ * Image writing is not supported for all graphics formats. For the most + * recent information on support for specific formats, refer to Format + * Support at the main project development web site. While the Apache + * Commons Imaging package does not fully support all formats, it can read + * image info, metadata and ICC profiles from all image formats that provide + * this data. + * + * @param src + * a valid BufferedImage object + * @param os + * the OutputStream to which the output image is to be written + * @param format + * the format in which the output image is to be written + * @param params + * an optional parameters map (nulls permitted) + * @throws ImageWriteException + * in the event of a format violation, unsupported image format, + * etc. + * @throws IOException + * in the event of an unrecoverable I/O exception. + * @see ImagingConstants + */ + public static void writeImage(final BufferedImage src, + final OutputStream os, final ImageFormat format, + Map params) throws ImageWriteException, IOException { + final ImageParser[] imageParsers = ImageParser.getAllImageParsers(); + + // make sure params are non-null + if (params == null) { + params = new HashMap(); + } + + params.put(PARAM_KEY_FORMAT, format); + + ImageParser imageParser = null; + for (final ImageParser imageParser2 : imageParsers) { + if (imageParser2.canAcceptType(format)) { + imageParser = imageParser2; + break; + } + } + if (imageParser != null) { + imageParser.writeImage(src, os, params); + } else { + throw new ImageWriteException("Unknown Format: " + format); + } + } } diff --git a/src/main/java/org/apache/commons/imaging/formats/dcx/DcxImageParser.java b/src/main/java/org/apache/commons/imaging/formats/dcx/DcxImageParser.java index 3f62baf67..8fe9b8dc6 100644 --- a/src/main/java/org/apache/commons/imaging/formats/dcx/DcxImageParser.java +++ b/src/main/java/org/apache/commons/imaging/formats/dcx/DcxImageParser.java @@ -250,6 +250,14 @@ public void writeImage(final BufferedImage src, final OutputStream os, Map srcs, + final OutputStream os, final Map params) + throws ImageWriteException, IOException { + // TODO it should be implemented + super.writeImages(srcs, os, params); + } /** * Extracts embedded XML metadata as XML string. diff --git a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java index 184c370af..497c2ecc4 100644 --- a/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java +++ b/src/main/java/org/apache/commons/imaging/formats/icns/IcnsImageParser.java @@ -283,7 +283,25 @@ public List getAllBufferedImages(final ByteSource byteSource) return IcnsDecoder.decodeAllImages(icnsContents.icnsElements); } - @Override + private IcnsType getIcnsTypeFromBufferedImage(BufferedImage src) throws ImageWriteException { + IcnsType imageType; + if (src.getWidth() == 16 && src.getHeight() == 16) { + imageType = IcnsType.ICNS_16x16_32BIT_IMAGE; + } else if (src.getWidth() == 32 && src.getHeight() == 32) { + imageType = IcnsType.ICNS_32x32_32BIT_IMAGE; + } else if (src.getWidth() == 48 && src.getHeight() == 48) { + imageType = IcnsType.ICNS_48x48_32BIT_IMAGE; + } else if (src.getWidth() == 128 && src.getHeight() == 128) { + imageType = IcnsType.ICNS_128x128_32BIT_IMAGE; + } else { + throw new ImageWriteException("Invalid/unsupported source width " + + src.getWidth() + " and height " + src.getHeight()); + } + return imageType; + } + + @SuppressWarnings("resource") + @Override public void writeImage(final BufferedImage src, final OutputStream os, Map params) throws ImageWriteException, IOException { // make copy of params; we'll clear keys as we consume them. @@ -299,19 +317,7 @@ public void writeImage(final BufferedImage src, final OutputStream os, Map srcs, + final OutputStream os, Map params) + throws ImageWriteException, IOException { + if (!srcs.isEmpty()) { + if (srcs.size() == 1) { + writeImage(srcs.get(0), os, params); + } else { + // make copy of params; we'll clear keys as we consume them. + params = (params == null) ? new HashMap() : new HashMap(params); + + // clear format key. + if (params.containsKey(PARAM_KEY_FORMAT)) { + params.remove(PARAM_KEY_FORMAT); + } + + if (!params.isEmpty()) { + final Object firstKey = params.keySet().iterator().next(); + throw new ImageWriteException("Unknown parameter: " + firstKey); + } + + List imageTypeList = new ArrayList(); + List lengthOfIconsDataList = new ArrayList(); + int lengthOfFile = 4 + 4;// magic literal + length of file + for (BufferedImage src : srcs) { + IcnsType imageType = getIcnsTypeFromBufferedImage(src); + imageTypeList.add(imageType); + int lengthOfIconData = 4 + 4 + 4 * imageType.getWidth() + * imageType.getHeight();// icon type + length of data + icon data + int lengthOfMaskData = 4 + 4 + imageType.getWidth() + * imageType.getHeight();// icon type + length of data + "mask" data + lengthOfFile += lengthOfIconData + lengthOfMaskData; + lengthOfIconsDataList.add(new int[]{lengthOfIconData, lengthOfMaskData}); + } + final BinaryOutputStream bos = new BinaryOutputStream(os, + ByteOrder.BIG_ENDIAN); + bos.write4Bytes(ICNS_MAGIC); + bos.write4Bytes(lengthOfFile); + int srcIndex = 0; + for (BufferedImage src : srcs) { + IcnsType imageType = imageTypeList.get(srcIndex); + bos.write4Bytes(imageType.getType()); + int lengthOfIconData = lengthOfIconsDataList.get(srcIndex)[0]; + bos.write4Bytes(lengthOfIconData); + for (int y = 0; y < src.getHeight(); y++) { + for (int x = 0; x < src.getWidth(); x++) { + final int argb = src.getRGB(x, y); + bos.write(0); + bos.write(argb >> 16); + bos.write(argb >> 8); + bos.write(argb); + } + } + + final IcnsType maskType = IcnsType.find8BPPMaskType(imageType); + bos.write4Bytes(maskType.getType()); + int lengthOfMaskData = lengthOfIconsDataList.get(srcIndex)[1]; + bos.write4Bytes(lengthOfMaskData); + for (int y = 0; y < src.getHeight(); y++) { + for (int x = 0; x < src.getWidth(); x++) { + final int argb = src.getRGB(x, y); + bos.write(argb >> 24); + } + } + + srcIndex++; + } + } + } + } /** * Extracts embedded XML metadata as XML string. diff --git a/src/main/java/org/apache/commons/imaging/formats/ico/IcoImageParser.java b/src/main/java/org/apache/commons/imaging/formats/ico/IcoImageParser.java index 068cde970..4d1c8d015 100644 --- a/src/main/java/org/apache/commons/imaging/formats/ico/IcoImageParser.java +++ b/src/main/java/org/apache/commons/imaging/formats/ico/IcoImageParser.java @@ -811,6 +811,14 @@ public void writeImage(final BufferedImage src, final OutputStream os, Map srcs, + final OutputStream os, final Map params) + throws ImageWriteException, IOException { + // TODO it should be implemented + super.writeImages(srcs, os, params); + } /** * Extracts embedded XML metadata as XML string. diff --git a/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java b/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java index 0dec3489b..5f5ac78c8 100644 --- a/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java +++ b/src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java @@ -733,5 +733,13 @@ public void writeImage(final BufferedImage src, final OutputStream os, final Map throws ImageWriteException, IOException { new TiffImageWriterLossy().writeImage(src, os, params); } + + @Override + public void writeImages(final List srcs, + final OutputStream os, final Map params) + throws ImageWriteException, IOException { + // TODO it should be implemented + super.writeImages(srcs, os, params); + } } diff --git a/src/main/resources/org/apache/commons/imaging/antlib.xml b/src/main/resources/org/apache/commons/imaging/antlib.xml new file mode 100644 index 000000000..42f257379 --- /dev/null +++ b/src/main/resources/org/apache/commons/imaging/antlib.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file