first commit

This commit is contained in:
MaddoScientisto 2026-03-14 20:04:39 +01:00
commit 4d332ef662
27586 changed files with 3281783 additions and 0 deletions

View file

@ -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 file

@ -0,0 +1,10 @@
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.6.0_35-b10-428-11M3811 (Apple Inc.)
Implementation-Title: Apache XML Graphics Commons
Implementation-Version: 1.5
Implementation-Vendor: The Apache Software Foundation (http://xmlgraph
ics.apache.org/)
Build-Id: 20121016-215324-ICT (glenn [Mac OS X 10.8.1 x86_64, Java 1.6
.0_35-b10-428-11M3811])

View file

@ -0,0 +1,5 @@
Apache XML Graphics Commons
Copyright 2006-2012 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

View file

@ -0,0 +1 @@
org.apache.xmlgraphics.util.uri.DataURIResolver

View file

@ -0,0 +1,4 @@
org.apache.xmlgraphics.image.loader.impl.ImageConverterBuffered2Rendered
org.apache.xmlgraphics.image.loader.impl.ImageConverterG2D2Bitmap
org.apache.xmlgraphics.image.loader.impl.ImageConverterBitmap2G2D
org.apache.xmlgraphics.image.loader.impl.ImageConverterRendered2PNG

View file

@ -0,0 +1,6 @@
org.apache.xmlgraphics.image.loader.impl.imageio.ImageLoaderFactoryImageIO
org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryRaw
org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryRawCCITTFax
org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryEPS
org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryInternalTIFF
org.apache.xmlgraphics.image.loader.impl.ImageLoaderFactoryPNG

View file

@ -0,0 +1,7 @@
org.apache.xmlgraphics.image.loader.impl.PreloaderTIFF
org.apache.xmlgraphics.image.loader.impl.PreloaderGIF
org.apache.xmlgraphics.image.loader.impl.PreloaderJPEG
org.apache.xmlgraphics.image.loader.impl.PreloaderBMP
org.apache.xmlgraphics.image.loader.impl.PreloaderEMF
org.apache.xmlgraphics.image.loader.impl.PreloaderEPS
org.apache.xmlgraphics.image.loader.impl.imageio.PreloaderImageIO

View file

@ -0,0 +1,5 @@
org.apache.xmlgraphics.image.writer.internal.PNGImageWriter
org.apache.xmlgraphics.image.writer.internal.TIFFImageWriter
org.apache.xmlgraphics.image.writer.imageio.ImageIOPNGImageWriter
org.apache.xmlgraphics.image.writer.imageio.ImageIOTIFFImageWriter
org.apache.xmlgraphics.image.writer.imageio.ImageIOJPEGImageWriter

View file

@ -0,0 +1,405 @@
package org.apache.xmlgraphics.fonts;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import org.apache.commons.io.IOUtils;
public final class Glyphs {
public static final String NOTDEF = ".notdef";
@Deprecated
public static final String[] MAC_GLYPH_NAMES = new String[] {
".notdef", ".null", "CR", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand",
"quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero",
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon",
"semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D",
"E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X",
"Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b",
"c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
"m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
"w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Adieresis", "Aring",
"Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde",
"aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
"ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
"dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright",
"trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
"yen", "mu", "partialdiff", "Sigma", "Pi", "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
"ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft",
"guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash",
"quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
"guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
"Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
"applelogo", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve",
"dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron",
"Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn", "thorn", "minus",
"multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
"Idot", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron", "dmacron" };
public static final String[] TEX8R_GLYPH_NAMES = new String[] {
".notdef", "dotaccent", "fi", "fl", "fraction", "hungarumlaut", "Lslash", "lslash", "ogonek", "ring",
".notdef", "breve", "minus", ".notdef", "Zcaron", "zcaron", "caron", "dotlessi", "dotlessj", "ff",
"ffi", "ffl", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
"grave", "quotesingle", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright",
"parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one",
"two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon",
"less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E",
"F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
"Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c",
"d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", ".notdef", "Euro", ".notdef",
"quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron", "guilsinglleft",
"OE", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", ".notdef", "quotedblleft", "quotedblright", "bullet",
"endash", "emdash", "tilde", "trademark", "scaron", "guilsinglright", "oe", ".notdef", ".notdef", "Ydieresis",
".notdef", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section", "dieresis", "copyright",
"ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron", "degree", "plusminus", "twosuperior", "threesuperior",
"acute", "mu", "paragraph", "periodcentered", "cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf",
"threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
"Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde",
"Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex",
"Udieresis", "Yacute", "Thorn", "germandbls", "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring",
"ae", "ccedilla", "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
"eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide", "oslash", "ugrave",
"uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis" };
public static final char[] WINANSI_ENCODING = new char[] {
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', ' ', '!', '"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/', '0', '1',
'2', '3', '4', '5', '6', '7', '8', '9', ':', ';',
'<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z', '[', '\\', ']', '^', '_', '', 'a', 'b', 'c',
'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', '•', '€', '•',
'', 'ƒ', '„', '…', '†', '‡', 'ˆ', '‰', 'Š', '',
'Œ', '•', 'Ž', '•', '•', '', '', '“', '”', '•',
'', '—', '~', '™', 'š', '', 'œ', '•', 'ž', 'Ÿ',
' ', '¡', '¢', '£', '¤', '¥', '¦', '§', '¨', '©',
'ª', '«', '¬', '\u00AD', '®', '¯', '°', '±', '²', '³',
'´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½',
'¾', '¿', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç',
'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ',
'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û',
'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å',
'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï',
'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù',
'ú', 'û', 'ü', 'ý', 'þ', 'ÿ' };
public static final char[] ADOBECYRILLIC_ENCODING = new char[] {
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', ' ', '!', '"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/', '0', '1',
'2', '3', '4', '5', '6', '7', '8', '9', ':', ';',
'<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c',
'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', '\000', 'Ђ', 'Ѓ',
'', 'ѓ', '„', '…', '†', '‡', '€', '‰', 'Љ', '',
'Њ', 'Ќ', 'Ћ', 'Џ', 'ђ', '', '', '“', '”', '•',
'', '—', '\000', '™', 'љ', '', 'њ', 'ќ', 'ћ', 'џ',
'\u00A0', 'Ў', 'ў', 'Ј', '¤', 'Ґ', '¦', '§', 'Ё', '©',
'Є', '«', '¬', '\u00AD', '®', 'Ї', '°', '±', 'І', 'і',
'ґ', 'µ', '¶', '·', 'ё', '№', 'є', '»', 'ј', 'Ѕ',
'ѕ', 'ї', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З',
'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С',
'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы',
'Ь', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е',
'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п',
'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ',
'ъ', 'ы', 'ь', 'э', 'ю', 'я' };
private static final String[] UNICODE_GLYPHS;
private static final String[] DINGBATS_GLYPHS;
private static final Map CHARNAME_ALTERNATIVES;
private static final Map CHARNAMES_TO_UNICODE;
static {
Map<?, ?> map = new TreeMap();
UNICODE_GLYPHS = loadGlyphList("glyphlist.txt", map);
DINGBATS_GLYPHS = loadGlyphList("zapfdingbats.txt", map);
CHARNAMES_TO_UNICODE = Collections.unmodifiableMap(map);
map = new TreeMap();
addAlternatives(map, new String[] { "Omega", "Omegagreek" });
addAlternatives(map, new String[] { "Delta", "Deltagreek" });
addAlternatives(map, new String[] { "fraction", "divisionslash" });
addAlternatives(map, new String[] { "hyphen", "sfthyphen", "softhyphen", "minus" });
addAlternatives(map, new String[] { "macron", "overscore" });
addAlternatives(map, new String[] { "mu", "mu1", "mugreek" });
addAlternatives(map, new String[] { "periodcentered", "middot", "bulletoperator", "anoteleia" });
addAlternatives(map, new String[] { "space", "nonbreakingspace", "nbspace" });
addAlternatives(map, new String[] { "zero", "zerooldstyle" });
addAlternatives(map, new String[] { "one", "oneoldstyle" });
addAlternatives(map, new String[] { "two", "twooldstyle" });
addAlternatives(map, new String[] { "three", "threeoldstyle" });
addAlternatives(map, new String[] { "four", "fouroldstyle" });
addAlternatives(map, new String[] { "five", "fiveoldstyle" });
addAlternatives(map, new String[] { "six", "sixoldstyle" });
addAlternatives(map, new String[] { "seven", "sevenoldstyle" });
addAlternatives(map, new String[] { "eight", "eightoldstyle" });
addAlternatives(map, new String[] { "nine", "nineoldstyle" });
addAlternatives(map, new String[] { "cent", "centoldstyle" });
addAlternatives(map, new String[] { "dollar", "dollaroldstyle" });
addAlternatives(map, new String[] { "Acyrillic", "afii10017" });
addAlternatives(map, new String[] { "Becyrillic", "afii10018" });
addAlternatives(map, new String[] { "Vecyrillic", "afii10019" });
addAlternatives(map, new String[] { "Gecyrillic", "afii10020" });
addAlternatives(map, new String[] { "Decyrillic", "afii10021" });
addAlternatives(map, new String[] { "Iecyrillic", "afii10022" });
addAlternatives(map, new String[] { "Iocyrillic", "afii10023" });
addAlternatives(map, new String[] { "Zhecyrillic", "afii10024" });
addAlternatives(map, new String[] { "Zecyrillic", "afii10025" });
addAlternatives(map, new String[] { "Iicyrillic", "afii10026" });
addAlternatives(map, new String[] { "Iishortcyrillic", "afii10027" });
addAlternatives(map, new String[] { "Kacyrillic", "afii10028" });
addAlternatives(map, new String[] { "Elcyrillic", "afii10029" });
addAlternatives(map, new String[] { "Emcyrillic", "afii10030" });
addAlternatives(map, new String[] { "Encyrillic", "afii10031" });
addAlternatives(map, new String[] { "Ocyrillic", "afii10032" });
addAlternatives(map, new String[] { "Pecyrillic", "afii10033" });
addAlternatives(map, new String[] { "Ercyrillic", "afii10034" });
addAlternatives(map, new String[] { "Escyrillic", "afii10035" });
addAlternatives(map, new String[] { "Tecyrillic", "afii10036" });
addAlternatives(map, new String[] { "Ucyrillic", "afii10037" });
addAlternatives(map, new String[] { "Efcyrillic", "afii10038" });
addAlternatives(map, new String[] { "Khacyrillic", "afii10039" });
addAlternatives(map, new String[] { "Tsecyrillic", "afii10040" });
addAlternatives(map, new String[] { "Checyrillic", "afii10041" });
addAlternatives(map, new String[] { "Shacyrillic", "afii10042" });
addAlternatives(map, new String[] { "Shchacyrillic", "afii10043" });
addAlternatives(map, new String[] { "Hardsigncyrillic", "afii10044" });
addAlternatives(map, new String[] { "Yericyrillic", "afii10045" });
addAlternatives(map, new String[] { "Softsigncyrillic", "afii10046" });
addAlternatives(map, new String[] { "Ereversedcyrillic", "afii10047" });
addAlternatives(map, new String[] { "IUcyrillic", "afii10048" });
addAlternatives(map, new String[] { "IAcyrillic", "afii10049" });
addAlternatives(map, new String[] { "acyrillic", "afii10065" });
addAlternatives(map, new String[] { "becyrillic", "afii10066" });
addAlternatives(map, new String[] { "vecyrillic", "afii10067" });
addAlternatives(map, new String[] { "gecyrillic", "afii10068" });
addAlternatives(map, new String[] { "decyrillic", "afii10069" });
addAlternatives(map, new String[] { "iecyrillic", "afii10070" });
addAlternatives(map, new String[] { "iocyrillic", "afii10071" });
addAlternatives(map, new String[] { "zhecyrillic", "afii10072" });
addAlternatives(map, new String[] { "zecyrillic", "afii10073" });
addAlternatives(map, new String[] { "iicyrillic", "afii10074" });
addAlternatives(map, new String[] { "iishortcyrillic", "afii10075" });
addAlternatives(map, new String[] { "kacyrillic", "afii10076" });
addAlternatives(map, new String[] { "elcyrillic", "afii10077" });
addAlternatives(map, new String[] { "emcyrillic", "afii10078" });
addAlternatives(map, new String[] { "encyrillic", "afii10079" });
addAlternatives(map, new String[] { "ocyrillic", "afii10080" });
addAlternatives(map, new String[] { "pecyrillic", "afii10081" });
addAlternatives(map, new String[] { "ercyrillic", "afii10082" });
addAlternatives(map, new String[] { "escyrillic", "afii10083" });
addAlternatives(map, new String[] { "tecyrillic", "afii10084" });
addAlternatives(map, new String[] { "ucyrillic", "afii10085" });
addAlternatives(map, new String[] { "efcyrillic", "afii10086" });
addAlternatives(map, new String[] { "khacyrillic", "afii10087" });
addAlternatives(map, new String[] { "tsecyrillic", "afii10088" });
addAlternatives(map, new String[] { "checyrillic", "afii10089" });
addAlternatives(map, new String[] { "shacyrillic", "afii10090" });
addAlternatives(map, new String[] { "shchacyrillic", "afii10091" });
addAlternatives(map, new String[] { "hardsigncyrillic", "afii10092" });
addAlternatives(map, new String[] { "yericyrillic", "afii10093" });
addAlternatives(map, new String[] { "softsigncyrillic", "afii10094" });
addAlternatives(map, new String[] { "ereversedcyrillic", "afii10095" });
addAlternatives(map, new String[] { "iucyrillic", "afii10096" });
addAlternatives(map, new String[] { "iacyrillic", "afii10097" });
addAlternatives(map, new String[] { "Gheupturncyrillic", "afii10050" });
addAlternatives(map, new String[] { "Djecyrillic", "afii10051" });
addAlternatives(map, new String[] { "Gjecyrillic", "afii10052" });
addAlternatives(map, new String[] { "Ecyrillic", "afii10053" });
addAlternatives(map, new String[] { "Dzecyrillic", "afii10054" });
addAlternatives(map, new String[] { "Icyrillic", "afii10055" });
addAlternatives(map, new String[] { "Yicyrillic", "afii10056" });
addAlternatives(map, new String[] { "Jecyrillic", "afii10057" });
addAlternatives(map, new String[] { "Ljecyrillic", "afii10058" });
addAlternatives(map, new String[] { "Njecyrillic", "afii10059" });
addAlternatives(map, new String[] { "Tshecyrillic", "afii10060" });
addAlternatives(map, new String[] { "Kjecyrillic", "afii10061" });
addAlternatives(map, new String[] { "Ushortcyrillic", "afii10062" });
addAlternatives(map, new String[] { "Dzhecyrillic", "afii10145" });
addAlternatives(map, new String[] { "Yatcyrillic", "afii10146" });
addAlternatives(map, new String[] { "Fitacyrillic", "afii10147" });
addAlternatives(map, new String[] { "Izhitsacyrillic", "afii10148" });
addAlternatives(map, new String[] { "gheupturncyrillic", "afii10098" });
addAlternatives(map, new String[] { "djecyrillic", "afii10099" });
addAlternatives(map, new String[] { "gjecyrillic", "afii10100" });
addAlternatives(map, new String[] { "ecyrillic", "afii10101" });
addAlternatives(map, new String[] { "dzecyrillic", "afii10102" });
addAlternatives(map, new String[] { "icyrillic", "afii10103" });
addAlternatives(map, new String[] { "yicyrillic", "afii10104" });
addAlternatives(map, new String[] { "jecyrillic", "afii10105" });
addAlternatives(map, new String[] { "ljecyrillic", "afii10106" });
addAlternatives(map, new String[] { "njecyrillic", "afii10107" });
addAlternatives(map, new String[] { "tshecyrillic", "afii10108" });
addAlternatives(map, new String[] { "kjecyrillic", "afii10109" });
addAlternatives(map, new String[] { "ushortcyrillic", "afii10110" });
addAlternatives(map, new String[] { "dzhecyrillic", "afii10193" });
addAlternatives(map, new String[] { "yatcyrillic", "afii10194" });
addAlternatives(map, new String[] { "fitacyrillic", "afii10195" });
addAlternatives(map, new String[] { "izhitsacyrillic", "afii10196" });
CHARNAME_ALTERNATIVES = Collections.unmodifiableMap(map);
}
private static void addAlternatives(Map map, String[] alternatives) {
for (int i = 0, c = alternatives.length; i < c; i++) {
String[] alt = new String[c - 1];
int idx = 0;
for (int j = 0; j < c; j++) {
if (i != j) {
alt[idx] = alternatives[j];
idx++;
}
}
map.put(alternatives[i], alt);
}
}
private static String[] loadGlyphList(String filename, Map charNameToUnicodeMap) {
List<String> lines = new ArrayList();
InputStream in = Glyphs.class.getResourceAsStream(filename);
if (in == null)
throw new RuntimeException("Cannot load " + filename + ". The Glyphs class cannot properly be initialized!");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "US-ASCII"));
String line;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("#"))
lines.add(line);
}
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Incompatible JVM! US-ASCII encoding is not supported. The Glyphs class cannot properly be initialized!");
} catch (IOException ioe) {
throw new RuntimeException("I/O error while loading " + filename + ". The Glyphs class cannot properly be initialized!");
} finally {
IOUtils.closeQuietly(in);
}
String[] arr = new String[lines.size() * 2];
int pos = 0;
StringBuffer buf = new StringBuffer();
for (int i = 0, c = lines.size(); i < c; i++) {
String line = lines.get(i);
int semicolon = line.indexOf(';');
if (semicolon > 0) {
String charName = line.substring(0, semicolon);
String rawUnicode = line.substring(semicolon + 1);
buf.setLength(0);
StringTokenizer tokenizer = new StringTokenizer(rawUnicode, " ", false);
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
assert token.length() == 4;
buf.append(hexToChar(token));
}
String unicode = buf.toString();
arr[pos] = unicode;
pos++;
arr[pos] = charName;
pos++;
assert !charNameToUnicodeMap.containsKey(charName);
charNameToUnicodeMap.put(charName, unicode);
}
}
return arr;
}
private static char hexToChar(String hex) {
return (char)Integer.parseInt(hex, 16);
}
public static String charToGlyphName(char ch) {
return stringToGlyph(Character.toString(ch));
}
public static String getUnicodeSequenceForGlyphName(String glyphName) {
int period = glyphName.indexOf('.');
if (period >= 0)
glyphName = glyphName.substring(0, period);
StringBuffer sb = new StringBuffer();
StringTokenizer tokenizer = new StringTokenizer(glyphName, "_", false);
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
String sequence = (String)CHARNAMES_TO_UNICODE.get(token);
if (sequence == null) {
if (token.startsWith("uni")) {
int len = token.length();
int pos = 3;
while (pos + 4 <= len) {
try {
sb.append(hexToChar(token.substring(pos, pos + 4)));
} catch (NumberFormatException nfe) {
return null;
}
pos += 4;
}
continue;
}
if (token.startsWith("u")) {
if (token.length() > 5)
return null;
if (token.length() < 5)
return null;
try {
sb.append(hexToChar(token.substring(1, 5)));
} catch (NumberFormatException nfe) {
return null;
}
}
continue;
}
sb.append(sequence);
}
if (sb.length() == 0)
return null;
return sb.toString();
}
@Deprecated
public static String glyphToString(String name) {
for (int i = 0; i < UNICODE_GLYPHS.length; i += 2) {
if (UNICODE_GLYPHS[i + 1].equals(name))
return UNICODE_GLYPHS[i];
}
return "";
}
public static String stringToGlyph(String name) {
for (int j = 0; j < UNICODE_GLYPHS.length; j += 2) {
if (UNICODE_GLYPHS[j].equals(name))
return UNICODE_GLYPHS[j + 1];
}
for (int i = 0; i < DINGBATS_GLYPHS.length; i += 2) {
if (DINGBATS_GLYPHS[i].equals(name))
return DINGBATS_GLYPHS[i + 1];
}
return "";
}
public static String[] getCharNameAlternativesFor(String charName) {
return (String[])CHARNAME_ALTERNATIVES.get(charName);
}
}

View file

@ -0,0 +1,243 @@
# ###################################################################################
# Copyright (c) 1997,1998,2002,2007 Adobe Systems Incorporated
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this documentation file to use, copy, publish, distribute,
# sublicense, and/or sell copies of the documentation, and to permit
# others to do the same, provided that:
# - No modification, editing or other alteration of this document is
# allowed; and
# - The above copyright notice and this permission notice shall be
# included in all copies of the documentation.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this documentation file, to create their own derivative works
# from the content of this document to use, copy, publish, distribute,
# sublicense, and/or sell the derivative works, and to permit others to do
# the same, provided that the derived work is not represented as being a
# copy or version of this document.
#
# Adobe shall not be liable to any party for any loss of revenue or profit
# or for indirect, incidental, special, consequential, or other similar
# damages, whether based on tort (including without limitation negligence
# or strict liability), contract or other legal or equitable grounds even
# if Adobe has been advised or had reason to know of the possibility of
# such damages.Ê The Adobe materials are provided on an "AS IS" basis.Ê
# Adobe specifically disclaims all express, statutory, or implied
# warranties relating to the Adobe materials, including but not limited to
# those concerning merchantability or fitness for a particular purpose or
# non-infringement of any third party rights regarding the Adobe
# materials.
# ###################################################################################
# Name: ITC Zapf Dingbats Glyph List
# Table version: 2.0
# Date: September 20, 2002
#
# See http://partners.adobe.com/asn/developer/typeforum/unicodegn.html
#
# Format: Semicolon-delimited fields:
# (1) glyph name
# (2) Unicode scalar value
#
a100;275E
a101;2761
a102;2762
a103;2763
a104;2764
a105;2710
a106;2765
a107;2766
a108;2767
a109;2660
a10;2721
a110;2665
a111;2666
a112;2663
a117;2709
a118;2708
a119;2707
a11;261B
a120;2460
a121;2461
a122;2462
a123;2463
a124;2464
a125;2465
a126;2466
a127;2467
a128;2468
a129;2469
a12;261E
a130;2776
a131;2777
a132;2778
a133;2779
a134;277A
a135;277B
a136;277C
a137;277D
a138;277E
a139;277F
a13;270C
a140;2780
a141;2781
a142;2782
a143;2783
a144;2784
a145;2785
a146;2786
a147;2787
a148;2788
a149;2789
a14;270D
a150;278A
a151;278B
a152;278C
a153;278D
a154;278E
a155;278F
a156;2790
a157;2791
a158;2792
a159;2793
a15;270E
a160;2794
a161;2192
a162;27A3
a163;2194
a164;2195
a165;2799
a166;279B
a167;279C
a168;279D
a169;279E
a16;270F
a170;279F
a171;27A0
a172;27A1
a173;27A2
a174;27A4
a175;27A5
a176;27A6
a177;27A7
a178;27A8
a179;27A9
a17;2711
a180;27AB
a181;27AD
a182;27AF
a183;27B2
a184;27B3
a185;27B5
a186;27B8
a187;27BA
a188;27BB
a189;27BC
a18;2712
a190;27BD
a191;27BE
a192;279A
a193;27AA
a194;27B6
a195;27B9
a196;2798
a197;27B4
a198;27B7
a199;27AC
a19;2713
a1;2701
a200;27AE
a201;27B1
a202;2703
a203;2750
a204;2752
a205;276E
a206;2770
a20;2714
a21;2715
a22;2716
a23;2717
a24;2718
a25;2719
a26;271A
a27;271B
a28;271C
a29;2722
a2;2702
a30;2723
a31;2724
a32;2725
a33;2726
a34;2727
a35;2605
a36;2729
a37;272A
a38;272B
a39;272C
a3;2704
a40;272D
a41;272E
a42;272F
a43;2730
a44;2731
a45;2732
a46;2733
a47;2734
a48;2735
a49;2736
a4;260E
a50;2737
a51;2738
a52;2739
a53;273A
a54;273B
a55;273C
a56;273D
a57;273E
a58;273F
a59;2740
a5;2706
a60;2741
a61;2742
a62;2743
a63;2744
a64;2745
a65;2746
a66;2747
a67;2748
a68;2749
a69;274A
a6;271D
a70;274B
a71;25CF
a72;274D
a73;25A0
a74;274F
a75;2751
a76;25B2
a77;25BC
a78;25C6
a79;2756
a7;271E
a81;25D7
a82;2758
a83;2759
a84;275A
a85;276F
a86;2771
a87;2772
a88;2773
a89;2768
a8;271F
a90;2769
a91;276C
a92;276D
a93;276A
a94;276B
a95;2774
a96;2775
a97;275B
a98;275C
a99;275D
a9;2720
#-- end

View file

@ -0,0 +1,7 @@
package org.apache.xmlgraphics.image;
public final class GraphicsConstants {
public static final int DEFAULT_DPI = 72;
public static final int DEFAULT_SAMPLE_DPI = 300;
}

View file

