jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
author ohair
Tue, 25 May 2010 15:58:33 -0700
changeset 5506 202f599c92aa
parent 2376 63e13f6d2319
child 21218 42223d597a64
permissions -rw-r--r--
6943119: Rebrand source copyright notices Reviewed-by: darcy, weijun
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2376
diff changeset
     2
 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2376
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2376
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2376
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2376
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2376
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package com.sun.imageio.plugins.png;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.awt.Point;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.awt.Rectangle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.awt.color.ColorSpace;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.awt.image.BufferedImage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.awt.image.DataBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.awt.image.DataBufferByte;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.awt.image.DataBufferUShort;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.awt.image.Raster;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.awt.image.WritableRaster;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.io.BufferedInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.io.ByteArrayInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.io.DataInputStream;
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
    40
import java.io.EOFException;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.io.InputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.io.SequenceInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.util.ArrayList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import java.util.Arrays;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import java.util.Enumeration;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import java.util.Iterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
import java.util.zip.Inflater;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
import java.util.zip.InflaterInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
import javax.imageio.IIOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
import javax.imageio.ImageReader;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
import javax.imageio.ImageReadParam;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
import javax.imageio.ImageTypeSpecifier;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
import javax.imageio.metadata.IIOMetadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
import javax.imageio.spi.ImageReaderSpi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
import javax.imageio.stream.ImageInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
import com.sun.imageio.plugins.common.InputStreamAdapter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
import com.sun.imageio.plugins.common.ReaderUtil;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
import com.sun.imageio.plugins.common.SubImageInputStream;
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
    60
import java.io.ByteArrayOutputStream;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
import sun.awt.image.ByteInterleavedRaster;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
    63
