Skip to content
Browse files

Merge of Temp_URI_Resolution

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/commons/trunk@1391005 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
2 parents d9882ed + 2c82d01 commit ff86e56dcebd045b512ddace7805e3d792d3f694 Mehdi Houshmand committed
Showing with 2,229 additions and 669 deletions.
  1. +202 −0 lib/build/resolver.LICENSE.txt
  2. +16 −0 lib/build/resolver.NOTICE.txt
  3. BIN lib/build/resolver.jar
  4. +84 −0 src/java/org/apache/xmlgraphics/image/codec/tiff/CompressionValue.java
  5. +43 −0 src/java/org/apache/xmlgraphics/image/codec/tiff/ExtraSamplesType.java
  6. +213 −0 src/java/org/apache/xmlgraphics/image/codec/tiff/ImageInfo.java
  7. +103 −0 src/java/org/apache/xmlgraphics/image/codec/tiff/ImageType.java
  8. +8 −60 src/java/org/apache/xmlgraphics/image/codec/tiff/TIFFEncodeParam.java
  9. +2 −4 src/java/org/apache/xmlgraphics/image/codec/tiff/TIFFImageDecoder.java
  10. +119 −337 src/java/org/apache/xmlgraphics/image/codec/tiff/TIFFImageEncoder.java
  11. +4 −3 src/java/org/apache/xmlgraphics/image/loader/ImageManager.java
  12. +188 −118 src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageSessionContext.java
  13. +3 −3 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderEPS.java
  14. +2 −2 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRaw.java
  15. +3 −2 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawCCITTFax.java
  16. +2 −1 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawJPEG.java
  17. +0 −15 src/java/org/apache/xmlgraphics/image/loader/impl/ImageRawStream.java
  18. +2 −1 src/java/org/apache/xmlgraphics/image/loader/impl/imageio/ImageLoaderImageIO.java
  19. +15 −107 src/java/org/apache/xmlgraphics/image/loader/util/ImageUtil.java
  20. +3 −14 src/java/org/apache/xmlgraphics/image/writer/internal/TIFFImageWriter.java
  21. +57 −0 src/java/org/apache/xmlgraphics/io/Resource.java
  22. +51 −0 src/java/org/apache/xmlgraphics/io/ResourceResolver.java
  23. +48 −0 src/java/org/apache/xmlgraphics/io/TempResourceResolver.java
  24. +57 −0 src/java/org/apache/xmlgraphics/io/TempResourceURIGenerator.java
  25. +70 −0 src/java/org/apache/xmlgraphics/io/URIResolverAdapter.java
  26. +167 −0 src/java/org/apache/xmlgraphics/io/XmlSourceUtil.java
  27. +188 −0 test/java/org/apache/xmlgraphics/image/codec/tiff/ImageInfoTestCase.java
  28. +122 −0 test/java/org/apache/xmlgraphics/image/codec/tiff/ImageTypeTestCase.java
  29. +63 −0 test/java/org/apache/xmlgraphics/image/codec/tiff/TIFFImageEncoderTestCase.java
  30. BIN test/java/org/apache/xmlgraphics/image/codec/tiff/bilevel.tiff
  31. BIN test/java/org/apache/xmlgraphics/image/codec/tiff/gray.tiff
  32. +3 −2 test/java/org/apache/xmlgraphics/image/loader/ImageSessionContextTestCase.java
  33. +68 −0 test/java/org/apache/xmlgraphics/io/TempResourceURIGeneratorTestCase.java
  34. +80 −0 test/java/org/apache/xmlgraphics/io/URIResolverAdapterTestCase.java
  35. +237 −0 test/java/org/apache/xmlgraphics/io/XmlSourceUtilTestCase.java
  36. +5 −0 test/resources/org/apache/xmlgraphics/io/test-catalog.xml
  37. +1 −0 test/resources/org/apache/xmlgraphics/io/testResource.txt