@ -0,0 +1,632 @@
package org.apache.xmlgraphics.image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.DataBufferUShort;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import org.apache.xmlgraphics.image.rendered.Any2LsRGBRed;
import org.apache.xmlgraphics.image.rendered.Any2sRGBRed;
import org.apache.xmlgraphics.image.rendered.BufferedImageCachableRed;
import org.apache.xmlgraphics.image.rendered.CachableRed;
import org.apache.xmlgraphics.image.rendered.RenderedImageCachableRed;
public final class GraphicsUtil {
public static AffineTransform IDENTITY = new AffineTransform();
public static final ColorModel Linear_sRGB = new DirectColorModel(ColorSpace.getInstance(1004), 24, 16711680, 65280, 255, 0, false, 3);
public static final ColorModel Linear_sRGB_Pre = new DirectColorModel(ColorSpace.getInstance(1004), 32, 16711680, 65280, 255, -16777216, true, 3);
public static final ColorModel Linear_sRGB_Unpre = new DirectColorModel(ColorSpace.getInstance(1004), 32, 16711680, 65280, 255, -16777216, false, 3);
public static final ColorModel sRGB = new DirectColorModel(ColorSpace.getInstance(1000), 24, 16711680, 65280, 255, 0, false, 3);
public static final ColorModel sRGB_Pre = new DirectColorModel(ColorSpace.getInstance(1000), 32, 16711680, 65280, 255, -16777216, true, 3);
public static final ColorModel sRGB_Unpre = new DirectColorModel(ColorSpace.getInstance(1000), 32, 16711680, 65280, 255, -16777216, false, 3);
public static ColorModel makeLinear_sRGBCM(boolean premult) {
return premult ? Linear_sRGB_Pre : Linear_sRGB_Unpre;
}
public static BufferedImage makeLinearBufferedImage(int width, int height, boolean premult) {
ColorModel cm = makeLinear_sRGBCM(premult);
WritableRaster wr = cm.createCompatibleWritableRaster(width, height);
return new BufferedImage(cm, wr, premult, null);
}
public static CachableRed convertToLsRGB(CachableRed src) {
ColorModel cm = src.getColorModel();
ColorSpace cs = cm.getColorSpace();
if (cs == ColorSpace.getInstance(1004))
return src;
return new Any2LsRGBRed(src);
}
public static CachableRed convertTosRGB(CachableRed src) {
ColorModel cm = src.getColorModel();
ColorSpace cs = cm.getColorSpace();
if (cs == ColorSpace.getInstance(1000))
return src;
return new Any2sRGBRed(src);
}
public static CachableRed wrap(RenderedImage ri) {
if (ri instanceof CachableRed)
return (CachableRed)ri;
if (ri instanceof BufferedImage)
return new BufferedImageCachableRed((BufferedImage)ri);
return new RenderedImageCachableRed(ri);
}
public static void copyData_INT_PACK(Raster src, WritableRaster dst) {
int x0 = dst.getMinX();
if (x0 < src.getMinX())
x0 = src.getMinX();
int y0 = dst.getMinY();
if (y0 < src.getMinY())
y0 = src.getMinY();
int x1 = dst.getMinX() + dst.getWidth() - 1;
if (x1 > src.getMinX() + src.getWidth() - 1)
x1 = src.getMinX() + src.getWidth() - 1;
int y1 = dst.getMinY() + dst.getHeight() - 1;
if (y1 > src.getMinY() + src.getHeight() - 1)
y1 = src.getMinY() + src.getHeight() - 1;
int width = x1 - x0 + 1;
int height = y1 - y0 + 1;
SinglePixelPackedSampleModel srcSPPSM = (SinglePixelPackedSampleModel)src.getSampleModel();
int srcScanStride = srcSPPSM.getScanlineStride();
DataBufferInt srcDB = (DataBufferInt)src.getDataBuffer();
int[] srcPixels = srcDB.getBankData()[0];
int srcBase = srcDB.getOffset() + srcSPPSM.getOffset(x0 - src.getSampleModelTranslateX(), y0 - src.getSampleModelTranslateY());
SinglePixelPackedSampleModel dstSPPSM = (SinglePixelPackedSampleModel)dst.getSampleModel();
int dstScanStride = dstSPPSM.getScanlineStride();
DataBufferInt dstDB = (DataBufferInt)dst.getDataBuffer();
int[] dstPixels = dstDB.getBankData()[0];
int dstBase = dstDB.getOffset() + dstSPPSM.getOffset(x0 - dst.getSampleModelTranslateX(), y0 - dst.getSampleModelTranslateY());
if (srcScanStride == dstScanStride && srcScanStride == width) {
System.arraycopy(srcPixels, srcBase, dstPixels, dstBase, width * height);
} else if (width > 128) {
int srcSP = srcBase;
int dstSP = dstBase;
for (int y = 0; y < height; y++) {
System.arraycopy(srcPixels, srcSP, dstPixels, dstSP, width);
srcSP += srcScanStride;
dstSP += dstScanStride;
}
} else {
for (int y = 0; y < height; y++) {
int srcSP = srcBase + y * srcScanStride;
int dstSP = dstBase + y * dstScanStride;
for (int x = 0; x < width; x++)
dstPixels[dstSP++] = srcPixels[srcSP++];
}
}
}
public static void copyData_FALLBACK(Raster src, WritableRaster dst) {
int x0 = dst.getMinX();
if (x0 < src.getMinX())
x0 = src.getMinX();
int y0 = dst.getMinY();
if (y0 < src.getMinY())
y0 = src.getMinY();
int x1 = dst.getMinX() + dst.getWidth() - 1;
if (x1 > src.getMinX() + src.getWidth() - 1)
x1 = src.getMinX() + src.getWidth() - 1;
int y1 = dst.getMinY() + dst.getHeight() - 1;
if (y1 > src.getMinY() + src.getHeight() - 1)
y1 = src.getMinY() + src.getHeight() - 1;
int width = x1 - x0 + 1;
int[] data = null;
for (int y = y0; y <= y1; y++) {
data = src.getPixels(x0, y, width, 1, data);
dst.setPixels(x0, y, width, 1, data);
}
}
public static void copyData(Raster src, WritableRaster dst) {
if (is_INT_PACK_Data(src.getSampleModel(), false) && is_INT_PACK_Data(dst.getSampleModel(), false)) {
copyData_INT_PACK(src, dst);
return;
}
copyData_FALLBACK(src, dst);
}
public static WritableRaster copyRaster(Raster ras) {
return copyRaster(ras, ras.getMinX(), ras.getMinY());
}
public static WritableRaster copyRaster(Raster ras, int minX, int minY) {
WritableRaster ret = Raster.createWritableRaster(ras.getSampleModel(), new Point(0, 0));
ret = ret.createWritableChild(ras.getMinX() - ras.getSampleModelTranslateX(), ras.getMinY() - ras.getSampleModelTranslateY(), ras.getWidth(), ras.getHeight(), minX, minY, null);
DataBuffer srcDB = ras.getDataBuffer();
DataBuffer retDB = ret.getDataBuffer();
if (srcDB.getDataType() != retDB.getDataType())
throw new IllegalArgumentException("New DataBuffer doesn't match original");
int len = srcDB.getSize();
int banks = srcDB.getNumBanks();
int[] offsets = srcDB.getOffsets();
for (int b = 0; b < banks; b++) {
DataBufferByte dataBufferByte1;
DataBufferInt dataBufferInt1;
DataBufferShort dataBufferShort1;
DataBufferUShort srcDBT;
DataBufferByte dataBufferByte2;
DataBufferInt dataBufferInt2;
DataBufferShort dataBufferShort2;
DataBufferUShort retDBT;
switch (srcDB.getDataType()) {
case 0:
dataBufferByte1 = (DataBufferByte)srcDB;
dataBufferByte2 = (DataBufferByte)retDB;
System.arraycopy(dataBufferByte1.getData(b), offsets[b], dataBufferByte2.getData(b), offsets[b], len);
break;
case 3:
dataBufferInt1 = (DataBufferInt)srcDB;
dataBufferInt2 = (DataBufferInt)retDB;
System.arraycopy(dataBufferInt1.getData(b), offsets[b], dataBufferInt2.getData(b), offsets[b], len);
break;
case 2:
dataBufferShort1 = (DataBufferShort)srcDB;
dataBufferShort2 = (DataBufferShort)retDB;
System.arraycopy(dataBufferShort1.getData(b), offsets[b], dataBufferShort2.getData(b), offsets[b], len);
break;
case 1:
srcDBT = (DataBufferUShort)srcDB;
retDBT = (DataBufferUShort)retDB;
System.arraycopy(srcDBT.getData(b), offsets[b], retDBT.getData(b), offsets[b], len);
break;
default:
throw new UnsupportedOperationException("unsupported data type: " + srcDB.getDataType());
}
}
return ret;
}
public static WritableRaster makeRasterWritable(Raster ras) {
return makeRasterWritable(ras, ras.getMinX(), ras.getMinY());
}
public static WritableRaster makeRasterWritable(Raster ras, int minX, int minY) {
WritableRaster ret = Raster.createWritableRaster(ras.getSampleModel(), ras.getDataBuffer(), new Point(0, 0));
ret = ret.createWritableChild(ras.getMinX() - ras.getSampleModelTranslateX(), ras.getMinY() - ras.getSampleModelTranslateY(), ras.getWidth(), ras.getHeight(), minX, minY, null);
return ret;
}
public static ColorModel coerceColorModel(ColorModel cm, boolean newAlphaPreMult) {
if (cm.isAlphaPremultiplied() == newAlphaPreMult)
return cm;
WritableRaster wr = cm.createCompatibleWritableRaster(1, 1);
return cm.coerceData(wr, newAlphaPreMult);
}
public static ColorModel coerceData(WritableRaster wr, ColorModel cm, boolean newAlphaPreMult) {
if (!cm.hasAlpha())
return cm;
if (cm.isAlphaPremultiplied() == newAlphaPreMult)
return cm;
if (newAlphaPreMult) {
multiplyAlpha(wr);
} else {
divideAlpha(wr);
}
return coerceColorModel(cm, newAlphaPreMult);
}
public static void multiplyAlpha(WritableRaster wr) {
if (is_BYTE_COMP_Data(wr.getSampleModel())) {
mult_BYTE_COMP_Data(wr);
} else if (is_INT_PACK_Data(wr.getSampleModel(), true)) {
mult_INT_PACK_Data(wr);
} else {
int[] pixel = null;
int bands = wr.getNumBands();
float norm = 0.003921569F;
int x0 = wr.getMinX();
int x1 = x0 + wr.getWidth();
int y0 = wr.getMinY();
int y1 = y0 + wr.getHeight();
for (int y = y0; y < y1; y++) {
for (int x = x0; x < x1; x++) {
pixel = wr.getPixel(x, y, pixel);
int a = pixel[bands - 1];
if (a >= 0 && a < 255) {
float alpha = (float)a * norm;
for (int b = 0; b < bands - 1; b++)
pixel[b] = (int)((float)pixel[b] * alpha + 0.5F);
wr.setPixel(x, y, pixel);
}
}
}
}
}
public static void divideAlpha(WritableRaster wr) {
if (is_BYTE_COMP_Data(wr.getSampleModel())) {
divide_BYTE_COMP_Data(wr);
} else if (is_INT_PACK_Data(wr.getSampleModel(), true)) {
divide_INT_PACK_Data(wr);
} else {
int bands = wr.getNumBands();
int[] pixel = null;
int x0 = wr.getMinX();
int x1 = x0 + wr.getWidth();
int y0 = wr.getMinY();
int y1 = y0 + wr.getHeight();
for (int y = y0; y < y1; y++) {
for (int x = x0; x < x1; x++) {
pixel = wr.getPixel(x, y, pixel);
int a = pixel[bands - 1];
if (a > 0 && a < 255) {
float ialpha = 255.0F / (float)a;
for (int b = 0; b < bands - 1; b++)
pixel[b] = (int)((float)pixel[b] * ialpha + 0.5F);
wr.setPixel(x, y, pixel);
}
}
}
}
}
public static void copyData(BufferedImage src, BufferedImage dst) {
Rectangle srcRect = new Rectangle(0, 0, src.getWidth(), src.getHeight());
copyData(src, srcRect, dst, new Point(0, 0));
}
public static void copyData(BufferedImage src, Rectangle srcRect, BufferedImage dst, Point destP) {
boolean srcAlpha = src.getColorModel().hasAlpha();
boolean dstAlpha = dst.getColorModel().hasAlpha();
if (srcAlpha == dstAlpha && (
!srcAlpha || src.isAlphaPremultiplied() == dst.isAlphaPremultiplied())) {
copyData(src.getRaster(), dst.getRaster());
return;
}
int[] pixel = null;
Raster srcR = src.getRaster();
WritableRaster dstR = dst.getRaster();
int bands = dstR.getNumBands();
int dx = destP.x - srcRect.x;
int dy = destP.y - srcRect.y;
int w = srcRect.width;
int x0 = srcRect.x;
int y0 = srcRect.y;
int y1 = y0 + srcRect.height - 1;
if (!srcAlpha) {
int[] oPix = new int[bands * w];
int out = w * bands - 1;
while (out >= 0) {
oPix[out] = 255;
out -= bands;
}
for (int y = y0; y <= y1; y++) {
pixel = srcR.getPixels(x0, y, w, 1, pixel);
int in = w * (bands - 1) - 1;
out = w * bands - 2;
switch (bands) {
case 4:
while (in >= 0) {
oPix[out--] = pixel[in--];
oPix[out--] = pixel[in--];
oPix[out--] = pixel[in--];
out--;
}
break;
default:
while (in >= 0) {
for (int b = 0; b < bands - 1; b++)
oPix[out--] = pixel[in--];
out--;
}
break;
}
dstR.setPixels(x0 + dx, y + dy, w, 1, oPix);
}
} else if (dstAlpha && dst.isAlphaPremultiplied()) {
int fpNorm = 65793, pt5 = 8388608;
for (int y = y0; y <= y1; y++) {
pixel = srcR.getPixels(x0, y, w, 1, pixel);
int in = bands * w - 1;
switch (bands) {
case 4:
while (in >= 0) {
int a = pixel[in];
if (a == 255) {
in -= 4;
continue;
}
in--;
int alpha = fpNorm * a;
pixel[in] = pixel[in] * alpha + pt5 >>> 24;
in--;
pixel[in] = pixel[in] * alpha + pt5 >>> 24;
in--;
pixel[in] = pixel[in] * alpha + pt5 >>> 24;
in--;
}
break;
default:
while (in >= 0) {
int i = pixel[in];
if (i == 255) {
in -= bands;
continue;
}
in--;
int j = fpNorm * i;
for (int b = 0; b < bands - 1; b++) {
pixel[in] = pixel[in] * j + pt5 >>> 24;
in--;
}
}
break;
}
dstR.setPixels(x0 + dx, y + dy, w, 1, pixel);
}
} else if (dstAlpha && !dst.isAlphaPremultiplied()) {
int fpNorm = 16711680, pt5 = 32768;
for (int y = y0; y <= y1; y++) {
pixel = srcR.getPixels(x0, y, w, 1, pixel);
int in = bands * w - 1;
switch (bands) {
case 4:
while (in >= 0) {
int a = pixel[in];
if (a <= 0 || a >= 255) {
in -= 4;
continue;
}
in--;
int ialpha = fpNorm / a;
pixel[in] = pixel[in] * ialpha + pt5 >>> 16;
in--;
pixel[in] = pixel[in] * ialpha + pt5 >>> 16;
in--;
pixel[in] = pixel[in] * ialpha + pt5 >>> 16;
in--;
}
break;
default:
while (in >= 0) {
int i = pixel[in];
if (i <= 0 || i >= 255) {
in -= bands;
continue;
}
in--;
int j = fpNorm / i;
for (int b = 0; b < bands - 1; b++) {
pixel[in] = pixel[in] * j + pt5 >>> 16;
in--;
}
}
break;
}
dstR.setPixels(x0 + dx, y + dy, w, 1, pixel);
}
} else if (src.isAlphaPremultiplied()) {
int[] oPix = new int[bands * w];
int fpNorm = 16711680, pt5 = 32768;
for (int y = y0; y <= y1; y++) {
pixel = srcR.getPixels(x0, y, w, 1, pixel);
int in = (bands + 1) * w - 1;
int out = bands * w - 1;
while (in >= 0) {
int a = pixel[in];
in--;
if (a > 0) {
if (a < 255) {
int ialpha = fpNorm / a;
for (int j = 0; j < bands; j++)
oPix[out--] = pixel[in--] * ialpha + pt5 >>> 16;
continue;
}
for (int i = 0; i < bands; i++)
oPix[out--] = pixel[in--];
continue;
}
in -= bands;
for (int b = 0; b < bands; b++)
oPix[out--] = 255;
}
dstR.setPixels(x0 + dx, y + dy, w, 1, oPix);
}
} else {
Rectangle dstRect = new Rectangle(destP.x, destP.y, srcRect.width, srcRect.height);
for (int b = 0; b < bands; b++)
copyBand(srcR, srcRect, b, dstR, dstRect, b);
}
}
public static void copyBand(Raster src, int srcBand, WritableRaster dst, int dstBand) {
Rectangle sR = src.getBounds();
Rectangle dR = dst.getBounds();
Rectangle cpR = sR.intersection(dR);
copyBand(src, cpR, srcBand, dst, cpR, dstBand);
}
public static void copyBand(Raster src, Rectangle sR, int sBand, WritableRaster dst, Rectangle dR, int dBand) {
int width, height;
int dy = dR.y - sR.y;
int dx = dR.x - sR.x;
sR = sR.intersection(src.getBounds());
dR = dR.intersection(dst.getBounds());
if (dR.width < sR.width) {
width = dR.width;
} else {
width = sR.width;
}
if (dR.height < sR.height) {
height = dR.height;
} else {
height = sR.height;
}
int x = sR.x + dx;
int[] samples = null;
for (int y = sR.y; y < sR.y + height; y++) {
samples = src.getSamples(sR.x, y, width, 1, sBand, samples);
dst.setSamples(x, y + dy, width, 1, dBand, samples);
}
}
public static boolean is_INT_PACK_Data(SampleModel sm, boolean requireAlpha) {
if (!(sm instanceof SinglePixelPackedSampleModel))
return false;
if (sm.getDataType() != 3)
return false;
SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)sm;
int[] masks = sppsm.getBitMasks();
if (masks.length == 3) {
if (requireAlpha)
return false;
} else if (masks.length != 4) {
return false;
}
if (masks[0] != 16711680)
return false;
if (masks[1] != 65280)
return false;
if (masks[2] != 255)
return false;
if (masks.length == 4 && masks[3] != -16777216)
return false;
return true;
}
public static boolean is_BYTE_COMP_Data(SampleModel sm) {
if (!(sm instanceof ComponentSampleModel))
return false;
if (sm.getDataType() != 0)
return false;
return true;
}
protected static void divide_INT_PACK_Data(WritableRaster wr) {
SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
int width = wr.getWidth();
int scanStride = sppsm.getScanlineStride();
DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
int base = db.getOffset() + sppsm.getOffset(wr.getMinX() - wr.getSampleModelTranslateX(), wr.getMinY() - wr.getSampleModelTranslateY());
int[] pixels = db.getBankData()[0];
for (int y = 0; y < wr.getHeight(); y++) {
int sp = base + y * scanStride;
int end = sp + width;
while (sp < end) {
int pixel = pixels[sp];
int a = pixel >>> 24;
if (a <= 0) {
pixels[sp] = 16777215;
} else if (a < 255) {
int aFP = 16711680 / a;
pixels[sp] = a << 24 | ((pixel & 0xFF0000) >> 16) * aFP & 0xFF0000 | (((pixel & 0xFF00) >> 8) * aFP & 0xFF0000) >> 8 | ((pixel & 0xFF) * aFP & 0xFF0000) >> 16;
}
sp++;
}
}
}
protected static void mult_INT_PACK_Data(WritableRaster wr) {
SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
int width = wr.getWidth();
int scanStride = sppsm.getScanlineStride();
DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
int base = db.getOffset() + sppsm.getOffset(wr.getMinX() - wr.getSampleModelTranslateX(), wr.getMinY() - wr.getSampleModelTranslateY());
int[] pixels = db.getBankData()[0];
for (int y = 0; y < wr.getHeight(); y++) {
int sp = base + y * scanStride;
int end = sp + width;
while (sp < end) {
int pixel = pixels[sp];
int a = pixel >>> 24;
if (a >= 0 && a < 255)
pixels[sp] = a << 24 | (pixel & 0xFF0000) * a >> 8 & 0xFF0000 | (pixel & 0xFF00) * a >> 8 & 0xFF00 | (pixel & 0xFF) * a >> 8 & 0xFF;
sp++;
}
}
}
protected static void divide_BYTE_COMP_Data(WritableRaster wr) {
ComponentSampleModel csm = (ComponentSampleModel)wr.getSampleModel();
int width = wr.getWidth();
int scanStride = csm.getScanlineStride();
int pixStride = csm.getPixelStride();
int[] bandOff = csm.getBandOffsets();
DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
int base = db.getOffset() + csm.getOffset(wr.getMinX() - wr.getSampleModelTranslateX(), wr.getMinY() - wr.getSampleModelTranslateY());
int aOff = bandOff[bandOff.length - 1];
int bands = bandOff.length - 1;
byte[] pixels = db.getBankData()[0];
for (int y = 0; y < wr.getHeight(); y++) {
int sp = base + y * scanStride;
int end = sp + width * pixStride;
while (sp < end) {
int a = pixels[sp + aOff] & 0xFF;
if (a == 0) {
for (int b = 0; b < bands; b++)
pixels[sp + bandOff[b]] = -1;
} else if (a < 255) {
int aFP = 16711680 / a;
for (int b = 0; b < bands; b++) {
int i = sp + bandOff[b];
pixels[i] = (byte)((pixels[i] & 0xFF) * aFP >>> 16);
}
}
sp += pixStride;
}
}
}
protected static void mult_BYTE_COMP_Data(WritableRaster wr) {
ComponentSampleModel csm = (ComponentSampleModel)wr.getSampleModel();
int width = wr.getWidth();
int scanStride = csm.getScanlineStride();
int pixStride = csm.getPixelStride();
int[] bandOff = csm.getBandOffsets();
DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
int base = db.getOffset() + csm.getOffset(wr.getMinX() - wr.getSampleModelTranslateX(), wr.getMinY() - wr.getSampleModelTranslateY());
int aOff = bandOff[bandOff.length - 1];
int bands = bandOff.length - 1;
byte[] pixels = db.getBankData()[0];
for (int y = 0; y < wr.getHeight(); y++) {
int sp = base + y * scanStride;
int end = sp + width * pixStride;
while (sp < end) {
int a = pixels[sp + aOff] & 0xFF;
if (a != 255)
for (int b = 0; b < bands; b++) {
int i = sp + bandOff[b];
pixels[i] = (byte)((pixels[i] & 0xFF) * a >> 8);
}
sp += pixStride;
}
}
}
public static Raster getAlphaRaster(RenderedImage image) {
Raster alpha;
ColorModel cm = image.getColorModel();
if (!cm.hasAlpha() || cm.getTransparency() != 3)
throw new IllegalStateException("Image doesn't have an alpha channel");
if (image instanceof BufferedImage) {
alpha = ((BufferedImage)image).getAlphaRaster();
} else {
WritableRaster wraster = makeRasterWritable(image.getData());
alpha = image.getColorModel().getAlphaRaster(wraster);
}
return alpha;
}
}

View file

@ -0,0 +1,142 @@
FileCacheSeekableStream0=pos < 0.
FileSeekableStream0=pos < 0.
FloatDoubleColorModel0=transferType must be DataBuffer.TYPE_FLOAT or DataBuffer.TYPE_DOUBLE.
FloatDoubleColorModel10=elements required in the components array.
FloatDoubleColorModel1=getRed(int) not supported by this ColorModel.
FloatDoubleColorModel2=getGreen(int) not supported by this ColorModel.
FloatDoubleColorModel3=getBlue(int) not supported by this ColorModel.
FloatDoubleColorModel4=getAlpha(int) not supported by this ColorModel.
FloatDoubleColorModel5=getRGB(int) not supported by this ColorModel.
FloatDoubleColorModel6=raster transfer type must match that of this ColorModel.
FloatDoubleColorModel7=Type of pixel does not match transfer type.
FloatDoubleColorModel8=pixel array is not large enough to hold all color/alpha components.
FloatDoubleColorModel9=Pixel values for FloatDoubleColorModel cannot be represented as a single integer.
MemoryCacheSeekableStream0=pos < 0.
PNGCodec0=PNG encoding not supported yet.
PNGDecodeParam0=User exponent must not be negative.
PNGDecodeParam1=Display exponent must not be negative.
PNGEncodeParam0=Bad palette length.
PNGEncodeParam10=Transparent RGB value has not been set.
PNGEncodeParam11=Grayscale bit depth has not been set.
PNGEncodeParam12=Chromaticity has not been set.
PNGEncodeParam13=Gamma has not been set.
PNGEncodeParam14=Palette histogram has not been set.
PNGEncodeParam15=ICC profile has not been set.
PNGEncodeParam16=Physical dimension information has not been set.
PNGEncodeParam17=Suggested palette information has not been set.
PNGEncodeParam18=Significant bits values have not been set.
PNGEncodeParam19=sRGB rendering intent has not been set.
PNGEncodeParam1=Not divisible by 3.
PNGEncodeParam20=Uncompressed text strings have not been set.
PNGEncodeParam21=Modification time has not been set.
PNGEncodeParam22=Compressed text strings have not been set.
PNGEncodeParam23='unsetBackground' not implemented by the superclass 'PNGEncodeParam'.
PNGEncodeParam24='isBackgroundSet' not implemented by the superclass 'PNGEncodeParam'.
PNGEncodeParam25=Bit shift must be greater than 0.
PNGEncodeParam26=Bit depth must be 8 or 16.
PNGEncodeParam27=RGB value must have three components.
PNGEncodeParam28=Chromaticity array must be non-empty.
PNGEncodeParam2=Bit depth not equal to 1, 2, 4, or 8.
PNGEncodeParam3=RGB palette has not been set.
PNGEncodeParam4=background palette index has not been set.
PNGEncodeParam5=Palette transparency has not been set.
PNGEncodeParam6=Background gray level has not been set.
PNGEncodeParam7=Transparent gray value has not been set.
PNGEncodeParam8=Bit shift has not been set.
PNGEncodeParam9=RGB background color has not been set.
PNGImageDecoder0=PNG magic number not found.
PNGImageDecoder10=Unsupported PNG filter method (not 0).
PNGImageDecoder11=Unsupported PNG interlace method (not 0 or 1).
PNGImageDecoder12=Unknown PNG pHYs unit specifier (not 0 or 1).
PNGImageDecoder13=Illegal PNG sBit value (< 0 or > bit depth).
PNGImageDecoder14=Too many PNG alpha palette entries.
PNGImageDecoder15=PNG image already has alpha, can't have tRNS chunk.
PNGImageDecoder16=Unknown PNG filter type (not 0-4).
PNGImageDecoder17=Illegal tile requested from a PNG image.
PNGImageDecoder18=PNG can't have hIST chunk without a PLTE chunk.
PNGImageDecoder19=Illegal page requested from a PNG file.
PNGImageDecoder1=Error reading PNG header.
PNGImageDecoder2=I/O error reading PNG file.
PNGImageDecoder3=Illegal bit depth for a PNG image.
PNGImageDecoder4=Bad color type for a PNG image.
PNGImageDecoder5=An RGB PNG image can't have a bit depth less than 8.
PNGImageDecoder6=A palette-color PNG image can't have a bit depth of 16.
PNGImageDecoder7=A PNG Gray+Alpha image can't have a bit depth less than 8.
PNGImageDecoder8=A PNG RGB+Alpha image can't have a bit depth less than 8.
PNGImageDecoder9=Unsupported PNG compression method (not 0).
PNGImageEncoder0=Sample size not equal to bit depth.
PNGImageEncoder1=Bit depth greater than 16.
PNGImageEncoder2=Bit depth less than 1 or greater than 8.
PNGImageEncoder3=Number of bands not equal to 1.
PNGImageEncoder4=PNG encode parameter must be Palette or Gray.
PropertySet0=Not implemented.
RasterFactory0=Number of bands must be greater than 0.
RasterFactory10=parentY lies outside raster.
RasterFactory11=(parentX + width) is outside raster.
RasterFactory12=(parentY + height) is outside raster.
RasterFactory13=Illegal value for transparency.
RasterFactory14=Transparency cannot be opaque when useAlpha is true.
RasterFactory15=bitsPerBands must be greater than 0.
RasterFactory16=Size of array must be smaller than Integer.MAX_VALUE.
RasterFactory1=Bank indices array is null.
RasterFactory2=bankIndices.length != bandOffsets.length
RasterFactory3=Unsupported data type.
RasterFactory4=Band offsets array is null.
RasterFactory5=Offsets between bands must be less than the scanline stride.
RasterFactory6=Pixel stride times width must be less than the scanline stride.
RasterFactory7=Pixel stride must be greater than or equal to the offset between bands.
RasterFactory8=This method does not support the input data type.
RasterFactory9=parentX lies outside raster.
SegmentedSeekableStream0=Source stream does not support seeking backwards.
SingleTileRenderedImage0=Illegal tile requested from a SingleTileRenderedImage.
TIFFImage0=Planar (band-sequential) format TIFF is not supported.
TIFFImage1=All samples must have the same bit depth.
TIFFImage2=All samples must have the same data format.
TIFFImage3=Unsupported combination of bit depth and sample format.
TIFFImage4=Unsupported image type.
TIFFImage5=Strip offsets, a required field, is not present in the TIFF file.
TIFFImage5=Strip byte counts, a required field, is not present in the TIFF file.
TIFFImage7=Unsupported compression type for non-bilevel data.
TIFFImage8=Illegal value for predictor in TIFF file.
TIFFImage9=Sample size must be 8 for horizontal differencing predictor.
TIFFImage10=Unsupported compression type
TIFFImage11=Colormap must be present for a Palette Color image.
TIFFImage12=Illegal tile requested from a TIFFImage.
TIFFImage13=IOException occured while reading TIFF image data
TIFFImage14=Unable to decode packbits compressed data - not enough data
TIFFImage15=Decoding of old style JPEG-in-TIFF data is not supported.
TIFFImage17=Error inflating data
TIFFImage18=Unsupported field type
TIFFImage19=Unsupported number of bands
TIFFImage20=Unsupported data type
TIFFImageDecoder0=Illegal page requested from a TIFF file.
TIFFImageEncoder0=All samples must have the same bit depth.
TIFFImageEncoder1=1- and 4-bit data supported for single band images only.
TIFFImageEncoder2=Byte buffers require 1-, 4-, or b-bit data.
TIFFImageEncoder3=Short or unsigned short buffers require 16-bit data.
TIFFImageEncoder4=Int or float buffers require 32-bit data.
TIFFImageEncoder5=Unsupported output data type.
TIFFImageEncoder6=TIFF encoder does not support (unsigned) short palette images.
TIFFImageEncoder7=Invalid image - An image with sampleSize of 1 bit must have IndexColorModel with mapsize of 2.
TIFFImageEncoder8=Image type not supported for output.
TIFFImageEncoder9=JPEG-in-TIFF encoding supported only for 8-bit samples and either 1 (grayscale) or 3 (RGB or YCbCr) samples per pixel.
TIFFImageEncoder10=Unsupported TIFFField type.
TIFFImageEncoder11=Extra images may not be used when encoding multiple page file.
TIFFImageEncoder12=JPEG compression not supported.
TIFFImageEncoder13=No output specified.
TIFFLZWDecoder0=TIFF 5.0 LZW codes are not supported.
TIFFFaxDecoder0=ERROR code word (0) encountered.
TIFFFaxDecoder1=EOL code word (15) encountered in White run.
TIFFFaxDecoder2=EOL code word (15) encountered in Black run.
TIFFFaxDecoder3=First scanline must be 1D encoded.
TIFFFaxDecoder4=Invalid code encountered while decoding 2D group 3 compressed data.
TIFFFaxDecoder5=Invalid code encountered while decoding 2D group 4 compressed data.
TIFFFaxDecoder6=Scanline must begin with EOL code word.
TIFFFaxDecoder7=TIFF_FILL_ORDER tag must be either 1 or 2.
TIFFFaxDecoder8=All fill bits preceding EOL code must be 0.
TIFFDirectory0=Unsupported TIFFField tag.
TIFFDirectory1=Bad endianness tag (not 0x4949 or 0x4d4d).
TIFFDirectory2=Bad magic number, should be 42.
TIFFDirectory3=Directory number too large.
TIFFEncodeParam0=Unsupported compression scheme specified.
TIFFEncodeParam1=Illegal DEFLATE compression level specified.

View file

@ -0,0 +1,26 @@
package org.apache.xmlgraphics.image.codec.png;
final class CRC {
private static int[] crcTable = new int[256];
static {
for (int n = 0; n < 256; n++) {
int c = n;
for (int k = 0; k < 8; k++) {
if ((c & 0x1) == 1) {
c = 0xEDB88320 ^ c >>> 1;
} else {
c >>>= 1;
}
crcTable[n] = c;
}
}
}
public static int updateCRC(int crc, byte[] data, int off, int len) {
int c = crc;
for (int n = 0; n < len; n++)
c = crcTable[(c ^ data[off + n]) & 0xFF] ^ c >>> 8;
return c;
}
}

View file

@ -0,0 +1,107 @@
package org.apache.xmlgraphics.image.codec.png;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
class ChunkStream extends OutputStream implements DataOutput {
private String type;
private ByteArrayOutputStream baos;
private DataOutputStream dos;
ChunkStream(String type) throws IOException {
this.type = type;
this.baos = new ByteArrayOutputStream();
this.dos = new DataOutputStream(this.baos);
}
public void write(byte[] b) throws IOException {
this.dos.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
this.dos.write(b, off, len);
}
public void write(int b) throws IOException {
this.dos.write(b);
}
public void writeBoolean(boolean v) throws IOException {
this.dos.writeBoolean(v);
}
public void writeByte(int v) throws IOException {
this.dos.writeByte(v);
}
public void writeBytes(String s) throws IOException {
this.dos.writeBytes(s);
}
public void writeChar(int v) throws IOException {
this.dos.writeChar(v);
}
public void writeChars(String s) throws IOException {
this.dos.writeChars(s);
}
public void writeDouble(double v) throws IOException {
this.dos.writeDouble(v);
}
public void writeFloat(float v) throws IOException {
this.dos.writeFloat(v);
}
public void writeInt(int v) throws IOException {
this.dos.writeInt(v);
}
public void writeLong(long v) throws IOException {
this.dos.writeLong(v);
}
public void writeShort(int v) throws IOException {
this.dos.writeShort(v);
}
public void writeUTF(String str) throws IOException {
this.dos.writeUTF(str);
}
public void writeToStream(DataOutputStream output) throws IOException {
byte[] typeSignature = new byte[4];
typeSignature[0] = (byte)this.type.charAt(0);
typeSignature[1] = (byte)this.type.charAt(1);
typeSignature[2] = (byte)this.type.charAt(2);
typeSignature[3] = (byte)this.type.charAt(3);
this.dos.flush();
this.baos.flush();
byte[] data = this.baos.toByteArray();
int len = data.length;
output.writeInt(len);
output.write(typeSignature);
output.write(data, 0, len);
int crc = -1;
crc = CRC.updateCRC(crc, typeSignature, 0, 4);
crc = CRC.updateCRC(crc, data, 0, len);
output.writeInt(crc ^ 0xFFFFFFFF);
}
public void close() throws IOException {
if (this.baos != null) {
this.baos.close();
this.baos = null;
}
if (this.dos != null) {
this.dos.close();
this.dos = null;
}
}
}

View file

@ -0,0 +1,67 @@
package org.apache.xmlgraphics.image.codec.png;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
class IDATOutputStream extends FilterOutputStream {
private static final byte[] typeSignature = new byte[] { 73, 68, 65, 84 };
private int bytesWritten = 0;
private int segmentLength;
private byte[] buffer;
public IDATOutputStream(OutputStream output, int segmentLength) {
super(output);
this.segmentLength = segmentLength;
this.buffer = new byte[segmentLength];
}
public void close() throws IOException {
flush();
}
private void writeInt(int x) throws IOException {
this.out.write(x >> 24);
this.out.write(x >> 16 & 0xFF);
this.out.write(x >> 8 & 0xFF);
this.out.write(x & 0xFF);
}
public void flush() throws IOException {
if (this.bytesWritten == 0)
return;
writeInt(this.bytesWritten);
this.out.write(typeSignature);
this.out.write(this.buffer, 0, this.bytesWritten);
int crc = -1;
crc = CRC.updateCRC(crc, typeSignature, 0, 4);
crc = CRC.updateCRC(crc, this.buffer, 0, this.bytesWritten);
writeInt(crc ^ 0xFFFFFFFF);
this.bytesWritten = 0;
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
while (len > 0) {
int bytes = Math.min(this.segmentLength - this.bytesWritten, len);
System.arraycopy(b, off, this.buffer, this.bytesWritten, bytes);
off += bytes;
len -= bytes;
this.bytesWritten += bytes;
if (this.bytesWritten == this.segmentLength)
flush();
}
}
public void write(int b) throws IOException {
this.buffer[this.bytesWritten++] = (byte)b;
if (this.bytesWritten == this.segmentLength)
flush();
}
}

View file