class PNGImageDataEnumeration implements Enumeration<InputStream> {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    boolean firstTime = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    ImageInputStream stream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    int length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    public PNGImageDataEnumeration(ImageInputStream stream)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
        throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
        this.stream = stream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
        this.length = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
        int type = stream.readInt(); // skip chunk type
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
    76
    public InputStream nextElement() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
            firstTime = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
            ImageInputStream iis = new SubImageInputStream(stream, length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
            return new InputStreamAdapter(iis);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    public boolean hasMoreElements() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        if (firstTime) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
            int crc = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
            this.length = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
            int type = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
            if (type == PNGImageReader.IDAT_TYPE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
public class PNGImageReader extends ImageReader {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
     * Note: The following chunk type constants are autogenerated.  Each
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
     * one is derived from the ASCII values of its 4-character name.  For
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     * example, IHDR_TYPE is calculated as follows:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     *            ('I' << 24) | ('H' << 16) | ('D' << 8) | 'R'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    // Critical chunks
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    static final int IHDR_TYPE = 0x49484452;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    static final int PLTE_TYPE = 0x504c5445;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    static final int IDAT_TYPE = 0x49444154;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    static final int IEND_TYPE = 0x49454e44;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    // Ancillary chunks
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    static final int bKGD_TYPE = 0x624b4744;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    static final int cHRM_TYPE = 0x6348524d;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    static final int gAMA_TYPE = 0x67414d41;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    static final int hIST_TYPE = 0x68495354;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    static final int iCCP_TYPE = 0x69434350;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    static final int iTXt_TYPE = 0x69545874;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    static final int pHYs_TYPE = 0x70485973;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    static final int sBIT_TYPE = 0x73424954;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    static final int sPLT_TYPE = 0x73504c54;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    static final int sRGB_TYPE = 0x73524742;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    static final int tEXt_TYPE = 0x74455874;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    static final int tIME_TYPE = 0x74494d45;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    static final int tRNS_TYPE = 0x74524e53;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    static final int zTXt_TYPE = 0x7a545874;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
    static final int PNG_COLOR_GRAY = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    static final int PNG_COLOR_RGB = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    static final int PNG_COLOR_PALETTE = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    static final int PNG_COLOR_GRAY_ALPHA = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    static final int PNG_COLOR_RGB_ALPHA = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    // The number of bands by PNG color type
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    static final int[] inputBandsForColorType = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
         1, // gray
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        -1, // unused
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
         3, // rgb
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
         1, // palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
         2, // gray + alpha
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        -1, // unused
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
         4  // rgb + alpha
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
    static final int PNG_FILTER_NONE = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
    static final int PNG_FILTER_SUB = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    static final int PNG_FILTER_UP = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
    static final int PNG_FILTER_AVERAGE = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
    static final int PNG_FILTER_PAETH = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
    static final int[] adam7XOffset = { 0, 4, 0, 2, 0, 1, 0 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    static final int[] adam7YOffset = { 0, 0, 4, 0, 2, 0, 1 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    static final int[] adam7XSubsampling = { 8, 8, 4, 4, 2, 2, 1, 1 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
    static final int[] adam7YSubsampling = { 8, 8, 8, 4, 4, 2, 2, 1 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    private static final boolean debug = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    ImageInputStream stream = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    boolean gotHeader = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
    boolean gotMetadata = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
    ImageReadParam lastParam = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
    long imageStartPosition = -1L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
    Rectangle sourceRegion = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    int sourceXSubsampling = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    int sourceYSubsampling = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
    int sourceMinProgressivePass = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    int sourceMaxProgressivePass = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
    int[] sourceBands = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
    int[] destinationBands = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
    Point destinationOffset = new Point(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    PNGMetadata metadata = new PNGMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    DataInputStream pixelStream = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
    BufferedImage theImage = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
    // The number of source pixels processed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
    int pixelsDone = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    // The total number of pixels in the source image
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
    int totalPixels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    public PNGImageReader(ImageReaderSpi originatingProvider) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        super(originatingProvider);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    public void setInput(Object input,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                         boolean seekForwardOnly,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                         boolean ignoreMetadata) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        super.setInput(input, seekForwardOnly, ignoreMetadata);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        this.stream = (ImageInputStream)input; // Always works
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        // Clear all values based on the previous stream contents
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        resetStreamSettings();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   211
    private String readNullTerminatedString(String charset, int maxLen) throws IOException {
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   212
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   213
        int b;
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   214
        int count = 0;
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   215
        while ((maxLen > count++) && ((b = stream.read()) != 0)) {
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   216
            if (b == -1) throw new EOFException();
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   217
            baos.write(b);
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   218
        }
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   219
        return new String(baos.toByteArray(), charset);
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   220
    }
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   221
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    private void readHeader() throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        if (gotHeader) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        if (stream == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            throw new IllegalStateException("Input source not set!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            byte[] signature = new byte[8];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
            stream.readFully(signature);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
            if (signature[0] != (byte)137 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                signature[1] != (byte)80 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                signature[2] != (byte)78 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                signature[3] != (byte)71 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                signature[4] != (byte)13 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                signature[5] != (byte)10 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                signature[6] != (byte)26 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                signature[7] != (byte)10) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                throw new IIOException("Bad PNG signature!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
            int IHDR_length = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
            if (IHDR_length != 13) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                throw new IIOException("Bad length for IHDR chunk!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            int IHDR_type = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            if (IHDR_type != IHDR_TYPE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                throw new IIOException("Bad type for IHDR chunk!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            this.metadata = new PNGMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
            int width = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
            int height = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            // Re-use signature array to bulk-read these unsigned byte values
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            stream.readFully(signature, 0, 5);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            int bitDepth          = signature[0] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
            int colorType         = signature[1] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            int compressionMethod = signature[2] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            int filterMethod      = signature[3] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            int interlaceMethod   = signature[4] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            // Skip IHDR CRC
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
            stream.skipBytes(4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            stream.flushBefore(stream.getStreamPosition());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
            if (width == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
                throw new IIOException("Image width == 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
            if (height == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                throw new IIOException("Image height == 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
                bitDepth != 8 && bitDepth != 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
                throw new IIOException("Bit depth must be 1, 2, 4, 8, or 16!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
            if (colorType != 0 && colorType != 2 && colorType != 3 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
                colorType != 4 && colorType != 6) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
                throw new IIOException("Color type must be 0, 2, 3, 4, or 6!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            if (colorType == PNG_COLOR_PALETTE && bitDepth == 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                throw new IIOException("Bad color type/bit depth combination!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            if ((colorType == PNG_COLOR_RGB ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
                 colorType == PNG_COLOR_RGB_ALPHA ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
                 colorType == PNG_COLOR_GRAY_ALPHA) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
                (bitDepth != 8 && bitDepth != 16)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
                throw new IIOException("Bad color type/bit depth combination!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
            if (compressionMethod != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
                throw new IIOException("Unknown compression method (not 0)!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            if (filterMethod != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
                throw new IIOException("Unknown filter method (not 0)!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            if (interlaceMethod != 0 && interlaceMethod != 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
                throw new IIOException("Unknown interlace method (not 0 or 1)!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            metadata.IHDR_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            metadata.IHDR_width = width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
            metadata.IHDR_height = height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
            metadata.IHDR_bitDepth = bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            metadata.IHDR_colorType = colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
            metadata.IHDR_compressionMethod = compressionMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
            metadata.IHDR_filterMethod = filterMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            metadata.IHDR_interlaceMethod = interlaceMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
            gotHeader = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            throw new IIOException("I/O error reading PNG header!", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
    private void parse_PLTE_chunk(int chunkLength) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        if (metadata.PLTE_present) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
"A PNG image may not contain more than one PLTE chunk.\n" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
"The chunk wil be ignored.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        } else if (metadata.IHDR_colorType == PNG_COLOR_GRAY ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                   metadata.IHDR_colorType == PNG_COLOR_GRAY_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
            processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
"A PNG gray or gray alpha image cannot have a PLTE chunk.\n" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
"The chunk wil be ignored.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        byte[] palette = new byte[chunkLength];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        stream.readFully(palette);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        int numEntries = chunkLength/3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        if (metadata.IHDR_colorType == PNG_COLOR_PALETTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            int maxEntries = 1 << metadata.IHDR_bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            if (numEntries > maxEntries) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
"PLTE chunk contains too many entries for bit depth, ignoring extras.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                numEntries = maxEntries;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            numEntries = Math.min(numEntries, maxEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        // Round array sizes up to 2^2^n
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        int paletteEntries;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        if (numEntries > 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            paletteEntries = 256;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        } else if (numEntries > 4) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            paletteEntries = 16;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        } else if (numEntries > 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
            paletteEntries = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
            paletteEntries = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        metadata.PLTE_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        metadata.PLTE_red = new byte[paletteEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        metadata.PLTE_green = new byte[paletteEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        metadata.PLTE_blue = new byte[paletteEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        int index = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        for (int i = 0; i < numEntries; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
            metadata.PLTE_red[i] = palette[index++];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
            metadata.PLTE_green[i] = palette[index++];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
            metadata.PLTE_blue[i] = palette[index++];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    private void parse_bKGD_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        if (metadata.IHDR_colorType == PNG_COLOR_PALETTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
            metadata.bKGD_colorType = PNG_COLOR_PALETTE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            metadata.bKGD_index = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        } else if (metadata.IHDR_colorType == PNG_COLOR_GRAY ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
                   metadata.IHDR_colorType == PNG_COLOR_GRAY_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            metadata.bKGD_colorType = PNG_COLOR_GRAY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            metadata.bKGD_gray = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        } else { // RGB or RGB_ALPHA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            metadata.bKGD_colorType = PNG_COLOR_RGB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            metadata.bKGD_red = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            metadata.bKGD_green = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            metadata.bKGD_blue = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        metadata.bKGD_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    private void parse_cHRM_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        metadata.cHRM_whitePointX = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        metadata.cHRM_whitePointY = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        metadata.cHRM_redX = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        metadata.cHRM_redY = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        metadata.cHRM_greenX = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
        metadata.cHRM_greenY = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        metadata.cHRM_blueX = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        metadata.cHRM_blueY = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        metadata.cHRM_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    private void parse_gAMA_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        int gamma = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        metadata.gAMA_gamma = gamma;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
        metadata.gAMA_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    private void parse_hIST_chunk(int chunkLength) throws IOException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        IIOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        if (!metadata.PLTE_present) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
            throw new IIOException("hIST chunk without prior PLTE chunk!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        /* According to PNG specification length of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
         * hIST chunk is specified in bytes and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
         * hIST chunk consists of 2 byte elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
         * (so we expect length is even).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        metadata.hIST_histogram = new char[chunkLength/2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        stream.readFully(metadata.hIST_histogram,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                         0, metadata.hIST_histogram.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
        metadata.hIST_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
    private void parse_iCCP_chunk(int chunkLength) throws IOException {
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   430
        String keyword = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
        metadata.iCCP_profileName = keyword;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        metadata.iCCP_compressionMethod = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        byte[] compressedProfile =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
          new byte[chunkLength - keyword.length() - 2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        stream.readFully(compressedProfile);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        metadata.iCCP_compressedProfile = compressedProfile;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        metadata.iCCP_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
    private void parse_iTXt_chunk(int chunkLength) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        long chunkStart = stream.getStreamPosition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   446
        String keyword = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        metadata.iTXt_keyword.add(keyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        int compressionFlag = stream.readUnsignedByte();
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   450
        metadata.iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag == 1));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        int compressionMethod = stream.readUnsignedByte();
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   453
        metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   455
        String languageTag = readNullTerminatedString("UTF8", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        metadata.iTXt_languageTag.add(languageTag);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   458
        long pos = stream.getStreamPosition();
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   459
        int maxLen = (int)(chunkStart + chunkLength - pos);
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   460
        String translatedKeyword =
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   461
            readNullTerminatedString("UTF8", maxLen);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
        metadata.iTXt_translatedKeyword.add(translatedKeyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
        String text;
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   465
        pos = stream.getStreamPosition();
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   466
        byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   467
        stream.readFully(b);
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   468
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
        if (compressionFlag == 1) { // Decompress the text
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   470
            text = new String(inflate(b), "UTF8");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
        } else {
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   472
            text = new String(b, "UTF8");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
        metadata.iTXt_text.add(text);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
    private void parse_pHYs_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
        metadata.pHYs_pixelsPerUnitXAxis = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        metadata.pHYs_pixelsPerUnitYAxis = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
        metadata.pHYs_unitSpecifier = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        metadata.pHYs_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
    private void parse_sBIT_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        if (colorType == PNG_COLOR_GRAY ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
            colorType == PNG_COLOR_GRAY_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
            metadata.sBIT_grayBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        } else if (colorType == PNG_COLOR_RGB ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                   colorType == PNG_COLOR_PALETTE ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                   colorType == PNG_COLOR_RGB_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            metadata.sBIT_redBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            metadata.sBIT_greenBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
            metadata.sBIT_blueBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
        if (colorType == PNG_COLOR_GRAY_ALPHA ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            colorType == PNG_COLOR_RGB_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            metadata.sBIT_alphaBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        metadata.sBIT_colorType = colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        metadata.sBIT_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
    private void parse_sPLT_chunk(int chunkLength)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
        throws IOException, IIOException {
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   509
        metadata.sPLT_paletteName = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        chunkLength -= metadata.sPLT_paletteName.length() + 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        int sampleDepth = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        metadata.sPLT_sampleDepth = sampleDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        int numEntries = chunkLength/(4*(sampleDepth/8) + 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        metadata.sPLT_red = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        metadata.sPLT_green = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        metadata.sPLT_blue = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        metadata.sPLT_alpha = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        metadata.sPLT_frequency = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        if (sampleDepth == 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
            for (int i = 0; i < numEntries; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                metadata.sPLT_red[i] = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                metadata.sPLT_green[i] = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                metadata.sPLT_blue[i] = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                metadata.sPLT_alpha[i] = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                metadata.sPLT_frequency[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        } else if (sampleDepth == 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            for (int i = 0; i < numEntries; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                metadata.sPLT_red[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
                metadata.sPLT_green[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                metadata.sPLT_blue[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                metadata.sPLT_alpha[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                metadata.sPLT_frequency[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            throw new IIOException("sPLT sample depth not 8 or 16!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
        metadata.sPLT_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
    private void parse_sRGB_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        metadata.sRGB_renderingIntent = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        metadata.sRGB_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
    private void parse_tEXt_chunk(int chunkLength) throws IOException {
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   552
        String keyword = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
        metadata.tEXt_keyword.add(keyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
        byte[] b = new byte[chunkLength - keyword.length() - 1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        stream.readFully(b);
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   557
        metadata.tEXt_text.add(new String(b, "ISO-8859-1"));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
    private void parse_tIME_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
        metadata.tIME_year = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        metadata.tIME_month = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        metadata.tIME_day = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        metadata.tIME_hour = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        metadata.tIME_minute = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        metadata.tIME_second = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
        metadata.tIME_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    private void parse_tRNS_chunk(int chunkLength) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        if (colorType == PNG_COLOR_PALETTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
            if (!metadata.PLTE_present) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
"tRNS chunk without prior PLTE chunk, ignoring it.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
            // Alpha table may have fewer entries than RGB palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
            int maxEntries = metadata.PLTE_red.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            int numEntries = chunkLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            if (numEntries > maxEntries) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
"tRNS chunk has more entries than prior PLTE chunk, ignoring extras.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
                numEntries = maxEntries;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
            metadata.tRNS_alpha = new byte[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
            metadata.tRNS_colorType = PNG_COLOR_PALETTE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            stream.read(metadata.tRNS_alpha, 0, numEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
            stream.skipBytes(chunkLength - numEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
        } else if (colorType == PNG_COLOR_GRAY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
            if (chunkLength != 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
"tRNS chunk for gray image must have length 2, ignoring chunk.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
                stream.skipBytes(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            metadata.tRNS_gray = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
            metadata.tRNS_colorType = PNG_COLOR_GRAY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        } else if (colorType == PNG_COLOR_RGB) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
            if (chunkLength != 6) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
"tRNS chunk for RGB image must have length 6, ignoring chunk.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
                stream.skipBytes(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            metadata.tRNS_red = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            metadata.tRNS_green = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            metadata.tRNS_blue = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            metadata.tRNS_colorType = PNG_COLOR_RGB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
"Gray+Alpha and RGBS images may not have a tRNS chunk, ignoring it.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        metadata.tRNS_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   621
    private static byte[] inflate(byte[] b) throws IOException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        InputStream bais = new ByteArrayInputStream(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
        InputStream iis = new InflaterInputStream(bais);
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   624
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   625
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
        int c;
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   627
        try {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   628
            while ((c = iis.read()) != -1) {
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   629
                baos.write(c);
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   630
            }
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   631
        } finally {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   632
            iis.close();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
        }
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   634
        return baos.toByteArray();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
    private void parse_zTXt_chunk(int chunkLength) throws IOException {
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   638
        String keyword = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        metadata.zTXt_keyword.add(keyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
        int method = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
        metadata.zTXt_compressionMethod.add(new Integer(method));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        byte[] b = new byte[chunkLength - keyword.length() - 2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        stream.readFully(b);
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   646
        metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
    private void readMetadata() throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        if (gotMetadata) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
         * Optimization: We can skip the remaining metadata if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
         * ignoreMetadata flag is set, and only if this is not a palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
         * image (in that case, we need to read the metadata to get the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
         * tRNS chunk, which is needed for the getImageTypes() method).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
        if (ignoreMetadata && colorType != PNG_COLOR_PALETTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
                    int chunkLength = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
                    int chunkType = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                    if (chunkType == IDAT_TYPE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
                        // We've reached the image data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
                        stream.skipBytes(-8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                        imageStartPosition = stream.getStreamPosition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                        // Skip the chunk plus the 4 CRC bytes that follow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                        stream.skipBytes(chunkLength + 4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                throw new IIOException("Error skipping PNG metadata", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
            gotMetadata = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
            loop: while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                int chunkLength = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                int chunkType = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
                switch (chunkType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
                case IDAT_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
                    // If chunk type is 'IDAT', we've reached the image data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                    stream.skipBytes(-8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
                    imageStartPosition = stream.getStreamPosition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
                    break loop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
                case PLTE_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                    parse_PLTE_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                case bKGD_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                    parse_bKGD_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                case cHRM_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                    parse_cHRM_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                case gAMA_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                    parse_gAMA_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                case hIST_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                    parse_hIST_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                case iCCP_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                    parse_iCCP_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
                case iTXt_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                    parse_iTXt_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                case pHYs_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                    parse_pHYs_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                case sBIT_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                    parse_sBIT_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
                case sPLT_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
                    parse_sPLT_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
                case sRGB_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
                    parse_sRGB_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                case tEXt_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
                    parse_tEXt_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                case tIME_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                    parse_tIME_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                case tRNS_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                    parse_tRNS_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
                case zTXt_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
                    parse_zTXt_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
                default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
                    // Read an unknown chunk
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
                    byte[] b = new byte[chunkLength];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
                    stream.readFully(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
                    StringBuilder chunkName = new StringBuilder(4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
                    chunkName.append((char)(chunkType >>> 24));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                    chunkName.append((char)((chunkType >> 16) & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
                    chunkName.append((char)((chunkType >> 8) & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
                    chunkName.append((char)(chunkType & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
                    int ancillaryBit = chunkType >>> 28;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
                    if (ancillaryBit == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
                        processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
"Encountered unknown chunk with critical bit set!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
                    metadata.unknownChunkType.add(chunkName.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                    metadata.unknownChunkData.add(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
                int chunkCRC = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
                stream.flushBefore(stream.getStreamPosition());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
            throw new IIOException("Error reading PNG metadata", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
        gotMetadata = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
    // Data filtering methods
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
    private static void decodeSubFilter(byte[] curr, int coff, int count,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
                                        int bpp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
        for (int i = bpp; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
            int val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
            val = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
            val += curr[i + coff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            curr[i + coff] = (byte)val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
    private static void decodeUpFilter(byte[] curr, int coff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
                                       byte[] prev, int poff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
                                       int count) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
        for (int i = 0; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
            int raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
            int prior = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
            curr[i + coff] = (byte)(raw + prior);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
    private static void decodeAverageFilter(byte[] curr, int coff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
                                            byte[] prev, int poff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                                            int count, int bpp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
        int raw, priorPixel, priorRow;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
        for (int i = 0; i < bpp; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
            curr[i + coff] = (byte)(raw + priorRow/2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
        for (int i = bpp; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
            priorPixel = curr[i + coff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
            curr[i + coff] = (byte)(raw + (priorPixel + priorRow)/2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
    private static int paethPredictor(int a, int b, int c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
        int p = a + b - c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
        int pa = Math.abs(p - a);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
        int pb = Math.abs(p - b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
        int pc = Math.abs(p - c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
        if ((pa <= pb) && (pa <= pc)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
            return a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
        } else if (pb <= pc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
            return b;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
            return c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
    private static void decodePaethFilter(byte[] curr, int coff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
                                          byte[] prev, int poff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
                                          int count, int bpp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
        int raw, priorPixel, priorRow, priorRowPixel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
        for (int i = 0; i < bpp; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
            curr[i + coff] = (byte)(raw + priorRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
        for (int i = bpp; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
            priorPixel = curr[i + coff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
            priorRowPixel = prev[i + poff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
            curr[i + coff] = (byte)(raw + paethPredictor(priorPixel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
                                                         priorRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
                                                         priorRowPixel));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
    private static final int[][] bandOffsets = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
        null,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
        { 0 }, // G
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
        { 0, 1 }, // GA in GA order
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
        { 0, 1, 2 }, // RGB in RGB order
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
        { 0, 1, 2, 3 } // RGBA in RGBA order
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
    private WritableRaster createRaster(int width, int height, int bands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
                                        int scanlineStride,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
                                        int bitDepth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
        DataBuffer dataBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
        WritableRaster ras = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
        Point origin = new Point(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
        if ((bitDepth < 8) && (bands == 1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
            dataBuffer = new DataBufferByte(height*scanlineStride);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
            ras = Raster.createPackedRaster(dataBuffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
                                            width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
                                            bitDepth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
                                            origin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
        } else if (bitDepth <= 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
            dataBuffer = new DataBufferByte(height*scanlineStride);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
            ras = Raster.createInterleavedRaster(dataBuffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
                                                 width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
                                                 scanlineStride,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
                                                 bands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
                                                 bandOffsets[bands],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
                                                 origin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
            dataBuffer = new DataBufferUShort(height*scanlineStride);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
            ras = Raster.createInterleavedRaster(dataBuffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
                                                 width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
                                                 scanlineStride,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
                                                 bands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
                                                 bandOffsets[bands],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
                                                 origin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        return ras;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
    private void skipPass(int passWidth, int passHeight)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
        throws IOException, IIOException  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
        if ((passWidth == 0) || (passHeight == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
        int inputBands = inputBandsForColorType[metadata.IHDR_colorType];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
        int bytesPerRow = (inputBands*passWidth*metadata.IHDR_bitDepth + 7)/8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
        // Read the image row-by-row
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
        for (int srcY = 0; srcY < passHeight; srcY++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
            // Skip filter byte and the remaining row bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
            pixelStream.skipBytes(1 + bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
            // If read has been aborted, just return
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
            // processReadAborted will be called later
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
            if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
    private void updateImageProgress(int newPixels) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
        pixelsDone += newPixels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
        processImageProgress(100.0F*pixelsDone/totalPixels);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
    private void decodePass(int passNum,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
                            int xStart, int yStart,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
                            int xStep, int yStep,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
                            int passWidth, int passHeight) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
        if ((passWidth == 0) || (passHeight == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
        WritableRaster imRas = theImage.getWritableTile(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
        int dstMinX = imRas.getMinX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
        int dstMaxX = dstMinX + imRas.getWidth() - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
        int dstMinY = imRas.getMinY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
        int dstMaxY = dstMinY + imRas.getHeight() - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
        // Determine which pixels will be updated in this pass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
        int[] vals =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
          ReaderUtil.computeUpdatedPixels(sourceRegion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
                                          destinationOffset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
                                          dstMinX, dstMinY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
                                          dstMaxX, dstMaxY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
                                          sourceXSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
                                          sourceYSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
                                          xStart, yStart,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
                                          passWidth, passHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
                                          xStep, yStep);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
        int updateMinX = vals[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
        int updateMinY = vals[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
        int updateWidth = vals[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
        int updateXStep = vals[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
        int updateYStep = vals[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
        int bitDepth = metadata.IHDR_bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
        int inputBands = inputBandsForColorType[metadata.IHDR_colorType];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
        int bytesPerPixel = (bitDepth == 16) ? 2 : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
        bytesPerPixel *= inputBands;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
        int bytesPerRow = (inputBands*passWidth*bitDepth + 7)/8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
        int eltsPerRow = (bitDepth == 16) ? bytesPerRow/2 : bytesPerRow;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
        // If no pixels need updating, just skip the input data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
        if (updateWidth == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
            for (int srcY = 0; srcY < passHeight; srcY++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
                // Update count of pixels read
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
                updateImageProgress(passWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
                // Skip filter byte and the remaining row bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
                pixelStream.skipBytes(1 + bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
        // Backwards map from destination pixels
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
        // (dstX = updateMinX + k*updateXStep)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
        // to source pixels (sourceX), and then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
        // to offset and skip in passRow (srcX and srcXStep)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
        int sourceX =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
            (updateMinX - destinationOffset.x)*sourceXSubsampling +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
            sourceRegion.x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
        int srcX = (sourceX - xStart)/xStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
        // Compute the step factor in the source
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
        int srcXStep = updateXStep*sourceXSubsampling/xStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
        byte[] byteData = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
        short[] shortData = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
        byte[] curr = new byte[bytesPerRow];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
        byte[] prior = new byte[bytesPerRow];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
        // Create a 1-row tall Raster to hold the data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
        WritableRaster passRow = createRaster(passWidth, 1, inputBands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
                                              eltsPerRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
                                              bitDepth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
        // Create an array suitable for holding one pixel
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
        int[] ps = passRow.getPixel(0, 0, (int[])null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
        DataBuffer dataBuffer = passRow.getDataBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
        int type = dataBuffer.getDataType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
        if (type == DataBuffer.TYPE_BYTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
            byteData = ((DataBufferByte)dataBuffer).getData();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
            shortData = ((DataBufferUShort)dataBuffer).getData();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
        processPassStarted(theImage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
                           passNum,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
                           sourceMinProgressivePass,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
                           sourceMaxProgressivePass,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
                           updateMinX, updateMinY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
                           updateXStep, updateYStep,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                           destinationBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
        // Handle source and destination bands
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
        if (sourceBands != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
            passRow = passRow.createWritableChild(0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
                                                  passRow.getWidth(), 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
                                                  0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
                                                  sourceBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        if (destinationBands != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
            imRas = imRas.createWritableChild(0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
                                              imRas.getWidth(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
                                              imRas.getHeight(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
                                              0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
                                              destinationBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
        // Determine if all of the relevant output bands have the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
        // same bit depth as the source data
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
        boolean adjustBitDepths = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
        int[] outputSampleSize = imRas.getSampleModel().getSampleSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
        int numBands = outputSampleSize.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
        for (int b = 0; b < numBands; b++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
            if (outputSampleSize[b] != bitDepth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
                adjustBitDepths = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
        // If the bit depths differ, create a lookup table per band to perform
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
        // the conversion
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
        int[][] scale = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
        if (adjustBitDepths) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
            int maxInSample = (1 << bitDepth) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
            int halfMaxInSample = maxInSample/2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
            scale = new int[numBands][];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
            for (int b = 0; b < numBands; b++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
                int maxOutSample = (1 << outputSampleSize[b]) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
                scale[b] = new int[maxInSample + 1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
                for (int s = 0; s <= maxInSample; s++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
                    scale[b][s] =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
                        (s*maxOutSample + halfMaxInSample)/maxInSample;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
        // Limit passRow to relevant area for the case where we
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
        // will can setRect to copy a contiguous span
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
        boolean useSetRect = srcXStep == 1 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
            updateXStep == 1 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
            !adjustBitDepths &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
            (imRas instanceof ByteInterleavedRaster);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
        if (useSetRect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
            passRow = passRow.createWritableChild(srcX, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
                                                  updateWidth, 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
                                                  0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
                                                  null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
        // Decode the (sub)image row-by-row
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
        for (int srcY = 0; srcY < passHeight; srcY++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
            // Update count of pixels read
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
            updateImageProgress(passWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
            // Read the filter type byte and a row of data
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
            int filter = pixelStream.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
                // Swap curr and prior
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
                byte[] tmp = prior;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
                prior = curr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
                curr = tmp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
                pixelStream.readFully(curr, 0, bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
            } catch (java.util.zip.ZipException ze) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
                // TODO - throw a more meaningful exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
                throw ze;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
            switch (filter) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
            case PNG_FILTER_NONE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
            case PNG_FILTER_SUB:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
                decodeSubFilter(curr, 0, bytesPerRow, bytesPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
            case PNG_FILTER_UP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
                decodeUpFilter(curr, 0, prior, 0, bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
            case PNG_FILTER_AVERAGE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
                decodeAverageFilter(curr, 0, prior, 0, bytesPerRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
                                    bytesPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
            case PNG_FILTER_PAETH:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
                decodePaethFilter(curr, 0, prior, 0, bytesPerRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
                                  bytesPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
                throw new IIOException("Unknown row filter type (= " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
                                       filter + ")!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
            // Copy data into passRow byte by byte
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
            if (bitDepth < 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
                System.arraycopy(curr, 0, byteData, 0, bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
                int idx = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
                for (int j = 0; j < eltsPerRow; j++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
                    shortData[j] =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
                        (short)((curr[idx] << 8) | (curr[idx + 1] & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
                    idx += 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
            // True Y position in source
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
            int sourceY = srcY*yStep + yStart;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
            if ((sourceY >= sourceRegion.y) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
                (sourceY < sourceRegion.y + sourceRegion.height) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
                (((sourceY - sourceRegion.y) %
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
                  sourceYSubsampling) == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
                int dstY = destinationOffset.y +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
                    (sourceY - sourceRegion.y)/sourceYSubsampling;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
                if (dstY < dstMinY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
                    continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
                if (dstY > dstMaxY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
                if (useSetRect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
                    imRas.setRect(updateMinX, dstY, passRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
                    int newSrcX = srcX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
                    for (int dstX = updateMinX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
                         dstX < updateMinX + updateWidth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
                         dstX += updateXStep) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
                        passRow.getPixel(newSrcX, 0, ps);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
                        if (adjustBitDepths) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
                            for (int b = 0; b < numBands; b++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
                                ps[b] = scale[b][ps[b]];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
                        imRas.setPixel(dstX, dstY, ps);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
                        newSrcX += srcXStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
                processImageUpdate(theImage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
                                   updateMinX, dstY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
                                   updateWidth, 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
                                   updateXStep, updateYStep,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
                                   destinationBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
                // If read has been aborted, just return
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
                // processReadAborted will be called later
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
        processPassComplete(theImage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
    private void decodeImage()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
        throws IOException, IIOException  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
        int width = metadata.IHDR_width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
        int height = metadata.IHDR_height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
        this.pixelsDone = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
        this.totalPixels = width*height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
        clearAbortRequest();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
        if (metadata.IHDR_interlaceMethod == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
            decodePass(0, 0, 0, 1, 1, width, height);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
            for (int i = 0; i <= sourceMaxProgressivePass; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
                int XOffset = adam7XOffset[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
                int YOffset = adam7YOffset[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
                int XSubsampling = adam7XSubsampling[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
                int YSubsampling = adam7YSubsampling[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
                int xbump = adam7XSubsampling[i + 1] - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
                int ybump = adam7YSubsampling[i + 1] - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
                if (i >= sourceMinProgressivePass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
                    decodePass(i,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
                               XOffset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
                               YOffset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
                               XSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
                               YSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
                               (width + xbump)/XSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
                               (height + ybump)/YSubsampling);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
                    skipPass((width + xbump)/XSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
                             (height + ybump)/YSubsampling);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
                // If read has been aborted, just return
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
                // processReadAborted will be called later
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
    private void readImage(ImageReadParam param) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
        readMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
        int width = metadata.IHDR_width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
        int height = metadata.IHDR_height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
        // Init default values
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
        sourceXSubsampling = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
        sourceYSubsampling = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
        sourceMinProgressivePass = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
        sourceMaxProgressivePass = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
        sourceBands = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
        destinationBands = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
        destinationOffset = new Point(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
        // If an ImageReadParam is available, get values from it
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
        if (param != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
            sourceXSubsampling = param.getSourceXSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
            sourceYSubsampling = param.getSourceYSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
            sourceMinProgressivePass =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
                Math.max(param.getSourceMinProgressivePass(), 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
            sourceMaxProgressivePass =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
                Math.min(param.getSourceMaxProgressivePass(), 6);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
            sourceBands = param.getSourceBands();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
            destinationBands = param.getDestinationBands();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
            destinationOffset = param.getDestinationOffset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
        }
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1257
        Inflater inf = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
            stream.seek(imageStartPosition);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
  1261
            Enumeration<InputStream> e = new PNGImageDataEnumeration(stream);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
            InputStream is = new SequenceInputStream(e);
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1263
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1264
           /* InflaterInputStream uses an Inflater instance which consumes
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1265
            * native (non-GC visible) resources. This is normally implicitly
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1266
            * freed when the stream is closed. However since the
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1267
            * InflaterInputStream wraps a client-supplied input stream,
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1268
            * we cannot close it.
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1269
            * But the app may depend on GC finalization to close the stream.
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1270
            * Therefore to ensure timely freeing of native resources we
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1271
            * explicitly create the Inflater instance and free its resources
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1272
            * when we are done with the InflaterInputStream by calling
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1273
            * inf.end();
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1274
            */
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1275
            inf = new Inflater();
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1276
            is = new InflaterInputStream(is, inf);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
            is = new BufferedInputStream(is);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
            this.pixelStream = new DataInputStream(is);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
            theImage = getDestination(param,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
                                      getImageTypes(0),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
                                      width,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
                                      height);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
            Rectangle destRegion = new Rectangle(0, 0, 0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
            sourceRegion = new Rectangle(0, 0, 0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
            computeRegions(param, width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
                           theImage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
                           sourceRegion, destRegion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
            destinationOffset.setLocation(destRegion.getLocation());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
            // At this point the header has been read and we know
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
            // how many bands are in the image, so perform checking
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
            // of the read param.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
            int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
            checkReadParamBandSettings(param,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
                                       inputBandsForColorType[colorType],
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
                                      theImage.getSampleModel().getNumBands());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
            processImageStarted(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
            decodeImage();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
            if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
                processReadAborted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
                processImageComplete();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
            throw new IIOException("Error reading PNG image data", e);
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1309
        } finally {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1310
            if (inf != null) {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1311
                inf.end();
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1312
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1313
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1314
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1315
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
    public int getNumImages(boolean allowSearch) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
        if (stream == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
            throw new IllegalStateException("No input source set!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
        if (seekForwardOnly && allowSearch) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
            throw new IllegalStateException
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
                ("seekForwardOnly and allowSearch can't both be true!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
        return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
    public int getWidth(int imageIndex) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1328
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1329
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1330
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1331
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1332
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1333
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1334
        return metadata.IHDR_width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1335
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1336
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1337
    public int getHeight(int imageIndex) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1338
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1339
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1340
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1341
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1342
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1343
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1344
        return metadata.IHDR_height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1345
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1346
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1347
    public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1348
      throws IIOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1349
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1350
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1351
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1352
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1353
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1354
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1355
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1356
        ArrayList<ImageTypeSpecifier> l =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1357
            new ArrayList<ImageTypeSpecifier>(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1358
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1359
        ColorSpace rgb;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1360
        ColorSpace gray;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1361
        int[] bandOffsets;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1362
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1363
        int bitDepth = metadata.IHDR_bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1364
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1365
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1366
        int dataType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1367
        if (bitDepth <= 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1368
            dataType = DataBuffer.TYPE_BYTE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1369
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1370
            dataType = DataBuffer.TYPE_USHORT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1371
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1372
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1373
        switch (colorType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1374
        case PNG_COLOR_GRAY:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1375
            // Packed grayscale
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1376
            l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1377
                                                     dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1378
                                                     false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1379
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1380
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1381
        case PNG_COLOR_RGB:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1382
            if (bitDepth == 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1383
                // some standard types of buffered images
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1384
                // which can be used as destination
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1385
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1386
                          BufferedImage.TYPE_3BYTE_BGR));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1387
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1388
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1389
                          BufferedImage.TYPE_INT_RGB));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1390
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1391
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1392
                          BufferedImage.TYPE_INT_BGR));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1393
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1394
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1395
            // Component R, G, B
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1396
            rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1397
            bandOffsets = new int[3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1398
            bandOffsets[0] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1399
            bandOffsets[1] = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1400
            bandOffsets[2] = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1401
            l.add(ImageTypeSpecifier.createInterleaved(rgb,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1402
                                                       bandOffsets,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1403
                                                       dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1404
                                                       false,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1405
                                                       false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1406
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1407
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1408
        case PNG_COLOR_PALETTE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1409
            readMetadata(); // Need tRNS chunk
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1410
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1411
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1412
             * The PLTE chunk spec says:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1413
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1414
             * The number of palette entries must not exceed the range that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1415
             * can be represented in the image bit depth (for example, 2^4 = 16
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1416
             * for a bit depth of 4). It is permissible to have fewer entries
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1417
             * than the bit depth would allow. In that case, any out-of-range
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1418
             * pixel value found in the image data is an error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1419
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1420
             * http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.PLTE
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1421
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1422
             * Consequently, the case when the palette length is smaller than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1423
             * 2^bitDepth is legal in the view of PNG spec.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1424
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1425
             * However the spec of createIndexed() method demands the exact
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1426
             * equality of the palette lengh and number of possible palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1427
             * entries (2^bitDepth).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1428
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1429
             * {@link javax.imageio.ImageTypeSpecifier.html#createIndexed}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1430
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1431
             * In order to avoid this contradiction we need to extend the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1432
             * palette arrays to the limit defined by the bitDepth.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1433
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1434
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1435
            int plength = 1 << bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1436
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1437
            byte[] red = metadata.PLTE_red;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1438
            byte[] green = metadata.PLTE_green;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1439
            byte[] blue = metadata.PLTE_blue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1440
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1441
            if (metadata.PLTE_red.length < plength) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1442
                red = Arrays.copyOf(metadata.PLTE_red, plength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1443
                Arrays.fill(red, metadata.PLTE_red.length, plength,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1444
                            metadata.PLTE_red[metadata.PLTE_red.length - 1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1445
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1446
                green = Arrays.copyOf(metadata.PLTE_green, plength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1447
                Arrays.fill(green, metadata.PLTE_green.length, plength,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1448
                            metadata.PLTE_green[metadata.PLTE_green.length - 1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1449
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1450
                blue = Arrays.copyOf(metadata.PLTE_blue, plength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1451
                Arrays.fill(blue, metadata.PLTE_blue.length, plength,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1452
                            metadata.PLTE_blue[metadata.PLTE_blue.length - 1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1453
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1454
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1455
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1456
            // Alpha from tRNS chunk may have fewer entries than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1457
            // the RGB LUTs from the PLTE chunk; if so, pad with
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1458
            // 255.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1459
            byte[] alpha = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1460
            if (metadata.tRNS_present && (metadata.tRNS_alpha != null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1461
                if (metadata.tRNS_alpha.length == red.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1462
                    alpha = metadata.tRNS_alpha;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1463
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1464
                    alpha = Arrays.copyOf(metadata.tRNS_alpha, red.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1465
                    Arrays.fill(alpha,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1466
                                metadata.tRNS_alpha.length,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1467
                                red.length, (byte)255);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1468
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1469
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1470
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1471
            l.add(ImageTypeSpecifier.createIndexed(red, green,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1472
                                                   blue, alpha,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1473
                                                   bitDepth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1474
                                                   DataBuffer.TYPE_BYTE));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1475
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1476
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1477
        case PNG_COLOR_GRAY_ALPHA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1478
            // Component G, A
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1479
            gray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1480
            bandOffsets = new int[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1481
            bandOffsets[0] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1482
            bandOffsets[1] = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1483
            l.add(ImageTypeSpecifier.createInterleaved(gray,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1484
                                                       bandOffsets,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1485
                                                       dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1486
                                                       true,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1487
                                                       false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1488
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1489
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1490
        case PNG_COLOR_RGB_ALPHA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1491
            if (bitDepth == 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1492
                // some standard types of buffered images
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1493
                // wich can be used as destination
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1494
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1495
                          BufferedImage.TYPE_4BYTE_ABGR));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1496
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1497
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1498
                          BufferedImage.TYPE_INT_ARGB));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1499
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1500
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1501
            // Component R, G, B, A (non-premultiplied)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1502
            rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1503
            bandOffsets = new int[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1504
            bandOffsets[0] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1505
            bandOffsets[1] = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1506
            bandOffsets[2] = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1507
            bandOffsets[3] = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1508
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1509
            l.add(ImageTypeSpecifier.createInterleaved(rgb,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1510
                                                       bandOffsets,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1511
                                                       dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1512
                                                       true,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1513
                                                       false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1514
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1515
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1516
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1517
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1518
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1519
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1520
        return l.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1521
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1522
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1523
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1524
     * Super class implementation uses first element
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1525
     * of image types list as raw image type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1526
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1527
     * Also, super implementation uses first element of this list
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1528
     * as default destination type image read param does not specify
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1529
     * anything other.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1530
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1531
     * However, in case of RGB and RGBA color types, raw image type
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1532
     * produces buffered image of custom type. It causes some
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1533
     * performance degradation of subsequent rendering operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1534
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1535
     * To resolve this contradiction we put standard image types
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1536
     * at the first positions of image types list (to produce standard
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1537
     * images by default) and put raw image type (which is custom)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1538
     * at the last position of this list.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1539
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1540
     * After this changes we should override getRawImageType()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1541
     * to return last element of image types list.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1542
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1543
    public ImageTypeSpecifier getRawImageType(int imageIndex)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1544
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1545
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1546
        Iterator<ImageTypeSpecifier> types = getImageTypes(imageIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1547
        ImageTypeSpecifier raw = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1548
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1549
            raw = types.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1550
        } while (types.hasNext());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1551
        return raw;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1552
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1553
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1554
    public ImageReadParam getDefaultReadParam() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1555
        return new ImageReadParam();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1556
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1557
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1558
    public IIOMetadata getStreamMetadata()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1559
        throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1560
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1561
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1562
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1563
    public IIOMetadata getImageMetadata(int imageIndex) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1564
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1565
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1566
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1567
        readMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1568
        return metadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1569
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1570
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1571
    public BufferedImage read(int imageIndex, ImageReadParam param)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1572
        throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1573
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1574
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1575
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1576
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1577
        readImage(param);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1578
        return theImage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1579
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1580
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1581
    public void reset() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1582
        super.reset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1583
        resetStreamSettings();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1584
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1585
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1586
    private void resetStreamSettings() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1587
        gotHeader = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1588
        gotMetadata = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1589
        metadata = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1590
        pixelStream = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1591
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1592
}