View
202 lib/build/resolver.LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
View
16 lib/build/resolver.NOTICE.txt
@@ -0,0 +1,16 @@
+ =========================================================================
+ == NOTICE file corresponding to section 4(d) of the Apache License, ==
+ == Version 2.0, in this case for the Apache xml-commons xml-apis ==
+ == distribution. ==
+ =========================================================================
+
+ Apache XML Commons
+ Copyright 2001-2003,2006 The Apache Software Foundation.
+
+ This product includes software developed at
+ The Apache Software Foundation (http://www.apache.org/).
+
+ Portions of this software were originally based on the following:
+ - software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
+ - software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
+ - software copyright (c) 2000 World Wide Web Consortium, http://www.w3.org
View
BIN lib/build/resolver.jar
Binary file not shown.
View
84 src/java/org/apache/xmlgraphics/image/codec/tiff/CompressionValue.java
@@ -0,0 +1,84 @@
+/*
+ * 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.xmlgraphics.image.codec.tiff;
+
+
+/** Enumerates the possible compression values for TIFF images. */
+public enum CompressionValue {
+ /** No compression. */
+ NONE(1),
+ /**
+ * Modified Huffman Compression (CCITT Group 3 1D facsimile compression).
+ * <p><b>Not currently supported.</b>
+ */
+ GROUP3_1D(2),
+ /**
+ * CCITT T.4 bilevel compression (CCITT Group 3 2D facsimile compression).
+ * <p><b>Not currently supported.</b>
+ */
+ GROUP3_2D(3),
+ /**
+ * CCITT T.6 bilevel compression (CCITT Group 4 facsimile compression).
+ * <p><b>Not currently supported.</b>
+ */
+ GROUP4(4),
+ /** LZW compression. <p><b>Not supported.</b> */
+ LZW(5),
+ /**
+ * Code for original JPEG-in-TIFF compression which has been depricated (for many good reasons)
+ * in favor of Tech Note 2 JPEG compression (compression scheme 7).
+ * <p><b>Not supported.</b>
+ */
+ JPEG_BROKEN(6),
+ /** <a href="ftp://ftp.sgi.com/graphics/tiff/TTN2.draft.txt"> JPEG-in-TIFF</a> compression. */
+ JPEG_TTN2(7),
+ /** Byte-oriented run-length encoding "PackBits" compression. */
+ PACKBITS(32773),
+ /**
+ * <a href="http://info.internet.isi.edu:80/in-notes/rfc/files/rfc1951.txt">
+ * DEFLATE</a> lossless compression (also known as "Zip-in-TIFF").
+ */
+ DEFLATE(32946);
+
+ private final int compressionValue;
+
+ private CompressionValue(int compressionValue) {
+ this.compressionValue = compressionValue;
+ }
+
+ int getValue() {
+ return compressionValue;
+ }
+
+ /**
+ * Gets the compression value given the name of the compression type.
+ * @param name the compression name
+ * @return the compression value
+ */
+ public static CompressionValue getValue(String name) {
+ if (name == null) {
+ return PACKBITS;
+ }
+ for (CompressionValue cv : CompressionValue.values()) {
+ if (cv.toString().equalsIgnoreCase(name)) {
+ return cv;
+ }
+ }
+ throw new IllegalArgumentException("Unknown compression value: " + name);
+ }
+}
View
43 src/java/org/apache/xmlgraphics/image/codec/tiff/ExtraSamplesType.java
@@ -0,0 +1,43 @@
+/*
+ * 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.xmlgraphics.image.codec.tiff;
+
+import java.awt.image.ColorModel;
+
+enum ExtraSamplesType {
+ UNSPECIFIED(0),
+ ASSOCIATED_ALPHA(1),
+ UNASSOCIATED_ALPHA(2);
+
+ private final int typeValue;
+
+ private ExtraSamplesType(int value) {
+ this.typeValue = value;
+ }
+
+ static ExtraSamplesType getValue(ColorModel colorModel, int numExtraSamples) {
+ if (numExtraSamples == 1 && colorModel.hasAlpha()) {
+ return colorModel.isAlphaPremultiplied() ? ASSOCIATED_ALPHA : UNASSOCIATED_ALPHA;
+ }
+ return UNSPECIFIED;
+ }
+
+ int getValue() {
+ return typeValue;
+ }
+}
View
213 src/java/org/apache/xmlgraphics/image/codec/tiff/ImageInfo.java
@@ -0,0 +1,213 @@
+/*
+ * 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.xmlgraphics.image.codec.tiff;
+
+import java.awt.color.ColorSpace;
+import java.awt.image.ColorModel;
+import java.awt.image.IndexColorModel;
+import java.awt.image.RenderedImage;
+
+final class ImageInfo {
+
+ // Default values
+ private static final int DEFAULT_ROWS_PER_STRIP = 8;
+
+ private final int numExtraSamples;
+ private final ExtraSamplesType extraSampleType;
+ private final ImageType imageType;
+ private final int colormapSize;
+ private final char[] colormap;
+ private final int tileWidth;
+ private final int tileHeight;
+ private final int numTiles;
+ private final long bytesPerRow;
+ private final long bytesPerTile;
+
+ private ImageInfo(ImageInfoBuilder builder) {
+ this.numExtraSamples = builder.numExtraSamples;
+ this.extraSampleType = builder.extraSampleType;
+ this.imageType = builder.imageType;
+ this.colormapSize = builder.colormapSize;
+ this.colormap = copyColormap(builder.colormap);
+ this.tileWidth = builder.tileWidth;
+ this.tileHeight = builder.tileHeight;
+ this.numTiles = builder.numTiles;
+ this.bytesPerRow = builder.bytesPerRow;
+ this.bytesPerTile = builder.bytesPerTile;
+ }
+
+ private static char[] copyColormap(char[] colorMap) {
+ if (colorMap == null) {
+ return null;
+ }
+ char[] copy = new char[colorMap.length];
+ System.arraycopy(colorMap, 0, copy, 0, colorMap.length);
+ return copy;
+ }
+
+ private static int getNumberOfExtraSamplesForColorSpace(ColorSpace colorSpace,
+ ImageType imageType, int numBands) {
+ if (imageType == ImageType.GENERIC) {
+ return numBands - 1;
+ } else if (numBands > 1) {
+ return numBands - colorSpace.getNumComponents();
+ } else {
+ return 0;
+ }
+ }
+
+ private static char[] createColormap(final int sizeOfColormap, byte[] r, byte[] g, byte[] b) {
+ int redIndex = 0;
+ int greenIndex = sizeOfColormap;
+ int blueIndex = 2 * sizeOfColormap;
+ char[] colormap = new char[sizeOfColormap * 3];
+ for (int i = 0; i < sizeOfColormap; i++) {
+ // beware of sign extended bytes
+ colormap[redIndex++] = convertColorToColormapChar(0xff & r[i]);
+ colormap[greenIndex++] = convertColorToColormapChar(0xff & g[i]);
+ colormap[blueIndex++] = convertColorToColormapChar(0xff & b[i]);
+ }
+ return colormap;
+ }
+
+ private static char convertColorToColormapChar(int color) {
+ return (char) (color << 8 | color);
+ }
+
+ int getNumberOfExtraSamples() {
+ return numExtraSamples;
+ }
+
+ ExtraSamplesType getExtraSamplesType() {
+ return extraSampleType;
+ }
+
+ ImageType getType() {
+ return imageType;
+ }
+
+ int getColormapSize() {
+ return colormapSize;
+ }
+
+ char[] getColormap() {
+ return copyColormap(colormap);
+ }
+
+ int getTileWidth() {
+ return tileWidth;
+ }
+
+ int getTileHeight() {
+ return tileHeight;
+ }
+
+ int getNumTiles() {
+ return numTiles;
+ }
+
+ long getBytesPerRow() {
+ return bytesPerRow;
+ }
+
+ long getBytesPerTile() {
+ return bytesPerTile;
+ }
+
+ static ImageInfo newInstance(RenderedImage im, int dataTypeSize, int numBands,
+ ColorModel colorModel, TIFFEncodeParam params) {
+ ImageInfoBuilder builder = new ImageInfoBuilder();
+ if (colorModel instanceof IndexColorModel) { // Bilevel or palette
+ IndexColorModel indexColorModel = (IndexColorModel) colorModel;
+ int colormapSize = indexColorModel.getMapSize();
+ byte[] r = new byte[colormapSize];
+ indexColorModel.getReds(r);
+ byte[] g = new byte[colormapSize];
+ indexColorModel.getGreens(g);
+ byte[] b = new byte[colormapSize];
+ indexColorModel.getBlues(b);
+
+ builder.imageType = ImageType.getTypeFromRGB(colormapSize, r, g, b, dataTypeSize,
+ numBands);
+ if (builder.imageType == ImageType.PALETTE) {
+ builder.colormap = createColormap(colormapSize, r, g, b);
+ builder.colormapSize = colormapSize * 3;
+ }
+ } else if (colorModel == null) {
+ if (dataTypeSize == 1 && numBands == 1) { // bilevel
+ builder.imageType = ImageType.BILEVEL_BLACK_IS_ZERO;
+ } else {
+ builder.imageType = ImageType.GENERIC;
+ builder.numExtraSamples = numBands > 1 ? numBands - 1 : 0;
+ }
+ } else {
+ ColorSpace colorSpace = colorModel.getColorSpace();
+ builder.imageType = ImageType.getTypeFromColorSpace(colorSpace, params);
+ builder.numExtraSamples = getNumberOfExtraSamplesForColorSpace(colorSpace,
+ builder.imageType, numBands);
+ builder.extraSampleType = ExtraSamplesType.getValue(colorModel,
+ builder.numExtraSamples);
+ }
+
+ // Initialize tile dimensions.
+ final int width = im.getWidth();
+ final int height = im.getHeight();
+ if (params.getWriteTiled()) {
+ builder.tileWidth = params.getTileWidth() > 0 ? params.getTileWidth() : width;
+ builder.tileHeight = params.getTileHeight() > 0 ? params.getTileHeight() : height;
+ // NB: Parentheses are used in this statement for correct rounding.
+ builder.numTiles = ((width + builder.tileWidth - 1) / builder.tileWidth)
+ * ((height + builder.tileHeight - 1) / builder.tileHeight);
+ } else {
+ builder.tileWidth = width;
+ builder.tileHeight = params.getTileHeight() > 0 ? params.getTileHeight()
+ : DEFAULT_ROWS_PER_STRIP;
+ builder.numTiles = (int) Math.ceil(height / (double) builder.tileHeight);
+ }
+ builder.setBytesPerRow(dataTypeSize, numBands)
+ .setBytesPerTile();
+ return builder.build();
+ }
+
+ private static final class ImageInfoBuilder {
+ private ImageType imageType = ImageType.UNSUPPORTED;
+ private int numExtraSamples;
+ private char[] colormap;
+ private int colormapSize;
+ private ExtraSamplesType extraSampleType = ExtraSamplesType.UNSPECIFIED;
+ private int tileWidth;
+ private int tileHeight;
+ private int numTiles;
+ private long bytesPerRow;
+ private long bytesPerTile;
+
+ private ImageInfoBuilder setBytesPerRow(int dataTypeSize, int numBands) {
+ bytesPerRow = (long) Math.ceil((dataTypeSize / 8.0) * tileWidth * numBands);
+ return this;
+ }
+
+ private ImageInfoBuilder setBytesPerTile() {
+ bytesPerTile = bytesPerRow * tileHeight;
+ return this;
+ }
+
+ private ImageInfo build() {
+ return new ImageInfo(this);
+ }
+ }
+}
View
103 src/java/org/apache/xmlgraphics/image/codec/tiff/ImageType.java
@@ -0,0 +1,103 @@
+/*
+ * 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.xmlgraphics.image.codec.tiff;
+
+import java.awt.color.ColorSpace;
+
+import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
+
+enum ImageType {
+ UNSUPPORTED(-1),
+ BILEVEL_WHITE_IS_ZERO(0),
+ BILEVEL_BLACK_IS_ZERO(1),
+ GRAY(1),
+ PALETTE(3),
+ RGB(2),
+ CMYK(5),
+ YCBCR(6),
+ CIELAB(8),
+ GENERIC(1);
+
+ private final int photometricInterpretation;
+
+ private ImageType(int photometricInterpretation) {
+ this.photometricInterpretation = photometricInterpretation;
+ }
+
+ int getPhotometricInterpretation() {
+ return photometricInterpretation;
+ }
+
+ static ImageType getTypeFromRGB(int mapSize, byte[] r, byte[] g, byte[] b,
+ int dataTypeSize, int numBands) {
+ if (numBands == 1) {
+ if (dataTypeSize == 1) { // Bilevel image
+ if (mapSize != 2) {
+ throw new IllegalArgumentException(PropertyUtil.getString("TIFFImageEncoder7"));
+ }
+
+ if (isBlackZero(r, g, b)) {
+ return BILEVEL_BLACK_IS_ZERO;
+ } else if (isWhiteZero(r, g, b)) {
+ return BILEVEL_WHITE_IS_ZERO;
+ }
+ }
+ return PALETTE;
+ }
+ return UNSUPPORTED;
+ }
+
+ private static boolean rgbIsValueAt(byte[] r, byte[] g, byte[] b, byte value, int i) {
+ return r[i] == value && g[i] == value && b[i] == value;
+ }
+
+ private static boolean bilevelColorValue(byte[] r, byte[] g, byte[] b, int blackValue,
+ int whiteValue) {
+ return rgbIsValueAt(r, g, b, (byte) blackValue, 0)
+ && rgbIsValueAt(r, g, b, (byte) whiteValue, 1);
+ }
+
+ private static boolean isBlackZero(byte[] r, byte[] g, byte[] b) {
+ return bilevelColorValue(r, g, b, 0, 0xff);
+ }
+
+ private static boolean isWhiteZero(byte[] r, byte[] g, byte[] b) {
+ return bilevelColorValue(r, g, b, 0xff, 0);
+ }
+
+ static ImageType getTypeFromColorSpace(ColorSpace colorSpace, TIFFEncodeParam params) {
+ switch (colorSpace.getType()) {
+ case ColorSpace.TYPE_CMYK:
+ return CMYK;
+ case ColorSpace.TYPE_GRAY:
+ return GRAY;
+ case ColorSpace.TYPE_Lab:
+ return CIELAB;
+ case ColorSpace.TYPE_RGB:
+ if (params.getJPEGCompressRGBToYCbCr()) {
+ return ImageType.YCBCR;
+ } else {
+ return ImageType.RGB;
+ }
+ case ColorSpace.TYPE_YCbCr:
+ return YCBCR;
+ default:
+ return GENERIC;
+ }
+ }
+}
View
68 src/java/org/apache/xmlgraphics/image/codec/tiff/TIFFEncodeParam.java
@@ -45,59 +45,9 @@
*/
public class TIFFEncodeParam implements ImageEncodeParam {
- /** No compression. */
- public static final int COMPRESSION_NONE = 1;
+ private CompressionValue compression = CompressionValue.NONE;
- /**
- * Modified Huffman Compression (CCITT Group 3 1D facsimile compression).
- * <p><b>Not currently supported.</b>
- */
- public static final int COMPRESSION_GROUP3_1D = 2;
-
- /**
- * CCITT T.4 bilevel compression (CCITT Group 3 2D facsimile compression).
- * <p><b>Not currently supported.</b>
- */
- public static final int COMPRESSION_GROUP3_2D = 3;
-
- /**
- * CCITT T.6 bilevel compression (CCITT Group 4 facsimile compression).
- * <p><b>Not currently supported.</b>
- */
- public static final int COMPRESSION_GROUP4 = 4;
-
- /**
- * LZW compression.
- * <p><b>Not supported.</b>
- */
- public static final int COMPRESSION_LZW = 5;
-
- /**
- * Code for original JPEG-in-TIFF compression which has been
- * depricated (for many good reasons) in favor of Tech Note 2
- * JPEG compression (compression scheme 7).
- * <p><b>Not supported.</b>
- */
- public static final int COMPRESSION_JPEG_BROKEN = 6;
-
- /**
- * <a href="ftp://ftp.sgi.com/graphics/tiff/TTN2.draft.txt">
- * JPEG-in-TIFF</a> compression.
- */
- public static final int COMPRESSION_JPEG_TTN2 = 7;
-
- /** Byte-oriented run-length encoding "PackBits" compression. */
- public static final int COMPRESSION_PACKBITS = 32773;
-
- /**
- * <a href="http://info.internet.isi.edu:80/in-notes/rfc/files/rfc1951.txt">
- * DEFLATE</a> lossless compression (also known as "Zip-in-TIFF").
- */
- public static final int COMPRESSION_DEFLATE = 32946;
-
- private int compression = COMPRESSION_NONE;
-
- private boolean writeTiled = false;
+ private boolean writeTiled;
private int tileWidth;
private int tileHeight;
@@ -117,10 +67,8 @@ public TIFFEncodeParam() {
//nop
}
- /**
- * Returns the value of the compression parameter.
- */
- public int getCompression() {
+ /** Returns the value of the compression parameter. */
+ public CompressionValue getCompression() {
return compression;
}
@@ -141,12 +89,12 @@ public int getCompression() {
*
* @param compression The compression type.
*/
- public void setCompression(int compression) {
+ public void setCompression(CompressionValue compression) {
switch(compression) {
- case COMPRESSION_NONE:
- case COMPRESSION_PACKBITS:
- case COMPRESSION_DEFLATE:
+ case NONE:
+ case PACKBITS:
+ case DEFLATE:
// Do nothing.
break;
default:
View
6 src/java/org/apache/xmlgraphics/image/codec/tiff/TIFFImageDecoder.java
@@ -22,7 +22,6 @@
import java.awt.image.RenderedImage;
import java.io.IOException;
-import org.apache.xmlgraphics.image.codec.util.ImageDecodeParam;
import org.apache.xmlgraphics.image.codec.util.ImageDecoderImpl;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
import org.apache.xmlgraphics.image.codec.util.SeekableStream;
@@ -74,8 +73,7 @@
public static final int TIFF_ICC_PROFILE = 34675;
- public TIFFImageDecoder(SeekableStream input,
- ImageDecodeParam param) {
+ public TIFFImageDecoder(SeekableStream input, TIFFDecodeParam param) {
super(input, param);
}
@@ -87,6 +85,6 @@ public RenderedImage decodeAsRenderedImage(int page) throws IOException {
if ((page < 0) || (page >= getNumPages())) {
throw new IOException(PropertyUtil.getString("TIFFImageDecoder0"));
}
- return new TIFFImage(input, (TIFFDecodeParam)param, page);
+ return new TIFFImage(input, (TIFFDecodeParam) param, page);
}
}
View
456 src/java/org/apache/xmlgraphics/image/codec/tiff/TIFFImageEncoder.java
@@ -20,7 +20,6 @@
package org.apache.xmlgraphics.image.codec.tiff;
import java.awt.Rectangle;
-import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
@@ -61,37 +60,13 @@
*/
public class TIFFImageEncoder extends ImageEncoderImpl {
- // Image Types
- private static final int TIFF_UNSUPPORTED = -1;
- private static final int TIFF_BILEVEL_WHITE_IS_ZERO = 0;
- private static final int TIFF_BILEVEL_BLACK_IS_ZERO = 1;
- private static final int TIFF_GRAY = 2;
- private static final int TIFF_PALETTE = 3;
- private static final int TIFF_RGB = 4;
- private static final int TIFF_CMYK = 5;
- private static final int TIFF_YCBCR = 6;
- private static final int TIFF_CIELAB = 7;
- private static final int TIFF_GENERIC = 8;
-
- // Compression types
- private static final int COMP_NONE = 1;
- private static final int COMP_JPEG_TTN2 = 7;
- private static final int COMP_PACKBITS = 32773;
- private static final int COMP_DEFLATE = 32946;
-
// Incidental tags
private static final int TIFF_JPEG_TABLES = 347;
private static final int TIFF_YCBCR_SUBSAMPLING = 530;
private static final int TIFF_YCBCR_POSITIONING = 531;
private static final int TIFF_REF_BLACK_WHITE = 532;
- // ExtraSamples types
- private static final int EXTRA_SAMPLE_UNSPECIFIED = 0;
- private static final int EXTRA_SAMPLE_ASSOCIATED_ALPHA = 1;
- private static final int EXTRA_SAMPLE_UNASSOCIATED_ALPHA = 2;
- // Default values
- private static final int DEFAULT_ROWS_PER_STRIP = 8;
public TIFFImageEncoder(OutputStream output, ImageEncodeParam param) {
super(output, param);
@@ -197,9 +172,9 @@ public void finishMultiple(Object context) throws IOException {
private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
int ifdOffset, boolean isLast) throws IOException {
// Currently all images are stored uncompressed.
- int compression = encodeParam.getCompression();
+ CompressionValue compression = encodeParam.getCompression();
- if (compression == COMP_JPEG_TTN2) {
+ if (compression == CompressionValue.JPEG_TTN2) {
throw new IllegalArgumentException(PropertyUtil.getString("TIFFImageEncoder12"));
}
@@ -214,263 +189,31 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
// Get SampleModel.
SampleModel sampleModel = im.getSampleModel();
-
- // Retrieve and verify sample size.
+ ColorModel colorModel = im.getColorModel();
int[] sampleSize = sampleModel.getSampleSize();
- for (int i = 1; i < sampleSize.length; i++) {
- if (sampleSize[i] != sampleSize[0]) {
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder0"));
- }
- }
-
- // Check low bit limits.
+ int dataTypeSize = sampleSize[0];
int numBands = sampleModel.getNumBands();
- if ((sampleSize[0] == 1 || sampleSize[0] == 4) && numBands != 1) {
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder1"));
- }
-
- // Retrieve and verify data type.
int dataType = sampleModel.getDataType();
- switch(dataType) {
- case DataBuffer.TYPE_BYTE:
- if (sampleSize[0] != 1 && sampleSize[0] == 4 && // todo does this make sense??
- sampleSize[0] != 8) { // we get error only for 4
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder2"));
- }
- break;
- case DataBuffer.TYPE_SHORT:
- case DataBuffer.TYPE_USHORT:
- if (sampleSize[0] != 16) {
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder3"));
- }
- break;
- case DataBuffer.TYPE_INT:
- case DataBuffer.TYPE_FLOAT:
- if (sampleSize[0] != 32) {
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder4"));
- }
- break;
- default:
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder5"));
- }
+ validateImage(dataTypeSize, sampleSize, numBands, dataType, colorModel);
- boolean dataTypeIsShort =
- dataType == DataBuffer.TYPE_SHORT ||
- dataType == DataBuffer.TYPE_USHORT;
-
- ColorModel colorModel = im.getColorModel();
- if (colorModel != null &&
- colorModel instanceof IndexColorModel &&
- dataType != DataBuffer.TYPE_BYTE) {
- // Don't support (unsigned) short palette-color images.
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder6"));
- }
- IndexColorModel icm = null;
- int sizeOfColormap = 0;
- char[] colormap = null;
+ boolean dataTypeIsShort = dataType == DataBuffer.TYPE_SHORT
+ || dataType == DataBuffer.TYPE_USHORT;
// Set image type.
- int imageType = TIFF_UNSUPPORTED;
- int numExtraSamples = 0;
- int extraSampleType = EXTRA_SAMPLE_UNSPECIFIED;
- if (colorModel instanceof IndexColorModel) { // Bilevel or palette
- icm = (IndexColorModel)colorModel;
- int mapSize = icm.getMapSize();
-
- if (sampleSize[0] == 1 && numBands == 1) { // Bilevel image
-
- if (mapSize != 2) {
- throw new IllegalArgumentException(PropertyUtil.getString("TIFFImageEncoder7"));
- }
-
- byte[] r = new byte[mapSize];
- icm.getReds(r);
- byte[] g = new byte[mapSize];
- icm.getGreens(g);
- byte[] b = new byte[mapSize];
- icm.getBlues(b);
-
- if ((r[0] & 0xff) == 0 &&
- (r[1] & 0xff) == 255 &&
- (g[0] & 0xff) == 0 &&
- (g[1] & 0xff) == 255 &&
- (b[0] & 0xff) == 0 &&
- (b[1] & 0xff) == 255) {
-
- imageType = TIFF_BILEVEL_BLACK_IS_ZERO;
-
- } else if ((r[0] & 0xff) == 255 &&
- (r[1] & 0xff) == 0 &&
- (g[0] & 0xff) == 255 &&
- (g[1] & 0xff) == 0 &&
- (b[0] & 0xff) == 255 &&
- (b[1] & 0xff) == 0) {
-
- imageType = TIFF_BILEVEL_WHITE_IS_ZERO;
-
- } else {
- imageType = TIFF_PALETTE;
- }
-
- } else if (numBands == 1) { // Non-bilevel image.
- // Palette color image.
- imageType = TIFF_PALETTE;
- }
- } else if (colorModel == null) {
-
- if (sampleSize[0] == 1 && numBands == 1) { // bilevel
- imageType = TIFF_BILEVEL_BLACK_IS_ZERO;
- } else { // generic image
- imageType = TIFF_GENERIC;
- if (numBands > 1) {
- numExtraSamples = numBands - 1;
- }
- }
-
- } else { // colorModel is non-null but not an IndexColorModel
- ColorSpace colorSpace = colorModel.getColorSpace();
-
- switch(colorSpace.getType()) {
- case ColorSpace.TYPE_CMYK:
- imageType = TIFF_CMYK;
- break;
- case ColorSpace.TYPE_GRAY:
- imageType = TIFF_GRAY;
- break;
- case ColorSpace.TYPE_Lab:
- imageType = TIFF_CIELAB;
- break;
- case ColorSpace.TYPE_RGB:
- if (compression == COMP_JPEG_TTN2
- && encodeParam.getJPEGCompressRGBToYCbCr()) {
- imageType = TIFF_YCBCR;
- } else {
- imageType = TIFF_RGB;
- }
- break;
- case ColorSpace.TYPE_YCbCr:
- imageType = TIFF_YCBCR;
- break;
- default:
- imageType = TIFF_GENERIC; // generic
- break;
- }
-
- if (imageType == TIFF_GENERIC) {
- numExtraSamples = numBands - 1;
- } else if (numBands > 1) {
- numExtraSamples = numBands - colorSpace.getNumComponents();
- }
-
- if (numExtraSamples == 1 && colorModel.hasAlpha()) {
- extraSampleType = colorModel.isAlphaPremultiplied() ?
- EXTRA_SAMPLE_ASSOCIATED_ALPHA :
- EXTRA_SAMPLE_UNASSOCIATED_ALPHA;
- }
- }
-
- if (imageType == TIFF_UNSUPPORTED) {
- throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder8"));
- }
-
- int photometricInterpretation = -1;
- switch (imageType) {
-
- case TIFF_BILEVEL_WHITE_IS_ZERO:
- photometricInterpretation = 0;
- break;
-
- case TIFF_BILEVEL_BLACK_IS_ZERO:
- photometricInterpretation = 1;
- break;
-
- case TIFF_GRAY:
- case TIFF_GENERIC:
- // Since the CS_GRAY colorspace is always of type black_is_zero
- photometricInterpretation = 1;
- break;
-
- case TIFF_PALETTE:
- photometricInterpretation = 3;
-
- icm = (IndexColorModel)colorModel;
- sizeOfColormap = icm.getMapSize();
-
- byte[] r = new byte[sizeOfColormap];
- icm.getReds(r);
- byte[] g = new byte[sizeOfColormap];
- icm.getGreens(g);
- byte[] b = new byte[sizeOfColormap];
- icm.getBlues(b);
-
- int redIndex = 0, greenIndex = sizeOfColormap;
- int blueIndex = 2 * sizeOfColormap;
- colormap = new char[sizeOfColormap * 3];
- for (int i = 0; i < sizeOfColormap; i++) {
- int tmp = 0xff & r[i]; // beware of sign extended bytes
- colormap[redIndex++] = (char)((tmp << 8) | tmp);
- tmp = 0xff & g[i];
- colormap[greenIndex++] = (char)((tmp << 8) | tmp);
- tmp = 0xff & b[i];
- colormap[blueIndex++] = (char)((tmp << 8) | tmp);
- }
-
- sizeOfColormap *= 3;
+ ImageInfo imageInfo = ImageInfo.newInstance(im, dataTypeSize, numBands, colorModel,
+ encodeParam);
- break;
-
- case TIFF_RGB:
- photometricInterpretation = 2;
- break;
-
- case TIFF_CMYK:
- photometricInterpretation = 5;
- break;
-
- case TIFF_YCBCR:
- photometricInterpretation = 6;
- break;
-
- case TIFF_CIELAB:
- photometricInterpretation = 8;
- break;
-
- default:
+ if (imageInfo.getType() == ImageType.UNSUPPORTED) {
throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder8"));
}
- // Initialize tile dimensions.
- int tileWidth;
- int tileHeight;
- if (isTiled) {
- tileWidth = encodeParam.getTileWidth() > 0 ?
- encodeParam.getTileWidth() : im.getTileWidth();
- tileHeight = encodeParam.getTileHeight() > 0 ?
- encodeParam.getTileHeight() : im.getTileHeight();
- } else {
- tileWidth = width;
-
- tileHeight = encodeParam.getTileHeight() > 0 ?
- encodeParam.getTileHeight() : DEFAULT_ROWS_PER_STRIP;
- }
-
- int numTiles;
- if (isTiled) {
- // NB: Parentheses are used in this statement for correct rounding.
- numTiles =
- ((width + tileWidth - 1) / tileWidth) *
- ((height + tileHeight - 1) / tileHeight);
- } else {
- numTiles = (int)Math.ceil((double)height / (double)tileHeight);
- }
+ final int numTiles = imageInfo.getNumTiles();
+ final long bytesPerTile = imageInfo.getBytesPerTile();
+ final long bytesPerRow = imageInfo.getBytesPerRow();
+ final int tileHeight = imageInfo.getTileHeight();
+ final int tileWidth = imageInfo.getTileWidth();
long[] tileByteCounts = new long[numTiles];
-
- long bytesPerRow =
- (long)Math.ceil((sampleSize[0] / 8.0) * tileWidth * numBands);
-
- long bytesPerTile = bytesPerRow * tileHeight;
-
for (int i = 0; i < numTiles; i++) {
tileByteCounts[i] = bytesPerTile;
}
@@ -480,12 +223,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
long lastStripRows = height - (tileHeight * (numTiles - 1));
tileByteCounts[numTiles - 1] = lastStripRows * bytesPerRow;
}
-
- long totalBytesOfData = bytesPerTile * (numTiles - 1) +
- tileByteCounts[numTiles - 1];
-
- // The data will be written after the IFD: create the array here
- // but fill it in later.
+ long totalBytesOfData = bytesPerTile * (numTiles - 1) + tileByteCounts[numTiles - 1];
long[] tileOffsets = new long[numTiles];
// Basic fields - have to be in increasing numerical order.
@@ -502,7 +240,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
// ResolutionUnit 296
// Create Directory
- SortedSet fields = new TreeSet();
+ SortedSet<TIFFField> fields = new TreeSet<TIFFField>();
// Image Width
fields.add(new TIFFField(TIFFImageDecoder.TIFF_IMAGE_WIDTH,
@@ -516,7 +254,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
char [] shortSampleSize = new char[numBands];
for (int i = 0; i < numBands; i++) {
- shortSampleSize[i] = (char)sampleSize[i];
+ shortSampleSize[i] = (char) dataTypeSize;
}
fields.add(new TIFFField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE,
TIFFField.TIFF_SHORT, numBands,
@@ -524,12 +262,12 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
fields.add(new TIFFField(TIFFImageDecoder.TIFF_COMPRESSION,
TIFFField.TIFF_SHORT, 1,
- new char[] {(char)compression}));
+ new char[] {(char)compression.getValue()}));
fields.add(
new TIFFField(TIFFImageDecoder.TIFF_PHOTOMETRIC_INTERPRETATION,
TIFFField.TIFF_SHORT, 1,
- new char[] {(char)photometricInterpretation}));
+ new char[] {(char) imageInfo.getType().getPhotometricInterpretation()}));
if (!isTiled) {
fields.add(new TIFFField(TIFFImageDecoder.TIFF_STRIP_OFFSETS,
@@ -551,10 +289,10 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
tileByteCounts));
}
- if (colormap != null) {
+ if (imageInfo.getColormap() != null) {
fields.add(new TIFFField(TIFFImageDecoder.TIFF_COLORMAP,
- TIFFField.TIFF_SHORT, sizeOfColormap,
- colormap));
+ TIFFField.TIFF_SHORT, imageInfo.getColormapSize(),
+ imageInfo.getColormap()));
}
if (isTiled) {
@@ -575,13 +313,13 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
tileByteCounts));
}
- if (numExtraSamples > 0) {
- char[] extraSamples = new char[numExtraSamples];
- for (int i = 0; i < numExtraSamples; i++) {
- extraSamples[i] = (char)extraSampleType;
+ if (imageInfo.getNumberOfExtraSamples() > 0) {
+ char[] extraSamples = new char[imageInfo.getNumberOfExtraSamples()];
+ for (int i = 0; i < imageInfo.getNumberOfExtraSamples(); i++) {
+ extraSamples[i] = (char) imageInfo.getExtraSamplesType().getValue();
}
fields.add(new TIFFField(TIFFImageDecoder.TIFF_EXTRA_SAMPLES,
- TIFFField.TIFF_SHORT, numExtraSamples,
+ TIFFField.TIFF_SHORT, imageInfo.getNumberOfExtraSamples(),
extraSamples));
}
@@ -610,7 +348,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
// use it if available.
}
- if (imageType == TIFF_YCBCR) {
+ if (imageInfo.getType() == ImageType.YCBCR) {
// YCbCrSubSampling: 2 is the default so we must write 1 as
// we do not (yet) do any subsampling.
char subsampleH = 1;
@@ -625,7 +363,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
fields.add(new TIFFField(TIFF_YCBCR_POSITIONING,
TIFFField.TIFF_SHORT, 1,
new char[]
- {(char)((compression == COMP_JPEG_TTN2) ? 1 : 2)}));
+ {(char) ((compression == CompressionValue.JPEG_TTN2) ? 1 : 2)}));
// Reference black/white.
long[][] refbw;
@@ -691,16 +429,16 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
Deflater deflater = null;
boolean jpegRGBToYCbCr = false;
- if (compression == COMP_NONE) {
+ if (compression == CompressionValue.NONE) {
// Determine the number of bytes of padding necessary between
// the end of the IFD and the first data segment such that the
// alignment of the data conforms to the specification (required
// for uncompressed data only).
int numBytesPadding = 0;
- if (sampleSize[0] == 16 && tileOffsets[0] % 2 != 0) {
+ if (dataTypeSize == 16 && tileOffsets[0] % 2 != 0) {
numBytesPadding = 1;
tileOffsets[0]++;
- } else if (sampleSize[0] == 32 && tileOffsets[0] % 4 != 0) {
+ } else if (dataTypeSize == 32 && tileOffsets[0] % 4 != 0) {
numBytesPadding = (int)(4 - tileOffsets[0] % 4);
tileOffsets[0] += numBytesPadding;
}
@@ -758,11 +496,11 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
int bufSize = 0;
switch(compression) {
- case COMP_PACKBITS:
- bufSize = (int)(bytesPerTile + ((bytesPerRow + 127) / 128) * tileHeight);
+ case PACKBITS:
+ bufSize = (int) (bytesPerTile + ((bytesPerRow + 127) / 128) * tileHeight);
break;
- case COMP_DEFLATE:
- bufSize = (int)bytesPerTile;
+ case DEFLATE:
+ bufSize = (int) bytesPerTile;
deflater = new Deflater(encodeParam.getDeflateLevel());
break;
default:
@@ -781,16 +519,16 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
// Whether to test for contiguous data.
boolean checkContiguous =
- ((sampleSize[0] == 1 &&
+ ((dataTypeSize == 1 &&
sampleModel instanceof MultiPixelPackedSampleModel &&
dataType == DataBuffer.TYPE_BYTE) ||
- (sampleSize[0] == 8 &&
+ (dataTypeSize == 8 &&
sampleModel instanceof ComponentSampleModel));
// Also create a buffer to hold tileHeight lines of the
// data to be written to the file, so we can use array writes.
byte[] bpixels = null;
- if (compression != COMP_JPEG_TTN2) {
+ if (compression != CompressionValue.JPEG_TTN2) {
if (dataType == DataBuffer.TYPE_BYTE) {
bpixels = new byte[tileHeight * tileWidth * numBands];
} else if (dataTypeIsShort) {
@@ -816,9 +554,9 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
im.getData(new Rectangle(col, row, tileWidth, rows));
boolean useDataBuffer = false;
- if (compression != COMP_JPEG_TTN2) { // JPEG access Raster
+ if (compression != CompressionValue.JPEG_TTN2) { // JPEG access Raster
if (checkContiguous) {
- if (sampleSize[0] == 8) { // 8-bit
+ if (dataTypeSize == 8) { // 8-bit
ComponentSampleModel csm =
(ComponentSampleModel)src.getSampleModel();
int[] bankIndices = csm.getBankIndices();
@@ -866,7 +604,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
int pixel = 0;
int k = 0;
- switch (sampleSize[0]) {
+ switch (dataTypeSize) {
case 1:
@@ -881,18 +619,18 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
src.getSampleModelTranslateX(),
row -
src.getSampleModelTranslateY());
- if (lineStride == (int)bytesPerRow) {
+ if (lineStride == bytesPerRow) {
System.arraycopy(btmp, inOffset,
bpixels, 0,
- (int)bytesPerRow * rows);
+ (int) bytesPerRow * rows);
} else {
int outOffset = 0;
for (int j = 0; j < rows; j++) {
System.arraycopy(btmp, inOffset,
bpixels, outOffset,
- (int)bytesPerRow);
+ (int) bytesPerRow);
inOffset += lineStride;
- outOffset += (int)bytesPerRow;
+ outOffset += bytesPerRow;
}
}
} else {
@@ -927,16 +665,16 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
}
}
- if (compression == COMP_NONE) {
+ if (compression == CompressionValue.NONE) {
output.write(bpixels, 0, rows * ((tileWidth + 7) / 8));
- } else if (compression == COMP_PACKBITS) {
+ } else if (compression == CompressionValue.PACKBITS) {
int numCompressedBytes =
compressPackBits(bpixels, rows,
- (int)bytesPerRow,
+ bytesPerRow,
compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
output.write(compressBuf, 0, numCompressedBytes);
- } else if (compression == COMP_DEFLATE) {
+ } else if (compression == CompressionValue.DEFLATE) {
int numCompressedBytes =
deflate(deflater, bpixels, compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
@@ -966,16 +704,16 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
}
}
- if (compression == COMP_NONE) {
+ if (compression == CompressionValue.NONE) {
output.write(bpixels, 0, rows * ((tileWidth + 1) / 2));
- } else if (compression == COMP_PACKBITS) {
+ } else if (compression == CompressionValue.PACKBITS) {
int numCompressedBytes =
compressPackBits(bpixels, rows,
- (int)bytesPerRow,
+ bytesPerRow,
compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
output.write(compressBuf, 0, numCompressedBytes);
- } else if (compression == COMP_DEFLATE) {
+ } else if (compression == CompressionValue.DEFLATE) {
int numCompressedBytes =
deflate(deflater, bpixels, compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
@@ -985,7 +723,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
case 8:
- if (compression != COMP_JPEG_TTN2) {
+ if (compression != CompressionValue.JPEG_TTN2) {
if (useDataBuffer) {
byte[] btmp =
((DataBufferByte)src.getDataBuffer()).getData();
@@ -997,19 +735,19 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
row -
src.getSampleModelTranslateY());
int lineStride = csm.getScanlineStride();
- if (lineStride == (int)bytesPerRow) {
+ if (lineStride == bytesPerRow) {
System.arraycopy(btmp,
inOffset,
bpixels, 0,
- (int)bytesPerRow * rows);
+ (int) bytesPerRow * rows);
} else {
int outOffset = 0;
for (int j = 0; j < rows; j++) {
System.arraycopy(btmp, inOffset,
bpixels, outOffset,
- (int)bytesPerRow);
+ (int) bytesPerRow);
inOffset += lineStride;
- outOffset += (int)bytesPerRow;
+ outOffset += bytesPerRow;
}
}
} else {
@@ -1019,16 +757,16 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
}
}
- if (compression == COMP_NONE) {
+ if (compression == CompressionValue.NONE) {
output.write(bpixels, 0, size);
- } else if (compression == COMP_PACKBITS) {
+ } else if (compression == CompressionValue.PACKBITS) {
int numCompressedBytes =
compressPackBits(bpixels, rows,
- (int)bytesPerRow,
+ bytesPerRow,
compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
output.write(compressBuf, 0, numCompressedBytes);
- } else if (compression == COMP_DEFLATE) {
+ } else if (compression == CompressionValue.DEFLATE) {
int numCompressedBytes =
deflate(deflater, bpixels, compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
@@ -1045,16 +783,16 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
bpixels[ls++] = (byte) (value & 0x00ff);
}
- if (compression == COMP_NONE) {
+ if (compression == CompressionValue.NONE) {
output.write(bpixels, 0, size*2);
- } else if (compression == COMP_PACKBITS) {
+ } else if (compression == CompressionValue.PACKBITS) {
int numCompressedBytes =
compressPackBits(bpixels, rows,
- (int)bytesPerRow,
+ bytesPerRow,
compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
output.write(compressBuf, 0, numCompressedBytes);
- } else if (compression == COMP_DEFLATE) {
+ } else if (compression == CompressionValue.DEFLATE) {
int numCompressedBytes =
deflate(deflater, bpixels, compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
@@ -1082,16 +820,16 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
bpixels[lf++] = (byte)( value & 0x000000ff);
}
}
- if (compression == COMP_NONE) {
+ if (compression == CompressionValue.NONE) {
output.write(bpixels, 0, size*4);
- } else if (compression == COMP_PACKBITS) {
+ } else if (compression == CompressionValue.PACKBITS) {
int numCompressedBytes =
compressPackBits(bpixels, rows,
- (int)bytesPerRow,
+ bytesPerRow,
compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
output.write(compressBuf, 0, numCompressedBytes);
- } else if (compression == COMP_DEFLATE) {
+ } else if (compression == CompressionValue.DEFLATE) {
int numCompressedBytes =
deflate(deflater, bpixels, compressBuf);
tileByteCounts[tileNum++] = numCompressedBytes;
@@ -1103,7 +841,7 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
}
}
- if (compression == COMP_NONE) {
+ if (compression == CompressionValue.NONE) {
// Write an extra byte for IFD word alignment if needed.
if (skipByte) {
output.write((byte)0);
@@ -1209,6 +947,50 @@ private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
return nextIFDOffset;
}
+ private void validateImage(int dataTypeSize, int[] sampleSize, int numBands, int dataType,
+ ColorModel colorModel) {
+ // Retrieve and verify sample size.
+ for (int i = 1; i < sampleSize.length; i++) {
+ if (sampleSize[i] != dataTypeSize) {
+ throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder0"));
+ }
+ }
+
+ // Check low bit limits.
+ if ((dataTypeSize == 1 || dataTypeSize == 4) && numBands != 1) {
+ throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder1"));
+ }
+
+ // Retrieve and verify data type.
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ if (dataTypeSize != 1 && dataTypeSize == 4 && // todo does this make sense??
+ dataTypeSize != 8) { // we get error only for 4
+ throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder2"));
+ }
+ break;
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ if (dataTypeSize != 16) {
+ throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder3"));
+ }
+ break;
+ case DataBuffer.TYPE_INT:
+ case DataBuffer.TYPE_FLOAT:
+ if (dataTypeSize != 32) {
+ throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder4"));
+ }
+ break;
+ default:
+ throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder5"));
+ }
+
+ if (colorModel instanceof IndexColorModel && dataType != DataBuffer.TYPE_BYTE) {
+ // Don't support (unsigned) short palette-color images.
+ throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder6"));
+ }
+ }
+
/**
* Calculates the size of the IFD.
*/
@@ -1515,12 +1297,12 @@ private long getOffset(OutputStream out) throws IOException {
* Performs PackBits compression on a tile of data.
*/
private static int compressPackBits(byte[] data, int numRows,
- int bytesPerRow, byte[] compData) {
+ long bytesPerRow, byte[] compData) {
int inOffset = 0;
int outOffset = 0;
for (int i = 0; i < numRows; i++) {
- outOffset = packBits(data, inOffset, bytesPerRow,
+ outOffset = packBits(data, inOffset, (int) bytesPerRow,
compData, outOffset);
inOffset += bytesPerRow;
}
View
7 src/java/org/apache/xmlgraphics/image/loader/ImageManager.java
@@ -35,6 +35,7 @@
import org.apache.xmlgraphics.image.loader.spi.ImagePreloader;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.image.loader.util.Penalty;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
/**
* ImageManager is the central starting point for image access.
@@ -171,7 +172,7 @@ public ImageInfo preloadImage(String uri, Source src)
throws ImageException, IOException {
Iterator iter = registry.getPreloaderIterator();
while (iter.hasNext()) {
- ImagePreloader preloader = (ImagePreloader)iter.next();
+ ImagePreloader preloader = (ImagePreloader) iter.next();
ImageInfo info = preloader.preloadImage(uri, src, imageContext);
if (info != null) {
return info;
@@ -231,7 +232,7 @@ public Image getImage(ImageInfo info, ImageFlavor flavor, Map hints,
"Cannot load image (no suitable loader/converter combination available) for "
+ info);
}
- ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
+ XmlSourceUtil.closeQuietly(session.getSource(info.getOriginalURI()));
return img;
}
@@ -272,7 +273,7 @@ public Image getImage(ImageInfo info, ImageFlavor[] flavors, Map hints,
"Cannot load image (no suitable loader/converter combination available) for "
+ info);
}
- ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
+ XmlSourceUtil.closeQuietly(session.getSource(info.getOriginalURI()));
return img;
}
View
306 src/java/org/apache/xmlgraphics/image/loader/impl/AbstractImageSessionContext.java
@@ -44,6 +44,7 @@
import org.apache.xmlgraphics.image.loader.ImageSource;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.image.loader.util.SoftMapCache;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
/**
* Abstract base class for classes implementing ImageSessionContext. This class provides all the
@@ -54,14 +55,28 @@
/** logger */
private static Log log = LogFactory.getLog(AbstractImageSessionContext.class);
- private static boolean noSourceReuse = false;
+ private static boolean noSourceReuse;
static {
//TODO Temporary measure to track down a problem
//See: http://markmail.org/message/k6mno3jsxmovaz2e
- String v = System.getProperty(
- AbstractImageSessionContext.class.getName() + ".no-source-reuse");
- noSourceReuse = Boolean.valueOf(v).booleanValue();
+ String noSourceReuseString = System.getProperty(
+ AbstractImageSessionContext.class.getName() + ".no-source-reuse");
+ noSourceReuse = Boolean.valueOf(noSourceReuseString);
+ }
+
+ private final FallbackResolver fallbackResolver;
+
+ public AbstractImageSessionContext() {
+ fallbackResolver = new UnrestrictedFallbackResolver();
+ }
+
+ /**
+ * @param fallbackResolver the fallback resolution mechanism to be used when simply getting an
+ * {@link InputStream} that backs a {@link Source} isn't possible.
+ */
+ public AbstractImageSessionContext(FallbackResolver fallbackResolver) {
+ this.fallbackResolver = fallbackResolver;
}
/**
@@ -75,120 +90,16 @@
/** {@inheritDoc} */
public Source newSource(String uri) {
Source source = resolveURI(uri);
- if (source == null) {
- if (log.isDebugEnabled()) {
- log.debug("URI could not be resolved: " + uri);
- }
- return null;
- }
- if (!(source instanceof StreamSource) && !(source instanceof SAXSource)) {
- //Return any non-stream Sources and let the ImageLoaders deal with them
- return source;
- }
-
- ImageSource imageSource = null;
-
- String resolvedURI = source.getSystemId();
- URL url;
- try {
- url = new URL(resolvedURI);
- } catch (MalformedURLException e) {
- url = null;
+ if (source instanceof StreamSource || source instanceof SAXSource) {
+ return fallbackResolver.createSource(source, uri);
}
- File f = /*FileUtils.*/toFile(url);
- if (f != null) {
- boolean directFileAccess = true;
- assert (source instanceof StreamSource) || (source instanceof SAXSource);
- InputStream in = ImageUtil.getInputStream(source);
- if (in == null) {
- try {
- in = new java.io.FileInputStream(f);
- } catch (FileNotFoundException fnfe) {
- log.error("Error while opening file."
- + " Could not load image from system identifier '"
- + source.getSystemId() + "' (" + fnfe.getMessage() + ")");
- return null;
- }
- }
- if (in != null) {
- in = ImageUtil.decorateMarkSupported(in);
- try {
- if (ImageUtil.isGZIPCompressed(in)) {
- //GZIPped stream are not seekable, so buffer/cache like other URLs
- directFileAccess = false;
- }
- } catch (IOException ioe) {
- log.error("Error while checking the InputStream for GZIP compression."
- + " Could not load image from system identifier '"
- + source.getSystemId() + "' (" + ioe.getMessage() + ")");
- return null;
- }
- }
-
- if (directFileAccess) {
- //Close as the file is reopened in a more optimal way
- IOUtils.closeQuietly(in);
- try {
- // We let the OS' file system cache do the caching for us
- // --> lower Java memory consumption, probably no speed loss
- final ImageInputStream newInputStream = ImageIO
- .createImageInputStream(f);
- if (newInputStream == null) {
- log.error("Unable to create ImageInputStream for local file "
- + f
- + " from system identifier '"
- + source.getSystemId() + "'");
- return null;
- } else {
- imageSource = new ImageSource(newInputStream,
- resolvedURI, true);
- }
- } catch (IOException ioe) {
- log.error("Unable to create ImageInputStream for local file"
- + " from system identifier '"
- + source.getSystemId() + "' (" + ioe.getMessage() + ")");
- }
- }
- }
-
- if (imageSource == null) {
- if (ImageUtil.hasReader(source) && !ImageUtil.hasInputStream(source)) {
- //We don't handle Reader instances here so return the Source unchanged
- return source;
- }
- // Got a valid source, obtain an InputStream from it
- InputStream in = ImageUtil.getInputStream(source);
- if (in == null && url != null) {
- try {
- in = url.openStream();
- } catch (Exception ex) {
- log.error("Unable to obtain stream from system identifier '"
- + source.getSystemId() + "'");
- }
- }
- if (in == null) {
- log.error("The Source that was returned from URI resolution didn't contain"
- + " an InputStream for URI: " + uri);
- return null;
- }
-
- try {
- //Buffer and uncompress if necessary
- in = ImageUtil.autoDecorateInputStream(in);
- imageSource = new ImageSource(
- createImageInputStream(in), source.getSystemId(), false);
- } catch (IOException ioe) {
- log.error("Unable to create ImageInputStream for InputStream"
- + " from system identifier '"
- + source.getSystemId() + "' (" + ioe.getMessage() + ")");
- }
- }
- return imageSource;
+ //Return any non-stream Sources and let the ImageLoaders deal with them
+ return source;
}
- protected ImageInputStream createImageInputStream(InputStream in) throws IOException {
+ protected static ImageInputStream createImageInputStream(InputStream in) throws IOException {
ImageInputStream iin = ImageIO.createImageInputStream(in);
- return (ImageInputStream)Proxy.newProxyInstance(
+ return (ImageInputStream) Proxy.newProxyInstance(
ImageInputStream.class.getClassLoader(),
new Class[] {ImageInputStream.class},
new ObservingImageInputStreamInvocationHandler(iin, in));
@@ -266,7 +177,7 @@ public static File toFile(URL url) {
/** {@inheritDoc} */
public Source getSource(String uri) {
- return (Source)sessionSources.remove(uri);
+ return (Source) sessionSources.remove(uri);
}
/** {@inheritDoc} */
@@ -299,7 +210,7 @@ public void returnSource(String uri, Source src) {
}
} catch (IOException ioe) {
//Ignore exception
- ImageUtil.closeQuietly(src);
+ XmlSourceUtil.closeQuietly(src);
}
if (isReusable(src)) {
@@ -308,7 +219,7 @@ public void returnSource(String uri, Source src) {
sessionSources.put(uri, src);
} else {
//Otherwise, try to close if possible and forget about it
- ImageUtil.closeQuietly(src);
+ XmlSourceUtil.closeQuietly(src);
}
}
@@ -323,7 +234,7 @@ protected boolean isReusable(Source src) {
return false;
}
if (src instanceof ImageSource) {
- ImageSource is = (ImageSource)src;
+ ImageSource is = (ImageSource) src;
if (is.getImageInputStream() != null) {
return true;
}
@@ -333,4 +244,163 @@ protected boolean isReusable(Source src) {
}
return false;
}
+
+ /**
+ * Implementations of this interface will be used as the mechanism for creating the
+ * {@link Source} that wraps resources. This interface allows clients to define their own
+ * implementations so that they have fine-grained control over how resources are acquired.
+ */
+ public interface FallbackResolver {
+
+ /**
+ * The fallback mechanism used to create the source which takes in both the {@link Source}
+ * that the the regular mechanisms attempted to create and the URI that the user provided.
+ *
+ * @param source the source
+ * @param uri the URI provided by the user
+ * @return the source that the contingency mechanism has been acquired
+ */
+ Source createSource(Source source, String uri);
+ }
+
+ /**
+ * An unrestricted resolver that has various contingency mechanisms that access the file-system.
+ * This is most suitable for use via the CLI or in environments where controlling I/O isn't a
+ * priority.
+ */
+ public static final class UnrestrictedFallbackResolver implements FallbackResolver {
+
+ /** {@inheritDoc} */
+ public Source createSource(Source source, String uri) {
+ if (source == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("URI could not be resolved: " + uri);
+ }
+ return null;
+ }
+ ImageSource imageSource = null;
+
+ String resolvedURI = source.getSystemId();
+ URL url;
+ try {
+ url = new URL(resolvedURI);
+ } catch (MalformedURLException e) {
+ url = null;
+ }
+ File f = /*FileUtils.*/toFile(url);
+ if (f != null) {
+ boolean directFileAccess = true;
+ assert (source instanceof StreamSource) || (source instanceof SAXSource);
+ InputStream in = XmlSourceUtil.getInputStream(source);
+ if (in == null) {
+ try {
+ in = new java.io.FileInputStream(f);
+ } catch (FileNotFoundException fnfe) {
+ log.error("Error while opening file."
+ + " Could not load image from system identifier '"
+ + source.getSystemId() + "' (" + fnfe.getMessage() + ")");
+ return null;
+ }
+ }
+ if (in != null) {
+ in = ImageUtil.decorateMarkSupported(in);
+ try {
+ if (ImageUtil.isGZIPCompressed(in)) {
+ //GZIPped stream are not seekable, so buffer/cache like other URLs
+ directFileAccess = false;
+ }
+ } catch (IOException ioe) {
+ log.error("Error while checking the InputStream for GZIP compression."
+ + " Could not load image from system identifier '"
+ + source.getSystemId() + "' (" + ioe.getMessage() + ")");
+ return null;
+ }
+ }
+
+ if (directFileAccess) {
+ //Close as the file is reopened in a more optimal way
+ IOUtils.closeQuietly(in);
+ try {
+ // We let the OS' file system cache do the caching for us
+ // --> lower Java memory consumption, probably no speed loss
+ final ImageInputStream newInputStream = ImageIO
+ .createImageInputStream(f);
+ if (newInputStream == null) {
+ log.error("Unable to create ImageInputStream for local file "
+ + f
+ + " from system identifier '"
+ + source.getSystemId() + "'");
+ return null;
+ } else {
+ imageSource = new ImageSource(newInputStream,
+ resolvedURI, true);
+ }
+ } catch (IOException ioe) {
+ log.error("Unable to create ImageInputStream for local file"
+ + " from system identifier '"
+ + source.getSystemId() + "' (" + ioe.getMessage() + ")");
+ }
+ }
+ }
+
+ if (imageSource == null) {
+ if (XmlSourceUtil.hasReader(source) && !ImageUtil.hasInputStream(source)) {
+ //We don't handle Reader instances here so return the Source unchanged
+ return source;
+ }
+ // Got a valid source, obtain an InputStream from it
+ InputStream in = XmlSourceUtil.getInputStream(source);
+ if (in == null && url != null) {
+ try {
+ in = url.openStream();
+ } catch (Exception ex) {
+ log.error("Unable to obtain stream from system identifier '"
+ + source.getSystemId() + "'");
+ }
+ }
+ if (in == null) {
+ log.error("The Source that was returned from URI resolution didn't contain"
+ + " an InputStream for URI: " + uri);
+ return null;
+ }
+ return createImageSource(in, source);
+ }
+ return imageSource;
+ }
+ }
+
+ private static ImageSource createImageSource(InputStream in, Source source) {
+ try {
+ //Buffer and uncompress if necessary
+ return new ImageSource(createImageInputStream(ImageUtil.autoDecorateInputStream(in)),
+ source.getSystemId(), false);
+ } catch (IOException ioe) {
+ log.error("Unable to create ImageInputStream for InputStream"
+ + " from system identifier '"
+ + source.getSystemId() + "' (" + ioe.getMessage() + ")");
+ }
+ return null;
+ }
+
+ /**
+ * This fallback resolver is to be used in environments where controlling file access is of
+ * critical importance. It disallows any contingency mechanisms by which a {@link Source} object
+ * would be created.
+ */
+ public static final class RestrictedFallbackResolver implements FallbackResolver {
+
+ /** {@inheritDoc} */
+ public Source createSource(Source source, String uri) {
+ if (source == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("URI could not be resolved: " + uri);
+ }
+ return null;
+ }
+ if (ImageUtil.hasInputStream(source)) {
+ return createImageSource(XmlSourceUtil.getInputStream(source), source);
+ }
+ throw new UnsupportedOperationException("There are no contingency mechanisms for I/O.");
+ }
+ }
}
View
6 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderEPS.java
@@ -30,7 +30,7 @@
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
import org.apache.xmlgraphics.util.MimeConstants;
import org.apache.xmlgraphics.util.io.SubInputStream;
@@ -58,8 +58,8 @@ public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
"ImageInfo must be from a image with MIME type: " + MimeConstants.MIME_EPS);
}
Source src = session.needSource(info.getOriginalURI());
- InputStream in = ImageUtil.needInputStream(src);
- ImageUtil.removeStreams(src); //so others cannot close them, we take them over
+ InputStream in = XmlSourceUtil.needInputStream(src);
+ XmlSourceUtil.removeStreams(src); //so others cannot close them, we take them over
PreloaderEPS.EPSBinaryFileHeader binaryHeader;
binaryHeader = (PreloaderEPS.EPSBinaryFileHeader)info.getCustomObjects().get(
View
4 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRaw.java
@@ -29,7 +29,7 @@
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
-import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
/**
* ImageLoader for formats consumed "raw" (undecoded). Provides a raw/undecoded stream.
@@ -62,7 +62,7 @@ public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
}
Source src = session.needSource(info.getOriginalURI());
ImageRawStream rawImage = new ImageRawStream(info, getTargetFlavor(),
- ImageUtil.needInputStream(src));
+ XmlSourceUtil.needInputStream(src));
return rawImage;
}
View
5 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawCCITTFax.java
@@ -42,6 +42,7 @@
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.image.loader.util.SeekableStreamAdapter;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
import org.apache.xmlgraphics.util.MimeConstants;
import org.apache.xmlgraphics.util.io.SubInputStream;
@@ -139,14 +140,14 @@ public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
}
in.seek(stripOffset);
- InputStream subin = new SubInputStream(ImageUtil.needInputStream(src), stripLength, true);
+ InputStream subin = new SubInputStream(XmlSourceUtil.needInputStream(src), stripLength, true);
if (fillOrder == 2) {
//Decorate to flip bit order
subin = new FillOrderChangeInputStream(subin);
}
ImageRawCCITTFax rawImage = new ImageRawCCITTFax(info, subin, compression);
//Strip stream from source as we pass it on internally
- ImageUtil.removeStreams(src);
+ XmlSourceUtil.removeStreams(src);
return rawImage;
}
View
3 src/java/org/apache/xmlgraphics/image/loader/impl/ImageLoaderRawJPEG.java
@@ -39,6 +39,7 @@
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
import org.apache.xmlgraphics.java2d.color.ColorSpaces;
import org.apache.xmlgraphics.java2d.color.profile.ColorProfileUtil;
import org.apache.xmlgraphics.util.MimeConstants;
@@ -211,7 +212,7 @@ public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session)
}
ImageRawJPEG rawImage = new ImageRawJPEG(info,
- ImageUtil.needInputStream(src),
+ XmlSourceUtil.needInputStream(src),
sofType, colorSpace, iccProfile, invertImage);
return rawImage;
}
View
15 src/java/org/apache/xmlgraphics/image/loader/impl/ImageRawStream.java
@@ -20,7 +20,6 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.ByteArrayInputStream;
-import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -121,20 +120,6 @@ public void writeTo(OutputStream out) throws IOException {
}
/**
- * Writes the content of the image to a File.
- * @param target the file to be written
- * @throws IOException if an I/O error occurs
- */
- public void writeTo(File target) throws IOException {
- OutputStream out = new java.io.FileOutputStream(target);
- try {
- writeTo(out);
- } finally {
- IOUtils.closeQuietly(out);
- }
- }
-
- /**
* Represents a factory for InputStream objects. Make sure the class is thread-safe!