/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
boolean firstTime = true;
int length;
throws IOException {
}
try {
firstTime = false;
return new InputStreamAdapter(iis);
} catch (IOException e) {
return null;
}
}
public boolean hasMoreElements() {
if (firstTime) {
return true;
}
try {
return true;
} else {
return false;
}
} catch (IOException e) {
return false;
}
}
}
/*
* Note: The following chunk type constants are autogenerated. Each
* one is derived from the ASCII values of its 4-character name. For
* example, IHDR_TYPE is calculated as follows:
* ('I' << 24) | ('H' << 16) | ('D' << 8) | 'R'
*/
// Critical chunks
// Ancillary chunks
// The number of bands by PNG color type
static final int[] inputBandsForColorType = {
1, // gray
-1, // unused
3, // rgb
1, // palette
2, // gray + alpha
-1, // unused
4 // rgb + alpha
};
private static final boolean debug = true;
boolean gotHeader = false;
boolean gotMetadata = false;
// The number of source pixels processed
// The total number of pixels in the source image
int totalPixels;
super(originatingProvider);
}
boolean seekForwardOnly,
boolean ignoreMetadata) {
// Clear all values based on the previous stream contents
}
int b;
int count = 0;
if (b == -1) throw new EOFException();
}
}
if (gotHeader) {
return;
}
throw new IllegalStateException("Input source not set!");
}
try {
byte[] signature = new byte[8];
throw new IIOException("Bad PNG signature!");
}
if (IHDR_length != 13) {
throw new IIOException("Bad length for IHDR chunk!");
}
throw new IIOException("Bad type for IHDR chunk!");
}
this.metadata = new PNGMetadata();
// Re-use signature array to bulk-read these unsigned byte values
// Skip IHDR CRC
if (width == 0) {
throw new IIOException("Image width == 0!");
}
if (height == 0) {
throw new IIOException("Image height == 0!");
}
throw new IIOException("Bit depth must be 1, 2, 4, 8, or 16!");
}
throw new IIOException("Color type must be 0, 2, 3, 4, or 6!");
}
throw new IIOException("Bad color type/bit depth combination!");
}
if ((colorType == PNG_COLOR_RGB ||
colorType == PNG_COLOR_RGB_ALPHA ||
colorType == PNG_COLOR_GRAY_ALPHA) &&
throw new IIOException("Bad color type/bit depth combination!");
}
if (compressionMethod != 0) {
throw new IIOException("Unknown compression method (not 0)!");
}
if (filterMethod != 0) {
throw new IIOException("Unknown filter method (not 0)!");
}
throw new IIOException("Unknown interlace method (not 0 or 1)!");
}
metadata.IHDR_present = true;
gotHeader = true;
} catch (IOException e) {
throw new IIOException("I/O error reading PNG header!", e);
}
}
if (metadata.PLTE_present) {
"A PNG image may not contain more than one PLTE chunk.\n" +
"The chunk wil be ignored.");
return;
"A PNG gray or gray alpha image cannot have a PLTE chunk.\n" +
"The chunk wil be ignored.");
return;
}
byte[] palette = new byte[chunkLength];
if (numEntries > maxEntries) {
"PLTE chunk contains too many entries for bit depth, ignoring extras.");
}
}
// Round array sizes up to 2^2^n
int paletteEntries;
if (numEntries > 16) {
paletteEntries = 256;
} else if (numEntries > 4) {
paletteEntries = 16;
} else if (numEntries > 2) {
paletteEntries = 4;
} else {
paletteEntries = 2;
}
metadata.PLTE_present = true;
int index = 0;
for (int i = 0; i < numEntries; i++) {
}
}
} else { // RGB or RGB_ALPHA
}
metadata.bKGD_present = true;
}
metadata.cHRM_present = true;
}
metadata.gAMA_present = true;
}
{
if (!metadata.PLTE_present) {
throw new IIOException("hIST chunk without prior PLTE chunk!");
}
/* According to PNG specification length of
* hIST chunk is specified in bytes and
* hIST chunk consists of 2 byte elements
* (so we expect length is even).
*/
metadata.hIST_present = true;
}
byte[] compressedProfile =
metadata.iCCP_present = true;
}
} else {
}
}
metadata.pHYs_present = true;
}
if (colorType == PNG_COLOR_GRAY ||
} else if (colorType == PNG_COLOR_RGB ||
colorType == PNG_COLOR_PALETTE ||
colorType == PNG_COLOR_RGB_ALPHA) {
}
if (colorType == PNG_COLOR_GRAY_ALPHA ||
colorType == PNG_COLOR_RGB_ALPHA) {
}
metadata.sBIT_present = true;
}
throws IOException, IIOException {
if (sampleDepth == 8) {
for (int i = 0; i < numEntries; i++) {
}
} else if (sampleDepth == 16) {
for (int i = 0; i < numEntries; i++) {
}
} else {
throw new IIOException("sPLT sample depth not 8 or 16!");
}
metadata.sPLT_present = true;
}
metadata.sRGB_present = true;
}
}
metadata.tIME_present = true;
}
if (colorType == PNG_COLOR_PALETTE) {
if (!metadata.PLTE_present) {
"tRNS chunk without prior PLTE chunk, ignoring it.");
return;
}
// Alpha table may have fewer entries than RGB palette
int numEntries = chunkLength;
if (numEntries > maxEntries) {
"tRNS chunk has more entries than prior PLTE chunk, ignoring extras.");
}
} else if (colorType == PNG_COLOR_GRAY) {
if (chunkLength != 2) {
"tRNS chunk for gray image must have length 2, ignoring chunk.");
return;
}
} else if (colorType == PNG_COLOR_RGB) {
if (chunkLength != 6) {
"tRNS chunk for RGB image must have length 6, ignoring chunk.");
return;
}
} else {
"Gray+Alpha and RGBS images may not have a tRNS chunk, ignoring it.");
return;
}
metadata.tRNS_present = true;
}
int c;
try {
}
} finally {
}
return baos.toByteArray();
}
}
if (gotMetadata) {
return;
}
readHeader();
/*
* Optimization: We can skip the remaining metadata if the
* ignoreMetadata flag is set, and only if this is not a palette
* image (in that case, we need to read the metadata to get the
* tRNS chunk, which is needed for the getImageTypes() method).
*/
try {
while (true) {
// We've reached the image data
break;
} else {
// Skip the chunk plus the 4 CRC bytes that follow
}
}
} catch (IOException e) {
throw new IIOException("Error skipping PNG metadata", e);
}
gotMetadata = true;
return;
}
try {
loop: while (true) {
switch (chunkType) {
case IDAT_TYPE:
// If chunk type is 'IDAT', we've reached the image data.
break loop;
case PLTE_TYPE:
break;
case bKGD_TYPE:
break;
case cHRM_TYPE:
break;
case gAMA_TYPE:
break;
case hIST_TYPE:
break;
case iCCP_TYPE:
break;
case iTXt_TYPE:
break;
case pHYs_TYPE:
break;
case sBIT_TYPE:
break;
case sPLT_TYPE:
break;
case sRGB_TYPE:
break;
case tEXt_TYPE:
break;
case tIME_TYPE:
break;
case tRNS_TYPE:
break;
case zTXt_TYPE:
break;
default:
// Read an unknown chunk
byte[] b = new byte[chunkLength];
if (ancillaryBit == 0) {
"Encountered unknown chunk with critical bit set!");
}
break;
}
}
} catch (IOException e) {
throw new IIOException("Error reading PNG metadata", e);
}
gotMetadata = true;
}
// Data filtering methods
int bpp) {
int val;
}
}
int count) {
for (int i = 0; i < count; i++) {
}
}
for (int i = 0; i < bpp; i++) {
}
}
}
private static int paethPredictor(int a, int b, int c) {
int p = a + b - c;
return a;
return b;
} else {
return c;
}
}
for (int i = 0; i < bpp; i++) {
}
}
}
private static final int[][] bandOffsets = {
null,
{ 0 }, // G
{ 0, 1 }, // GA in GA order
{ 0, 1, 2 }, // RGB in RGB order
{ 0, 1, 2, 3 } // RGBA in RGBA order
};
int scanlineStride,
int bitDepth) {
origin);
} else if (bitDepth <= 8) {
origin);
} else {
origin);
}
return ras;
}
throws IOException, IIOException {
return;
}
// Read the image row-by-row
// Skip filter byte and the remaining row bytes
// If read has been aborted, just return
// processReadAborted will be called later
if (abortRequested()) {
return;
}
}
}
pixelsDone += newPixels;
}
return;
}
// Determine which pixels will be updated in this pass
int[] vals =
// If no pixels need updating, just skip the input data
if (updateWidth == 0) {
// Update count of pixels read
// Skip filter byte and the remaining row bytes
}
return;
}
// Backwards map from destination pixels
// (dstX = updateMinX + k*updateXStep)
// to source pixels (sourceX), and then
// to offset and skip in passRow (srcX and srcXStep)
int sourceX =
sourceRegion.x;
// Compute the step factor in the source
byte[] curr = new byte[bytesPerRow];
byte[] prior = new byte[bytesPerRow];
// Create a 1-row tall Raster to hold the data
bitDepth);
// Create an array suitable for holding one pixel
} else {
}
// Handle source and destination bands
if (sourceBands != null) {
0, 0,
}
if (destinationBands != null) {
0, 0,
}
// Determine if all of the relevant output bands have the
// same bit depth as the source data
boolean adjustBitDepths = false;
for (int b = 0; b < numBands; b++) {
if (outputSampleSize[b] != bitDepth) {
adjustBitDepths = true;
break;
}
}
// If the bit depths differ, create a lookup table per band to perform
// the conversion
if (adjustBitDepths) {
for (int b = 0; b < numBands; b++) {
for (int s = 0; s <= maxInSample; s++) {
scale[b][s] =
}
}
}
// Limit passRow to relevant area for the case where we
// will can setRect to copy a contiguous span
updateXStep == 1 &&
!adjustBitDepths &&
(imRas instanceof ByteInterleavedRaster);
if (useSetRect) {
updateWidth, 1,
0, 0,
null);
}
// Decode the (sub)image row-by-row
// Update count of pixels read
// Read the filter type byte and a row of data
try {
// Swap curr and prior
// TODO - throw a more meaningful exception
throw ze;
}
switch (filter) {
case PNG_FILTER_NONE:
break;
case PNG_FILTER_SUB:
break;
case PNG_FILTER_UP:
break;
case PNG_FILTER_AVERAGE:
break;
case PNG_FILTER_PAETH:
break;
default:
throw new IIOException("Unknown row filter type (= " +
filter + ")!");
}
// Copy data into passRow byte by byte
if (bitDepth < 16) {
} else {
int idx = 0;
for (int j = 0; j < eltsPerRow; j++) {
shortData[j] =
idx += 2;
}
}
// True Y position in source
if ((sourceY >= sourceRegion.y) &&
(((sourceY - sourceRegion.y) %
sourceYSubsampling) == 0)) {
int dstY = destinationOffset.y +
continue;
}
break;
}
if (useSetRect) {
} else {
for (int dstX = updateMinX;
dstX += updateXStep) {
if (adjustBitDepths) {
for (int b = 0; b < numBands; b++) {
}
}
}
}
updateWidth, 1,
// If read has been aborted, just return
// processReadAborted will be called later
if (abortRequested()) {
return;
}
}
}
}
private void decodeImage()
throws IOException, IIOException {
this.pixelsDone = 0;
} else {
for (int i = 0; i <= sourceMaxProgressivePass; i++) {
int XOffset = adam7XOffset[i];
int YOffset = adam7YOffset[i];
int XSubsampling = adam7XSubsampling[i];
int YSubsampling = adam7YSubsampling[i];
if (i >= sourceMinProgressivePass) {
decodePass(i,
} else {
}
// If read has been aborted, just return
// processReadAborted will be called later
if (abortRequested()) {
return;
}
}
}
}
readMetadata();
// Init default values
sourceXSubsampling = 1;
sourceYSubsampling = 1;
sourceBands = null;
// If an ImageReadParam is available, get values from it
}
try {
/* InflaterInputStream uses an Inflater instance which consumes
* native (non-GC visible) resources. This is normally implicitly
* freed when the stream is closed. However since the
* InflaterInputStream wraps a client-supplied input stream,
* we cannot close it.
* But the app may depend on GC finalization to close the stream.
* Therefore to ensure timely freeing of native resources we
* explicitly create the Inflater instance and free its resources
* when we are done with the InflaterInputStream by calling
* inf.end();
*/
getImageTypes(0),
height);
// At this point the header has been read and we know
// how many bands are in the image, so perform checking
// of the read param.
decodeImage();
if (abortRequested()) {
} else {
}
} catch (IOException e) {
throw new IIOException("Error reading PNG image data", e);
} finally {
}
}
}
throw new IllegalStateException("No input source set!");
}
if (seekForwardOnly && allowSearch) {
throw new IllegalStateException
("seekForwardOnly and allowSearch can't both be true!");
}
return 1;
}
if (imageIndex != 0) {
throw new IndexOutOfBoundsException("imageIndex != 0!");
}
readHeader();
return metadata.IHDR_width;
}
if (imageIndex != 0) {
throw new IndexOutOfBoundsException("imageIndex != 0!");
}
readHeader();
return metadata.IHDR_height;
}
throws IIOException
{
if (imageIndex != 0) {
throw new IndexOutOfBoundsException("imageIndex != 0!");
}
readHeader();
int[] bandOffsets;
int dataType;
if (bitDepth <= 8) {
} else {
}
switch (colorType) {
case PNG_COLOR_GRAY:
// Packed grayscale
false));
break;
case PNG_COLOR_RGB:
if (bitDepth == 8) {
// some standard types of buffered images
// which can be used as destination
}
// Component R, G, B
bandOffsets = new int[3];
false,
false));
break;
case PNG_COLOR_PALETTE:
readMetadata(); // Need tRNS chunk
/*
* The PLTE chunk spec says:
*
* The number of palette entries must not exceed the range that
* can be represented in the image bit depth (for example, 2^4 = 16
* for a bit depth of 4). It is permissible to have fewer entries
* than the bit depth would allow. In that case, any out-of-range
* pixel value found in the image data is an error.
*
*
* Consequently, the case when the palette length is smaller than
* 2^bitDepth is legal in the view of PNG spec.
*
* However the spec of createIndexed() method demands the exact
* equality of the palette lengh and number of possible palette
* entries (2^bitDepth).
*
* {@link javax.imageio.ImageTypeSpecifier.html#createIndexed}
*
* In order to avoid this contradiction we need to extend the
* palette arrays to the limit defined by the bitDepth.
*/
}
// Alpha from tRNS chunk may have fewer entries than
// the RGB LUTs from the PLTE chunk; if so, pad with
// 255.
} else {
}
}
break;
case PNG_COLOR_GRAY_ALPHA:
// Component G, A
bandOffsets = new int[2];
true,
false));
break;
case PNG_COLOR_RGB_ALPHA:
if (bitDepth == 8) {
// some standard types of buffered images
// wich can be used as destination
}
// Component R, G, B, A (non-premultiplied)
bandOffsets = new int[4];
true,
false));
break;
default:
break;
}
return l.iterator();
}
/*
* Super class implementation uses first element
* of image types list as raw image type.
*
* Also, super implementation uses first element of this list
* as default destination type image read param does not specify
* anything other.
*
* However, in case of RGB and RGBA color types, raw image type
* produces buffered image of custom type. It causes some
* performance degradation of subsequent rendering operations.
*
* To resolve this contradiction we put standard image types
* at the first positions of image types list (to produce standard
* images by default) and put raw image type (which is custom)
* at the last position of this list.
*
* After this changes we should override getRawImageType()
* to return last element of image types list.
*/
throws IOException {
do {
return raw;
}
return new ImageReadParam();
}
throws IIOException {
return null;
}
if (imageIndex != 0) {
throw new IndexOutOfBoundsException("imageIndex != 0!");
}
readMetadata();
return metadata;
}
throws IIOException {
if (imageIndex != 0) {
throw new IndexOutOfBoundsException("imageIndex != 0!");
}
return theImage;
}
public void reset() {
super.reset();
}
private void resetStreamSettings() {
gotHeader = false;
gotMetadata = false;
pixelStream = null;
}
}