@ -0,0 +1,124 @@
package org.apache.xmlgraphics.image.codec.png;
import java.io.DataInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class PNGChunk {
int length;
int type;
byte[] data;
int crc;
String typeString;
protected static Log log = LogFactory.getLog(PNGChunk.class);
public enum ChunkType {
IHDR, PLTE, IDAT, IEND, bKGD, cHRM, gAMA, hIST, iCCP, iTXt, pHYs, sBIT, sPLT, sRGB, sTER, tEXt, tIME, tRNS, zTXt;
}
public PNGChunk(int length, int type, byte[] data, int crc) {
this.length = length;
this.type = type;
this.data = data;
this.crc = crc;
this.typeString = typeIntToString(this.type);
}
public int getLength() {
return this.length;
}
public int getType() {
return this.type;
}
public String getTypeString() {
return this.typeString;
}
public byte[] getData() {
return this.data;
}
public byte getByte(int offset) {
return this.data[offset];
}
public int getInt1(int offset) {
return this.data[offset] & 0xFF;
}
public int getInt2(int offset) {
return (this.data[offset] & 0xFF) << 8 | this.data[offset + 1] & 0xFF;
}
public int getInt4(int offset) {
return (this.data[offset] & 0xFF) << 24 | (this.data[offset + 1] & 0xFF) << 16 | (this.data[offset + 2] & 0xFF) << 8 | this.data[offset + 3] & 0xFF;
}
public String getString4(int offset) {
return "" + (char)this.data[offset] + (char)this.data[offset + 1] + (char)this.data[offset + 2] + (char)this.data[offset + 3];
}
public boolean isType(String typeName) {
return this.typeString.equals(typeName);
}
public static PNGChunk readChunk(DataInputStream distream) {
try {
int length = distream.readInt();
int type = distream.readInt();
byte[] data = new byte[length];
distream.readFully(data);
int crc = distream.readInt();
return new PNGChunk(length, type, data, crc);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String getChunkType(DataInputStream distream) {
try {
distream.mark(8);
distream.readInt();
int type = distream.readInt();
distream.reset();
return typeIntToString(type);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static String typeIntToString(int type) {
String typeString = "";
typeString = typeString + (char)(type >> 24);
typeString = typeString + (char)(type >> 16 & 0xFF);
typeString = typeString + (char)(type >> 8 & 0xFF);
typeString = typeString + (char)(type & 0xFF);
return typeString;
}
public static boolean skipChunk(DataInputStream distream) {
try {
int length = distream.readInt();
int type = distream.readInt();
int skipped = distream.skipBytes(length);
int crc = distream.readInt();
if (skipped != length) {
log.warn("Incorrect number of bytes skipped.");
return false;
}
return true;
} catch (Exception e) {
log.warn(e.getMessage());
return false;
}
}
}

View file

@ -0,0 +1,100 @@
package org.apache.xmlgraphics.image.codec.png;
import org.apache.xmlgraphics.image.codec.util.ImageDecodeParam;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
public class PNGDecodeParam implements ImageDecodeParam {
private boolean suppressAlpha = false;
public boolean getSuppressAlpha() {
return this.suppressAlpha;
}
public void setSuppressAlpha(boolean suppressAlpha) {
this.suppressAlpha = suppressAlpha;
}
private boolean expandPalette = false;
public boolean getExpandPalette() {
return this.expandPalette;
}
public void setExpandPalette(boolean expandPalette) {
this.expandPalette = expandPalette;
}
private boolean output8BitGray = false;
public boolean getOutput8BitGray() {
return this.output8BitGray;
}
public void setOutput8BitGray(boolean output8BitGray) {
this.output8BitGray = output8BitGray;
}
private boolean performGammaCorrection = true;
public boolean getPerformGammaCorrection() {
return this.performGammaCorrection;
}
public void setPerformGammaCorrection(boolean performGammaCorrection) {
this.performGammaCorrection = performGammaCorrection;
}
private float userExponent = 1.0F;
public float getUserExponent() {
return this.userExponent;
}
public void setUserExponent(float userExponent) {
if (userExponent <= 0.0F)
throw new IllegalArgumentException(PropertyUtil.getString("PNGDecodeParam0"));
this.userExponent = userExponent;
}
private float displayExponent = 2.2F;
public float getDisplayExponent() {
return this.displayExponent;
}
public void setDisplayExponent(float displayExponent) {
if (displayExponent <= 0.0F)
throw new IllegalArgumentException(PropertyUtil.getString("PNGDecodeParam1"));
this.displayExponent = displayExponent;
}
private boolean expandGrayAlpha = false;
public boolean getExpandGrayAlpha() {
return this.expandGrayAlpha;
}
public void setExpandGrayAlpha(boolean expandGrayAlpha) {
this.expandGrayAlpha = expandGrayAlpha;
}
private boolean generateEncodeParam = false;
private PNGEncodeParam encodeParam = null;
public boolean getGenerateEncodeParam() {
return this.generateEncodeParam;
}
public void setGenerateEncodeParam(boolean generateEncodeParam) {
this.generateEncodeParam = generateEncodeParam;
}
public PNGEncodeParam getEncodeParam() {
return this.encodeParam;
}
public void setEncodeParam(PNGEncodeParam encodeParam) {
this.encodeParam = encodeParam;
}
}

View file

@ -0,0 +1,710 @@
package org.apache.xmlgraphics.image.codec.png;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.xmlgraphics.image.codec.util.ImageEncodeParam;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
public abstract class PNGEncodeParam implements ImageEncodeParam {
public static final int INTENT_PERCEPTUAL = 0;
public static final int INTENT_RELATIVE = 1;
public static final int INTENT_SATURATION = 2;
public static final int INTENT_ABSOLUTE = 3;
public static final int PNG_FILTER_NONE = 0;
public static final int PNG_FILTER_SUB = 1;
public static final int PNG_FILTER_UP = 2;
public static final int PNG_FILTER_AVERAGE = 3;
public static final int PNG_FILTER_PAETH = 4;
protected int bitDepth;
public static PNGEncodeParam getDefaultEncodeParam(RenderedImage im) {
ColorModel colorModel = im.getColorModel();
if (colorModel instanceof java.awt.image.IndexColorModel)
return new Palette();
SampleModel sampleModel = im.getSampleModel();
int numBands = sampleModel.getNumBands();
if (numBands == 1 || numBands == 2)
return new Gray();
return new RGB();
}
public static class Palette extends PNGEncodeParam {
private boolean backgroundSet = false;
public void unsetBackground() {
this.backgroundSet = false;
}
public boolean isBackgroundSet() {
return this.backgroundSet;
}
public void setBitDepth(int bitDepth) {
if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 && bitDepth != 8)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam2"));
this.bitDepth = bitDepth;
this.bitDepthSet = true;
}
private int[] palette = null;
private boolean paletteSet = false;
private int backgroundPaletteIndex;
private int[] transparency;
public void setPalette(int[] rgb) {
if (rgb.length < 3 || rgb.length > 768)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam0"));
if (rgb.length % 3 != 0)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam1"));
this.palette = (int[])rgb.clone();
this.paletteSet = true;
}
public int[] getPalette() {
if (!this.paletteSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam3"));
return (int[])this.palette.clone();
}
public void unsetPalette() {
this.palette = null;
this.paletteSet = false;
}
public boolean isPaletteSet() {
return this.paletteSet;
}
public void setBackgroundPaletteIndex(int index) {
this.backgroundPaletteIndex = index;
this.backgroundSet = true;
}
public int getBackgroundPaletteIndex() {
if (!this.backgroundSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam4"));
return this.backgroundPaletteIndex;
}
public void setPaletteTransparency(byte[] alpha) {
this.transparency = new int[alpha.length];
for (int i = 0; i < alpha.length; i++)
this.transparency[i] = alpha[i] & 0xFF;
this.transparencySet = true;
}
public byte[] getPaletteTransparency() {
if (!this.transparencySet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam5"));
byte[] alpha = new byte[this.transparency.length];
for (int i = 0; i < alpha.length; i++)
alpha[i] = (byte)this.transparency[i];
return alpha;
}
}
public static class Gray extends PNGEncodeParam {
private boolean backgroundSet = false;
private int backgroundPaletteGray;
private int[] transparency;
private int bitShift;
public void unsetBackground() {
this.backgroundSet = false;
}
public boolean isBackgroundSet() {
return this.backgroundSet;
}
public void setBitDepth(int bitDepth) {
if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 && bitDepth != 8 && bitDepth != 16)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam2"));
this.bitDepth = bitDepth;
this.bitDepthSet = true;
}
public void setBackgroundGray(int gray) {
this.backgroundPaletteGray = gray;
this.backgroundSet = true;
}
public int getBackgroundGray() {
if (!this.backgroundSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam6"));
return this.backgroundPaletteGray;
}
public void setTransparentGray(int transparentGray) {
this.transparency = new int[1];
this.transparency[0] = transparentGray;
this.transparencySet = true;
}
public int getTransparentGray() {
if (!this.transparencySet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam7"));
int gray = this.transparency[0];
return gray;
}
private boolean bitShiftSet = false;
public void setBitShift(int bitShift) {
if (bitShift < 0)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam25"));
this.bitShift = bitShift;
this.bitShiftSet = true;
}
public int getBitShift() {
if (!this.bitShiftSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam8"));
return this.bitShift;
}
public void unsetBitShift() {
this.bitShiftSet = false;
}
public boolean isBitShiftSet() {
return this.bitShiftSet;
}
public boolean isBitDepthSet() {
return this.bitDepthSet;
}
}
public static class RGB extends PNGEncodeParam {
private boolean backgroundSet = false;
private int[] backgroundRGB;
private int[] transparency;
public void unsetBackground() {
this.backgroundSet = false;
}
public boolean isBackgroundSet() {
return this.backgroundSet;
}
public void setBitDepth(int bitDepth) {
if (bitDepth != 8 && bitDepth != 16)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam26"));
this.bitDepth = bitDepth;
this.bitDepthSet = true;
}
public void setBackgroundRGB(int[] rgb) {
if (rgb.length != 3)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam27"));
this.backgroundRGB = rgb;
this.backgroundSet = true;
}
public int[] getBackgroundRGB() {
if (!this.backgroundSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam9"));
return this.backgroundRGB;
}
public void setTransparentRGB(int[] transparentRGB) {
this.transparency = (int[])transparentRGB.clone();
this.transparencySet = true;
}
public int[] getTransparentRGB() {
if (!this.transparencySet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam10"));
return (int[])this.transparency.clone();
}
}
protected boolean bitDepthSet = false;
public abstract void setBitDepth(int paramInt);
public int getBitDepth() {
if (!this.bitDepthSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam11"));
return this.bitDepth;
}
public void unsetBitDepth() {
this.bitDepthSet = false;
}
private boolean useInterlacing = false;
public void setInterlacing(boolean useInterlacing) {
this.useInterlacing = useInterlacing;
}
public boolean getInterlacing() {
return this.useInterlacing;
}
public void unsetBackground() {
throw new RuntimeException(PropertyUtil.getString("PNGEncodeParam23"));
}
public boolean isBackgroundSet() {
throw new RuntimeException(PropertyUtil.getString("PNGEncodeParam24"));
}
private float[] chromaticity = null;
private boolean chromaticitySet = false;
private float gamma;
public void setChromaticity(float[] chromaticity) {
if (chromaticity.length != 8)
throw new IllegalArgumentException(PropertyUtil.getString("PNGEncodeParam28"));
this.chromaticity = (float[])chromaticity.clone();
this.chromaticitySet = true;
}
public void setChromaticity(float whitePointX, float whitePointY, float redX, float redY, float greenX, float greenY, float blueX, float blueY) {
float[] chroma = new float[8];
chroma[0] = whitePointX;
chroma[1] = whitePointY;
chroma[2] = redX;
chroma[3] = redY;
chroma[4] = greenX;
chroma[5] = greenY;
chroma[6] = blueX;
chroma[7] = blueY;
setChromaticity(chroma);
}
public float[] getChromaticity() {
if (!this.chromaticitySet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam12"));
return (float[])this.chromaticity.clone();
}
public void unsetChromaticity() {
this.chromaticity = null;
this.chromaticitySet = false;
}
public boolean isChromaticitySet() {
return this.chromaticitySet;
}
private boolean gammaSet = false;
public void setGamma(float gamma) {
this.gamma = gamma;
this.gammaSet = true;
}
public float getGamma() {
if (!this.gammaSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam13"));
return this.gamma;
}
public void unsetGamma() {
this.gammaSet = false;
}
public boolean isGammaSet() {
return this.gammaSet;
}
private int[] paletteHistogram = null;
private boolean paletteHistogramSet = false;
public void setPaletteHistogram(int[] paletteHistogram) {
this.paletteHistogram = (int[])paletteHistogram.clone();
this.paletteHistogramSet = true;
}
public int[] getPaletteHistogram() {
if (!this.paletteHistogramSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam14"));
return this.paletteHistogram;
}
public void unsetPaletteHistogram() {
this.paletteHistogram = null;
this.paletteHistogramSet = false;
}
public boolean isPaletteHistogramSet() {
return this.paletteHistogramSet;
}
private byte[] ICCProfileData = null;
private boolean ICCProfileDataSet = false;
public void setICCProfileData(byte[] ICCProfileData) {
this.ICCProfileData = (byte[])ICCProfileData.clone();
this.ICCProfileDataSet = true;
}
public byte[] getICCProfileData() {
if (!this.ICCProfileDataSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam15"));
return (byte[])this.ICCProfileData.clone();
}
public void unsetICCProfileData() {
this.ICCProfileData = null;
this.ICCProfileDataSet = false;
}
public boolean isICCProfileDataSet() {
return this.ICCProfileDataSet;
}
private int[] physicalDimension = null;
private boolean physicalDimensionSet = false;
public void setPhysicalDimension(int[] physicalDimension) {
this.physicalDimension = (int[])physicalDimension.clone();
this.physicalDimensionSet = true;
}
public void setPhysicalDimension(int xPixelsPerUnit, int yPixelsPerUnit, int unitSpecifier) {
int[] pd = new int[3];
pd[0] = xPixelsPerUnit;
pd[1] = yPixelsPerUnit;
pd[2] = unitSpecifier;
setPhysicalDimension(pd);
}
public int[] getPhysicalDimension() {
if (!this.physicalDimensionSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam16"));
return (int[])this.physicalDimension.clone();
}
public void unsetPhysicalDimension() {
this.physicalDimension = null;
this.physicalDimensionSet = false;
}
public boolean isPhysicalDimensionSet() {
return this.physicalDimensionSet;
}
private PNGSuggestedPaletteEntry[] suggestedPalette = null;
private boolean suggestedPaletteSet = false;
public void setSuggestedPalette(PNGSuggestedPaletteEntry[] palette) {
this.suggestedPalette = (PNGSuggestedPaletteEntry[])palette.clone();
this.suggestedPaletteSet = true;
}
public PNGSuggestedPaletteEntry[] getSuggestedPalette() {
if (!this.suggestedPaletteSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam17"));
return (PNGSuggestedPaletteEntry[])this.suggestedPalette.clone();
}
public void unsetSuggestedPalette() {
this.suggestedPalette = null;
this.suggestedPaletteSet = false;
}
public boolean isSuggestedPaletteSet() {
return this.suggestedPaletteSet;
}
private int[] significantBits = null;
private boolean significantBitsSet = false;
private int SRGBIntent;
public void setSignificantBits(int[] significantBits) {
this.significantBits = (int[])significantBits.clone();
this.significantBitsSet = true;
}
public int[] getSignificantBits() {
if (!this.significantBitsSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam18"));
return (int[])this.significantBits.clone();
}
public void unsetSignificantBits() {
this.significantBits = null;
this.significantBitsSet = false;
}
public boolean isSignificantBitsSet() {
return this.significantBitsSet;
}
private boolean SRGBIntentSet = false;
public void setSRGBIntent(int SRGBIntent) {
this.SRGBIntent = SRGBIntent;
this.SRGBIntentSet = true;
}
public int getSRGBIntent() {
if (!this.SRGBIntentSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam19"));
return this.SRGBIntent;
}
public void unsetSRGBIntent() {
this.SRGBIntentSet = false;
}
public boolean isSRGBIntentSet() {
return this.SRGBIntentSet;
}
private String[] text = null;
private boolean textSet = false;
private Date modificationTime;
public void setText(String[] text) {
this.text = text;
this.textSet = true;
}
public String[] getText() {
if (!this.textSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam20"));
return this.text;
}
public void unsetText() {
this.text = null;
this.textSet = false;
}
public boolean isTextSet() {
return this.textSet;
}
private boolean modificationTimeSet = false;
public void setModificationTime(Date modificationTime) {
this.modificationTime = modificationTime;
this.modificationTimeSet = true;
}
public Date getModificationTime() {
if (!this.modificationTimeSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam21"));
return this.modificationTime;
}
public void unsetModificationTime() {
this.modificationTime = null;
this.modificationTimeSet = false;
}
public boolean isModificationTimeSet() {
return this.modificationTimeSet;
}
boolean transparencySet = false;
public void unsetTransparency() {
this.transparencySet = false;
}
public boolean isTransparencySet() {
return this.transparencySet;
}
private String[] zText = null;
private boolean zTextSet = false;
public void setCompressedText(String[] text) {
this.zText = text;
this.zTextSet = true;
}
public String[] getCompressedText() {
if (!this.zTextSet)
throw new IllegalStateException(PropertyUtil.getString("PNGEncodeParam22"));
return this.zText;
}
public void unsetCompressedText() {
this.zText = null;
this.zTextSet = false;
}
public boolean isCompressedTextSet() {
return this.zTextSet;
}
List chunkType = new ArrayList();
List chunkData = new ArrayList();
public synchronized void addPrivateChunk(String type, byte[] data) {
this.chunkType.add(type);
this.chunkData.add(data.clone());
}
public synchronized int getNumPrivateChunks() {
return this.chunkType.size();
}
public synchronized String getPrivateChunkType(int index) {
return this.chunkType.get(index);
}
public synchronized byte[] getPrivateChunkData(int index) {
return this.chunkData.get(index);
}
public synchronized void removeUnsafeToCopyPrivateChunks() {
List<String> newChunkType = new ArrayList();
List<byte[]> newChunkData = new ArrayList();
int len = getNumPrivateChunks();
for (int i = 0; i < len; i++) {
String type = getPrivateChunkType(i);
char lastChar = type.charAt(3);
if (lastChar >= 'a' && lastChar <= 'z') {
newChunkType.add(type);
newChunkData.add(getPrivateChunkData(i));
}
}
this.chunkType = newChunkType;
this.chunkData = newChunkData;
}
public synchronized void removeAllPrivateChunks() {
this.chunkType = new ArrayList();
this.chunkData = new ArrayList();
}
private static int abs(int x) {
return (x < 0) ? -x : x;
}
public static int paethPredictor(int a, int b, int c) {
int p = a + b - c;
int pa = abs(p - a);
int pb = abs(p - b);
int pc = abs(p - c);
if (pa <= pb && pa <= pc)
return a;
if (pb <= pc)
return b;
return c;
}
public int filterRow(byte[] currRow, byte[] prevRow, byte[][] scratchRows, int bytesPerRow, int bytesPerPixel) {
int[] badness = { 0, 0, 0, 0, 0 };
for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
int curr = currRow[i] & 0xFF;
int left = currRow[i - bytesPerPixel] & 0xFF;
int up = prevRow[i] & 0xFF;
int upleft = prevRow[i - bytesPerPixel] & 0xFF;
badness[0] = badness[0] + curr;
int diff = curr - left;
scratchRows[1][i] = (byte)diff;
badness[1] = badness[1] + ((diff > 0) ? diff : -diff);
diff = curr - up;
scratchRows[2][i] = (byte)diff;
badness[2] = badness[2] + ((diff >= 0) ? diff : -diff);
diff = curr - (left + up >> 1);
scratchRows[3][i] = (byte)diff;
badness[3] = badness[3] + ((diff >= 0) ? diff : -diff);
int pa = up - upleft;
int pb = left - upleft;
if (pa < 0) {
if (pb < 0) {
if (pa >= pb) {
diff = curr - left;
} else {
diff = curr - up;
}
} else {
int pc = pa + pb;
pa = -pa;
if (pa <= pb) {
if (pa <= pc) {
diff = curr - left;
} else {
diff = curr - upleft;
}
} else if (pb <= -pc) {
diff = curr - up;
} else {
diff = curr - upleft;
}
}
} else if (pb < 0) {
pb = -pb;
if (pa <= pb) {
int pc = pb - pa;
if (pa <= pc) {
diff = curr - left;
} else if (pb == pc) {
diff = curr - up;
} else {
diff = curr - upleft;
}
} else {
int pc = pa - pb;
if (pb <= pc) {
diff = curr - up;
} else {
diff = curr - upleft;
}
}
} else if (pa <= pb) {
diff = curr - left;
} else {
diff = curr - up;
}
scratchRows[4][i] = (byte)diff;
badness[4] = badness[4] + ((diff >= 0) ? diff : -diff);
}
int filterType = 0;
int minBadness = badness[0];
for (int j = 1; j < 5; j++) {
if (badness[j] < minBadness) {
minBadness = badness[j];
filterType = j;
}
}
if (filterType == 0)
System.arraycopy(currRow, bytesPerPixel, scratchRows[0], bytesPerPixel, bytesPerRow);
return filterType;
}
}

View file

@ -0,0 +1,19 @@
package org.apache.xmlgraphics.image.codec.png;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.InputStream;
import org.apache.xmlgraphics.image.codec.util.ImageDecoderImpl;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
public class PNGImageDecoder extends ImageDecoderImpl {
public PNGImageDecoder(InputStream input, PNGDecodeParam param) {
super(input, param);
}
public RenderedImage decodeAsRenderedImage(int page) throws IOException {
if (page != 0)
throw new IOException(PropertyUtil.getString("PNGImageDecoder19"));
return new PNGImage(this.input, (PNGDecodeParam)this.param);
}
}

View file

@ -0,0 +1,609 @@
package org.apache.xmlgraphics.image.codec.png;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import org.apache.xmlgraphics.image.codec.util.ImageEncoderImpl;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
public class PNGImageEncoder extends ImageEncoderImpl {
private static final int PNG_COLOR_GRAY = 0;
private static final int PNG_COLOR_RGB = 2;
private static final int PNG_COLOR_PALETTE = 3;
private static final int PNG_COLOR_GRAY_ALPHA = 4;
private static final int PNG_COLOR_RGB_ALPHA = 6;
private static final byte[] magic = new byte[] { -119, 80, 78, 71, 13, 10, 26, 10 };
private PNGEncodeParam param;
private RenderedImage image;
private int width;
private int height;
private int bitDepth;
private int bitShift;
private int numBands;
private int colorType;
private int bpp;
private boolean skipAlpha = false;
private boolean compressGray = false;
private boolean interlace;
private byte[] redPalette = null;
private byte[] greenPalette = null;
private byte[] bluePalette = null;
private byte[] alphaPalette = null;
private DataOutputStream dataOutput;
public PNGImageEncoder(OutputStream output, PNGEncodeParam param) {
super(output, param);
if (param != null)
this.param = param;
this.dataOutput = new DataOutputStream(output);
}
private void writeMagic() throws IOException {
this.dataOutput.write(magic);
}
private void writeIHDR() throws IOException {
ChunkStream cs = new ChunkStream("IHDR");
cs.writeInt(this.width);
cs.writeInt(this.height);
cs.writeByte((byte)this.bitDepth);
cs.writeByte((byte)this.colorType);
cs.writeByte(0);
cs.writeByte(0);
cs.writeByte(this.interlace ? 1 : 0);
cs.writeToStream(this.dataOutput);
cs.close();
}
private byte[] prevRow = null;
private byte[] currRow = null;
private byte[][] filteredRows = null;
private static int clamp(int val, int maxValue) {
return (val > maxValue) ? maxValue : val;
}
private void encodePass(OutputStream os, Raster ras, int xOffset, int yOffset, int xSkip, int ySkip) throws IOException {
int minX = ras.getMinX();
int minY = ras.getMinY();
int width = ras.getWidth();
int height = ras.getHeight();
xOffset *= this.numBands;
xSkip *= this.numBands;
int samplesPerByte = 8 / this.bitDepth;
int numSamples = width * this.numBands;
int[] samples = new int[numSamples];
int pixels = (numSamples - xOffset + xSkip - 1) / xSkip;
int bytesPerRow = pixels * this.numBands;
if (this.bitDepth < 8) {
bytesPerRow = (bytesPerRow + samplesPerByte - 1) / samplesPerByte;
} else if (this.bitDepth == 16) {
bytesPerRow *= 2;
}
if (bytesPerRow == 0)
return;
this.currRow = new byte[bytesPerRow + this.bpp];
this.prevRow = new byte[bytesPerRow + this.bpp];
this.filteredRows = new byte[5][bytesPerRow + this.bpp];
int maxValue = (1 << this.bitDepth) - 1;
for (int row = minY + yOffset; row < minY + height; row += ySkip) {
int mask, s;
ras.getPixels(minX, row, width, 1, samples);
if (this.compressGray) {
int shift = 8 - this.bitDepth;
for (int i = 0; i < width; i++)
samples[i] = samples[i] >> shift;
}
int count = this.bpp;
int pos = 0;
int tmp = 0;
switch (this.bitDepth) {
case 1:
case 2:
case 4:
mask = samplesPerByte - 1;
for (s = xOffset; s < numSamples; s += xSkip) {
int val = clamp(samples[s] >> this.bitShift, maxValue);
tmp = tmp << this.bitDepth | val;
if (pos++ == mask) {
this.currRow[count++] = (byte)tmp;
tmp = 0;
pos = 0;
}
}
if (pos != 0) {
tmp <<= (samplesPerByte - pos) * this.bitDepth;
this.currRow[count++] = (byte)tmp;
}
break;
case 8:
for (s = xOffset; s < numSamples; s += xSkip) {
for (int b = 0; b < this.numBands; b++)
this.currRow[count++] = (byte)clamp(samples[s + b] >> this.bitShift, maxValue);
}
break;
case 16:
for (s = xOffset; s < numSamples; s += xSkip) {
for (int b = 0; b < this.numBands; b++) {
int val = clamp(samples[s + b] >> this.bitShift, maxValue);
this.currRow[count++] = (byte)(val >> 8);
this.currRow[count++] = (byte)(val & 0xFF);
}
}
break;
}
int filterType = this.param.filterRow(this.currRow, this.prevRow, this.filteredRows, bytesPerRow, this.bpp);
os.write(filterType);
os.write(this.filteredRows[filterType], this.bpp, bytesPerRow);
byte[] swap = this.currRow;
this.currRow = this.prevRow;
this.prevRow = swap;
}
}
private void writeIDAT() throws IOException {
IDATOutputStream ios = new IDATOutputStream(this.dataOutput, 8192);
DeflaterOutputStream dos = new DeflaterOutputStream(ios, new Deflater(9));
Raster ras = this.image.getData(new Rectangle(this.image.getMinX(), this.image.getMinY(), this.image.getWidth(), this.image.getHeight()));
if (this.skipAlpha) {
int numBands = ras.getNumBands() - 1;
int[] bandList = new int[numBands];
for (int i = 0; i < numBands; i++)
bandList[i] = i;
ras = ras.createChild(0, 0, ras.getWidth(), ras.getHeight(), 0, 0, bandList);
}
if (this.interlace) {
encodePass(dos, ras, 0, 0, 8, 8);
encodePass(dos, ras, 4, 0, 8, 8);
encodePass(dos, ras, 0, 4, 4, 8);
encodePass(dos, ras, 2, 0, 4, 4);
encodePass(dos, ras, 0, 2, 2, 4);
encodePass(dos, ras, 1, 0, 2, 2);
encodePass(dos, ras, 0, 1, 1, 2);
} else {
encodePass(dos, ras, 0, 0, 1, 1);
}
dos.finish();
dos.close();
ios.flush();
ios.close();
}
private void writeIEND() throws IOException {
ChunkStream cs = new ChunkStream("IEND");
cs.writeToStream(this.dataOutput);
cs.close();
}
private static final float[] srgbChroma = new float[] { 0.3127F, 0.329F, 0.64F, 0.33F, 0.3F, 0.6F, 0.15F, 0.06F };
private void writeCHRM() throws IOException {
if (this.param.isChromaticitySet() || this.param.isSRGBIntentSet()) {
float[] chroma;
ChunkStream cs = new ChunkStream("cHRM");
if (!this.param.isSRGBIntentSet()) {
chroma = this.param.getChromaticity();
} else {
chroma = srgbChroma;
}
for (int i = 0; i < 8; i++)
cs.writeInt((int)(chroma[i] * 100000.0F));
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeGAMA() throws IOException {
if (this.param.isGammaSet() || this.param.isSRGBIntentSet()) {
float gamma;
ChunkStream cs = new ChunkStream("gAMA");
if (!this.param.isSRGBIntentSet()) {
gamma = this.param.getGamma();
} else {
gamma = 0.45454544F;
}
cs.writeInt((int)(gamma * 100000.0F));
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeICCP() throws IOException {
if (this.param.isICCProfileDataSet()) {
ChunkStream cs = new ChunkStream("iCCP");
byte[] ICCProfileData = this.param.getICCProfileData();
cs.write(ICCProfileData);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeSBIT() throws IOException {
if (this.param.isSignificantBitsSet()) {
ChunkStream cs = new ChunkStream("sBIT");
int[] significantBits = this.param.getSignificantBits();
int len = significantBits.length;
for (int i = 0; i < len; i++)
cs.writeByte(significantBits[i]);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeSRGB() throws IOException {
if (this.param.isSRGBIntentSet()) {
ChunkStream cs = new ChunkStream("sRGB");
int intent = this.param.getSRGBIntent();
cs.write(intent);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writePLTE() throws IOException {
if (this.redPalette == null)
return;
ChunkStream cs = new ChunkStream("PLTE");
for (int i = 0; i < this.redPalette.length; i++) {
cs.writeByte(this.redPalette[i]);
cs.writeByte(this.greenPalette[i]);
cs.writeByte(this.bluePalette[i]);
}
cs.writeToStream(this.dataOutput);
cs.close();
}
private void writeBKGD() throws IOException {
if (this.param.isBackgroundSet()) {
int gray, index, rgb[];
ChunkStream cs = new ChunkStream("bKGD");
switch (this.colorType) {
case 0:
case 4:
gray = ((PNGEncodeParam.Gray)this.param).getBackgroundGray();
cs.writeShort(gray);
break;
case 3:
index = ((PNGEncodeParam.Palette)this.param).getBackgroundPaletteIndex();
cs.writeByte(index);
break;
case 2:
case 6:
rgb = ((PNGEncodeParam.RGB)this.param).getBackgroundRGB();
cs.writeShort(rgb[0]);
cs.writeShort(rgb[1]);
cs.writeShort(rgb[2]);
break;
}
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeHIST() throws IOException {
if (this.param.isPaletteHistogramSet()) {
ChunkStream cs = new ChunkStream("hIST");
int[] hist = this.param.getPaletteHistogram();
for (int i = 0; i < hist.length; i++)
cs.writeShort(hist[i]);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeTRNS() throws IOException {
if (this.param.isTransparencySet() && this.colorType != 4 && this.colorType != 6) {
ChunkStream cs = new ChunkStream("tRNS");
if (this.param instanceof PNGEncodeParam.Palette) {
byte[] t = ((PNGEncodeParam.Palette)this.param).getPaletteTransparency();
for (int i = 0; i < t.length; i++)
cs.writeByte(t[i]);
} else if (this.param instanceof PNGEncodeParam.Gray) {
int t = ((PNGEncodeParam.Gray)this.param).getTransparentGray();
cs.writeShort(t);
} else if (this.param instanceof PNGEncodeParam.RGB) {
int[] t = ((PNGEncodeParam.RGB)this.param).getTransparentRGB();
cs.writeShort(t[0]);
cs.writeShort(t[1]);
cs.writeShort(t[2]);
}
cs.writeToStream(this.dataOutput);
cs.close();
} else if (this.colorType == 3) {
int lastEntry = Math.min(255, this.alphaPalette.length - 1);
int nonOpaque;
for (nonOpaque = lastEntry; nonOpaque >= 0 &&
this.alphaPalette[nonOpaque] == -1; nonOpaque--);
if (nonOpaque >= 0) {
ChunkStream cs = new ChunkStream("tRNS");
for (int i = 0; i <= nonOpaque; i++)
cs.writeByte(this.alphaPalette[i]);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
}
private void writePHYS() throws IOException {
if (this.param.isPhysicalDimensionSet()) {
ChunkStream cs = new ChunkStream("pHYs");
int[] dims = this.param.getPhysicalDimension();
cs.writeInt(dims[0]);
cs.writeInt(dims[1]);
cs.writeByte((byte)dims[2]);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeSPLT() throws IOException {
if (this.param.isSuggestedPaletteSet()) {
ChunkStream cs = new ChunkStream("sPLT");
System.out.println("sPLT not supported yet.");
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeTIME() throws IOException {
if (this.param.isModificationTimeSet()) {
ChunkStream cs = new ChunkStream("tIME");
Date date = this.param.getModificationTime();
TimeZone gmt = TimeZone.getTimeZone("GMT");
GregorianCalendar cal = new GregorianCalendar(gmt);
cal.setTime(date);
int year = cal.get(1);
int month = cal.get(2);
int day = cal.get(5);
int hour = cal.get(11);
int minute = cal.get(12);
int second = cal.get(13);
cs.writeShort(year);
cs.writeByte(month + 1);
cs.writeByte(day);
cs.writeByte(hour);
cs.writeByte(minute);
cs.writeByte(second);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private void writeTEXT() throws IOException {
if (this.param.isTextSet()) {
String[] text = this.param.getText();
for (int i = 0; i < text.length / 2; i++) {
byte[] keyword = text[2 * i].getBytes();
byte[] value = text[2 * i + 1].getBytes();
ChunkStream cs = new ChunkStream("tEXt");
cs.write(keyword, 0, Math.min(keyword.length, 79));
cs.write(0);
cs.write(value);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
}
private void writeZTXT() throws IOException {
if (this.param.isCompressedTextSet()) {
String[] text = this.param.getCompressedText();
for (int i = 0; i < text.length / 2; i++) {
byte[] keyword = text[2 * i].getBytes();
byte[] value = text[2 * i + 1].getBytes();
ChunkStream cs = new ChunkStream("zTXt");
cs.write(keyword, 0, Math.min(keyword.length, 79));
cs.write(0);
cs.write(0);
DeflaterOutputStream dos = new DeflaterOutputStream(cs);
dos.write(value);
dos.finish();
dos.close();
cs.writeToStream(this.dataOutput);
cs.close();
}
}
}
private void writePrivateChunks() throws IOException {
int numChunks = this.param.getNumPrivateChunks();
for (int i = 0; i < numChunks; i++) {
String type = this.param.getPrivateChunkType(i);
byte[] data = this.param.getPrivateChunkData(i);
ChunkStream cs = new ChunkStream(type);
cs.write(data);
cs.writeToStream(this.dataOutput);
cs.close();
}
}
private PNGEncodeParam.Gray createGrayParam(byte[] redPalette, byte[] greenPalette, byte[] bluePalette, byte[] alphaPalette) {
PNGEncodeParam.Gray param = new PNGEncodeParam.Gray();
int numTransparent = 0;
int grayFactor = 255 / ((1 << this.bitDepth) - 1);
int entries = 1 << this.bitDepth;
for (int i = 0; i < entries; i++) {
byte red = redPalette[i];
if (red != i * grayFactor || red != greenPalette[i] || red != bluePalette[i])
return null;
byte alpha = alphaPalette[i];
if (alpha == 0) {
param.setTransparentGray(i);
numTransparent++;
if (numTransparent > 1)
return null;
} else if (alpha != -1) {
return null;
}
}
return param;
}
public void encode(RenderedImage im) throws IOException {
this.image = im;
this.width = this.image.getWidth();
this.height = this.image.getHeight();
SampleModel sampleModel = this.image.getSampleModel();
int[] sampleSize = sampleModel.getSampleSize();
this.bitDepth = -1;
this.bitShift = 0;
if (this.param instanceof PNGEncodeParam.Gray) {
PNGEncodeParam.Gray paramg = (PNGEncodeParam.Gray)this.param;
if (paramg.isBitDepthSet())
this.bitDepth = paramg.getBitDepth();
if (paramg.isBitShiftSet())
this.bitShift = paramg.getBitShift();
}
if (this.bitDepth == -1) {
this.bitDepth = sampleSize[0];
for (int i = 1; i < sampleSize.length; i++) {
if (sampleSize[i] != this.bitDepth)
throw new RuntimeException(PropertyUtil.getString("PNGImageEncoder0"));
}
if (this.bitDepth > 2 && this.bitDepth < 4) {
this.bitDepth = 4;
} else if (this.bitDepth > 4 && this.bitDepth < 8) {
this.bitDepth = 8;
} else if (this.bitDepth > 8 && this.bitDepth < 16) {
this.bitDepth = 16;
} else if (this.bitDepth > 16) {
throw new RuntimeException(PropertyUtil.getString("PNGImageEncoder1"));
}
}
this.numBands = sampleModel.getNumBands();
this.bpp = this.numBands * ((this.bitDepth == 16) ? 2 : 1);
ColorModel colorModel = this.image.getColorModel();
if (colorModel instanceof IndexColorModel) {
if (this.bitDepth < 1 || this.bitDepth > 8)
throw new RuntimeException(PropertyUtil.getString("PNGImageEncoder2"));
if (sampleModel.getNumBands() != 1)
throw new RuntimeException(PropertyUtil.getString("PNGImageEncoder3"));
IndexColorModel icm = (IndexColorModel)colorModel;
int size = icm.getMapSize();
this.redPalette = new byte[size];
this.greenPalette = new byte[size];
this.bluePalette = new byte[size];
this.alphaPalette = new byte[size];
icm.getReds(this.redPalette);
icm.getGreens(this.greenPalette);
icm.getBlues(this.bluePalette);
icm.getAlphas(this.alphaPalette);
this.bpp = 1;
if (this.param == null)
this.param = createGrayParam(this.redPalette, this.greenPalette, this.bluePalette, this.alphaPalette);
if (this.param == null)
this.param = new PNGEncodeParam.Palette();
if (this.param instanceof PNGEncodeParam.Palette) {
PNGEncodeParam.Palette parami = (PNGEncodeParam.Palette)this.param;
if (parami.isPaletteSet()) {
int[] palette = parami.getPalette();
size = palette.length / 3;
int index = 0;
for (int i = 0; i < size; i++) {
this.redPalette[i] = (byte)palette[index++];
this.greenPalette[i] = (byte)palette[index++];
this.bluePalette[i] = (byte)palette[index++];
this.alphaPalette[i] = -1;
}
}
this.colorType = 3;
} else if (this.param instanceof PNGEncodeParam.Gray) {
this.redPalette = this.greenPalette = this.bluePalette = this.alphaPalette = null;
this.colorType = 0;
} else {
throw new RuntimeException(PropertyUtil.getString("PNGImageEncoder4"));
}
} else if (this.numBands == 1) {
if (this.param == null)
this.param = new PNGEncodeParam.Gray();
this.colorType = 0;
} else if (this.numBands == 2) {
if (this.param == null)
this.param = new PNGEncodeParam.Gray();
if (this.param.isTransparencySet()) {
this.skipAlpha = true;
this.numBands = 1;
if (sampleSize[0] == 8 && this.bitDepth < 8)
this.compressGray = true;
this.bpp = (this.bitDepth == 16) ? 2 : 1;
this.colorType = 0;
} else {
if (this.bitDepth < 8)
this.bitDepth = 8;
this.colorType = 4;
}
} else if (this.numBands == 3) {
if (this.param == null)
this.param = new PNGEncodeParam.RGB();
this.colorType = 2;
} else if (this.numBands == 4) {
if (this.param == null)
this.param = new PNGEncodeParam.RGB();
if (this.param.isTransparencySet()) {
this.skipAlpha = true;
this.numBands = 3;
this.bpp = (this.bitDepth == 16) ? 6 : 3;
this.colorType = 2;
} else {
this.colorType = 6;
}
}
this.interlace = this.param.getInterlacing();
writeMagic();
writeIHDR();
writeCHRM();
writeGAMA();
writeICCP();
writeSBIT();
writeSRGB();
writePLTE();
writeHIST();
writeTRNS();
writeBKGD();
writePHYS();
writeSPLT();
writeTIME();
writeTEXT();
writeZTXT();
writePrivateChunks();
writeIDAT();
writeIEND();
this.dataOutput.flush();
this.dataOutput.close();
}
}

View file

@ -0,0 +1,19 @@
package org.apache.xmlgraphics.image.codec.png;
import java.io.Serializable;
public class PNGSuggestedPaletteEntry implements Serializable {
public String name;
public int sampleDepth;
public int red;
public int green;
public int blue;
public int alpha;
public int frequency;
}

View file

@ -0,0 +1,43 @@
package org.apache.xmlgraphics.image.codec.tiff;
import org.apache.xmlgraphics.image.codec.util.ImageDecodeParam;
public class TIFFDecodeParam implements ImageDecodeParam {
private boolean decodePaletteAsShorts = false;
private Long ifdOffset = null;
private boolean convertJPEGYCbCrToRGB = true;
public void setDecodePaletteAsShorts(boolean decodePaletteAsShorts) {
this.decodePaletteAsShorts = decodePaletteAsShorts;
}
public boolean getDecodePaletteAsShorts() {
return this.decodePaletteAsShorts;
}
public byte decode16BitsTo8Bits(int s) {
return (byte)(s >> 8 & 0xFFFF);
}
public byte decodeSigned16BitsTo8Bits(short s) {
return (byte)(s + -32768 >> 8);
}
public void setIFDOffset(long offset) {
this.ifdOffset = new Long(offset);
}
public Long getIFDOffset() {
return this.ifdOffset;
}
public void setJPEGDecompressYCbCrToRGB(boolean convertJPEGYCbCrToRGB) {
this.convertJPEGYCbCrToRGB = convertJPEGYCbCrToRGB;
}
public boolean getJPEGDecompressYCbCrToRGB() {
return this.convertJPEGYCbCrToRGB;
}
}

View file

@ -0,0 +1,348 @@
package org.apache.xmlgraphics.image.codec.tiff;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
import org.apache.xmlgraphics.image.codec.util.SeekableStream;
public class TIFFDirectory implements Serializable {
boolean isBigEndian;
int numEntries;
TIFFField[] fields;
Map fieldIndex = new HashMap();
long IFDOffset = 8L;
long nextIFDOffset = 0L;
TIFFDirectory() {}
private static boolean isValidEndianTag(int endian) {
return (endian == 18761 || endian == 19789);
}
public TIFFDirectory(SeekableStream stream, int directory) throws IOException {
long global_save_offset = stream.getFilePointer();
stream.seek(0L);
int endian = stream.readUnsignedShort();
if (!isValidEndianTag(endian))
throw new IllegalArgumentException(PropertyUtil.getString("TIFFDirectory1"));
this.isBigEndian = (endian == 19789);
int magic = readUnsignedShort(stream);
if (magic != 42)
throw new IllegalArgumentException(PropertyUtil.getString("TIFFDirectory2"));
long ifd_offset = readUnsignedInt(stream);
for (int i = 0; i < directory; i++) {
if (ifd_offset == 0L)
throw new IllegalArgumentException(PropertyUtil.getString("TIFFDirectory3"));
stream.seek(ifd_offset);
long entries = (long)readUnsignedShort(stream);
stream.skip(12L * entries);
ifd_offset = readUnsignedInt(stream);
}
if (ifd_offset == 0L)
throw new IllegalArgumentException(PropertyUtil.getString("TIFFDirectory3"));
stream.seek(ifd_offset);
initialize(stream);
stream.seek(global_save_offset);
}
public TIFFDirectory(SeekableStream stream, long ifd_offset, int directory) throws IOException {
long global_save_offset = stream.getFilePointer();
stream.seek(0L);
int endian = stream.readUnsignedShort();
if (!isValidEndianTag(endian))
throw new IllegalArgumentException(PropertyUtil.getString("TIFFDirectory1"));
this.isBigEndian = (endian == 19789);
stream.seek(ifd_offset);
int dirNum = 0;
while (dirNum < directory) {
long numEntries = (long)readUnsignedShort(stream);
stream.seek(ifd_offset + 12L * numEntries);
ifd_offset = readUnsignedInt(stream);
stream.seek(ifd_offset);
dirNum++;
}
initialize(stream);
stream.seek(global_save_offset);
}
private static final int[] sizeOfType = new int[] {
0, 1, 1, 2, 4, 8, 1, 1, 2, 4,
8, 4, 8 };
private void initialize(SeekableStream stream) throws IOException {
this.IFDOffset = stream.getFilePointer();
this.numEntries = readUnsignedShort(stream);
this.fields = new TIFFField[this.numEntries];
for (int i = 0; i < this.numEntries; i++) {
int j;
byte[] bvalues;
char[] cvalues;
long lvalues[], llvalues[][];
short[] svalues;
int ivalues[], iivalues[][];
float[] fvalues;
double[] dvalues;
int tag = readUnsignedShort(stream);
int type = readUnsignedShort(stream);
int count = (int)readUnsignedInt(stream);
int value = 0;
long nextTagOffset = stream.getFilePointer() + 4L;
try {
if (count * sizeOfType[type] > 4) {
value = (int)readUnsignedInt(stream);
stream.seek((long)value);
}
} catch (ArrayIndexOutOfBoundsException ae) {
stream.seek(nextTagOffset);
}
this.fieldIndex.put(new Integer(tag), new Integer(i));
Object obj = null;
switch (type) {
case 1:
case 2:
case 6:
case 7:
bvalues = new byte[count];
stream.readFully(bvalues, 0, count);
if (type == 2) {
int index = 0, prevIndex = 0;
List<String> v = new ArrayList();
while (index < count) {
while (index < count && bvalues[index++] != 0);
v.add(new String(bvalues, prevIndex, index - prevIndex));
prevIndex = index;
}
count = v.size();
String[] strings = new String[count];
v.<String>toArray(strings);
obj = strings;
} else {
obj = bvalues;
}
break;
case 3:
cvalues = new char[count];
for (j = 0; j < count; j++)
cvalues[j] = (char)readUnsignedShort(stream);
obj = cvalues;
break;
case 4:
lvalues = new long[count];
for (j = 0; j < count; j++)
lvalues[j] = readUnsignedInt(stream);
obj = lvalues;
break;
case 5:
llvalues = new long[count][2];
for (j = 0; j < count; j++) {
llvalues[j][0] = readUnsignedInt(stream);
llvalues[j][1] = readUnsignedInt(stream);
}
obj = llvalues;
break;
case 8:
svalues = new short[count];
for (j = 0; j < count; j++)
svalues[j] = readShort(stream);
obj = svalues;
break;
case 9:
ivalues = new int[count];
for (j = 0; j < count; j++)
ivalues[j] = readInt(stream);
obj = ivalues;
break;
case 10:
iivalues = new int[count][2];
for (j = 0; j < count; j++) {
iivalues[j][0] = readInt(stream);
iivalues[j][1] = readInt(stream);
}
obj = iivalues;
break;
case 11:
fvalues = new float[count];
for (j = 0; j < count; j++)
fvalues[j] = readFloat(stream);
obj = fvalues;
break;
case 12:
dvalues = new double[count];
for (j = 0; j < count; j++)
dvalues[j] = readDouble(stream);
obj = dvalues;
break;
default:
throw new RuntimeException(PropertyUtil.getString("TIFFDirectory0"));
}
this.fields[i] = new TIFFField(tag, type, count, obj);
stream.seek(nextTagOffset);
}
this.nextIFDOffset = readUnsignedInt(stream);
}
public int getNumEntries() {
return this.numEntries;
}
public TIFFField getField(int tag) {
Integer i = (Integer)this.fieldIndex.get(new Integer(tag));
if (i == null)
return null;
return this.fields[i];
}
public boolean isTagPresent(int tag) {
return this.fieldIndex.containsKey(new Integer(tag));
}
public int[] getTags() {
int[] tags = new int[this.fieldIndex.size()];
Iterator iter = this.fieldIndex.keySet().iterator();
int i = 0;
while (iter.hasNext())
tags[i++] = (Integer)iter.next();
return tags;
}
public TIFFField[] getFields() {
return this.fields;
}
public byte getFieldAsByte(int tag, int index) {
Integer i = (Integer)this.fieldIndex.get(new Integer(tag));
byte[] b = this.fields[i].getAsBytes();
return b[index];
}
public byte getFieldAsByte(int tag) {
return getFieldAsByte(tag, 0);
}
public long getFieldAsLong(int tag, int index) {
Integer i = (Integer)this.fieldIndex.get(new Integer(tag));
return this.fields[i].getAsLong(index);
}
public long getFieldAsLong(int tag) {
return getFieldAsLong(tag, 0);
}
public float getFieldAsFloat(int tag, int index) {
Integer i = (Integer)this.fieldIndex.get(new Integer(tag));
return this.fields[i].getAsFloat(index);
}
public float getFieldAsFloat(int tag) {
return getFieldAsFloat(tag, 0);
}
public double getFieldAsDouble(int tag, int index) {
Integer i = (Integer)this.fieldIndex.get(new Integer(tag));
return this.fields[i].getAsDouble(index);
}
public double getFieldAsDouble(int tag) {
return getFieldAsDouble(tag, 0);
}
private short readShort(SeekableStream stream) throws IOException {
if (this.isBigEndian)
return stream.readShort();
return stream.readShortLE();
}
private int readUnsignedShort(SeekableStream stream) throws IOException {
if (this.isBigEndian)
return stream.readUnsignedShort();
return stream.readUnsignedShortLE();
}
private int readInt(SeekableStream stream) throws IOException {
if (this.isBigEndian)
return stream.readInt();
return stream.readIntLE();
}
private long readUnsignedInt(SeekableStream stream) throws IOException {
if (this.isBigEndian)
return stream.readUnsignedInt();
return stream.readUnsignedIntLE();
}
private long readLong(SeekableStream stream) throws IOException {
if (this.isBigEndian)
return stream.readLong();
return stream.readLongLE();
}
private float readFloat(SeekableStream stream) throws IOException {
if (this.isBigEndian)
return stream.readFloat();
return stream.readFloatLE();
}
private double readDouble(SeekableStream stream) throws IOException {
if (this.isBigEndian)
return stream.readDouble();
return stream.readDoubleLE();
}
private static int readUnsignedShort(SeekableStream stream, boolean isBigEndian) throws IOException {
if (isBigEndian)
return stream.readUnsignedShort();
return stream.readUnsignedShortLE();
}
private static long readUnsignedInt(SeekableStream stream, boolean isBigEndian) throws IOException {
if (isBigEndian)
return stream.readUnsignedInt();
return stream.readUnsignedIntLE();
}
public static int getNumDirectories(SeekableStream stream) throws IOException {
long pointer = stream.getFilePointer();
stream.seek(0L);
int endian = stream.readUnsignedShort();
if (!isValidEndianTag(endian))
throw new IllegalArgumentException(PropertyUtil.getString("TIFFDirectory1"));
boolean isBigEndian = (endian == 19789);
int magic = readUnsignedShort(stream, isBigEndian);
if (magic != 42)
throw new IllegalArgumentException(PropertyUtil.getString("TIFFDirectory2"));
stream.seek(4L);
long offset = readUnsignedInt(stream, isBigEndian);
int numDirectories = 0;
while (offset != 0L) {
numDirectories++;
stream.seek(offset);
long entries = (long)readUnsignedShort(stream, isBigEndian);
stream.skip(12L * entries);
offset = readUnsignedInt(stream, isBigEndian);
}
stream.seek(pointer);
return numDirectories;
}
public boolean isBigEndian() {
return this.isBigEndian;
}
public long getIFDOffset() {
return this.IFDOffset;
}
public long getNextIFDOffset() {
return this.nextIFDOffset;
}
}

View file

@ -0,0 +1,112 @@
package org.apache.xmlgraphics.image.codec.tiff;
import java.util.Iterator;
import org.apache.xmlgraphics.image.codec.util.ImageEncodeParam;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
public class TIFFEncodeParam implements ImageEncodeParam {
public static final int COMPRESSION_NONE = 1;
public static final int COMPRESSION_GROUP3_1D = 2;
public static final int COMPRESSION_GROUP3_2D = 3;
public static final int COMPRESSION_GROUP4 = 4;
public static final int COMPRESSION_LZW = 5;
public static final int COMPRESSION_JPEG_BROKEN = 6;
public static final int COMPRESSION_JPEG_TTN2 = 7;
public static final int COMPRESSION_PACKBITS = 32773;
public static final int COMPRESSION_DEFLATE = 32946;
private int compression = 1;
private boolean writeTiled = false;
private int tileWidth;
private int tileHeight;
private Iterator extraImages;
private TIFFField[] extraFields;
private boolean convertJPEGRGBToYCbCr = true;
private int deflateLevel = -1;
public int getCompression() {
return this.compression;
}
public void setCompression(int compression) {
switch (compression) {
case 1:
case 32773:
case 32946:
break;
default:
throw new RuntimeException(PropertyUtil.getString("TIFFEncodeParam0"));
}
this.compression = compression;
}
public boolean getWriteTiled() {
return this.writeTiled;
}
public void setWriteTiled(boolean writeTiled) {
this.writeTiled = writeTiled;
}
public void setTileSize(int tileWidth, int tileHeight) {
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
}
public int getTileWidth() {
return this.tileWidth;
}
public int getTileHeight() {
return this.tileHeight;
}
public synchronized void setExtraImages(Iterator extraImages) {
this.extraImages = extraImages;
}
public synchronized Iterator getExtraImages() {
return this.extraImages;
}
public void setDeflateLevel(int deflateLevel) {
if (deflateLevel < 1 && deflateLevel > 9 && deflateLevel != -1)
throw new RuntimeException(PropertyUtil.getString("TIFFEncodeParam1"));
this.deflateLevel = deflateLevel;
}
public int getDeflateLevel() {
return this.deflateLevel;
}
public void setJPEGCompressRGBToYCbCr(boolean convertJPEGRGBToYCbCr) {
this.convertJPEGRGBToYCbCr = convertJPEGRGBToYCbCr;
}
public boolean getJPEGCompressRGBToYCbCr() {
return this.convertJPEGRGBToYCbCr;
}
public void setExtraFields(TIFFField[] extraFields) {
this.extraFields = extraFields;
}
public TIFFField[] getExtraFields() {
return this.extraFields;
}
}

View file

@ -0,0 +1,847 @@
package org.apache.xmlgraphics.image.codec.tiff;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
class TIFFFaxDecoder {
private int bitPointer;
private int bytePointer;
private byte[] data;
private int w;
private int h;
private int fillOrder;
private int changingElemSize = 0;
private int[] prevChangingElems;
private int[] currChangingElems;
private int lastChangingElement = 0;
private int compression = 2;
private int uncompressedMode = 0;
private int fillBits = 0;
private int oneD;
static int[] table1 = new int[] { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
static int[] table2 = new int[] { 0, 128, 192, 224, 240, 248, 252, 254, 255 };
static byte[] flipTable = new byte[] {
0, Byte.MIN_VALUE, 64, -64, 32, -96, 96, -32, 16, -112,
80, -48, 48, -80, 112, -16, 8, -120, 72, -56,
40, -88, 104, -24, 24, -104, 88, -40, 56, -72,
120, -8, 4, -124, 68, -60, 36, -92, 100, -28,
20, -108, 84, -44, 52, -76, 116, -12, 12, -116,
76, -52, 44, -84, 108, -20, 28, -100, 92, -36,
60, -68, 124, -4, 2, -126, 66, -62, 34, -94,
98, -30, 18, -110, 82, -46, 50, -78, 114, -14,
10, -118, 74, -54, 42, -86, 106, -22, 26, -102,
90, -38, 58, -70, 122, -6, 6, -122, 70, -58,
38, -90, 102, -26, 22, -106, 86, -42, 54, -74,
118, -10, 14, -114, 78, -50, 46, -82, 110, -18,
30, -98, 94, -34, 62, -66, 126, -2, 1, -127,
65, -63, 33, -95, 97, -31, 17, -111, 81, -47,
49, -79, 113, -15, 9, -119, 73, -55, 41, -87,
105, -23, 25, -103, 89, -39, 57, -71, 121, -7,
5, -123, 69, -59, 37, -91, 101, -27, 21, -107,
85, -43, 53, -75, 117, -11, 13, -115, 77, -51,
45, -83, 109, -19, 29, -99, 93, -35, 61, -67,
125, -3, 3, -125, 67, -61, 35, -93, 99, -29,
19, -109, 83, -45, 51, -77, 115, -13, 11, -117,
75, -53, 43, -85, 107, -21, 27, -101, 91, -37,
59, -69, 123, -5, 7, -121, 71, -57, 39, -89,
103, -25, 23, -105, 87, -41, 55, -73, 119, -9,
15, -113, 79, -49, 47, -81, 111, -17, 31, -97,
95, -33, 63, -65, Byte.MAX_VALUE, -1 };
static short[] white = new short[] {
6430, 6400, 6400, 6400, 3225, 3225, 3225, 3225, 944, 944,
944, 944, 976, 976, 976, 976, 1456, 1456, 1456, 1456,
1488, 1488, 1488, 1488, 718, 718, 718, 718, 718, 718,
718, 718, 750, 750, 750, 750, 750, 750, 750, 750,
1520, 1520, 1520, 1520, 1552, 1552, 1552, 1552, 428, 428,
428, 428, 428, 428, 428, 428, 428, 428, 428, 428,
428, 428, 428, 428, 654, 654, 654, 654, 654, 654,
654, 654, 1072, 1072, 1072, 1072, 1104, 1104, 1104, 1104,
1136, 1136, 1136, 1136, 1168, 1168, 1168, 1168, 1200, 1200,
1200, 1200, 1232, 1232, 1232, 1232, 622, 622, 622, 622,
622, 622, 622, 622, 1008, 1008, 1008, 1008, 1040, 1040,
1040, 1040, 44, 44, 44, 44, 44, 44, 44, 44,
44, 44, 44, 44, 44, 44, 44, 44, 396, 396,
396, 396, 396, 396, 396, 396, 396, 396, 396, 396,
396, 396, 396, 396, 1712, 1712, 1712, 1712, 1744, 1744,
1744, 1744, 846, 846, 846, 846, 846, 846, 846, 846,
1264, 1264, 1264, 1264, 1296, 1296, 1296, 1296, 1328, 1328,
1328, 1328, 1360, 1360, 1360, 1360, 1392, 1392, 1392, 1392,
1424, 1424, 1424, 1424, 686, 686, 686, 686, 686, 686,
686, 686, 910, 910, 910, 910, 910, 910, 910, 910,
1968, 1968, 1968, 1968, 2000, 2000, 2000, 2000, 2032, 2032,
2032, 2032, 16, 16, 16, 16, 10257, 10257, 10257, 10257,
12305, 12305, 12305, 12305, 330, 330, 330, 330, 330, 330,
330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
330, 330, 330, 330, 330, 330, 362, 362, 362, 362,
362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
362, 362, 362, 362, 362, 362, 362, 362, 878, 878,
878, 878, 878, 878, 878, 878, 1904, 1904, 1904, 1904,
1936, 1936, 1936, 1936, -18413, -18413, -16365, -16365, -14317, -14317,
-10221, -10221, 590, 590, 590, 590, 590, 590, 590, 590,
782, 782, 782, 782, 782, 782, 782, 782, 1584, 1584,
1584, 1584, 1616, 1616, 1616, 1616, 1648, 1648, 1648, 1648,
1680, 1680, 1680, 1680, 814, 814, 814, 814, 814, 814,
814, 814, 1776, 1776, 1776, 1776, 1808, 1808, 1808, 1808,
1840, 1840, 1840, 1840, 1872, 1872, 1872, 1872, 6157, 6157,
6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157,
6157, 6157, 6157, 6157, -12275, -12275, -12275, -12275, -12275, -12275,
-12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275,
14353, 14353, 14353, 14353, 16401, 16401, 16401, 16401, 22547, 22547,
24595, 24595, 20497, 20497, 20497, 20497, 18449, 18449, 18449, 18449,
26643, 26643, 28691, 28691, 30739, 30739, -32749, -32749, -30701, -30701,
-28653, -28653, -26605, -26605, -24557, -24557, -22509, -22509, -20461, -20461,
8207, 8207, 8207, 8207, 8207, 8207, 8207, 8207, 72, 72,
72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
72, 72, 104, 104, 104, 104, 104, 104, 104, 104,
104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
104, 104, 104, 104, 104, 104, 4107, 4107, 4107, 4107,
4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107,
4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107,
4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, 266, 266,
266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
298, 298, 524, 524, 524, 524, 524, 524, 524, 524,
524, 524, 524, 524, 524, 524, 524, 524, 556, 556,
556, 556, 556, 556, 556, 556, 556, 556, 556, 556,
556, 556, 556, 556, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 460, 460, 460, 460, 460, 460, 460, 460,
460, 460, 460, 460, 460, 460, 460, 460, 492, 492,
492, 492, 492, 492, 492, 492, 492, 492, 492, 492,
492, 492, 492, 492, 2059, 2059, 2059, 2059, 2059, 2059,
2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059,
2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059,
2059, 2059, 2059, 2059, 2059, 2059, 200, 200, 200, 200,
200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 232, 232, 232 };
static short[] additionalMakeup = new short[] {
28679, 28679, 31752, -32759, -31735, -30711, -29687, -28663, 29703, 29703,
30727, 30727, -27639, -26615, -25591, -24567 };
static short[] initBlack = new short[] {
3226, 6412, 200, 168, 38, 38, 134, 134, 100, 100,
100, 100, 68, 68, 68, 68 };
static short[] twoBitBlack = new short[] { 292, 260, 226, 226 };
static short[] black = new short[] {
62, 62, 30, 30, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225,
3225, 3225, 3225, 3225, 588, 588, 588, 588, 588, 588,
588, 588, 1680, 1680, 20499, 22547, 24595, 26643, 1776, 1776,
1808, 1808, -24557, -22509, -20461, -18413, 1904, 1904, 1936, 1936,
-16365, -14317, 782, 782, 782, 782, 814, 814, 814, 814,
-12269, -10221, 10257, 10257, 12305, 12305, 14353, 14353, 16403, 18451,
1712, 1712, 1744, 1744, 28691, 30739, -32749, -30701, -28653, -26605,
2061, 2061, 2061, 2061, 2061, 2061, 2061, 2061, 424, 424,
424, 424, 424, 424, 424, 424, 424, 424, 424, 424,
424, 424, 424, 424, 424, 424, 424, 424, 424, 424,
424, 424, 424, 424, 424, 424, 424, 424, 424, 424,
750, 750, 750, 750, 1616, 1616, 1648, 1648, 1424, 1424,
1456, 1456, 1488, 1488, 1520, 1520, 1840, 1840, 1872, 1872,
1968, 1968, 8209, 8209, 524, 524, 524, 524, 524, 524,
524, 524, 556, 556, 556, 556, 556, 556, 556, 556,
1552, 1552, 1584, 1584, 2000, 2000, 2032, 2032, 976, 976,
1008, 1008, 1040, 1040, 1072, 1072, 1296, 1296, 1328, 1328,
718, 718, 718, 718, 456, 456, 456, 456, 456, 456,
456, 456, 456, 456, 456, 456, 456, 456, 456, 456,
456, 456, 456, 456, 456, 456, 456, 456, 456, 456,
456, 456, 456, 456, 456, 456, 326, 326, 326, 326,
326, 326, 326, 326, 326, 326, 326, 326, 326, 326,
326, 326, 326, 326, 326, 326, 326, 326, 326, 326,
326, 326, 326, 326, 326, 326, 326, 326, 326, 326,
326, 326, 326, 326, 326, 326, 326, 326, 326, 326,
326, 326, 326, 326, 326, 326, 326, 326, 326, 326,
326, 326, 326, 326, 326, 326, 326, 326, 326, 326,
358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
358, 358, 358, 358, 490, 490, 490, 490, 490, 490,
490, 490, 490, 490, 490, 490, 490, 490, 490, 490,
4113, 4113, 6161, 6161, 848, 848, 880, 880, 912, 912,
944, 944, 622, 622, 622, 622, 654, 654, 654, 654,
1104, 1104, 1136, 1136, 1168, 1168, 1200, 1200, 1232, 1232,
1264, 1264, 686, 686, 686, 686, 1360, 1360, 1392, 1392,
12, 12, 12, 12, 12, 12, 12, 12, 390, 390,
390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
390, 390 };
static byte[] twoDCodes = new byte[] {
80, 88, 23, 71, 30, 30, 62, 62, 4, 4,
4, 4, 4, 4, 4, 4, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 35, 35, 35, 35, 35, 35, 35, 35,
35, 35, 35, 35, 35, 35, 35, 35, 51, 51,
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41 };
public TIFFFaxDecoder(int fillOrder, int w, int h) {
this.fillOrder = fillOrder;
this.w = w;
this.h = h;
this.bitPointer = 0;
this.bytePointer = 0;
this.prevChangingElems = new int[w];
this.currChangingElems = new int[w];
}
public void decode1D(byte[] buffer, byte[] compData, int startX, int height) {
this.data = compData;
int lineOffset = 0;
int scanlineStride = (this.w + 7) / 8;
this.bitPointer = 0;
this.bytePointer = 0;
for (int i = 0; i < height; i++) {
decodeNextScanline(buffer, lineOffset, startX);
lineOffset += scanlineStride;
}
}
public void decodeNextScanline(byte[] buffer, int lineOffset, int bitOffset) {
int bits = 0, code = 0, isT = 0;
boolean isWhite = true;
this.changingElemSize = 0;
while (bitOffset < this.w) {
while (isWhite) {
int current = nextNBits(10);
int entry = white[current];
isT = entry & 0x1;
bits = entry >>> 1 & 0xF;
if (bits == 12) {
int twoBits = nextLesserThan8Bits(2);
current = current << 2 & 0xC | twoBits;
entry = additionalMakeup[current];
bits = entry >>> 1 & 0x7;
code = entry >>> 4 & 0xFFF;
bitOffset += code;
updatePointer(4 - bits);
continue;
}
if (bits == 0)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder0"));
if (bits == 15)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder1"));
code = entry >>> 5 & 0x7FF;
bitOffset += code;
updatePointer(10 - bits);
if (isT == 0) {
isWhite = false;
this.currChangingElems[this.changingElemSize++] = bitOffset;
}
}
if (bitOffset == this.w) {
if (this.compression == 2) {
advancePointer();
break;
}
break;
}
while (!isWhite) {
int current = nextLesserThan8Bits(4);
int entry = initBlack[current];
isT = entry & 0x1;
bits = entry >>> 1 & 0xF;
code = entry >>> 5 & 0x7FF;
if (code == 100) {
current = nextNBits(9);
entry = black[current];
isT = entry & 0x1;
bits = entry >>> 1 & 0xF;
code = entry >>> 5 & 0x7FF;
if (bits == 12) {
updatePointer(5);
current = nextLesserThan8Bits(4);
entry = additionalMakeup[current];
bits = entry >>> 1 & 0x7;
code = entry >>> 4 & 0xFFF;
setToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
updatePointer(4 - bits);
continue;
}
if (bits == 15)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder2"));
setToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
updatePointer(9 - bits);
if (isT == 0) {
isWhite = true;
this.currChangingElems[this.changingElemSize++] = bitOffset;
}
continue;
}
if (code == 200) {
current = nextLesserThan8Bits(2);
entry = twoBitBlack[current];
code = entry >>> 5 & 0x7FF;
bits = entry >>> 1 & 0xF;
setToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
updatePointer(2 - bits);
isWhite = true;
this.currChangingElems[this.changingElemSize++] = bitOffset;
continue;
}
setToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
updatePointer(4 - bits);
isWhite = true;
this.currChangingElems[this.changingElemSize++] = bitOffset;
}
if (bitOffset == this.w) {
if (this.compression == 2) {
advancePointer();
break;
}
break;
}
}
this.currChangingElems[this.changingElemSize++] = bitOffset;
}
public void decode2D(byte[] buffer, byte[] compData, int startX, int height, long tiffT4Options) {
this.data = compData;
this.compression = 3;
this.bitPointer = 0;
this.bytePointer = 0;
int scanlineStride = (this.w + 7) / 8;
int[] b = new int[2];
int currIndex = 0;
this.oneD = (int)(tiffT4Options & 0x1L);
this.uncompressedMode = (int)((tiffT4Options & 0x2L) >> 1L);
this.fillBits = (int)((tiffT4Options & 0x4L) >> 2L);
if (readEOL() != 1)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder3"));
int lineOffset = 0;
decodeNextScanline(buffer, lineOffset, startX);
lineOffset += scanlineStride;
for (int lines = 1; lines < height; lines++) {
if (readEOL() == 0) {
int[] temp = this.prevChangingElems;
this.prevChangingElems = this.currChangingElems;
this.currChangingElems = temp;
currIndex = 0;
int a0 = -1;
boolean isWhite = true;
int bitOffset = startX;
this.lastChangingElement = 0;
while (bitOffset < this.w) {
getNextChangingElement(a0, isWhite, b);
int b1 = b[0];
int b2 = b[1];
int entry = nextLesserThan8Bits(7);
entry = twoDCodes[entry] & 0xFF;
int code = (entry & 0x78) >>> 3;
int bits = entry & 0x7;
if (code == 0) {
if (!isWhite)
setToBlack(buffer, lineOffset, bitOffset, b2 - bitOffset);
bitOffset = a0 = b2;
updatePointer(7 - bits);
continue;
}
if (code == 1) {
updatePointer(7 - bits);
if (isWhite) {
int number = decodeWhiteCodeWord();
bitOffset += number;
this.currChangingElems[currIndex++] = bitOffset;
number = decodeBlackCodeWord();
setToBlack(buffer, lineOffset, bitOffset, number);
bitOffset += number;
this.currChangingElems[currIndex++] = bitOffset;
} else {
int number = decodeBlackCodeWord();
setToBlack(buffer, lineOffset, bitOffset, number);
bitOffset += number;
this.currChangingElems[currIndex++] = bitOffset;
number = decodeWhiteCodeWord();
bitOffset += number;
this.currChangingElems[currIndex++] = bitOffset;
}
a0 = bitOffset;
continue;
}
if (code <= 8) {
int a1 = b1 + code - 5;
this.currChangingElems[currIndex++] = a1;
if (!isWhite)
setToBlack(buffer, lineOffset, bitOffset, a1 - bitOffset);
bitOffset = a0 = a1;
isWhite = !isWhite;
updatePointer(7 - bits);
continue;
}
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder4"));
}
this.currChangingElems[currIndex++] = bitOffset;
this.changingElemSize = currIndex;
} else {
decodeNextScanline(buffer, lineOffset, startX);
}
lineOffset += scanlineStride;
}
}
public synchronized void decodeT6(byte[] buffer, byte[] compData, int startX, int height, long tiffT6Options) {
this.data = compData;
this.compression = 4;
this.bitPointer = 0;
this.bytePointer = 0;
int scanlineStride = (this.w + 7) / 8;
int[] b = new int[2];
this.uncompressedMode = (int)((tiffT6Options & 0x2L) >> 1L);
int[] cce = this.currChangingElems;
this.changingElemSize = 0;
cce[this.changingElemSize++] = this.w;
cce[this.changingElemSize++] = this.w;
int lineOffset = 0;
for (int lines = 0; lines < height; lines++) {
int a0 = -1;
boolean isWhite = true;
int[] temp = this.prevChangingElems;
this.prevChangingElems = this.currChangingElems;
cce = this.currChangingElems = temp;
int currIndex = 0;
int bitOffset = startX;
this.lastChangingElement = 0;
while (bitOffset < this.w) {
getNextChangingElement(a0, isWhite, b);
int b1 = b[0];
int b2 = b[1];
int entry = nextLesserThan8Bits(7);
entry = twoDCodes[entry] & 0xFF;
int code = (entry & 0x78) >>> 3;
int bits = entry & 0x7;
if (code == 0) {
if (!isWhite)
setToBlack(buffer, lineOffset, bitOffset, b2 - bitOffset);
bitOffset = a0 = b2;
updatePointer(7 - bits);
continue;
}
if (code == 1) {
updatePointer(7 - bits);
if (isWhite) {
int number = decodeWhiteCodeWord();
bitOffset += number;
cce[currIndex++] = bitOffset;
number = decodeBlackCodeWord();
setToBlack(buffer, lineOffset, bitOffset, number);
bitOffset += number;
cce[currIndex++] = bitOffset;
} else {
int number = decodeBlackCodeWord();
setToBlack(buffer, lineOffset, bitOffset, number);
bitOffset += number;
cce[currIndex++] = bitOffset;
number = decodeWhiteCodeWord();
bitOffset += number;
cce[currIndex++] = bitOffset;
}
a0 = bitOffset;
continue;
}
if (code <= 8) {
int a1 = b1 + code - 5;
cce[currIndex++] = a1;
if (!isWhite)
setToBlack(buffer, lineOffset, bitOffset, a1 - bitOffset);
bitOffset = a0 = a1;
isWhite = !isWhite;
updatePointer(7 - bits);
continue;
}
if (code == 11) {
if (nextLesserThan8Bits(3) != 7)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder5"));
int zeros = 0;
boolean exit = false;
while (!exit) {
while (nextLesserThan8Bits(1) != 1)
zeros++;
if (zeros > 5) {
zeros -= 6;
if (!isWhite && zeros > 0)
cce[currIndex++] = bitOffset;
bitOffset += zeros;
if (zeros > 0)
isWhite = true;
if (nextLesserThan8Bits(1) == 0) {
if (!isWhite)
cce[currIndex++] = bitOffset;
isWhite = true;
} else {
if (isWhite)
cce[currIndex++] = bitOffset;
isWhite = false;
}
exit = true;
}
if (zeros == 5) {
if (!isWhite)
cce[currIndex++] = bitOffset;
bitOffset += zeros;
isWhite = true;
continue;
}
bitOffset += zeros;
cce[currIndex++] = bitOffset;
setToBlack(buffer, lineOffset, bitOffset, 1);
bitOffset++;
isWhite = false;
}
continue;
}
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder5"));
}
cce[currIndex++] = bitOffset;
this.changingElemSize = currIndex;
lineOffset += scanlineStride;
}
}
private void setToBlack(byte[] buffer, int lineOffset, int bitOffset, int numBits) {
int bitNum = 8 * lineOffset + bitOffset;
int lastBit = bitNum + numBits;
int byteNum = bitNum >> 3;
int shift = bitNum & 0x7;
if (shift > 0) {
int maskVal = 1 << 7 - shift;
byte val = buffer[byteNum];
while (maskVal > 0 && bitNum < lastBit) {
val = (byte)(val | maskVal);
maskVal >>= 1;
bitNum++;
}
buffer[byteNum] = val;
}
byteNum = bitNum >> 3;
while (bitNum < lastBit - 7) {
buffer[byteNum++] = -1;
bitNum += 8;
}
while (bitNum < lastBit) {
byteNum = bitNum >> 3;
buffer[byteNum] = (byte)(buffer[byteNum] | 1 << 7 - (bitNum & 0x7));
bitNum++;
}
}
private int decodeWhiteCodeWord() {
int code = -1;
int runLength = 0;
boolean isWhite = true;
while (isWhite) {
int current = nextNBits(10);
int entry = white[current];
int isT = entry & 0x1;
int bits = entry >>> 1 & 0xF;
if (bits == 12) {
int twoBits = nextLesserThan8Bits(2);
current = current << 2 & 0xC | twoBits;
entry = additionalMakeup[current];
bits = entry >>> 1 & 0x7;
code = entry >>> 4 & 0xFFF;
runLength += code;
updatePointer(4 - bits);
continue;
}
if (bits == 0)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder0"));
if (bits == 15)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder1"));
code = entry >>> 5 & 0x7FF;
runLength += code;
updatePointer(10 - bits);
if (isT == 0)
isWhite = false;
}
return runLength;
}
private int decodeBlackCodeWord() {
int code = -1;
int runLength = 0;
boolean isWhite = false;
while (!isWhite) {
int current = nextLesserThan8Bits(4);
int entry = initBlack[current];
int isT = entry & 0x1;
int bits = entry >>> 1 & 0xF;
code = entry >>> 5 & 0x7FF;
if (code == 100) {
current = nextNBits(9);
entry = black[current];
isT = entry & 0x1;
bits = entry >>> 1 & 0xF;
code = entry >>> 5 & 0x7FF;
if (bits == 12) {
updatePointer(5);
current = nextLesserThan8Bits(4);
entry = additionalMakeup[current];
bits = entry >>> 1 & 0x7;
code = entry >>> 4 & 0xFFF;
runLength += code;
updatePointer(4 - bits);
continue;
}
if (bits == 15)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder2"));
runLength += code;
updatePointer(9 - bits);
if (isT == 0)
isWhite = true;
continue;
}
if (code == 200) {
current = nextLesserThan8Bits(2);
entry = twoBitBlack[current];
code = entry >>> 5 & 0x7FF;
runLength += code;
bits = entry >>> 1 & 0xF;
updatePointer(2 - bits);
isWhite = true;
continue;
}
runLength += code;
updatePointer(4 - bits);
isWhite = true;
}
return runLength;
}
private int readEOL() {
if (this.fillBits == 0) {
if (nextNBits(12) != 1)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder6"));
} else if (this.fillBits == 1) {
int bitsLeft = 8 - this.bitPointer;
if (nextNBits(bitsLeft) != 0)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder8"));
if (bitsLeft < 4 &&
nextNBits(8) != 0)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder8"));
int n;
while ((n = nextNBits(8)) != 1) {
if (n != 0)
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder8"));
}
}
if (this.oneD == 0)
return 1;
return nextLesserThan8Bits(1);
}
private void getNextChangingElement(int a0, boolean isWhite, int[] ret) {
int[] pce = this.prevChangingElems;
int ces = this.changingElemSize;
int start = (this.lastChangingElement > 0) ? (this.lastChangingElement - 1) : 0;
if (isWhite) {
start &= 0xFFFFFFFE;
} else {
start |= 0x1;
}
int i = start;
for (; i < ces; i += 2) {
int temp = pce[i];
if (temp > a0) {
this.lastChangingElement = i;
ret[0] = temp;
break;
}
}
if (i + 1 < ces)
ret[1] = pce[i + 1];
}
private int nextNBits(int bitsToGet) {
byte b, next, next2next;
int l = this.data.length - 1;
int bp = this.bytePointer;
if (this.fillOrder == 1) {
b = this.data[bp];
if (bp == l) {
next = 0;
next2next = 0;
} else if (bp + 1 == l) {
next = this.data[bp + 1];
next2next = 0;
} else {
next = this.data[bp + 1];
next2next = this.data[bp + 2];
}
} else if (this.fillOrder == 2) {
b = flipTable[this.data[bp] & 0xFF];
if (bp == l) {
next = 0;
next2next = 0;
} else if (bp + 1 == l) {
next = flipTable[this.data[bp + 1] & 0xFF];
next2next = 0;
} else {
next = flipTable[this.data[bp + 1] & 0xFF];
next2next = flipTable[this.data[bp + 2] & 0xFF];
}
} else {
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder7"));
}
int bitsLeft = 8 - this.bitPointer;
int bitsFromNextByte = bitsToGet - bitsLeft;
int bitsFromNext2NextByte = 0;
if (bitsFromNextByte > 8) {
bitsFromNext2NextByte = bitsFromNextByte - 8;
bitsFromNextByte = 8;
}
this.bytePointer++;
int i1 = (b & table1[bitsLeft]) << bitsToGet - bitsLeft;
int i2 = (next & table2[bitsFromNextByte]) >>> 8 - bitsFromNextByte;
int i3 = 0;
if (bitsFromNext2NextByte != 0) {
i2 <<= bitsFromNext2NextByte;
i3 = (next2next & table2[bitsFromNext2NextByte]) >>> 8 - bitsFromNext2NextByte;
i2 |= i3;
this.bytePointer++;
this.bitPointer = bitsFromNext2NextByte;
} else if (bitsFromNextByte == 8) {
this.bitPointer = 0;
this.bytePointer++;
} else {
this.bitPointer = bitsFromNextByte;
}
int i = i1 | i2;
return i;
}
private int nextLesserThan8Bits(int bitsToGet) {
byte b, next;
int i1;
int l = this.data.length - 1;
int bp = this.bytePointer;
if (this.fillOrder == 1) {
b = this.data[bp];
if (bp == l) {
next = 0;
} else {
next = this.data[bp + 1];
}
} else if (this.fillOrder == 2) {
b = flipTable[this.data[bp] & 0xFF];
if (bp == l) {
next = 0;
} else {
next = flipTable[this.data[bp + 1] & 0xFF];
}
} else {
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder7"));
}
int bitsLeft = 8 - this.bitPointer;
int bitsFromNextByte = bitsToGet - bitsLeft;
int shift = bitsLeft - bitsToGet;
if (shift >= 0) {
i1 = (b & table1[bitsLeft]) >>> shift;
this.bitPointer += bitsToGet;
if (this.bitPointer == 8) {
this.bitPointer = 0;
this.bytePointer++;
}
} else {
i1 = (b & table1[bitsLeft]) << -shift;
int i2 = (next & table2[bitsFromNextByte]) >>> 8 - bitsFromNextByte;
i1 |= i2;
this.bytePointer++;
this.bitPointer = bitsFromNextByte;
}
return i1;
}
private void updatePointer(int bitsToMoveBack) {
int i = this.bitPointer - bitsToMoveBack;
if (i < 0) {
this.bytePointer--;
this.bitPointer = 8 + i;
} else {
this.bitPointer = i;
}
}
private boolean advancePointer() {
if (this.bitPointer != 0) {
this.bytePointer++;
this.bitPointer = 0;
}
return true;
}
}

View file

@ -0,0 +1,213 @@
package org.apache.xmlgraphics.image.codec.tiff;
import java.io.Serializable;
public class TIFFField implements Comparable, Serializable {
public static final int TIFF_BYTE = 1;
public static final int TIFF_ASCII = 2;
public static final int TIFF_SHORT = 3;
public static final int TIFF_LONG = 4;
public static final int TIFF_RATIONAL = 5;
public static final int TIFF_SBYTE = 6;
public static final int TIFF_UNDEFINED = 7;
public static final int TIFF_SSHORT = 8;
public static final int TIFF_SLONG = 9;
public static final int TIFF_SRATIONAL = 10;
public static final int TIFF_FLOAT = 11;
public static final int TIFF_DOUBLE = 12;
int tag;
int type;
int count;
Object data;
TIFFField() {}
public TIFFField(int tag, int type, int count, Object data) {
this.tag = tag;
this.type = type;
this.count = count;
this.data = data;
}
public int getTag() {
return this.tag;
}
public int getType() {
return this.type;
}
public int getCount() {
return this.count;
}
public byte[] getAsBytes() {
return (byte[])this.data;
}
public char[] getAsChars() {
return (char[])this.data;
}
public short[] getAsShorts() {
return (short[])this.data;
}
public int[] getAsInts() {
return (int[])this.data;
}
public long[] getAsLongs() {
return (long[])this.data;
}
public float[] getAsFloats() {
return (float[])this.data;
}
public double[] getAsDoubles() {
return (double[])this.data;
}
public int[][] getAsSRationals() {
return (int[][])this.data;
}
public long[][] getAsRationals() {
return (long[][])this.data;
}
public int getAsInt(int index) {
switch (this.type) {
case 1:
case 7:
return ((byte[])this.data)[index] & 0xFF;
case 6:
return ((byte[])this.data)[index];
case 3:
return ((char[])this.data)[index] & Character.MAX_VALUE;
case 8:
return ((short[])this.data)[index];
case 9:
return ((int[])this.data)[index];
}
throw new ClassCastException();
}
public long getAsLong(int index) {
switch (this.type) {
case 1:
case 7:
return (long)(((byte[])this.data)[index] & 0xFF);
case 6:
return (long)((byte[])this.data)[index];
case 3:
return (long)(((char[])this.data)[index] & Character.MAX_VALUE);
case 8:
return (long)((short[])this.data)[index];
case 9:
return (long)((int[])this.data)[index];
case 4:
return ((long[])this.data)[index];
}
throw new ClassCastException();
}
public float getAsFloat(int index) {
int[] ivalue;
long[] lvalue;
switch (this.type) {
case 1:
return (float)(((byte[])this.data)[index] & 0xFF);
case 6:
return (float)((byte[])this.data)[index];
case 3:
return (float)(((char[])this.data)[index] & Character.MAX_VALUE);
case 8:
return (float)((short[])this.data)[index];
case 9:
return (float)((int[])this.data)[index];
case 4:
return (float)((long[])this.data)[index];
case 11:
return ((float[])this.data)[index];
case 12:
return (float)((double[])this.data)[index];
case 10:
ivalue = getAsSRational(index);
return (float)((double)ivalue[0] / (double)ivalue[1]);
case 5:
lvalue = getAsRational(index);
return (float)((double)lvalue[0] / (double)lvalue[1]);
}
throw new ClassCastException();
}
public double getAsDouble(int index) {
int[] ivalue;
long[] lvalue;
switch (this.type) {
case 1:
return (double)(((byte[])this.data)[index] & 0xFF);
case 6:
return (double)((byte[])this.data)[index];
case 3:
return (double)(((char[])this.data)[index] & Character.MAX_VALUE);
case 8:
return (double)((short[])this.data)[index];
case 9:
return (double)((int[])this.data)[index];
case 4:
return (double)((long[])this.data)[index];
case 11:
return (double)((float[])this.data)[index];
case 12:
return ((double[])this.data)[index];
case 10:
ivalue = getAsSRational(index);
return (double)ivalue[0] / (double)ivalue[1];
case 5:
lvalue = getAsRational(index);
return (double)lvalue[0] / (double)lvalue[1];
}
throw new ClassCastException();
}
public String getAsString(int index) {
return ((String[])this.data)[index];
}
public int[] getAsSRational(int index) {
return ((int[][])this.data)[index];
}
public long[] getAsRational(int index) {
return ((long[][])this.data)[index];
}
public int compareTo(Object o) {
if (o == null)
throw new NullPointerException();
int oTag = ((TIFFField)o).getTag();
if (this.tag < oTag)
return -1;
if (this.tag > oTag)
return 1;
return 0;
}
}

View file

@ -0,0 +1,78 @@
package org.apache.xmlgraphics.image.codec.tiff;
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;
public class TIFFImageDecoder extends ImageDecoderImpl {
public static final int TIFF_IMAGE_WIDTH = 256;
public static final int TIFF_IMAGE_LENGTH = 257;
public static final int TIFF_BITS_PER_SAMPLE = 258;
public static final int TIFF_COMPRESSION = 259;
public static final int TIFF_PHOTOMETRIC_INTERPRETATION = 262;
public static final int TIFF_FILL_ORDER = 266;
public static final int TIFF_STRIP_OFFSETS = 273;
public static final int TIFF_SAMPLES_PER_PIXEL = 277;
public static final int TIFF_ROWS_PER_STRIP = 278;
public static final int TIFF_STRIP_BYTE_COUNTS = 279;
public static final int TIFF_X_RESOLUTION = 282;
public static final int TIFF_Y_RESOLUTION = 283;
public static final int TIFF_PLANAR_CONFIGURATION = 284;
public static final int TIFF_T4_OPTIONS = 292;
public static final int TIFF_T6_OPTIONS = 293;
public static final int TIFF_RESOLUTION_UNIT = 296;
public static final int TIFF_PREDICTOR = 317;
public static final int TIFF_COLORMAP = 320;
public static final int TIFF_TILE_WIDTH = 322;
public static final int TIFF_TILE_LENGTH = 323;
public static final int TIFF_TILE_OFFSETS = 324;
public static final int TIFF_TILE_BYTE_COUNTS = 325;
public static final int TIFF_EXTRA_SAMPLES = 338;
public static final int TIFF_SAMPLE_FORMAT = 339;
public static final int TIFF_S_MIN_SAMPLE_VALUE = 340;
public static final int TIFF_S_MAX_SAMPLE_VALUE = 341;
public static final int TIFF_ICC_PROFILE = 34675;
public TIFFImageDecoder(SeekableStream input, ImageDecodeParam param) {
super(input, param);
}
public int getNumPages() throws IOException {
return TIFFDirectory.getNumDirectories(this.input);
}
public RenderedImage decodeAsRenderedImage(int page) throws IOException {
if (page < 0 || page >= getNumPages())
throw new IOException(PropertyUtil.getString("TIFFImageDecoder0"));
return new TIFFImage(this.input, (TIFFDecodeParam)this.param, page);
}
}

View file

@ -0,0 +1,154 @@
package org.apache.xmlgraphics.image.codec.tiff;
import org.apache.xmlgraphics.image.codec.util.PropertyUtil;
public class TIFFLZWDecoder {
byte[][] stringTable;
byte[] data = null;
byte[] uncompData;
int tableIndex;
int bitsToGet = 9;
int bytePointer;
int bitPointer;
int dstIndex;
int w;
int h;
int predictor;
int samplesPerPixel;
int nextData = 0;
int nextBits = 0;
int[] andTable = new int[] { 511, 1023, 2047, 4095 };
public TIFFLZWDecoder(int w, int predictor, int samplesPerPixel) {
this.w = w;
this.predictor = predictor;
this.samplesPerPixel = samplesPerPixel;
}
public byte[] decode(byte[] data, byte[] uncompData, int h) {
if (data[0] == 0 && data[1] == 1)
throw new UnsupportedOperationException(PropertyUtil.getString("TIFFLZWDecoder0"));
initializeStringTable();
this.data = data;
this.h = h;
this.uncompData = uncompData;
this.bytePointer = 0;
this.bitPointer = 0;
this.dstIndex = 0;
this.nextData = 0;
this.nextBits = 0;
int oldCode = 0;
int code;
while ((code = getNextCode()) != 257 && this.dstIndex != uncompData.length) {
if (code == 256) {
initializeStringTable();
code = getNextCode();
if (code == 257)
break;
writeString(this.stringTable[code]);
oldCode = code;
continue;
}
if (code < this.tableIndex) {
byte[] arrayOfByte = this.stringTable[code];
writeString(arrayOfByte);
addStringToTable(this.stringTable[oldCode], arrayOfByte[0]);
oldCode = code;
continue;
}
byte[] string = this.stringTable[oldCode];
string = composeString(string, string[0]);
writeString(string);
addStringToTable(string);
oldCode = code;
}
if (this.predictor == 2)
for (int j = 0; j < h; j++) {
int count = this.samplesPerPixel * (j * this.w + 1);
for (int i = this.samplesPerPixel; i < this.w * this.samplesPerPixel; i++) {
uncompData[count] = (byte)(uncompData[count] + uncompData[count - this.samplesPerPixel]);
count++;
}
}
return uncompData;
}
public void initializeStringTable() {
this.stringTable = new byte[4096][];
for (int i = 0; i < 256; i++) {
this.stringTable[i] = new byte[1];
this.stringTable[i][0] = (byte)i;
}
this.tableIndex = 258;
this.bitsToGet = 9;
}
public void writeString(byte[] string) {
for (int i = 0; i < string.length; i++)
this.uncompData[this.dstIndex++] = string[i];
}
public void addStringToTable(byte[] oldString, byte newString) {
int length = oldString.length;
byte[] string = new byte[length + 1];
System.arraycopy(oldString, 0, string, 0, length);
string[length] = newString;
this.stringTable[this.tableIndex++] = string;
if (this.tableIndex == 511) {
this.bitsToGet = 10;
} else if (this.tableIndex == 1023) {
this.bitsToGet = 11;
} else if (this.tableIndex == 2047) {
this.bitsToGet = 12;
}
}
public void addStringToTable(byte[] string) {
this.stringTable[this.tableIndex++] = string;
if (this.tableIndex == 511) {
this.bitsToGet = 10;
} else if (this.tableIndex == 1023) {
this.bitsToGet = 11;
} else if (this.tableIndex == 2047) {
this.bitsToGet = 12;
}
}
public byte[] composeString(byte[] oldString, byte newString) {
int length = oldString.length;
byte[] string = new byte[length + 1];
System.arraycopy(oldString, 0, string, 0, length);
string[length] = newString;
return string;
}
public int getNextCode() {
try {
this.nextData = this.nextData << 8 | this.data[this.bytePointer++] & 0xFF;
this.nextBits += 8;
if (this.nextBits < this.bitsToGet) {
this.nextData = this.nextData << 8 | this.data[this.bytePointer++] & 0xFF;
this.nextBits += 8;
}
int code = this.nextData >> this.nextBits - this.bitsToGet & this.andTable[this.bitsToGet - 9];
this.nextBits -= this.bitsToGet;
return code;
} catch (ArrayIndexOutOfBoundsException e) {
return 257;
}
}
}

View file

@ -0,0 +1,100 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
public final class FileCacheSeekableStream extends SeekableStream {
private InputStream stream;
private File cacheFile;
private RandomAccessFile cache;
private int bufLen = 1024;
private byte[] buf = new byte[this.bufLen];
private long length = 0L;
private long pointer = 0L;
private boolean foundEOF = false;
public FileCacheSeekableStream(InputStream stream) throws IOException {
this.stream = stream;
this.cacheFile = File.createTempFile("jai-FCSS-", ".tmp");
this.cacheFile.deleteOnExit();
this.cache = new RandomAccessFile(this.cacheFile, "rw");
}
private long readUntil(long pos) throws IOException {
if (pos < this.length)
return pos;
if (this.foundEOF)
return this.length;
long len = pos - this.length;
this.cache.seek(this.length);
while (len > 0L) {
int nbytes = this.stream.read(this.buf, 0, (int)Math.min(len, (long)this.bufLen));
if (nbytes == -1) {
this.foundEOF = true;
return this.length;
}
this.cache.setLength(this.cache.length() + (long)nbytes);
this.cache.write(this.buf, 0, nbytes);
len -= (long)nbytes;
this.length += (long)nbytes;
}
return pos;
}
public boolean canSeekBackwards() {
return true;
}
public long getFilePointer() {
return this.pointer;
}
public void seek(long pos) throws IOException {
if (pos < 0L)
throw new IOException(PropertyUtil.getString("FileCacheSeekableStream0"));
this.pointer = pos;
}
public int read() throws IOException {
long next = this.pointer + 1L;
long pos = readUntil(next);
if (pos >= next) {
this.cache.seek(this.pointer++);
return this.cache.read();
}
return -1;
}
public int read(byte[] b, int off, int len) throws IOException {
if (b == null)
throw new NullPointerException();
if (off < 0 || len < 0 || off + len > b.length)
throw new IndexOutOfBoundsException();
if (len == 0)
return 0;
long pos = readUntil(this.pointer + (long)len);
len = (int)Math.min((long)len, pos - this.pointer);
if (len > 0) {
this.cache.seek(this.pointer);
this.cache.readFully(b, off, len);
this.pointer += (long)len;
return len;
}
return -1;
}
public void close() throws IOException {
super.close();
this.cache.close();
this.cacheFile.delete();
}
}

View file

@ -0,0 +1,70 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.IOException;
import java.io.InputStream;
public class ForwardSeekableStream extends SeekableStream {
private InputStream src;
long pointer = 0L;
public ForwardSeekableStream(InputStream src) {
this.src = src;
}
public final int read() throws IOException {
int result = this.src.read();
if (result != -1)
this.pointer++;
return result;
}
public final int read(byte[] b, int off, int len) throws IOException {
int result = this.src.read(b, off, len);
if (result != -1)
this.pointer += (long)result;
return result;
}
public final long skip(long n) throws IOException {
long skipped = this.src.skip(n);
this.pointer += skipped;
return skipped;
}
public final int available() throws IOException {
return this.src.available();
}
public final void close() throws IOException {
this.src.close();
}
public final synchronized void mark(int readLimit) {
this.markPos = this.pointer;
this.src.mark(readLimit);
}
public final synchronized void reset() throws IOException {
if (this.markPos != -1L)
this.pointer = this.markPos;
this.src.reset();
}
public boolean markSupported() {
return this.src.markSupported();
}
public final boolean canSeekBackwards() {
return false;
}
public final long getFilePointer() {
return this.pointer;
}
public final void seek(long pos) throws IOException {
while (pos - this.pointer > 0L)
this.pointer += this.src.skip(pos - this.pointer);
}
}

View file

@ -0,0 +1,5 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.Serializable;
public interface ImageDecodeParam extends Cloneable, Serializable {}

View file

@ -0,0 +1,23 @@
package org.apache.xmlgraphics.image.codec.util;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.IOException;
public interface ImageDecoder {
ImageDecodeParam getParam();
void setParam(ImageDecodeParam paramImageDecodeParam);
SeekableStream getInputStream();
int getNumPages() throws IOException;
Raster decodeAsRaster() throws IOException;
Raster decodeAsRaster(int paramInt) throws IOException;
RenderedImage decodeAsRenderedImage() throws IOException;
RenderedImage decodeAsRenderedImage(int paramInt) throws IOException;
}

View file

@ -0,0 +1,53 @@
package org.apache.xmlgraphics.image.codec.util;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.InputStream;
public abstract class ImageDecoderImpl implements ImageDecoder {
protected SeekableStream input;
protected ImageDecodeParam param;
public ImageDecoderImpl(SeekableStream input, ImageDecodeParam param) {
this.input = input;
this.param = param;
}
public ImageDecoderImpl(InputStream input, ImageDecodeParam param) {
this.input = new ForwardSeekableStream(input);
this.param = param;
}
public ImageDecodeParam getParam() {
return this.param;
}
public void setParam(ImageDecodeParam param) {
this.param = param;
}
public SeekableStream getInputStream() {
return this.input;
}
public int getNumPages() throws IOException {
return 1;
}
public Raster decodeAsRaster() throws IOException {
return decodeAsRaster(0);
}
public Raster decodeAsRaster(int page) throws IOException {
RenderedImage im = decodeAsRenderedImage(page);
return im.getData();
}
public RenderedImage decodeAsRenderedImage() throws IOException {
return decodeAsRenderedImage(0);
}
public abstract RenderedImage decodeAsRenderedImage(int paramInt) throws IOException;
}

View file

@ -0,0 +1,5 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.Serializable;
public interface ImageEncodeParam extends ImageDecodeParam, Cloneable, Serializable {}

View file

@ -0,0 +1,19 @@
package org.apache.xmlgraphics.image.codec.util;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
public interface ImageEncoder {
ImageEncodeParam getParam();
void setParam(ImageEncodeParam paramImageEncodeParam);
OutputStream getOutputStream();
void encode(Raster paramRaster, ColorModel paramColorModel) throws IOException;
void encode(RenderedImage paramRenderedImage) throws IOException;
}

View file

@ -0,0 +1,37 @@
package org.apache.xmlgraphics.image.codec.util;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
public abstract class ImageEncoderImpl implements ImageEncoder {
protected OutputStream output;
protected ImageEncodeParam param;
public ImageEncoderImpl(OutputStream output, ImageEncodeParam param) {
this.output = output;
this.param = param;
}
public ImageEncodeParam getParam() {
return this.param;
}
public void setParam(ImageEncodeParam param) {
this.param = param;
}
public OutputStream getOutputStream() {
return this.output;
}
public void encode(Raster ras, ColorModel cm) throws IOException {
RenderedImage im = new SingleTileRenderedImage(ras, cm);
encode(im);
}
public abstract void encode(RenderedImage paramRenderedImage) throws IOException;
}

View file

@ -0,0 +1,37 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.IOException;
import javax.imageio.stream.ImageInputStream;
public final class ImageInputStreamSeekableStreamAdapter extends SeekableStream {
private ImageInputStream stream;
public ImageInputStreamSeekableStreamAdapter(ImageInputStream stream) throws IOException {
this.stream = stream;
}
public boolean canSeekBackwards() {
return true;
}
public long getFilePointer() throws IOException {
return this.stream.getStreamPosition();
}
public void seek(long pos) throws IOException {
this.stream.seek(pos);
}
public int read() throws IOException {
return this.stream.read();
}
public int read(byte[] b, int off, int len) throws IOException {
return this.stream.read(b, off, len);
}
public void close() throws IOException {
super.close();
this.stream.close();
}
}

View file

@ -0,0 +1,97 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public final class MemoryCacheSeekableStream extends SeekableStream {
private InputStream src;
private long pointer = 0L;
private static final int SECTOR_SHIFT = 9;
private static final int SECTOR_SIZE = 512;
private static final int SECTOR_MASK = 511;
private List data = new ArrayList();
int sectors = 0;
int length = 0;
boolean foundEOS = false;
public MemoryCacheSeekableStream(InputStream src) {
this.src = src;
}
private long readUntil(long pos) throws IOException {
if (pos < (long)this.length)
return pos;
if (this.foundEOS)
return (long)this.length;
int sector = (int)(pos >> 9L);
int startSector = this.length >> 9;
for (int i = startSector; i <= sector; i++) {
byte[] buf = new byte[512];
this.data.add(buf);
int len = 512;
int off = 0;
while (len > 0) {
int nbytes = this.src.read(buf, off, len);
if (nbytes == -1) {
this.foundEOS = true;
return (long)this.length;
}
off += nbytes;
len -= nbytes;
this.length += nbytes;
}
}
return (long)this.length;
}
public boolean canSeekBackwards() {
return true;
}
public long getFilePointer() {
return this.pointer;
}
public void seek(long pos) throws IOException {
if (pos < 0L)
throw new IOException(PropertyUtil.getString("MemoryCacheSeekableStream0"));
this.pointer = pos;
}
public int read() throws IOException {
long next = this.pointer + 1L;
long pos = readUntil(next);
if (pos >= next) {
byte[] buf = this.data.get((int)(this.pointer >> 9L));
return buf[(int)(this.pointer++ & 0x1FFL)] & 0xFF;
}
return -1;
}
public int read(byte[] b, int off, int len) throws IOException {
if (b == null)
throw new NullPointerException();
if (off < 0 || len < 0 || off + len > b.length)
throw new IndexOutOfBoundsException();
if (len == 0)
return 0;
long pos = readUntil(this.pointer + (long)len);
if (pos <= this.pointer)
return -1;
byte[] buf = this.data.get((int)(this.pointer >> 9L));
int nbytes = Math.min(len, 512 - (int)(this.pointer & 0x1FFL));
System.arraycopy(buf, (int)(this.pointer & 0x1FFL), b, off, nbytes);
this.pointer += (long)nbytes;
return nbytes;
}
}

View file

@ -0,0 +1,18 @@
package org.apache.xmlgraphics.image.codec.util;
import java.util.MissingResourceException;
import org.apache.xmlgraphics.util.i18n.LocalizableSupport;
public final class PropertyUtil {
protected static final String RESOURCES = "org.apache.xmlgraphics.image.codec.Messages";
protected static LocalizableSupport localizableSupport = new LocalizableSupport("org.apache.xmlgraphics.image.codec.Messages", PropertyUtil.class.getClassLoader());
public static String getString(String key) {
try {
return localizableSupport.formatMessage(key, null);
} catch (MissingResourceException e) {
return key;
}
}
}

View file

@ -0,0 +1,43 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public class SeekableOutputStream extends OutputStream {
private RandomAccessFile file;
public SeekableOutputStream(RandomAccessFile file) {
if (file == null)
throw new IllegalArgumentException("SeekableOutputStream0");
this.file = file;
}
public void write(int b) throws IOException {
this.file.write(b);
}
public void write(byte[] b) throws IOException {
this.file.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
this.file.write(b, off, len);
}
public void flush() throws IOException {
this.file.getFD().sync();
}
public void close() throws IOException {
this.file.close();
}
public long getFilePointer() throws IOException {
return this.file.getFilePointer();
}
public void seek(long pos) throws IOException {
this.file.seek(pos);
}
}

View file

@ -0,0 +1,245 @@
package org.apache.xmlgraphics.image.codec.util;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
public abstract class SeekableStream extends InputStream implements DataInput {
public static SeekableStream wrapInputStream(InputStream is, boolean canSeekBackwards) {
SeekableStream stream = null;
if (canSeekBackwards) {
try {
stream = new FileCacheSeekableStream(is);
} catch (Exception e) {
stream = new MemoryCacheSeekableStream(is);
}
} else {
stream = new ForwardSeekableStream(is);
}
return stream;
}
protected long markPos = -1L;
public abstract int read() throws IOException;
public abstract int read(byte[] paramArrayOfbyte, int paramInt1, int paramInt2) throws IOException;
public synchronized void mark(int readLimit) {
try {
this.markPos = getFilePointer();
} catch (IOException e) {
this.markPos = -1L;
}
}
public synchronized void reset() throws IOException {
if (this.markPos != -1L)
seek(this.markPos);
}
public boolean markSupported() {
return canSeekBackwards();
}
public boolean canSeekBackwards() {
return false;
}
public abstract long getFilePointer() throws IOException;
public abstract void seek(long paramLong) throws IOException;
public final void readFully(byte[] b) throws IOException {
readFully(b, 0, b.length);
}
public final void readFully(byte[] b, int off, int len) throws IOException {
int n = 0;
do {
int count = read(b, off + n, len - n);
if (count < 0)
throw new EOFException();
n += count;
} while (n < len);
}
public int skipBytes(int n) throws IOException {
if (n <= 0)
return 0;
return (int)skip((long)n);
}
public final boolean readBoolean() throws IOException {
int ch = read();
if (ch < 0)
throw new EOFException();
return (ch != 0);
}
public final byte readByte() throws IOException {
int ch = read();
if (ch < 0)
throw new EOFException();
return (byte)ch;
}
public final int readUnsignedByte() throws IOException {
int ch = read();
if (ch < 0)
throw new EOFException();
return ch;
}
public final short readShort() throws IOException {
int ch1 = read();
int ch2 = read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (short)((ch1 << 8) + (ch2 << 0));
}
public final short readShortLE() throws IOException {
int ch1 = read();
int ch2 = read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (short)((ch2 << 8) + (ch1 << 0));
}
public final int readUnsignedShort() throws IOException {
int ch1 = read();
int ch2 = read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (ch1 << 8) + (ch2 << 0);
}
public final int readUnsignedShortLE() throws IOException {
int ch1 = read();
int ch2 = read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (ch2 << 8) + (ch1 << 0);
}
public final char readChar() throws IOException {
int ch1 = read();
int ch2 = read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (char)((ch1 << 8) + (ch2 << 0));
}
public final char readCharLE() throws IOException {
int ch1 = read();
int ch2 = read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (char)((ch2 << 8) + (ch1 << 0));
}
public final int readInt() throws IOException {
int ch1 = read();
int ch2 = read();
int ch3 = read();
int ch4 = read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0);
}
public final int readIntLE() throws IOException {
int ch1 = read();
int ch2 = read();
int ch3 = read();
int ch4 = read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
}
public final long readUnsignedInt() throws IOException {
long ch1 = (long)read();
long ch2 = (long)read();
long ch3 = (long)read();
long ch4 = (long)read();
if ((ch1 | ch2 | ch3 | ch4) < 0L)
throw new EOFException();
return (ch1 << 24L) + (ch2 << 16L) + (ch3 << 8L) + (ch4 << 0L);
}
private byte[] ruileBuf = new byte[4];
public final long readUnsignedIntLE() throws IOException {
readFully(this.ruileBuf);
long ch1 = (long)(this.ruileBuf[0] & 0xFF);
long ch2 = (long)(this.ruileBuf[1] & 0xFF);
long ch3 = (long)(this.ruileBuf[2] & 0xFF);
long ch4 = (long)(this.ruileBuf[3] & 0xFF);
return (ch4 << 24L) + (ch3 << 16L) + (ch2 << 8L) + (ch1 << 0L);
}
public final long readLong() throws IOException {
return ((long)readInt() << 32L) + ((long)readInt() & 0xFFFFFFFFL);
}
public final long readLongLE() throws IOException {
int i1 = readIntLE();
int i2 = readIntLE();
return ((long)i2 << 32L) + ((long)i1 & 0xFFFFFFFFL);
}
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
public final float readFloatLE() throws IOException {
return Float.intBitsToFloat(readIntLE());
}
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
public final double readDoubleLE() throws IOException {
return Double.longBitsToDouble(readLongLE());
}
public final String readLine() throws IOException {
StringBuffer input = new StringBuffer();
int c = -1;
boolean eol = false;
while (!eol) {
long cur;
c = read();
switch (c) {
case -1:
case 10:
eol = true;
continue;
case 13:
eol = true;
cur = getFilePointer();
if (read() != 10)
seek(cur);
continue;
}
input.append((char)c);
}
if (c == -1 && input.length() == 0)
return null;
return input.toString();
}
public final String readUTF() throws IOException {
return DataInputStream.readUTF(this);
}
protected void finalize() throws Throwable {
super.finalize();
close();
}
}

View file

@ -0,0 +1,238 @@
package org.apache.xmlgraphics.image.codec.util;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
public abstract class SimpleRenderedImage implements RenderedImage {
protected int minX;
protected int minY;
protected int width;
protected int height;
protected int tileWidth;
protected int tileHeight;
protected int tileGridXOffset = 0;
protected int tileGridYOffset = 0;
protected SampleModel sampleModel = null;
protected ColorModel colorModel = null;
protected List sources = new ArrayList();
protected Map properties = new HashMap();
public int getMinX() {
return this.minX;
}
public final int getMaxX() {
return getMinX() + getWidth();
}
public int getMinY() {
return this.minY;
}
public final int getMaxY() {
return getMinY() + getHeight();
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public Rectangle getBounds() {
return new Rectangle(getMinX(), getMinY(), getWidth(), getHeight());
}
public int getTileWidth() {
return this.tileWidth;
}
public int getTileHeight() {
return this.tileHeight;
}
public int getTileGridXOffset() {
return this.tileGridXOffset;
}
public int getTileGridYOffset() {
return this.tileGridYOffset;
}
public int getMinTileX() {
return convertXToTileX(getMinX());
}
public int getMaxTileX() {
return convertXToTileX(getMaxX() - 1);
}
public int getNumXTiles() {
return getMaxTileX() - getMinTileX() + 1;
}
public int getMinTileY() {
return convertYToTileY(getMinY());
}
public int getMaxTileY() {
return convertYToTileY(getMaxY() - 1);
}
public int getNumYTiles() {
return getMaxTileY() - getMinTileY() + 1;
}
public SampleModel getSampleModel() {
return this.sampleModel;
}
public ColorModel getColorModel() {
return this.colorModel;
}
public Object getProperty(String name) {
name = name.toLowerCase();
return this.properties.get(name);
}
public String[] getPropertyNames() {
String[] names = new String[this.properties.size()];
this.properties.keySet().toArray(names);
return names;
}
public String[] getPropertyNames(String prefix) {
String[] propertyNames = getPropertyNames();
if (propertyNames == null)
return null;
prefix = prefix.toLowerCase();
List<String> names = new ArrayList();
for (int i = 0; i < propertyNames.length; i++) {
if (propertyNames[i].startsWith(prefix))
names.add(propertyNames[i]);
}
if (names.size() == 0)
return null;
String[] prefixNames = new String[names.size()];
names.<String>toArray(prefixNames);
return prefixNames;
}
public static int convertXToTileX(int x, int tileGridXOffset, int tileWidth) {
x -= tileGridXOffset;
if (x < 0)
x += 1 - tileWidth;
return x / tileWidth;
}
public static int convertYToTileY(int y, int tileGridYOffset, int tileHeight) {
y -= tileGridYOffset;
if (y < 0)
y += 1 - tileHeight;
return y / tileHeight;
}
public int convertXToTileX(int x) {
return convertXToTileX(x, getTileGridXOffset(), getTileWidth());
}
public int convertYToTileY(int y) {
return convertYToTileY(y, getTileGridYOffset(), getTileHeight());
}
public static int tileXToX(int tx, int tileGridXOffset, int tileWidth) {
return tx * tileWidth + tileGridXOffset;
}
public static int tileYToY(int ty, int tileGridYOffset, int tileHeight) {
return ty * tileHeight + tileGridYOffset;
}
public int tileXToX(int tx) {
return tx * this.tileWidth + this.tileGridXOffset;
}
public int tileYToY(int ty) {
return ty * this.tileHeight + this.tileGridYOffset;
}
public Vector getSources() {
return null;
}
public Raster getData() {
Rectangle rect = new Rectangle(getMinX(), getMinY(), getWidth(), getHeight());
return getData(rect);
}
public Raster getData(Rectangle bounds) {
int startX = convertXToTileX(bounds.x);
int startY = convertYToTileY(bounds.y);
int endX = convertXToTileX(bounds.x + bounds.width - 1);
int endY = convertYToTileY(bounds.y + bounds.height - 1);
if (startX == endX && startY == endY) {
Raster tile = getTile(startX, startY);
return tile.createChild(bounds.x, bounds.y, bounds.width, bounds.height, bounds.x, bounds.y, null);
}
SampleModel sm = this.sampleModel.createCompatibleSampleModel(bounds.width, bounds.height);
WritableRaster dest = Raster.createWritableRaster(sm, bounds.getLocation());
for (int j = startY; j <= endY; j++) {
for (int i = startX; i <= endX; i++) {
Raster tile = getTile(i, j);
Rectangle intersectRect = bounds.intersection(tile.getBounds());
Raster liveRaster = tile.createChild(intersectRect.x, intersectRect.y, intersectRect.width, intersectRect.height, intersectRect.x, intersectRect.y, null);
dest.setDataElements(0, 0, liveRaster);
}
}
return dest;
}
public WritableRaster copyData(WritableRaster dest) {
Rectangle bounds;
if (dest == null) {
bounds = getBounds();
Point p = new Point(this.minX, this.minY);
SampleModel sm = this.sampleModel.createCompatibleSampleModel(this.width, this.height);
dest = Raster.createWritableRaster(sm, p);
} else {
bounds = dest.getBounds();
}
int startX = convertXToTileX(bounds.x);
int startY = convertYToTileY(bounds.y);
int endX = convertXToTileX(bounds.x + bounds.width - 1);
int endY = convertYToTileY(bounds.y + bounds.height - 1);
for (int j = startY; j <= endY; j++) {
for (int i = startX; i <= endX; i++) {
Raster tile = getTile(i, j);
Rectangle intersectRect = bounds.intersection(tile.getBounds());
Raster liveRaster = tile.createChild(intersectRect.x, intersectRect.y, intersectRect.width, intersectRect.height, intersectRect.x, intersectRect.y, null);
dest.setDataElements(0, 0, liveRaster);
}
}
return dest;
}
}

View file

@ -0,0 +1,24 @@
package org.apache.xmlgraphics.image.codec.util;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
public class SingleTileRenderedImage extends SimpleRenderedImage {
Raster ras;
public SingleTileRenderedImage(Raster ras, ColorModel colorModel) {
this.ras = ras;
this.tileGridXOffset = this.minX = ras.getMinX();
this.tileGridYOffset = this.minY = ras.getMinY();
this.tileWidth = this.width = ras.getWidth();
this.tileHeight = this.height = ras.getHeight();
this.sampleModel = ras.getSampleModel();
this.colorModel = colorModel;
}
public Raster getTile(int tileX, int tileY) {
if (tileX != 0 || tileY != 0)
throw new IllegalArgumentException(PropertyUtil.getString("SingleTileRenderedImage0"));
return this.ras;
}
}

View file

@ -0,0 +1,18 @@
package org.apache.xmlgraphics.image.loader;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
public interface Image {
ImageInfo getInfo();
ImageSize getSize();
ImageFlavor getFlavor();
boolean isCacheable();
ICC_Profile getICCProfile();
ColorSpace getColorSpace();
}

View file

@ -0,0 +1,5 @@
package org.apache.xmlgraphics.image.loader;
public interface ImageContext {
float getSourceResolution();
}

View file

@ -0,0 +1,13 @@
package org.apache.xmlgraphics.image.loader;
public class ImageException extends Exception {
private static final long serialVersionUID = 3785613905389979249L;
public ImageException(String s) {
super(s);
}
public ImageException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,79 @@
package org.apache.xmlgraphics.image.loader;
public class ImageFlavor {
public static final ImageFlavor RENDERED_IMAGE = new ImageFlavor("RenderedImage");
public static final ImageFlavor BUFFERED_IMAGE = new SimpleRefinedImageFlavor(RENDERED_IMAGE, "BufferedImage");
private static final ImageFlavor DOM = new ImageFlavor("DOM");
public static final ImageFlavor XML_DOM = new MimeEnabledImageFlavor(DOM, "text/xml");
public static final ImageFlavor RAW = new ImageFlavor("Raw");
public static final ImageFlavor RAW_PNG = new MimeEnabledImageFlavor(RAW, "image/png");
public static final ImageFlavor RAW_JPEG = new MimeEnabledImageFlavor(RAW, "image/jpeg");
public static final ImageFlavor RAW_TIFF = new MimeEnabledImageFlavor(RAW, "image/tiff");
public static final ImageFlavor RAW_EMF = new MimeEnabledImageFlavor(RAW, "image/x-emf");
public static final ImageFlavor RAW_EPS = new MimeEnabledImageFlavor(RAW, "application/postscript");
public static final ImageFlavor RAW_LZW = new ImageFlavor("RawLZW");
public static final ImageFlavor RAW_CCITTFAX = new ImageFlavor("RawCCITTFax");
public static final ImageFlavor GRAPHICS2D = new ImageFlavor("Graphics2DImage");
private String name;
public ImageFlavor(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public String getMimeType() {
return null;
}
public String getNamespace() {
return null;
}
public boolean isCompatible(ImageFlavor flavor) {
return equals(flavor);
}
public int hashCode() {
int prime = 31;
int result = 1;
result = 31 * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ImageFlavor other = (ImageFlavor)obj;
if (this.name == null) {
if (other.name != null)
return false;
} else if (!this.name.equals(other.name)) {
return false;
}
return true;
}
public String toString() {
return getName();
}
}

View file

@ -0,0 +1,51 @@
package org.apache.xmlgraphics.image.loader;
import java.util.HashMap;
import java.util.Map;
public class ImageInfo {
public static final Object ORIGINAL_IMAGE = Image.class;
public static final Object HAS_MORE_IMAGES = "HAS_MORE_IMAGES";
private String originalURI;
private String mimeType;
private ImageSize size;
private Map customObjects = new HashMap();
public ImageInfo(String originalURI, String mimeType) {
this.originalURI = originalURI;
this.mimeType = mimeType;
}
public String getOriginalURI() {
return this.originalURI;
}
public String getMimeType() {
return this.mimeType;
}
public ImageSize getSize() {
return this.size;
}
public void setSize(ImageSize size) {
this.size = size;
}
public Map getCustomObjects() {
return this.customObjects;
}
public Image getOriginalImage() {
return (Image)this.customObjects.get(ORIGINAL_IMAGE);
}
public String toString() {
return getOriginalURI() + " (" + getMimeType() + ")";
}
}

View file

@ -0,0 +1,169 @@
package org.apache.xmlgraphics.image.loader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.transform.Source;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.cache.ImageCache;
import org.apache.xmlgraphics.image.loader.pipeline.ImageProviderPipeline;
import org.apache.xmlgraphics.image.loader.pipeline.PipelineFactory;
import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
import org.apache.xmlgraphics.image.loader.spi.ImagePreloader;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.image.loader.util.Penalty;
public class ImageManager {
protected static Log log = LogFactory.getLog(ImageManager.class);
private ImageImplRegistry registry;
private ImageContext imageContext;
private ImageCache cache = new ImageCache();
private PipelineFactory pipelineFactory = new PipelineFactory(this);
public ImageManager(ImageContext context) {
this(ImageImplRegistry.getDefaultInstance(), context);
}
public ImageManager(ImageImplRegistry registry, ImageContext context) {
this.registry = registry;
this.imageContext = context;
}
public ImageImplRegistry getRegistry() {
return this.registry;
}
public ImageContext getImageContext() {
return this.imageContext;
}
public ImageCache getCache() {
return this.cache;
}
public PipelineFactory getPipelineFactory() {
return this.pipelineFactory;
}
public ImageInfo getImageInfo(String uri, ImageSessionContext session) throws ImageException, IOException {
if (getCache() != null)
return getCache().needImageInfo(uri, session, this);
return preloadImage(uri, session);
}
public ImageInfo preloadImage(String uri, ImageSessionContext session) throws ImageException, IOException {
Source src = session.needSource(uri);
ImageInfo info = preloadImage(uri, src);
session.returnSource(uri, src);
return info;
}
public ImageInfo preloadImage(String uri, Source src) throws ImageException, IOException {
Iterator<ImagePreloader> iter = this.registry.getPreloaderIterator();
while (iter.hasNext()) {
ImagePreloader preloader = iter.next();
ImageInfo info = preloader.preloadImage(uri, src, this.imageContext);
if (info != null)
return info;
}
throw new ImageException("The file format is not supported. No ImagePreloader found for " + uri);
}
private Map prepareHints(Map hints, ImageSessionContext sessionContext) {
Map newHints = new HashMap();
if (hints != null)
newHints.putAll(hints);
if (!newHints.containsKey(ImageProcessingHints.IMAGE_SESSION_CONTEXT) && sessionContext != null)
newHints.put(ImageProcessingHints.IMAGE_SESSION_CONTEXT, sessionContext);
if (!newHints.containsKey(ImageProcessingHints.IMAGE_MANAGER))
newHints.put(ImageProcessingHints.IMAGE_MANAGER, this);
return newHints;
}
public Image getImage(ImageInfo info, ImageFlavor flavor, Map hints, ImageSessionContext session) throws ImageException, IOException {
hints = prepareHints(hints, session);
Image img = null;
ImageProviderPipeline pipeline = getPipelineFactory().newImageConverterPipeline(info, flavor);
if (pipeline != null)
img = pipeline.execute(info, hints, session);
if (img == null)
throw new ImageException("Cannot load image (no suitable loader/converter combination available) for " + info);
ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
return img;
}
public Image getImage(ImageInfo info, ImageFlavor[] flavors, Map hints, ImageSessionContext session) throws ImageException, IOException {
hints = prepareHints(hints, session);
Image img = null;
ImageProviderPipeline[] candidates = getPipelineFactory().determineCandidatePipelines(info, flavors);
ImageProviderPipeline pipeline = choosePipeline(candidates);
if (pipeline != null)
img = pipeline.execute(info, hints, session);
if (img == null)
throw new ImageException("Cannot load image (no suitable loader/converter combination available) for " + info);
ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
return img;
}
public Image getImage(ImageInfo info, ImageFlavor flavor, ImageSessionContext session) throws ImageException, IOException {
return getImage(info, flavor, ImageUtil.getDefaultHints(session), session);
}
public Image getImage(ImageInfo info, ImageFlavor[] flavors, ImageSessionContext session) throws ImageException, IOException {
return getImage(info, flavors, ImageUtil.getDefaultHints(session), session);
}
public Image convertImage(Image image, ImageFlavor[] flavors, Map hints) throws ImageException, IOException {
hints = prepareHints(hints, null);
ImageInfo info = image.getInfo();
Image img = null;
int count = flavors.length;
for (int i = 0; i < count; i++) {
if (image.getFlavor().equals(flavors[i]))
return image;
}
ImageProviderPipeline[] candidates = getPipelineFactory().determineCandidatePipelines(image, flavors);
ImageProviderPipeline pipeline = choosePipeline(candidates);
if (pipeline != null)
img = pipeline.execute(info, image, hints, null);
if (img == null)
throw new ImageException("Cannot convert image " + image + " (no suitable converter combination available)");
return img;
}
public Image convertImage(Image image, ImageFlavor[] flavors) throws ImageException, IOException {
return convertImage(image, flavors, null);
}
public ImageProviderPipeline choosePipeline(ImageProviderPipeline[] candidates) {
ImageProviderPipeline pipeline = null;
int minPenalty = Integer.MAX_VALUE;
int count = candidates.length;
if (log.isTraceEnabled()) {
log.trace("Candidate Pipelines:");
for (int j = 0; j < count; j++) {
if (candidates[j] != null)
log.trace(" " + j + ": " + candidates[j].getConversionPenalty(getRegistry()) + " for " + candidates[j]);
}
}
for (int i = count - 1; i >= 0; i--) {
if (candidates[i] != null) {
Penalty penalty = candidates[i].getConversionPenalty(getRegistry());
if (!penalty.isInfinitePenalty())
if (penalty.getValue() <= minPenalty) {
pipeline = candidates[i];
minPenalty = penalty.getValue();
}
}
}
if (log.isDebugEnabled())
log.debug("Chosen pipeline: " + pipeline);
return pipeline;
}
}

View file

@ -0,0 +1,25 @@
package org.apache.xmlgraphics.image.loader;
public interface ImageProcessingHints {
public static final Object SOURCE_RESOLUTION = "SOURCE_RESOLUTION";
public static final Object TARGET_RESOLUTION = "TARGET_RESOLUTION";
public static final Object IMAGE_SESSION_CONTEXT = "IMAGE_SESSION_CONTEXT";
public static final Object IMAGE_MANAGER = "IMAGE_MANAGER";
public static final Object IGNORE_COLOR_PROFILE = "IGNORE_COLOR_PROFILE";
public static final Object BITMAP_TYPE_INTENT = "BITMAP_TYPE_INTENT";
public static final String BITMAP_TYPE_INTENT_GRAY = "gray";
public static final String BITMAP_TYPE_INTENT_MONO = "mono";
public static final Object TRANSPARENCY_INTENT = "TRANSPARENCY_INTENT";
public static final String TRANSPARENCY_INTENT_PRESERVE = "preserve";
public static final String TRANSPARENCY_INTENT_IGNORE = "ignore";
}

View file

@ -0,0 +1,18 @@
package org.apache.xmlgraphics.image.loader;
import java.io.FileNotFoundException;
import javax.xml.transform.Source;
public interface ImageSessionContext {
ImageContext getParentContext();
float getTargetResolution();
Source newSource(String paramString);
Source getSource(String paramString);
Source needSource(String paramString) throws FileNotFoundException;
void returnSource(String paramString, Source paramSource);
}

View file

@ -0,0 +1,125 @@
package org.apache.xmlgraphics.image.loader;
import java.awt.Dimension;
import java.awt.geom.Dimension2D;
import org.apache.xmlgraphics.java2d.Dimension2DDouble;
import org.apache.xmlgraphics.util.UnitConv;
public class ImageSize {
private int widthPx;
private int heightPx;
private int widthMpt;
private int heightMpt;
private int baselinePositionFromBottomMpt;
private double dpiHorizontal;
private double dpiVertical;
public ImageSize(int widthPx, int heightPx, double dpiHorizontal, double dpiVertical) {
setSizeInPixels(widthPx, heightPx);
setResolution(dpiHorizontal, dpiVertical);
}
public ImageSize(int widthPx, int heightPx, double dpi) {
this(widthPx, heightPx, dpi, dpi);
}
public ImageSize() {}
public void setSizeInPixels(int width, int height) {
this.widthPx = width;
this.heightPx = height;
}
public void setSizeInMillipoints(int width, int height) {
this.widthMpt = width;
this.heightMpt = height;
}
public void setResolution(double horizontal, double vertical) {
this.dpiHorizontal = horizontal;
this.dpiVertical = vertical;
}
public void setResolution(double resolution) {
setResolution(resolution, resolution);
}
public void setBaselinePositionFromBottom(int distance) {
this.baselinePositionFromBottomMpt = distance;
}
public int getBaselinePositionFromBottom() {
return this.baselinePositionFromBottomMpt;
}
public int getWidthPx() {
return this.widthPx;
}
public int getHeightPx() {
return this.heightPx;
}
public int getWidthMpt() {
return this.widthMpt;
}
public int getHeightMpt() {
return this.heightMpt;
}
public double getDpiHorizontal() {
return this.dpiHorizontal;
}
public double getDpiVertical() {
return this.dpiVertical;
}
public Dimension getDimensionMpt() {
return new Dimension(getWidthMpt(), getHeightMpt());
}
public Dimension2D getDimensionPt() {
return new Dimension2DDouble((double)getWidthMpt() / 1000.0D, (double)getHeightMpt() / 1000.0D);
}
public Dimension getDimensionPx() {
return new Dimension(getWidthPx(), getHeightPx());
}
private void checkResolutionAvailable() {
if (this.dpiHorizontal == 0.0D || this.dpiVertical == 0.0D)
throw new IllegalStateException("The resolution must be set");
}
public void calcSizeFromPixels() {
checkResolutionAvailable();
this.widthMpt = (int)Math.round(UnitConv.in2mpt((double)this.widthPx / this.dpiHorizontal));
this.heightMpt = (int)Math.round(UnitConv.in2mpt((double)this.heightPx / this.dpiVertical));
}
public void calcPixelsFromSize() {
checkResolutionAvailable();
this.widthPx = (int)Math.round(UnitConv.mpt2in((double)this.widthMpt * this.dpiHorizontal));
this.heightPx = (int)Math.round(UnitConv.mpt2in((double)this.heightMpt * this.dpiVertical));
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Size: ");
sb.append(getWidthMpt()).append('x').append(getHeightMpt()).append(" mpt");
sb.append(" (");
sb.append(getWidthPx()).append('x').append(getHeightPx()).append(" px");
sb.append(" at ").append(getDpiHorizontal()).append('x').append(getDpiVertical());
sb.append(" dpi");
sb.append(")");
return sb.toString();
}
}

View file

@ -0,0 +1,51 @@
package org.apache.xmlgraphics.image.loader;
import java.io.InputStream;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.xmlgraphics.image.loader.util.ImageInputStreamAdapter;
public class ImageSource implements Source {
private String systemId;
private ImageInputStream iin;
private boolean fastSource;
public ImageSource(ImageInputStream in, String systemId, boolean fastSource) {
assert in != null : "InputStream is null";
this.iin = in;
this.systemId = systemId;
this.fastSource = fastSource;
}
public InputStream getInputStream() {
if (this.iin == null)
return null;
return new ImageInputStreamAdapter(this.iin);
}
public ImageInputStream getImageInputStream() {
return this.iin;
}
public void setImageInputStream(ImageInputStream in) {
this.iin = in;
}
public String getSystemId() {
return this.systemId;
}
public void setSystemId(String systemId) {
this.systemId = systemId;
}
public boolean isFastSource() {
return this.fastSource;
}
public String toString() {
return (isFastSource() ? "FAST " : "") + "ImageSource: " + getSystemId() + " " + getImageInputStream();
}
}

View file

@ -0,0 +1,14 @@
package org.apache.xmlgraphics.image.loader;
public class MimeEnabledImageFlavor extends RefinedImageFlavor {
private String mime;
public MimeEnabledImageFlavor(ImageFlavor parentFlavor, String mime) {
super(mime + ";" + parentFlavor.getName(), parentFlavor);
this.mime = mime;
}
public String getMimeType() {
return this.mime;
}
}

View file

@ -0,0 +1,30 @@
package org.apache.xmlgraphics.image.loader;
public abstract class RefinedImageFlavor extends ImageFlavor {
private ImageFlavor parentFlavor;
protected RefinedImageFlavor(ImageFlavor parentFlavor) {
this(parentFlavor.getName(), parentFlavor);
}
protected RefinedImageFlavor(String name, ImageFlavor parentFlavor) {
super(name);
this.parentFlavor = parentFlavor;
}
public ImageFlavor getParentFlavor() {
return this.parentFlavor;
}
public String getMimeType() {
return this.parentFlavor.getMimeType();
}
public String getNamespace() {
return this.parentFlavor.getNamespace();
}
public boolean isCompatible(ImageFlavor flavor) {
return (getParentFlavor().isCompatible(flavor) || super.isCompatible(flavor));
}
}

View file

@ -0,0 +1,7 @@
package org.apache.xmlgraphics.image.loader;
public class SimpleRefinedImageFlavor extends RefinedImageFlavor {
public SimpleRefinedImageFlavor(ImageFlavor parentFlavor, String name) {
super(name, parentFlavor);
}
}

View file

@ -0,0 +1,13 @@
package org.apache.xmlgraphics.image.loader;
public class SubImageNotFoundException extends ImageException {
private static final long serialVersionUID = 3785613905389979249L;
public SubImageNotFoundException(String s) {
super(s);
}
public SubImageNotFoundException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,16 @@
package org.apache.xmlgraphics.image.loader;
public class XMLNamespaceEnabledImageFlavor extends RefinedImageFlavor {
public static final ImageFlavor SVG_DOM = new XMLNamespaceEnabledImageFlavor(ImageFlavor.XML_DOM, "http://www.w3.org/2000/svg");
private String namespace;
public XMLNamespaceEnabledImageFlavor(ImageFlavor parentFlavor, String namespace) {
super(parentFlavor.getName() + ";namespace=" + namespace, parentFlavor);
this.namespace = namespace;
}
public String getNamespace() {
return this.namespace;
}
}

View file

@ -0,0 +1,28 @@
package org.apache.xmlgraphics.image.loader.cache;
public class DefaultExpirationPolicy implements ExpirationPolicy {
public static final int EXPIRATION_IMMEDIATE = 0;
public static final int EXPIRATION_NEVER = -1;
private int expirationAfter;
public DefaultExpirationPolicy() {
this(60);
}
public DefaultExpirationPolicy(int expirationAfter) {
this.expirationAfter = expirationAfter;
}
private boolean isNeverExpired() {
return (this.expirationAfter < 0);
}
public boolean isExpired(TimeStampProvider provider, long timestamp) {
if (isNeverExpired())
return false;
long now = provider.getTimeStamp();
return (now >= timestamp + (long)(this.expirationAfter * 1000));
}
}

View file

@ -0,0 +1,5 @@
package org.apache.xmlgraphics.image.loader.cache;
public interface ExpirationPolicy {
boolean isExpired(TimeStampProvider paramTimeStampProvider, long paramLong);
}

View file

@ -0,0 +1,177 @@
package org.apache.xmlgraphics.image.loader.cache;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.xml.transform.Source;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.util.SoftMapCache;
public class ImageCache {
protected static Log log = LogFactory.getLog(ImageCache.class);
private Map invalidURIs = Collections.synchronizedMap(new HashMap());
private ExpirationPolicy invalidURIExpirationPolicy;
private SoftMapCache imageInfos = new SoftMapCache(true);
private SoftMapCache images = new SoftMapCache(true);
private ImageCacheListener cacheListener;
private TimeStampProvider timeStampProvider;
private long lastHouseKeeping;
private static final long ONE_HOUR = 3600000L;
public ImageCache() {
this(new TimeStampProvider(), new DefaultExpirationPolicy());
}
public ImageCache(TimeStampProvider timeStampProvider, ExpirationPolicy invalidURIExpirationPolicy) {
this.timeStampProvider = timeStampProvider;
this.invalidURIExpirationPolicy = invalidURIExpirationPolicy;
this.lastHouseKeeping = this.timeStampProvider.getTimeStamp();
}
public void setCacheListener(ImageCacheListener listener) {
this.cacheListener = listener;
}
public ImageInfo needImageInfo(String uri, ImageSessionContext session, ImageManager manager) throws ImageException, IOException {
if (isInvalidURI(uri))
throw new FileNotFoundException("Image not found: " + uri);
String lockURI = uri.intern();
synchronized (lockURI) {
ImageInfo info = getImageInfo(uri);
if (info == null) {
try {
Source src = session.needSource(uri);
if (src == null) {
registerInvalidURI(uri);
throw new FileNotFoundException("Image not found: " + uri);
}
info = manager.preloadImage(uri, src);
session.returnSource(uri, src);
} catch (IOException ioe) {
registerInvalidURI(uri);
throw ioe;
} catch (ImageException e) {
registerInvalidURI(uri);
throw e;
}
putImageInfo(info);
}
return info;
}
}
public boolean isInvalidURI(String uri) {
boolean expired = removeInvalidURIIfExpired(uri);
if (expired)
return false;
if (this.cacheListener != null)
this.cacheListener.invalidHit(uri);
return true;
}
private boolean removeInvalidURIIfExpired(String uri) {
Long timestamp = (Long)this.invalidURIs.get(uri);
boolean expired = (timestamp == null || this.invalidURIExpirationPolicy.isExpired(this.timeStampProvider, timestamp.longValue()));
if (expired)
this.invalidURIs.remove(uri);
return expired;
}
protected ImageInfo getImageInfo(String uri) {
ImageInfo info = (ImageInfo)this.imageInfos.get(uri);
if (this.cacheListener != null)
if (info != null) {
this.cacheListener.cacheHitImageInfo(uri);
} else if (!isInvalidURI(uri)) {
this.cacheListener.cacheMissImageInfo(uri);
}
return info;
}
protected void putImageInfo(ImageInfo info) {
this.imageInfos.put(info.getOriginalURI(), info);
}
void registerInvalidURI(String uri) {
this.invalidURIs.put(uri, new Long(this.timeStampProvider.getTimeStamp()));
considerHouseKeeping();
}
public Image getImage(ImageInfo info, ImageFlavor flavor) {
return getImage(info.getOriginalURI(), flavor);
}
public Image getImage(String uri, ImageFlavor flavor) {
if (uri == null || "".equals(uri))
return null;
ImageKey key = new ImageKey(uri, flavor);
Image img = (Image)this.images.get(key);
if (this.cacheListener != null)
if (img != null) {
this.cacheListener.cacheHitImage(key);
} else {
this.cacheListener.cacheMissImage(key);
}
return img;
}
public void putImage(Image img) {
String originalURI = img.getInfo().getOriginalURI();
if (originalURI == null || "".equals(originalURI))
return;
if (!img.isCacheable())
throw new IllegalArgumentException("Image is not cacheable! (Flavor: " + img.getFlavor() + ")");
ImageKey key = new ImageKey(originalURI, img.getFlavor());
this.images.put(key, img);
}
public void clearCache() {
this.invalidURIs.clear();
this.imageInfos.clear();
this.images.clear();
doHouseKeeping();
}
private void considerHouseKeeping() {
long ts = this.timeStampProvider.getTimeStamp();
if (this.lastHouseKeeping + 3600000L > ts) {
this.lastHouseKeeping = ts;
doHouseKeeping();
}
}
public void doHouseKeeping() {
this.imageInfos.doHouseKeeping();
this.images.doHouseKeeping();
doInvalidURIHouseKeeping();
}
private void doInvalidURIHouseKeeping() {
Set currentEntries = new HashSet(this.invalidURIs.keySet());
Iterator<String> iter = currentEntries.iterator();
while (iter.hasNext()) {
String key = iter.next();
removeInvalidURIIfExpired(key);
}
}
}

View file

@ -0,0 +1,15 @@
package org.apache.xmlgraphics.image.loader.cache;
import java.util.EventListener;
public interface ImageCacheListener extends EventListener {
void invalidHit(String paramString);
void cacheHitImageInfo(String paramString);
void cacheMissImageInfo(String paramString);
void cacheHitImage(ImageKey paramImageKey);
void cacheMissImage(ImageKey paramImageKey);
}

View file

@ -0,0 +1,96 @@
package org.apache.xmlgraphics.image.loader.cache;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class ImageCacheStatistics implements ImageCacheListener {
private int invalidHits;
private int imageInfoCacheHits;
private int imageInfoCacheMisses;
private int imageCacheHits;
private int imageCacheMisses;
private Map imageCacheHitMap;
private Map imageCacheMissMap;
public ImageCacheStatistics(boolean detailed) {
if (detailed) {
this.imageCacheHitMap = new HashMap();
this.imageCacheMissMap = new HashMap();
}
}
public void reset() {
this.imageInfoCacheHits = 0;
this.imageInfoCacheMisses = 0;
this.invalidHits = 0;
}
public void invalidHit(String uri) {
this.invalidHits++;
}
public void cacheHitImageInfo(String uri) {
this.imageInfoCacheHits++;
}
public void cacheMissImageInfo(String uri) {
this.imageInfoCacheMisses++;
}
private void increaseEntry(Map map, Object key) {
Integer v = (Integer)map.get(key);
if (v == null) {
v = new Integer(1);
} else {
v = new Integer(v + 1);
}
map.put(key, v);
}
public void cacheHitImage(ImageKey key) {
this.imageCacheHits++;
if (this.imageCacheHitMap != null)
increaseEntry(this.imageCacheHitMap, key);
}
public void cacheMissImage(ImageKey key) {
this.imageCacheMisses++;
if (this.imageCacheMissMap != null)
increaseEntry(this.imageCacheMissMap, key);
}
public int getInvalidHits() {
return this.invalidHits;
}
public int getImageInfoCacheHits() {
return this.imageInfoCacheHits;
}
public int getImageInfoCacheMisses() {
return this.imageInfoCacheMisses;
}
public int getImageCacheHits() {
return this.imageCacheHits;
}
public int getImageCacheMisses() {
return this.imageCacheMisses;
}
public Map getImageCacheHitMap() {
return Collections.unmodifiableMap(this.imageCacheHitMap);
}
public Map getImageCacheMissMap() {
return Collections.unmodifiableMap(this.imageCacheMissMap);
}
}

View file

@ -0,0 +1,45 @@
package org.apache.xmlgraphics.image.loader.cache;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
public class ImageKey {
private String uri;
private ImageFlavor flavor;
public ImageKey(String uri, ImageFlavor flavor) {
if (uri == null)
throw new NullPointerException("URI must not be null");
if (flavor == null)
throw new NullPointerException("flavor must not be null");
this.uri = uri;
this.flavor = flavor;
}
public int hashCode() {
int prime = 31;
int result = 1;
result = 31 * result + ((this.flavor == null) ? 0 : this.flavor.hashCode());
result = 31 * result + ((this.uri == null) ? 0 : this.uri.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ImageKey other = (ImageKey)obj;
if (!this.uri.equals(other.uri))
return false;
if (!this.flavor.equals(other.flavor))
return false;
return true;
}
public String toString() {
return this.uri + " (" + this.flavor + ")";
}
}

View file

@ -0,0 +1,7 @@
package org.apache.xmlgraphics.image.loader.cache;
class TimeStampProvider {
public long getTimeStamp() {
return System.currentTimeMillis();
}
}

View file

@ -0,0 +1,38 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
public abstract class AbstractImage implements Image {
private ImageInfo info;
public AbstractImage(ImageInfo info) {
this.info = info;
}
public ImageInfo getInfo() {
return this.info;
}
public ImageSize getSize() {
return getInfo().getSize();
}
public ColorSpace getColorSpace() {
return null;
}
public ICC_Profile getICCProfile() {
if (getColorSpace() instanceof ICC_ColorSpace)
return ((ICC_ColorSpace)getColorSpace()).getProfile();
return null;
}
public String toString() {
return getClass().getName() + ": " + getInfo();
}
}

View file

@ -0,0 +1,15 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.spi.ImageConverter;
public abstract class AbstractImageConverter implements ImageConverter {
protected void checkSourceFlavor(Image img) {
if (!getSourceFlavor().equals(img.getFlavor()))
throw new IllegalArgumentException("Incompatible image: " + img);
}
public int getConversionPenalty() {
return 10;
}
}

View file

@ -0,0 +1,27 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.IOException;
import java.util.Map;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageProcessingHints;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
public abstract class AbstractImageLoader implements ImageLoader {
public Image loadImage(ImageInfo info, ImageSessionContext session) throws ImageException, IOException {
return loadImage(info, null, session);
}
public int getUsagePenalty() {
return 0;
}
protected boolean ignoreColorProfile(Map hints) {
if (hints == null)
return false;
Boolean b = (Boolean)hints.get(ImageProcessingHints.IGNORE_COLOR_PROFILE);
return (b != null && b);
}
}

View file

@ -0,0 +1,17 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
import org.apache.xmlgraphics.image.loader.spi.ImageLoaderFactory;
public abstract class AbstractImageLoaderFactory implements ImageLoaderFactory {
public boolean isSupported(ImageInfo imageInfo) {
return true;
}
public int getUsagePenalty(String mime, ImageFlavor flavor) {
ImageLoader loader = newImageLoader(flavor);
return loader.getUsagePenalty();
}
}

View file

@ -0,0 +1,22 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.IOException;
import java.util.Arrays;
import javax.imageio.stream.ImageInputStream;
import org.apache.xmlgraphics.image.loader.spi.ImagePreloader;
public abstract class AbstractImagePreloader implements ImagePreloader {
protected byte[] getHeader(ImageInputStream in, int size) throws IOException {
byte[] header = new byte[size];
long startPos = in.getStreamPosition();
int read = in.read(header);
if (read < size)
Arrays.fill(header, (byte)0);
in.seek(startPos);
return header;
}
public int getPriority() {
return 1000;
}
}

View file

@ -0,0 +1,209 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.ImageSource;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.image.loader.util.SoftMapCache;
public abstract class AbstractImageSessionContext implements ImageSessionContext {
private static Log log = LogFactory.getLog(AbstractImageSessionContext.class);
private static boolean noSourceReuse = false;
static {
String v = System.getProperty(AbstractImageSessionContext.class.getName() + ".no-source-reuse");
noSourceReuse = Boolean.valueOf(v);
}
public Source newSource(String uri) {
URL uRL;
Source source = resolveURI(uri);
if (source == null) {
if (log.isDebugEnabled())
log.debug("URI could not be resolved: " + uri);
return null;
}
if (!(source instanceof javax.xml.transform.stream.StreamSource) && !(source instanceof javax.xml.transform.sax.SAXSource))
return source;
ImageSource imageSource = null;
String resolvedURI = source.getSystemId();
try {
uRL = new URL(resolvedURI);
} catch (MalformedURLException e) {
uRL = null;
}
File f = toFile(uRL);
if (f != null) {
boolean directFileAccess = true;
assert source instanceof javax.xml.transform.stream.StreamSource || source instanceof javax.xml.transform.sax.SAXSource;
InputStream in = ImageUtil.getInputStream(source);
if (in == null)
try {
in = new 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))
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) {
IOUtils.closeQuietly(in);
try {
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;
}
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))
return source;
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 {
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;
}
protected ImageInputStream createImageInputStream(InputStream in) throws IOException {
ImageInputStream iin = ImageIO.createImageInputStream(in);
return (ImageInputStream)Proxy.newProxyInstance(ImageInputStream.class.getClassLoader(), new Class<?>[] { ImageInputStream.class }, new ObservingImageInputStreamInvocationHandler(iin, in));
}
private static class ObservingImageInputStreamInvocationHandler implements InvocationHandler {
private ImageInputStream iin;
private InputStream in;
public ObservingImageInputStreamInvocationHandler(ImageInputStream iin, InputStream underlyingStream) {
this.iin = iin;
this.in = underlyingStream;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("close".equals(method.getName()))
try {
return method.invoke(this.iin, args);
} finally {
IOUtils.closeQuietly(this.in);
this.in = null;
}
return method.invoke(this.iin, args);
}
}
public static File toFile(URL url) {
if (url == null || !url.getProtocol().equals("file"))
return null;
try {
String filename = "";
if (url.getHost() != null && url.getHost().length() > 0)
filename = filename + Character.toString(File.separatorChar) + Character.toString(File.separatorChar) + url.getHost();
filename = filename + url.getFile().replace('/', File.separatorChar);
filename = URLDecoder.decode(filename, "UTF-8");
File f = new File(filename);
if (!f.isFile())
return null;
return f;
} catch (UnsupportedEncodingException uee) {
assert false;
return null;
}
}
private SoftMapCache sessionSources = new SoftMapCache(false);
public Source getSource(String uri) {
return (Source)this.sessionSources.remove(uri);
}
public Source needSource(String uri) throws FileNotFoundException {
Source src = getSource(uri);
if (src == null) {
if (log.isDebugEnabled())
log.debug("Creating new Source for " + uri);
src = newSource(uri);
if (src == null)
throw new FileNotFoundException("Image not found: " + uri);
} else if (log.isDebugEnabled()) {
log.debug("Reusing Source for " + uri);
}
return src;
}
public void returnSource(String uri, Source src) {
ImageInputStream in = ImageUtil.getImageInputStream(src);
try {
if (in != null && in.getStreamPosition() != 0L)
throw new IllegalStateException("ImageInputStream is not reset for: " + uri);
} catch (IOException ioe) {
ImageUtil.closeQuietly(src);
}
if (isReusable(src)) {
log.debug("Returning Source for " + uri);
this.sessionSources.put(uri, src);
} else {
ImageUtil.closeQuietly(src);
}
}
protected boolean isReusable(Source src) {
if (noSourceReuse)
return false;
if (src instanceof ImageSource) {
ImageSource is = (ImageSource)src;
if (is.getImageInputStream() != null)
return true;
}
if (src instanceof javax.xml.transform.dom.DOMSource)
return true;
return false;
}
protected abstract Source resolveURI(String paramString);
}

View file

@ -0,0 +1,67 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.IOException;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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.spi.ImageLoader;
public class CompositeImageLoader extends AbstractImageLoader {
protected static Log log = LogFactory.getLog(CompositeImageLoader.class);
private ImageLoader[] loaders;
public CompositeImageLoader(ImageLoader[] loaders) {
if (loaders == null || loaders.length == 0)
throw new IllegalArgumentException("Must at least pass one ImageLoader as parameter");
for (int i = 1, c = loaders.length; i < c; i++) {
if (!loaders[0].getTargetFlavor().equals(loaders[i].getTargetFlavor()))
throw new IllegalArgumentException("All ImageLoaders must produce the same target flavor");
}
this.loaders = loaders;
}
public ImageFlavor getTargetFlavor() {
return this.loaders[0].getTargetFlavor();
}
public int getUsagePenalty() {
int maxPenalty = 0;
for (int i = 1, c = this.loaders.length; i < c; i++)
maxPenalty = Math.max(maxPenalty, this.loaders[i].getUsagePenalty());
return maxPenalty;
}
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
ImageException firstException = null;
for (int i = 0, c = this.loaders.length; i < c; i++) {
ImageLoader loader = this.loaders[i];
try {
Image img = loader.loadImage(info, hints, session);
if (img != null && firstException != null)
log.debug("First ImageLoader failed (" + firstException.getMessage() + "). Fallback was successful.");
return img;
} catch (ImageException ie) {
if (firstException == null)
firstException = ie;
}
}
throw firstException;
}
public String toString() {
StringBuffer sb = new StringBuffer("[");
for (int i = 0; i < this.loaders.length; i++) {
if (i > 0)
sb.append(",");
sb.append(this.loaders[i].toString());
}
sb.append("]");
return sb.toString();
}
}

View file

@ -0,0 +1,21 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import org.apache.xmlgraphics.image.loader.ImageContext;
public class DefaultImageContext implements ImageContext {
private final float sourceResolution;
public DefaultImageContext() {
if (GraphicsEnvironment.isHeadless()) {
this.sourceResolution = 72.0F;
} else {
this.sourceResolution = (float)Toolkit.getDefaultToolkit().getScreenResolution();
}
}
public float getSourceResolution() {
return this.sourceResolution;
}
}

View file

@ -0,0 +1,46 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.apache.xmlgraphics.image.loader.ImageContext;
public class DefaultImageSessionContext extends AbstractImageSessionContext {
private ImageContext context;
private File baseDir;
public DefaultImageSessionContext(ImageContext context, File baseDir) {
this.context = context;
this.baseDir = baseDir;
}
public ImageContext getParentContext() {
return this.context;
}
public File getBaseDir() {
return this.baseDir;
}
protected Source resolveURI(String uri) {
try {
URL url = new URL(uri);
return new StreamSource(url.openStream(), url.toExternalForm());
} catch (MalformedURLException e) {
File f = new File(this.baseDir, uri);
if (f.isFile())
return new StreamSource(f);
return null;
} catch (IOException ioe) {
return null;
}
}
public float getTargetResolution() {
return getParentContext().getSourceResolution();
}
}

View file

@ -0,0 +1,20 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.Color;
import java.awt.image.BufferedImage;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
public class ImageBuffered extends ImageRendered {
public ImageBuffered(ImageInfo info, BufferedImage buffered, Color transparentColor) {
super(info, buffered, transparentColor);
}
public ImageFlavor getFlavor() {
return ImageFlavor.BUFFERED_IMAGE;
}
public BufferedImage getBufferedImage() {
return (BufferedImage)getRenderedImage();
}
}

View file

@ -0,0 +1,46 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.util.Map;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
public class ImageConverterBitmap2G2D extends AbstractImageConverter {
public Image convert(Image src, Map hints) {
checkSourceFlavor(src);
final ImageRendered rendImage = (ImageRendered)src;
Graphics2DImagePainter painter = new Graphics2DImagePainter() {
public Dimension getImageSize() {
return rendImage.getSize().getDimensionMpt();
}
public void paint(Graphics2D g2d, Rectangle2D area) {
RenderedImage ri = rendImage.getRenderedImage();
double w = area.getWidth();
double h = area.getHeight();
AffineTransform at = new AffineTransform();
at.translate(area.getX(), area.getY());
double sx = w / (double)ri.getWidth();
double sy = h / (double)ri.getHeight();
if (sx != 1.0D || sy != 1.0D)
at.scale(sx, sy);
g2d.drawRenderedImage(ri, at);
}
};
ImageGraphics2D g2dImage = new ImageGraphics2D(src.getInfo(), painter);
return g2dImage;
}
public ImageFlavor getSourceFlavor() {
return ImageFlavor.RENDERED_IMAGE;
}
public ImageFlavor getTargetFlavor() {
return ImageFlavor.GRAPHICS2D;
}
}

View file

@ -0,0 +1,25 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.util.Map;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
public class ImageConverterBuffered2Rendered extends AbstractImageConverter {
public Image convert(Image src, Map hints) {
checkSourceFlavor(src);
ImageBuffered buffered = (ImageBuffered)src;
return new ImageRendered(buffered.getInfo(), buffered.getRenderedImage(), buffered.getTransparentColor());
}
public ImageFlavor getSourceFlavor() {
return ImageFlavor.BUFFERED_IMAGE;
}
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RENDERED_IMAGE;
}
public int getConversionPenalty() {
return 0;
}
}

View file

@ -0,0 +1,118 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.color.ColorSpace;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.util.Map;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageProcessingHints;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.util.UnitConv;
public class ImageConverterG2D2Bitmap extends AbstractImageConverter {
public Image convert(Image src, Map hints) {
checkSourceFlavor(src);
ImageGraphics2D g2dImage = (ImageGraphics2D)src;
Object formatIntent = hints.get(ImageProcessingHints.BITMAP_TYPE_INTENT);
int bitsPerPixel = 24;
if ("gray".equals(formatIntent)) {
bitsPerPixel = 8;
} else if ("mono".equals(formatIntent)) {
bitsPerPixel = 1;
}
Object transparencyIntent = hints.get(ImageProcessingHints.TRANSPARENCY_INTENT);
boolean withAlpha = true;
if ("ignore".equals(transparencyIntent))
withAlpha = false;
int resolution = 300;
Number res = (Number)hints.get(ImageProcessingHints.TARGET_RESOLUTION);
if (res != null)
resolution = res.intValue();
BufferedImage bi = paintToBufferedImage(g2dImage, bitsPerPixel, withAlpha, resolution);
ImageBuffered bufImage = new ImageBuffered(src.getInfo(), bi, null);
return bufImage;
}
protected BufferedImage paintToBufferedImage(ImageGraphics2D g2dImage, int bitsPerPixel, boolean withAlpha, int resolution) {
BufferedImage bi;
ImageSize size = g2dImage.getSize();
RenderingHints additionalHints = null;
int bmw = (int)Math.ceil(UnitConv.mpt2px((double)size.getWidthMpt(), resolution));
int bmh = (int)Math.ceil(UnitConv.mpt2px((double)size.getHeightMpt(), resolution));
switch (bitsPerPixel) {
case 1:
bi = new BufferedImage(bmw, bmh, 12);
withAlpha = false;
additionalHints = new RenderingHints(null);
additionalHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
break;
case 8:
if (withAlpha) {
bi = createGrayBufferedImageWithAlpha(bmw, bmh);
} else {
bi = new BufferedImage(bmw, bmh, 10);
}
break;
default:
if (withAlpha) {
bi = new BufferedImage(bmw, bmh, 2);
} else {
bi = new BufferedImage(bmw, bmh, 1);
}
break;
}
Graphics2D g2d = bi.createGraphics();
try {
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
setRenderingHintsForBufferedImage(g2d);
if (additionalHints != null)
g2d.addRenderingHints(additionalHints);
g2d.setBackground(Color.white);
g2d.setColor(Color.black);
if (!withAlpha)
g2d.clearRect(0, 0, bmw, bmh);
double sx = (double)bmw / (double)size.getWidthMpt();
double sy = (double)bmh / (double)size.getHeightMpt();
g2d.scale(sx, sy);
Rectangle2D area = new Rectangle2D.Double(0.0D, 0.0D, (double)size.getWidthMpt(), (double)size.getHeightMpt());
g2dImage.getGraphics2DImagePainter().paint(g2d, area);
} finally {
g2d.dispose();
}
return bi;
}
private static BufferedImage createGrayBufferedImageWithAlpha(int width, int height) {
boolean alphaPremultiplied = true;
int bands = 2;
int[] bits = new int[bands];
for (int i = 0; i < bands; i++)
bits[i] = 8;
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(1003), bits, true, alphaPremultiplied, 3, 0);
WritableRaster wr = Raster.createInterleavedRaster(0, width, height, bands, new Point(0, 0));
BufferedImage bi = new BufferedImage(cm, wr, alphaPremultiplied, null);
return bi;
}
protected void setRenderingHintsForBufferedImage(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
public ImageFlavor getSourceFlavor() {
return ImageFlavor.GRAPHICS2D;
}
public ImageFlavor getTargetFlavor() {
return ImageFlavor.BUFFERED_IMAGE;
}
}

View file

@ -0,0 +1,35 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.writer.ImageWriter;
import org.apache.xmlgraphics.image.writer.ImageWriterParams;
import org.apache.xmlgraphics.image.writer.ImageWriterRegistry;
public class ImageConverterRendered2PNG extends AbstractImageConverter {
public Image convert(Image src, Map hints) throws ImageException, IOException {
checkSourceFlavor(src);
ImageRendered rendered = (ImageRendered)src;
ImageWriter writer = ImageWriterRegistry.getInstance().getWriterFor("image/png");
if (writer == null)
throw new ImageException("Cannot convert image to PNG. No suitable ImageWriter found.");
ByteArrayOutputStream baout = new ByteArrayOutputStream();
ImageWriterParams params = new ImageWriterParams();
params.setResolution((int)Math.round(src.getSize().getDpiHorizontal()));
writer.writeImage(rendered.getRenderedImage(), baout, params);
return new ImageRawStream(src.getInfo(), getTargetFlavor(), new ByteArrayInputStream(baout.toByteArray()));
}
public ImageFlavor getSourceFlavor() {
return ImageFlavor.RENDERED_IMAGE;
}
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RAW_PNG;
}
}

View file

@ -0,0 +1,30 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
public class ImageGraphics2D extends AbstractImage {
private Graphics2DImagePainter painter;
public ImageGraphics2D(ImageInfo info, Graphics2DImagePainter painter) {
super(info);
setGraphics2DImagePainter(painter);
}
public ImageFlavor getFlavor() {
return ImageFlavor.GRAPHICS2D;
}
public boolean isCacheable() {
return true;
}
public Graphics2DImagePainter getGraphics2DImagePainter() {
return this.painter;
}
public void setGraphics2DImagePainter(Graphics2DImagePainter painter) {
this.painter = painter;
}
}

View file

@ -0,0 +1,34 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import javax.xml.transform.Source;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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.util.io.SubInputStream;
public class ImageLoaderEPS extends AbstractImageLoader {
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RAW_EPS;
}
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
if (!"application/postscript".equals(info.getMimeType()))
throw new IllegalArgumentException("ImageInfo must be from a image with MIME type: application/postscript");
Source src = session.needSource(info.getOriginalURI());
InputStream in = ImageUtil.needInputStream(src);
ImageUtil.removeStreams(src);
PreloaderEPS.EPSBinaryFileHeader binaryHeader = (PreloaderEPS.EPSBinaryFileHeader)info.getCustomObjects().get(PreloaderEPS.EPS_BINARY_HEADER);
if (binaryHeader != null) {
in.skip(binaryHeader.getPSStart());
in = new SubInputStream(in, binaryHeader.getPSLength(), true);
}
ImageRawEPS epsImage = new ImageRawEPS(info, in);
return epsImage;
}
}

View file

@ -0,0 +1,28 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
public class ImageLoaderFactoryEPS extends AbstractImageLoaderFactory {
private static final String[] MIMES = new String[] { "application/postscript" };
private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { ImageFlavor.RAW_EPS };
public String[] getSupportedMIMETypes() {
return MIMES;
}
public ImageFlavor[] getSupportedFlavors(String mime) {
if ("application/postscript".equals(mime))
return FLAVORS;
throw new IllegalArgumentException("Unsupported MIME type: " + mime);
}
public ImageLoader newImageLoader(ImageFlavor targetFlavor) {
return new ImageLoaderEPS();
}
public boolean isAvailable() {
return true;
}
}

View file

@ -0,0 +1,28 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
public class ImageLoaderFactoryInternalTIFF extends AbstractImageLoaderFactory {
private static final String[] MIMES = new String[] { "image/tiff" };
private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { ImageFlavor.RENDERED_IMAGE };
public String[] getSupportedMIMETypes() {
return MIMES;
}
public ImageFlavor[] getSupportedFlavors(String mime) {
if ("image/tiff".equals(mime))
return FLAVORS;
throw new IllegalArgumentException("Unsupported MIME type: " + mime);
}
public ImageLoader newImageLoader(ImageFlavor targetFlavor) {
return new ImageLoaderInternalTIFF();
}
public boolean isAvailable() {
return true;
}
}

View file

@ -0,0 +1,28 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
public class ImageLoaderFactoryPNG extends AbstractImageLoaderFactory {
private static final String[] MIMES = new String[] { "image/png" };
private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { ImageFlavor.RENDERED_IMAGE };
public String[] getSupportedMIMETypes() {
return MIMES;
}
public ImageFlavor[] getSupportedFlavors(String mime) {
if ("image/png".equals(mime))
return FLAVORS;
throw new IllegalArgumentException("Unsupported MIME type: " + mime);
}
public ImageLoader newImageLoader(ImageFlavor targetFlavor) {
return new ImageLoaderPNG();
}
public boolean isAvailable() {
return true;
}
}

View file

@ -0,0 +1,46 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
public class ImageLoaderFactoryRaw extends AbstractImageLoaderFactory {
public static final String MIME_EMF = "image/x-emf";
private static final String[] MIMES = new String[] { "image/png", "image/jpeg", "image/tiff", "image/x-emf" };
private static final ImageFlavor[][] FLAVORS = new ImageFlavor[][] { new ImageFlavor[] { ImageFlavor.RAW_PNG }, new ImageFlavor[] { ImageFlavor.RAW_JPEG }, new ImageFlavor[] { ImageFlavor.RAW_TIFF }, new ImageFlavor[] { ImageFlavor.RAW_EMF } };
public static String getMimeForRawFlavor(ImageFlavor flavor) {
for (int i = 0, ci = FLAVORS.length; i < ci; i++) {
for (int j = 0, cj = (FLAVORS[i]).length; j < cj; j++) {
if (FLAVORS[i][j].equals(flavor))
return MIMES[i];
}
}
throw new IllegalArgumentException("ImageFlavor is not a \"raw\" flavor: " + flavor);
}
public String[] getSupportedMIMETypes() {
return MIMES;
}
public ImageFlavor[] getSupportedFlavors(String mime) {
for (int i = 0, c = MIMES.length; i < c; i++) {
if (MIMES[i].equals(mime))
return FLAVORS[i];
}
throw new IllegalArgumentException("Unsupported MIME type: " + mime);
}
public ImageLoader newImageLoader(ImageFlavor targetFlavor) {
if (targetFlavor.equals(ImageFlavor.RAW_JPEG))
return new ImageLoaderRawJPEG();
if (targetFlavor.equals(ImageFlavor.RAW_PNG))
return new ImageLoaderRawPNG();
return new ImageLoaderRaw(targetFlavor);
}
public boolean isAvailable() {
return true;
}
}

View file

@ -0,0 +1,71 @@
package org.apache.xmlgraphics.image.loader.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.spi.ImageLoader;
public class ImageLoaderFactoryRawCCITTFax extends AbstractImageLoaderFactory {
private transient Log log = LogFactory.getLog(ImageLoaderFactoryRawCCITTFax.class);
private static final String[] MIMES = new String[] { "image/tiff" };
private static final ImageFlavor[][] FLAVORS = new ImageFlavor[][] { new ImageFlavor[] { ImageFlavor.RAW_CCITTFAX } };
public static String getMimeForRawFlavor(ImageFlavor flavor) {
for (int i = 0, ci = FLAVORS.length; i < ci; i++) {
for (int j = 0, cj = (FLAVORS[i]).length; j < cj; j++) {
if (FLAVORS[i][j].equals(flavor))
return MIMES[i];
}
}
throw new IllegalArgumentException("ImageFlavor is not a \"raw\" flavor: " + flavor);
}
public String[] getSupportedMIMETypes() {
return MIMES;
}
public ImageFlavor[] getSupportedFlavors(String mime) {
for (int i = 0, c = MIMES.length; i < c; i++) {
if (MIMES[i].equals(mime))
return FLAVORS[i];
}
throw new IllegalArgumentException("Unsupported MIME type: " + mime);
}
public ImageLoader newImageLoader(ImageFlavor targetFlavor) {
if (targetFlavor.equals(ImageFlavor.RAW_CCITTFAX))
return new ImageLoaderRawCCITTFax();
throw new IllegalArgumentException("Unsupported image flavor: " + targetFlavor);
}
public boolean isAvailable() {
return true;
}
public boolean isSupported(ImageInfo imageInfo) {
Integer stripCount;
boolean supported;
Boolean tiled = (Boolean)imageInfo.getCustomObjects().get("TIFF_TILED");
if (Boolean.TRUE.equals(tiled)) {
this.log.trace("Raw CCITT loading not supported for tiled TIFF image");
return false;
}
Integer compression = (Integer)imageInfo.getCustomObjects().get("TIFF_COMPRESSION");
if (compression == null)
return false;
switch (compression) {
case 2:
case 3:
case 4:
stripCount = (Integer)imageInfo.getCustomObjects().get("TIFF_STRIP_COUNT");
supported = (stripCount != null && stripCount == 1);
if (!supported)
this.log.trace("Raw CCITT loading not supported for multi-strip TIFF image");
return supported;
}
return false;
}
}

View file

@ -0,0 +1,41 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.IOException;
import java.util.Map;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
import org.apache.xmlgraphics.image.codec.util.ImageInputStreamSeekableStreamAdapter;
import org.apache.xmlgraphics.image.codec.util.SeekableStream;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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;
public class ImageLoaderInternalTIFF extends AbstractImageLoader {
protected static Log log = LogFactory.getLog(ImageLoaderInternalTIFF.class);
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RENDERED_IMAGE;
}
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
Source src = session.needSource(info.getOriginalURI());
ImageInputStream imgStream = ImageUtil.needImageInputStream(src);
SeekableStream seekStream = new ImageInputStreamSeekableStreamAdapter(imgStream);
try {
TIFFImage img = new TIFFImage(seekStream, null, 0);
return new ImageRendered(info, img, null);
} catch (RuntimeException e) {
throw new ImageException("Could not load image with internal TIFF codec", e);
}
}
public int getUsagePenalty() {
return 1000;
}
}

View file

@ -0,0 +1,36 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.util.Map;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.xmlgraphics.image.codec.png.PNGDecodeParam;
import org.apache.xmlgraphics.image.codec.png.PNGImageDecoder;
import org.apache.xmlgraphics.image.codec.util.ImageInputStreamSeekableStreamAdapter;
import org.apache.xmlgraphics.image.codec.util.SeekableStream;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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;
public class ImageLoaderPNG extends AbstractImageLoader {
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
Source src = session.needSource(info.getOriginalURI());
ImageInputStream imgStream = ImageUtil.needImageInputStream(src);
SeekableStream seekStream = new ImageInputStreamSeekableStreamAdapter(imgStream);
PNGImageDecoder decoder = new PNGImageDecoder(seekStream, new PNGDecodeParam());
RenderedImage image = decoder.decodeAsRenderedImage();
return new ImageRendered(info, image, null);
}
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RENDERED_IMAGE;
}
public int getUsagePenalty() {
return 1000;
}
}

View file

@ -0,0 +1,34 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.IOException;
import java.util.Map;
import javax.xml.transform.Source;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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;
public class ImageLoaderRaw extends AbstractImageLoader {
private String mime;
private ImageFlavor targetFlavor;
public ImageLoaderRaw(ImageFlavor targetFlavor) {
this.targetFlavor = targetFlavor;
this.mime = ImageLoaderFactoryRaw.getMimeForRawFlavor(targetFlavor);
}
public ImageFlavor getTargetFlavor() {
return this.targetFlavor;
}
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
if (!this.mime.equals(info.getMimeType()))
throw new IllegalArgumentException("ImageInfo must be from a image with MIME type: " + this.mime);
Source src = session.needSource(info.getOriginalURI());
ImageRawStream rawImage = new ImageRawStream(info, getTargetFlavor(), ImageUtil.needInputStream(src));
return rawImage;
}
}

View file

@ -0,0 +1,147 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.codec.tiff.TIFFDirectory;
import org.apache.xmlgraphics.image.codec.tiff.TIFFField;
import org.apache.xmlgraphics.image.codec.util.SeekableStream;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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.image.loader.util.SeekableStreamAdapter;
import org.apache.xmlgraphics.util.io.SubInputStream;
public class ImageLoaderRawCCITTFax extends AbstractImageLoader implements JPEGConstants {
private static final int COMPRESSION_CCITT_1D = 2;
private static final int COMPRESSION_FAX_GROUP3 = 3;
private static final int COMPRESSION_FAX_GROUP4 = 4;
protected static Log log = LogFactory.getLog(ImageLoaderRawCCITTFax.class);
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RAW_CCITTFAX;
}
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
long stripOffset, stripLength;
if (!"image/tiff".equals(info.getMimeType()))
throw new IllegalArgumentException("ImageInfo must be from a image with MIME type: image/tiff");
int fillOrder = 1;
int compression = 1;
Source src = session.needSource(info.getOriginalURI());
ImageInputStream in = ImageUtil.needImageInputStream(src);
in.mark();
try {
int stripCount;
SeekableStream seekable = new SeekableStreamAdapter(in);
TIFFDirectory dir = new TIFFDirectory(seekable, 0);
TIFFField fld = dir.getField(259);
if (fld != null) {
compression = fld.getAsInt(0);
switch (compression) {
case 2:
case 4:
break;
case 3:
compression = 2;
fld = dir.getField(292);
if (fld != null) {
long t4Options = fld.getAsLong(0);
if ((t4Options & 0x1L) != 0L)
compression = 3;
}
break;
default:
log.debug("Unsupported compression " + compression);
throw new ImageException("ImageLoader doesn't support TIFF compression: " + compression);
}
}
fld = dir.getField(266);
if (fld != null)
fillOrder = fld.getAsInt(0);
fld = dir.getField(278);
if (fld == null) {
stripCount = 1;
} else {
stripCount = (int)((long)info.getSize().getHeightPx() / fld.getAsLong(0));
}
if (stripCount > 1) {
log.debug("More than one strip found in TIFF image.");
throw new ImageException("ImageLoader doesn't support multiple strips");
}
stripOffset = dir.getField(273).getAsLong(0);
stripLength = dir.getField(279).getAsLong(0);
} finally {
in.reset();
}
in.seek(stripOffset);
InputStream subin = new SubInputStream(ImageUtil.needInputStream(src), stripLength, true);
if (fillOrder == 2)
subin = new FillOrderChangeInputStream(subin);
ImageRawCCITTFax rawImage = new ImageRawCCITTFax(info, subin, compression);
ImageUtil.removeStreams(src);
return rawImage;
}
private static class FillOrderChangeInputStream extends FilterInputStream {
protected FillOrderChangeInputStream(InputStream in) {
super(in);
}
public int read(byte[] b, int off, int len) throws IOException {
int result = super.read(b, off, len);
if (result > 0) {
int endpos = off + result;
for (int i = off; i < endpos; i++)
b[i] = FLIP_TABLE[b[i] & 0xFF];
}
return result;
}
public int read() throws IOException {
int b = super.read();
if (b < 0)
return b;
return FLIP_TABLE[b] & 0xFF;
}
private static final byte[] FLIP_TABLE = new byte[] {
0, Byte.MIN_VALUE, 64, -64, 32, -96, 96, -32, 16, -112,
80, -48, 48, -80, 112, -16, 8, -120, 72, -56,
40, -88, 104, -24, 24, -104, 88, -40, 56, -72,
120, -8, 4, -124, 68, -60, 36, -92, 100, -28,
20, -108, 84, -44, 52, -76, 116, -12, 12, -116,
76, -52, 44, -84, 108, -20, 28, -100, 92, -36,
60, -68, 124, -4, 2, -126, 66, -62, 34, -94,
98, -30, 18, -110, 82, -46, 50, -78, 114, -14,
10, -118, 74, -54, 42, -86, 106, -22, 26, -102,
90, -38, 58, -70, 122, -6, 6, -122, 70, -58,
38, -90, 102, -26, 22, -106, 86, -42, 54, -74,
118, -10, 14, -114, 78, -50, 46, -82, 110, -18,
30, -98, 94, -34, 62, -66, 126, -2, 1, -127,
65, -63, 33, -95, 97, -31, 17, -111, 81, -47,
49, -79, 113, -15, 9, -119, 73, -55, 41, -87,
105, -23, 25, -103, 89, -39, 57, -71, 121, -7,
5, -123, 69, -59, 37, -91, 101, -27, 21, -107,
85, -43, 53, -75, 117, -11, 13, -115, 77, -51,
45, -83, 109, -19, 29, -99, 93, -35, 61, -67,
125, -3, 3, -125, 67, -61, 35, -93, 99, -29,
19, -109, 83, -45, 51, -77, 115, -13, 11, -117,
75, -53, 43, -85, 107, -21, 27, -101, 91, -37,
59, -69, 123, -5, 7, -121, 71, -57, 39, -89,
103, -25, 23, -105, 87, -41, 55, -73, 119, -9,
15, -113, 79, -49, 47, -81, 111, -17, 31, -97,
95, -33, 63, -65, Byte.MAX_VALUE, -1 };
}
}

View file

@ -0,0 +1,178 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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.java2d.color.ColorSpaces;
import org.apache.xmlgraphics.java2d.color.profile.ColorProfileUtil;
public class ImageLoaderRawJPEG extends AbstractImageLoader implements JPEGConstants {
protected static Log log = LogFactory.getLog(ImageLoaderRawJPEG.class);
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RAW_JPEG;
}
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
if (!"image/jpeg".equals(info.getMimeType()))
throw new IllegalArgumentException("ImageInfo must be from a image with MIME type: image/jpeg");
ColorSpace colorSpace = null;
boolean appeFound = false;
int sofType = 0;
ByteArrayOutputStream iccStream = null;
Source src = session.needSource(info.getOriginalURI());
ImageInputStream in = ImageUtil.needImageInputStream(src);
JPEGFile jpeg = new JPEGFile(in);
in.mark();
try {
while (true) {
int reclen;
int segID = jpeg.readMarkerSegment();
if (log.isTraceEnabled())
log.trace("Seg Marker: " + Integer.toHexString(segID));
switch (segID) {
case 217:
log.trace("EOI found. Stopping.");
break;
case 218:
log.trace("SOS found. Stopping early.");
break;
case 0:
case 216:
continue;
case 192:
case 193:
case 194:
case 202:
sofType = segID;
if (log.isTraceEnabled())
log.trace("SOF: " + Integer.toHexString(sofType));
in.mark();
try {
reclen = jpeg.readSegmentLength();
in.skipBytes(1);
in.skipBytes(2);
in.skipBytes(2);
int numComponents = in.readUnsignedByte();
if (numComponents == 1) {
colorSpace = ColorSpace.getInstance(1003);
} else if (numComponents == 3) {
colorSpace = ColorSpace.getInstance(1004);
} else if (numComponents == 4) {
colorSpace = ColorSpaces.getDeviceCMYKColorSpace();
} else {
throw new ImageException("Unsupported ColorSpace for image " + info + ". The number of components supported are 1, 3 and 4.");
}
} finally {
in.reset();
}
in.skipBytes(reclen);
continue;
case 226:
in.mark();
try {
reclen = jpeg.readSegmentLength();
byte[] iccString = new byte[11];
in.readFully(iccString);
in.skipBytes(1);
if ("ICC_PROFILE".equals(new String(iccString, "US-ASCII"))) {
in.skipBytes(2);
int payloadSize = reclen - 2 - 12 - 2;
if (ignoreColorProfile(hints)) {
log.debug("Ignoring ICC profile data in JPEG");
in.skipBytes(payloadSize);
} else {
byte[] buf = new byte[payloadSize];
in.readFully(buf);
if (iccStream == null) {
if (log.isDebugEnabled()) {
log.debug("JPEG has an ICC profile");
DataInputStream din = new DataInputStream(new ByteArrayInputStream(buf));
log.debug("Declared ICC profile size: " + din.readInt());
}
iccStream = new ByteArrayOutputStream();
}
iccStream.write(buf);
}
}
} finally {
in.reset();
}
in.skipBytes(reclen);
continue;
case 238:
in.mark();
try {
reclen = jpeg.readSegmentLength();
byte[] adobeHeader = new byte[5];
in.readFully(adobeHeader);
if ("Adobe".equals(new String(adobeHeader, "US-ASCII")))
appeFound = true;
} finally {
in.reset();
}
in.skipBytes(reclen);
continue;
}
jpeg.skipCurrentMarkerSegment();
}
} finally {
in.reset();
}
ICC_Profile iccProfile = buildICCProfile(info, colorSpace, iccStream);
if (iccProfile == null && colorSpace == null)
throw new ImageException("ColorSpace could not be identified for JPEG image " + info);
boolean invertImage = false;
if (appeFound && colorSpace.getType() == 9) {
if (log.isDebugEnabled())
log.debug("JPEG has an Adobe APPE marker. Note: CMYK Image will be inverted. (" + info.getOriginalURI() + ")");
invertImage = true;
}
ImageRawJPEG rawImage = new ImageRawJPEG(info, ImageUtil.needInputStream(src), sofType, colorSpace, iccProfile, invertImage);
return rawImage;
}
private ICC_Profile buildICCProfile(ImageInfo info, ColorSpace colorSpace, ByteArrayOutputStream iccStream) throws IOException, ImageException {
if (iccStream != null && iccStream.size() > 0) {
if (log.isDebugEnabled())
log.debug("Effective ICC profile size: " + iccStream.size());
int alignment = 4;
int padding = (4 - iccStream.size() % 4) % 4;
if (padding != 0)
try {
iccStream.write(new byte[padding]);
} catch (IOException ioe) {
throw new IOException("Error while aligning ICC stream: " + ioe.getMessage());
}
ICC_Profile iccProfile = null;
try {
iccProfile = ColorProfileUtil.getICC_Profile(iccStream.toByteArray());
if (log.isDebugEnabled())
log.debug("JPEG has an ICC profile: " + iccProfile.toString());
} catch (IllegalArgumentException iae) {
log.warn("An ICC profile is present in the JPEG file but it is invalid (" + iae.getMessage() + "). The color profile will be ignored. (" + info.getOriginalURI() + ")");
return null;
}
if (iccProfile.getNumComponents() != colorSpace.getNumComponents()) {
log.warn("The number of components of the ICC profile (" + iccProfile.getNumComponents() + ") doesn't match the image (" + colorSpace.getNumComponents() + "). Ignoring the ICC color profile.");
return null;
}
return iccProfile;
}
return null;
}
}

View file

@ -0,0 +1,40 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.io.IOException;
import java.util.Map;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.codec.util.ImageInputStreamSeekableStreamAdapter;
import org.apache.xmlgraphics.image.codec.util.SeekableStream;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
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;
public class ImageLoaderRawPNG extends AbstractImageLoader {
protected static Log log = LogFactory.getLog(ImageLoaderRawPNG.class);
public ImageFlavor getTargetFlavor() {
return ImageFlavor.RAW_PNG;
}
public Image loadImage(ImageInfo info, Map hints, ImageSessionContext session) throws ImageException, IOException {
if (!"image/png".equals(info.getMimeType()))
throw new IllegalArgumentException("ImageInfo must be from a image with MIME type: image/png");
Source src = session.needSource(info.getOriginalURI());
ImageInputStream in = ImageUtil.needImageInputStream(src);
ImageUtil.removeStreams(src);
SeekableStream seekStream = new ImageInputStreamSeekableStreamAdapter(in);
PNGFile im = new PNGFile(seekStream);
ImageRawPNG irpng = im.getImageRawPNG(info);
return irpng;
}
public int getUsagePenalty() {
return 1000;
}
}

View file

@ -0,0 +1,23 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.color.ColorSpace;
import java.io.InputStream;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
public class ImageRawCCITTFax extends ImageRawStream {
private int compression;
public ImageRawCCITTFax(ImageInfo info, InputStream in, int compression) {
super(info, ImageFlavor.RAW_CCITTFAX, in);
this.compression = compression;
}
public ColorSpace getColorSpace() {
return ColorSpace.getInstance(1003);
}
public int getCompression() {
return this.compression;
}
}

View file

@ -0,0 +1,21 @@
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.geom.Rectangle2D;
import java.io.InputStream;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
public class ImageRawEPS extends ImageRawStream {
public ImageRawEPS(ImageInfo info, ImageRawStream.InputStreamFactory streamFactory) {
super(info, ImageFlavor.RAW_EPS, streamFactory);
}
public ImageRawEPS(ImageInfo info, InputStream in) {
super(info, ImageFlavor.RAW_EPS, in);
}
public Rectangle2D getBoundingBox() {
Rectangle2D bbox = (Rectangle2D)getInfo().getCustomObjects().get(PreloaderEPS.EPS_BOUNDING_BOX);
return bbox;
}
}

Some files were not shown because too many files have changed in this diff Show more