first commit
This commit is contained in:
commit
4d332ef662
27586 changed files with 3281783 additions and 0 deletions
202
rus/WEB-INF/lib/xmlgraphics-commons-1.5_src/META-INF/LICENSE
Normal file
202
rus/WEB-INF/lib/xmlgraphics-commons-1.5_src/META-INF/LICENSE
Normal 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.
|
||||
|
|
@ -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])
|
||||
|
||||
|
|
@ -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/).
|
||||
|
|
@ -0,0 +1 @@
|
|||
org.apache.xmlgraphics.util.uri.DataURIResolver
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.xmlgraphics.image.codec.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface ImageDecodeParam extends Cloneable, Serializable {}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.xmlgraphics.image.codec.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface ImageEncodeParam extends ImageDecodeParam, Cloneable, Serializable {}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.xmlgraphics.image.loader;
|
||||
|
||||
public interface ImageContext {
|
||||
float getSourceResolution();
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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() + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.apache.xmlgraphics.image.loader;
|
||||
|
||||
public class SimpleRefinedImageFlavor extends RefinedImageFlavor {
|
||||
public SimpleRefinedImageFlavor(ImageFlavor parentFlavor, String name) {
|
||||
super(name, parentFlavor);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.apache.xmlgraphics.image.loader.cache;
|
||||
|
||||
public interface ExpirationPolicy {
|
||||
boolean isExpired(TimeStampProvider paramTimeStampProvider, long paramLong);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.apache.xmlgraphics.image.loader.cache;
|
||||
|
||||
class TimeStampProvider {
|
||||
public long getTimeStamp() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 };
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue