src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
author jdv
Wed, 17 Jan 2018 10:58:22 +0530
changeset 48645 6cfee3ad7a76
parent 48641 35b5da568499
child 48728 fb62f481671e
permissions -rw-r--r--
8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper Reviewed-by: serb, bpb, pnarayanan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
48645
6cfee3ad7a76 8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper
jdv
parents: 48641
diff changeset
     2
 * Copyright (c) 2000, 2018, 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
47836
f17a797c910a 8190512: PngReader incorrectly throws IllegalArgumentException for malformed images with negative dimensions
jdv
parents: 47216
diff changeset
   272
            if (width <= 0) {
f17a797c910a 8190512: PngReader incorrectly throws IllegalArgumentException for malformed images with negative dimensions
jdv
parents: 47216
diff changeset
   273
                throw new IIOException("Image width <= 0!");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            }
47836
f17a797c910a 8190512: PngReader incorrectly throws IllegalArgumentException for malformed images with negative dimensions
jdv
parents: 47216
diff changeset
   275
            if (height <= 0) {
f17a797c910a 8190512: PngReader incorrectly throws IllegalArgumentException for malformed images with negative dimensions
jdv
parents: 47216
diff changeset
   276
                throw new IIOException("Image height <= 0!");
2
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);
47197
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   475
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   476
        // Check if the text chunk contains image creation time
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   477
        if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   478
            // Update Standard/Document/ImageCreationTime from text chunk
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   479
            int index = metadata.iTXt_text.size() - 1;
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   480
            metadata.decodeImageCreationTimeFromTextChunk(
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   481
                    metadata.iTXt_text.listIterator(index));
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   482
        }
2
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_pHYs_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
        metadata.pHYs_pixelsPerUnitXAxis = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        metadata.pHYs_pixelsPerUnitYAxis = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
        metadata.pHYs_unitSpecifier = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        metadata.pHYs_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
    private void parse_sBIT_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        if (colorType == PNG_COLOR_GRAY ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
            colorType == PNG_COLOR_GRAY_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            metadata.sBIT_grayBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
        } else if (colorType == PNG_COLOR_RGB ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
                   colorType == PNG_COLOR_PALETTE ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
                   colorType == PNG_COLOR_RGB_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            metadata.sBIT_redBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            metadata.sBIT_greenBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
            metadata.sBIT_blueBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        if (colorType == PNG_COLOR_GRAY_ALPHA ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
            colorType == PNG_COLOR_RGB_ALPHA) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
            metadata.sBIT_alphaBits = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        metadata.sBIT_colorType = colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        metadata.sBIT_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
    private void parse_sPLT_chunk(int chunkLength)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        throws IOException, IIOException {
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   517
        metadata.sPLT_paletteName = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        chunkLength -= metadata.sPLT_paletteName.length() + 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        int sampleDepth = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
        metadata.sPLT_sampleDepth = sampleDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        int numEntries = chunkLength/(4*(sampleDepth/8) + 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        metadata.sPLT_red = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        metadata.sPLT_green = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
        metadata.sPLT_blue = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        metadata.sPLT_alpha = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        metadata.sPLT_frequency = new int[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        if (sampleDepth == 8) {
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.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
                metadata.sPLT_green[i] = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                metadata.sPLT_blue[i] = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                metadata.sPLT_alpha[i] = stream.readUnsignedByte();
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 if (sampleDepth == 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            for (int i = 0; i < numEntries; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                metadata.sPLT_red[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                metadata.sPLT_green[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
                metadata.sPLT_blue[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                metadata.sPLT_alpha[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                metadata.sPLT_frequency[i] = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            throw new IIOException("sPLT sample depth not 8 or 16!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        metadata.sPLT_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
    private void parse_sRGB_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
        metadata.sRGB_renderingIntent = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        metadata.sRGB_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
    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
   560
        String keyword = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
        metadata.tEXt_keyword.add(keyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        byte[] b = new byte[chunkLength - keyword.length() - 1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        stream.readFully(b);
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   565
        metadata.tEXt_text.add(new String(b, "ISO-8859-1"));
47197
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   566
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   567
        // Check if the text chunk contains image creation time
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   568
        if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   569
            // Update Standard/Document/ImageCreationTime from text chunk
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   570
            int index = metadata.tEXt_text.size() - 1;
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   571
            metadata.decodeImageCreationTimeFromTextChunk(
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   572
                    metadata.tEXt_text.listIterator(index));
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   573
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
    private void parse_tIME_chunk() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
        metadata.tIME_year = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        metadata.tIME_month = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
        metadata.tIME_day = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        metadata.tIME_hour = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        metadata.tIME_minute = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        metadata.tIME_second = stream.readUnsignedByte();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        metadata.tIME_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
    private void parse_tRNS_chunk(int chunkLength) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
        if (colorType == PNG_COLOR_PALETTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            if (!metadata.PLTE_present) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
"tRNS chunk without prior PLTE chunk, ignoring it.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
            // Alpha table may have fewer entries than RGB palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            int maxEntries = metadata.PLTE_red.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            int numEntries = chunkLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            if (numEntries > maxEntries) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
"tRNS chunk has more entries than prior PLTE chunk, ignoring extras.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
                numEntries = maxEntries;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
            metadata.tRNS_alpha = new byte[numEntries];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            metadata.tRNS_colorType = PNG_COLOR_PALETTE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
            stream.read(metadata.tRNS_alpha, 0, numEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            stream.skipBytes(chunkLength - numEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        } else if (colorType == PNG_COLOR_GRAY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            if (chunkLength != 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
"tRNS chunk for gray image must have length 2, ignoring chunk.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                stream.skipBytes(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            metadata.tRNS_gray = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            metadata.tRNS_colorType = PNG_COLOR_GRAY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
        } else if (colorType == PNG_COLOR_RGB) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            if (chunkLength != 6) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
"tRNS chunk for RGB image must have length 6, ignoring chunk.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                stream.skipBytes(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
            metadata.tRNS_red = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
            metadata.tRNS_green = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            metadata.tRNS_blue = stream.readUnsignedShort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
            metadata.tRNS_colorType = PNG_COLOR_RGB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
"Gray+Alpha and RGBS images may not have a tRNS chunk, ignoring it.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
        metadata.tRNS_present = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   637
    private static byte[] inflate(byte[] b) throws IOException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
        InputStream bais = new ByteArrayInputStream(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        InputStream iis = new InflaterInputStream(bais);
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   640
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   641
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
        int c;
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   643
        try {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   644
            while ((c = iis.read()) != -1) {
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   645
                baos.write(c);
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   646
            }
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   647
        } finally {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
   648
            iis.close();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
        }
1734
861400729115 6541476: PNG imageio plugin incorrectly handles iTXt chunk
bae
parents: 1715
diff changeset
   650
        return baos.toByteArray();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
    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
   654
        String keyword = readNullTerminatedString("ISO-8859-1", 80);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
        metadata.zTXt_keyword.add(keyword);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
        int method = stream.readUnsignedByte();
25777
bb88947b6766 8049893: Replace uses of 'new Integer()' with appropriate alternative across client classes
prr
parents: 24562
diff changeset
   658
        metadata.zTXt_compressionMethod.add(method);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
        byte[] b = new byte[chunkLength - keyword.length() - 2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
        stream.readFully(b);
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
   662
        metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
47197
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   663
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   664
        // Check if the text chunk contains image creation time
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   665
        if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   666
            // Update Standard/Document/ImageCreationTime from text chunk
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   667
            int index = metadata.zTXt_text.size() - 1;
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   668
            metadata.decodeImageCreationTimeFromTextChunk(
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   669
                    metadata.zTXt_text.listIterator(index));
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   670
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
    private void readMetadata() throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
        if (gotMetadata) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
         * Optimization: We can skip the remaining metadata if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
         * ignoreMetadata flag is set, and only if this is not a palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
         * image (in that case, we need to read the metadata to get the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
         * tRNS chunk, which is needed for the getImageTypes() method).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        if (ignoreMetadata && colorType != PNG_COLOR_PALETTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                    int chunkLength = stream.readInt();
24562
694f2eed1a76 6945174: IndexOutOfBoundsException calling ImageIO.read() on malformed PNG
bae
parents: 23010
diff changeset
   691
694f2eed1a76 6945174: IndexOutOfBoundsException calling ImageIO.read() on malformed PNG
bae
parents: 23010
diff changeset
   692
                    // verify the chunk length first
694f2eed1a76 6945174: IndexOutOfBoundsException calling ImageIO.read() on malformed PNG
bae
parents: 23010
diff changeset
   693
                    if (chunkLength < 0 || chunkLength + 4 < 0) {
694f2eed1a76 6945174: IndexOutOfBoundsException calling ImageIO.read() on malformed PNG
bae
parents: 23010
diff changeset
   694
                        throw new IIOException("Invalid chunk length " + chunkLength);
694f2eed1a76 6945174: IndexOutOfBoundsException calling ImageIO.read() on malformed PNG
bae
parents: 23010
diff changeset
   695
                    }
694f2eed1a76 6945174: IndexOutOfBoundsException calling ImageIO.read() on malformed PNG
bae
parents: 23010
diff changeset
   696
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
                    int chunkType = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                    if (chunkType == IDAT_TYPE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                        // We've reached the image data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                        stream.skipBytes(-8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                        imageStartPosition = stream.getStreamPosition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                        // Skip the chunk plus the 4 CRC bytes that follow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                        stream.skipBytes(chunkLength + 4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                throw new IIOException("Error skipping PNG metadata", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
            gotMetadata = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
            loop: while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                int chunkLength = stream.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                int chunkType = stream.readInt();
21218
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   721
                int chunkCRC;
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   722
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   723
                // verify the chunk length
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   724
                if (chunkLength < 0) {
24562
694f2eed1a76 6945174: IndexOutOfBoundsException calling ImageIO.read() on malformed PNG
bae
parents: 23010
diff changeset
   725
                    throw new IIOException("Invalid chunk length " + chunkLength);
21218
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   726
                };
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   727
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   728
                try {
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   729
                    stream.mark();
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   730
                    stream.seek(stream.getStreamPosition() + chunkLength);
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   731
                    chunkCRC = stream.readInt();
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   732
                    stream.reset();
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   733
                } catch (IOException e) {
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   734
                    throw new IIOException("Invalid chunk length " + chunkLength);
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   735
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                switch (chunkType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                case IDAT_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                    // If chunk type is 'IDAT', we've reached the image data.
47197
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   740
                    if (imageStartPosition == -1L) {
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   741
                        /*
48641
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   742
                         * The PNG specification mandates that if colorType is
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   743
                         * PNG_COLOR_PALETTE then the PLTE chunk should appear
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   744
                         * before the first IDAT chunk.
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   745
                         */
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   746
                        if (colorType == PNG_COLOR_PALETTE &&
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   747
                            !(metadata.PLTE_present))
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   748
                        {
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   749
                            throw new IIOException("Required PLTE chunk"
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   750
                                    + " missing");
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   751
                        }
35b5da568499 8190997: PNGImageReader throws NullPointerException when PLTE section is missing
jdv
parents: 47972
diff changeset
   752
                        /*
47197
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   753
                         * PNGs may contain multiple IDAT chunks containing
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   754
                         * a portion of image data. We store the position of
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   755
                         * the first IDAT chunk and continue with iteration
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   756
                         * of other chunks that follow image data.
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   757
                         */
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   758
                        imageStartPosition = stream.getStreamPosition() - 8;
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   759
                    }
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   760
                    // Move to the CRC byte location.
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   761
                    stream.skipBytes(chunkLength);
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   762
                    break;
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   763
                case IEND_TYPE:
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   764
                    /*
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   765
                     * If the chunk type is 'IEND', we've reached end of image.
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   766
                     * Seek to the first IDAT chunk for subsequent decoding.
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   767
                     */
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   768
                    stream.seek(imageStartPosition);
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   769
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   770
                    /*
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   771
                     * flushBefore discards the portion of the stream before
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   772
                     * the indicated position. Hence this should be used after
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   773
                     * we complete iteration over available chunks including
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   774
                     * those that appear after the IDAT.
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   775
                     */
a7033867ee20 8164971: PNG metadata does not handle ImageCreationTime
pnarayanan
parents: 43209
diff changeset
   776
                    stream.flushBefore(stream.getStreamPosition());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
                    break loop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
                case PLTE_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                    parse_PLTE_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
                case bKGD_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
                    parse_bKGD_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
                case cHRM_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
                    parse_cHRM_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
                case gAMA_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
                    parse_gAMA_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
                case hIST_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
                    parse_hIST_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
                case iCCP_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
                    parse_iCCP_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
                case iTXt_TYPE:
43209
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   797
                    if (ignoreMetadata) {
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   798
                        stream.skipBytes(chunkLength);
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   799
                    } else {
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   800
                        parse_iTXt_chunk(chunkLength);
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   801
                    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
                case pHYs_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
                    parse_pHYs_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
                case sBIT_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
                    parse_sBIT_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
                case sPLT_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
                    parse_sPLT_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
                case sRGB_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
                    parse_sRGB_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
                case tEXt_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
                    parse_tEXt_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
                case tIME_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                    parse_tIME_chunk();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
                case tRNS_TYPE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
                    parse_tRNS_chunk(chunkLength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
                case zTXt_TYPE:
43209
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   825
                    if (ignoreMetadata) {
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   826
                        stream.skipBytes(chunkLength);
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   827
                    } else {
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   828
                        parse_zTXt_chunk(chunkLength);
98dd38700c36 8166988: Improve image processing performance
prr
parents: 41010
diff changeset
   829
                    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
                default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
                    // Read an unknown chunk
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
                    byte[] b = new byte[chunkLength];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                    stream.readFully(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
                    StringBuilder chunkName = new StringBuilder(4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
                    chunkName.append((char)(chunkType >>> 24));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
                    chunkName.append((char)((chunkType >> 16) & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
                    chunkName.append((char)((chunkType >> 8) & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
                    chunkName.append((char)(chunkType & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
                    int ancillaryBit = chunkType >>> 28;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
                    if (ancillaryBit == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
                        processWarningOccurred(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
"Encountered unknown chunk with critical bit set!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
                    metadata.unknownChunkType.add(chunkName.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
                    metadata.unknownChunkData.add(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
21218
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   853
                // double check whether all chunk data were consumed
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   854
                if (chunkCRC != stream.readInt()) {
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   855
                    throw new IIOException("Failed to read a chunk of type " +
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   856
                            chunkType);
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
   857
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
            throw new IIOException("Error reading PNG metadata", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
        gotMetadata = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
    // Data filtering methods
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
    private static void decodeSubFilter(byte[] curr, int coff, int count,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
                                        int bpp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
        for (int i = bpp; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
            int val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
            val = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
            val += curr[i + coff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
            curr[i + coff] = (byte)val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
    private static void decodeUpFilter(byte[] curr, int coff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
                                       byte[] prev, int poff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
                                       int count) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
        for (int i = 0; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
            int raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
            int prior = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
            curr[i + coff] = (byte)(raw + prior);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
    private static void decodeAverageFilter(byte[] curr, int coff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
                                            byte[] prev, int poff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
                                            int count, int bpp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
        int raw, priorPixel, priorRow;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
        for (int i = 0; i < bpp; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
            curr[i + coff] = (byte)(raw + priorRow/2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
        for (int i = bpp; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
            priorPixel = curr[i + coff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
            curr[i + coff] = (byte)(raw + (priorPixel + priorRow)/2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
    private static int paethPredictor(int a, int b, int c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
        int p = a + b - c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
        int pa = Math.abs(p - a);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        int pb = Math.abs(p - b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        int pc = Math.abs(p - c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
        if ((pa <= pb) && (pa <= pc)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
            return a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
        } else if (pb <= pc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
            return b;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
            return c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
    private static void decodePaethFilter(byte[] curr, int coff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
                                          byte[] prev, int poff,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
                                          int count, int bpp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
        int raw, priorPixel, priorRow, priorRowPixel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
        for (int i = 0; i < bpp; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
            curr[i + coff] = (byte)(raw + priorRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
        for (int i = bpp; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
            raw = curr[i + coff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
            priorPixel = curr[i + coff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
            priorRow = prev[i + poff] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
            priorRowPixel = prev[i + poff - bpp] & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
            curr[i + coff] = (byte)(raw + paethPredictor(priorPixel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
                                                         priorRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
                                                         priorRowPixel));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
    private static final int[][] bandOffsets = {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
        null,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
        { 0 }, // G
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
        { 0, 1 }, // GA in GA order
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
        { 0, 1, 2 }, // RGB in RGB order
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
        { 0, 1, 2, 3 } // RGBA in RGBA order
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
    };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
    private WritableRaster createRaster(int width, int height, int bands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
                                        int scanlineStride,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
                                        int bitDepth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
        DataBuffer dataBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
        WritableRaster ras = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
        Point origin = new Point(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
        if ((bitDepth < 8) && (bands == 1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
            dataBuffer = new DataBufferByte(height*scanlineStride);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
            ras = Raster.createPackedRaster(dataBuffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
                                            width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
                                            bitDepth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
                                            origin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
        } else if (bitDepth <= 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
            dataBuffer = new DataBufferByte(height*scanlineStride);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
            ras = Raster.createInterleavedRaster(dataBuffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
                                                 width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
                                                 scanlineStride,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
                                                 bands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                                                 bandOffsets[bands],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
                                                 origin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
            dataBuffer = new DataBufferUShort(height*scanlineStride);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
            ras = Raster.createInterleavedRaster(dataBuffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
                                                 width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
                                                 scanlineStride,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
                                                 bands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
                                                 bandOffsets[bands],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
                                                 origin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
        return ras;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
    private void skipPass(int passWidth, int passHeight)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
        throws IOException, IIOException  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
        if ((passWidth == 0) || (passHeight == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
        int inputBands = inputBandsForColorType[metadata.IHDR_colorType];
48645
6cfee3ad7a76 8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper
jdv
parents: 48641
diff changeset
  1000
        int bitsPerRow = Math.
6cfee3ad7a76 8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper
jdv
parents: 48641
diff changeset
  1001
                multiplyExact((inputBands * metadata.IHDR_bitDepth), passWidth);
6cfee3ad7a76 8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper
jdv
parents: 48641
diff changeset
  1002
        int bytesPerRow = (bitsPerRow + 7) / 8;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
        // Read the image row-by-row
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
        for (int srcY = 0; srcY < passHeight; srcY++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
            // Skip filter byte and the remaining row bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
            pixelStream.skipBytes(1 + bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
    private void updateImageProgress(int newPixels) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
        pixelsDone += newPixels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
        processImageProgress(100.0F*pixelsDone/totalPixels);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
    private void decodePass(int passNum,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
                            int xStart, int yStart,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
                            int xStep, int yStep,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                            int passWidth, int passHeight) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
        if ((passWidth == 0) || (passHeight == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
        WritableRaster imRas = theImage.getWritableTile(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
        int dstMinX = imRas.getMinX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
        int dstMaxX = dstMinX + imRas.getWidth() - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        int dstMinY = imRas.getMinY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
        int dstMaxY = dstMinY + imRas.getHeight() - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
        // Determine which pixels will be updated in this pass
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
        int[] vals =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
          ReaderUtil.computeUpdatedPixels(sourceRegion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
                                          destinationOffset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
                                          dstMinX, dstMinY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                                          dstMaxX, dstMaxY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
                                          sourceXSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
                                          sourceYSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
                                          xStart, yStart,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
                                          passWidth, passHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
                                          xStep, yStep);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
        int updateMinX = vals[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
        int updateMinY = vals[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
        int updateWidth = vals[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
        int updateXStep = vals[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
        int updateYStep = vals[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
        int bitDepth = metadata.IHDR_bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
        int inputBands = inputBandsForColorType[metadata.IHDR_colorType];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
        int bytesPerPixel = (bitDepth == 16) ? 2 : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
        bytesPerPixel *= inputBands;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
48645
6cfee3ad7a76 8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper
jdv
parents: 48641
diff changeset
  1053
        int bitsPerRow = Math.multiplyExact((inputBands * bitDepth), passWidth);
6cfee3ad7a76 8191174: PngReader throws IllegalArgumentException because ScanlineStride calculation logic is not proper
jdv
parents: 48641
diff changeset
  1054
        int bytesPerRow = (bitsPerRow + 7) / 8;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
        int eltsPerRow = (bitDepth == 16) ? bytesPerRow/2 : bytesPerRow;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
        // If no pixels need updating, just skip the input data
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
        if (updateWidth == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
            for (int srcY = 0; srcY < passHeight; srcY++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
                // Update count of pixels read
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
                updateImageProgress(passWidth);
41010
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1062
                /*
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1063
                 * If read has been aborted, just return
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1064
                 * processReadAborted will be called later
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1065
                 */
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1066
                if (abortRequested()) {
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1067
                    return;
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1068
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
                // Skip filter byte and the remaining row bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
                pixelStream.skipBytes(1 + bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
        // Backwards map from destination pixels
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
        // (dstX = updateMinX + k*updateXStep)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
        // to source pixels (sourceX), and then
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
        // to offset and skip in passRow (srcX and srcXStep)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
        int sourceX =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
            (updateMinX - destinationOffset.x)*sourceXSubsampling +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
            sourceRegion.x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
        int srcX = (sourceX - xStart)/xStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
        // Compute the step factor in the source
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
        int srcXStep = updateXStep*sourceXSubsampling/xStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
        byte[] byteData = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
        short[] shortData = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
        byte[] curr = new byte[bytesPerRow];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
        byte[] prior = new byte[bytesPerRow];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
        // Create a 1-row tall Raster to hold the data
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
        WritableRaster passRow = createRaster(passWidth, 1, inputBands,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
                                              eltsPerRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
                                              bitDepth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
        // Create an array suitable for holding one pixel
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
        int[] ps = passRow.getPixel(0, 0, (int[])null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
        DataBuffer dataBuffer = passRow.getDataBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
        int type = dataBuffer.getDataType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
        if (type == DataBuffer.TYPE_BYTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
            byteData = ((DataBufferByte)dataBuffer).getData();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
            shortData = ((DataBufferUShort)dataBuffer).getData();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
        processPassStarted(theImage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
                           passNum,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
                           sourceMinProgressivePass,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
                           sourceMaxProgressivePass,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
                           updateMinX, updateMinY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
                           updateXStep, updateYStep,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
                           destinationBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
        // Handle source and destination bands
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
        if (sourceBands != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
            passRow = passRow.createWritableChild(0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
                                                  passRow.getWidth(), 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
                                                  0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
                                                  sourceBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
        if (destinationBands != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
            imRas = imRas.createWritableChild(0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
                                              imRas.getWidth(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
                                              imRas.getHeight(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
                                              0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
                                              destinationBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
        // Determine if all of the relevant output bands have the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
        // same bit depth as the source data
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
        boolean adjustBitDepths = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
        int[] outputSampleSize = imRas.getSampleModel().getSampleSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
        int numBands = outputSampleSize.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
        for (int b = 0; b < numBands; b++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
            if (outputSampleSize[b] != bitDepth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
                adjustBitDepths = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
        // If the bit depths differ, create a lookup table per band to perform
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
        // the conversion
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
        int[][] scale = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
        if (adjustBitDepths) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
            int maxInSample = (1 << bitDepth) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
            int halfMaxInSample = maxInSample/2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
            scale = new int[numBands][];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
            for (int b = 0; b < numBands; b++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
                int maxOutSample = (1 << outputSampleSize[b]) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
                scale[b] = new int[maxInSample + 1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
                for (int s = 0; s <= maxInSample; s++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
                    scale[b][s] =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
                        (s*maxOutSample + halfMaxInSample)/maxInSample;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
        // Limit passRow to relevant area for the case where we
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
        // will can setRect to copy a contiguous span
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
        boolean useSetRect = srcXStep == 1 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
            updateXStep == 1 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
            !adjustBitDepths &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
            (imRas instanceof ByteInterleavedRaster);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
        if (useSetRect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
            passRow = passRow.createWritableChild(srcX, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
                                                  updateWidth, 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
                                                  0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
                                                  null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
        // Decode the (sub)image row-by-row
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
        for (int srcY = 0; srcY < passHeight; srcY++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
            // Update count of pixels read
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
            updateImageProgress(passWidth);
41010
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1178
            /*
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1179
             * If read has been aborted, just return
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1180
             * processReadAborted will be called later
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1181
             */
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1182
            if (abortRequested()) {
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1183
                return;
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1184
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
            // Read the filter type byte and a row of data
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
            int filter = pixelStream.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
                // Swap curr and prior
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
                byte[] tmp = prior;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
                prior = curr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
                curr = tmp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
                pixelStream.readFully(curr, 0, bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
            } catch (java.util.zip.ZipException ze) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
                // TODO - throw a more meaningful exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
                throw ze;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
            switch (filter) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
            case PNG_FILTER_NONE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
            case PNG_FILTER_SUB:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
                decodeSubFilter(curr, 0, bytesPerRow, bytesPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
            case PNG_FILTER_UP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
                decodeUpFilter(curr, 0, prior, 0, bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
            case PNG_FILTER_AVERAGE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
                decodeAverageFilter(curr, 0, prior, 0, bytesPerRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
                                    bytesPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
            case PNG_FILTER_PAETH:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
                decodePaethFilter(curr, 0, prior, 0, bytesPerRow,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
                                  bytesPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
                throw new IIOException("Unknown row filter type (= " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
                                       filter + ")!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
            // Copy data into passRow byte by byte
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
            if (bitDepth < 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
                System.arraycopy(curr, 0, byteData, 0, bytesPerRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
                int idx = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
                for (int j = 0; j < eltsPerRow; j++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
                    shortData[j] =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
                        (short)((curr[idx] << 8) | (curr[idx + 1] & 0xff));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
                    idx += 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
            // True Y position in source
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
            int sourceY = srcY*yStep + yStart;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
            if ((sourceY >= sourceRegion.y) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
                (sourceY < sourceRegion.y + sourceRegion.height) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
                (((sourceY - sourceRegion.y) %
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
                  sourceYSubsampling) == 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
                int dstY = destinationOffset.y +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
                    (sourceY - sourceRegion.y)/sourceYSubsampling;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
                if (dstY < dstMinY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
                    continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
                if (dstY > dstMaxY) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
                if (useSetRect) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
                    imRas.setRect(updateMinX, dstY, passRow);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
                    int newSrcX = srcX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
                    for (int dstX = updateMinX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
                         dstX < updateMinX + updateWidth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
                         dstX += updateXStep) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
                        passRow.getPixel(newSrcX, 0, ps);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
                        if (adjustBitDepths) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
                            for (int b = 0; b < numBands; b++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
                                ps[b] = scale[b][ps[b]];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
                        imRas.setPixel(dstX, dstY, ps);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
                        newSrcX += srcXStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
                processImageUpdate(theImage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
                                   updateMinX, dstY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
                                   updateWidth, 1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
                                   updateXStep, updateYStep,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
                                   destinationBands);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
        processPassComplete(theImage);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
    private void decodeImage()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
        throws IOException, IIOException  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
        int width = metadata.IHDR_width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
        int height = metadata.IHDR_height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
        this.pixelsDone = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
        this.totalPixels = width*height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
        if (metadata.IHDR_interlaceMethod == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
            decodePass(0, 0, 0, 1, 1, width, height);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
            for (int i = 0; i <= sourceMaxProgressivePass; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
                int XOffset = adam7XOffset[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
                int YOffset = adam7YOffset[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
                int XSubsampling = adam7XSubsampling[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
                int YSubsampling = adam7YSubsampling[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
                int xbump = adam7XSubsampling[i + 1] - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
                int ybump = adam7YSubsampling[i + 1] - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
                if (i >= sourceMinProgressivePass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
                    decodePass(i,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
                               XOffset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
                               YOffset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
                               XSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
                               YSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
                               (width + xbump)/XSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
                               (height + ybump)/YSubsampling);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
                    skipPass((width + xbump)/XSubsampling,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1309
                             (height + ybump)/YSubsampling);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1310
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1311
41010
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1312
                /*
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1313
                 * If read has been aborted, just return
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1314
                 * processReadAborted will be called later
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1315
                 */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
    private void readImage(ImageReadParam param) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
        readMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
        int width = metadata.IHDR_width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
        int height = metadata.IHDR_height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1328
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1329
        // Init default values
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1330
        sourceXSubsampling = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1331
        sourceYSubsampling = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1332
        sourceMinProgressivePass = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1333
        sourceMaxProgressivePass = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1334
        sourceBands = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1335
        destinationBands = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1336
        destinationOffset = new Point(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1337
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1338
        // If an ImageReadParam is available, get values from it
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1339
        if (param != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1340
            sourceXSubsampling = param.getSourceXSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1341
            sourceYSubsampling = param.getSourceYSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1342
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1343
            sourceMinProgressivePass =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1344
                Math.max(param.getSourceMinProgressivePass(), 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1345
            sourceMaxProgressivePass =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1346
                Math.min(param.getSourceMaxProgressivePass(), 6);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1347
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1348
            sourceBands = param.getSourceBands();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1349
            destinationBands = param.getDestinationBands();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1350
            destinationOffset = param.getDestinationOffset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1351
        }
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1352
        Inflater inf = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1353
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1354
            stream.seek(imageStartPosition);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1355
2376
63e13f6d2319 6782079: PNG: reading metadata may cause OOM on truncated images.
bae
parents: 1734
diff changeset
  1356
            Enumeration<InputStream> e = new PNGImageDataEnumeration(stream);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1357
            InputStream is = new SequenceInputStream(e);
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1358
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1359
           /* InflaterInputStream uses an Inflater instance which consumes
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1360
            * native (non-GC visible) resources. This is normally implicitly
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1361
            * freed when the stream is closed. However since the
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1362
            * InflaterInputStream wraps a client-supplied input stream,
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1363
            * we cannot close it.
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1364
            * 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
  1365
            * Therefore to ensure timely freeing of native resources we
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1366
            * explicitly create the Inflater instance and free its resources
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1367
            * when we are done with the InflaterInputStream by calling
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1368
            * inf.end();
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1369
            */
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1370
            inf = new Inflater();
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1371
            is = new InflaterInputStream(is, inf);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1372
            is = new BufferedInputStream(is);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1373
            this.pixelStream = new DataInputStream(is);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1374
21218
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
  1375
            /*
47962
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1376
             * PNG spec declares that valid range for width
21218
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
  1377
             * and height is [1, 2^31-1], so here we may fail to allocate
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
  1378
             * a buffer for destination image due to memory limitation.
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
  1379
             *
47962
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1380
             * If the read operation triggers OutOfMemoryError, the same
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1381
             * will be wrapped in an IIOException at PNGImageReader.read
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1382
             * method.
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1383
             *
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1384
             * The recovery strategy for this case should be defined at
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1385
             * the level of application, so we will not try to estimate
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1386
             * the required amount of the memory and/or handle OOM in
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1387
             * any way.
21218
42223d597a64 7058618: PNG parser bugs found via zzuf fuzzing
bae
parents: 5506
diff changeset
  1388
             */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1389
            theImage = getDestination(param,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1390
                                      getImageTypes(0),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1391
                                      width,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1392
                                      height);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1393
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1394
            Rectangle destRegion = new Rectangle(0, 0, 0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1395
            sourceRegion = new Rectangle(0, 0, 0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1396
            computeRegions(param, width, height,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1397
                           theImage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1398
                           sourceRegion, destRegion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1399
            destinationOffset.setLocation(destRegion.getLocation());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1400
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1401
            // At this point the header has been read and we know
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1402
            // how many bands are in the image, so perform checking
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1403
            // of the read param.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1404
            int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1405
            checkReadParamBandSettings(param,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1406
                                       inputBandsForColorType[colorType],
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1407
                                      theImage.getSampleModel().getNumBands());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1408
41010
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1409
            clearAbortRequest();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1410
            processImageStarted(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1411
            if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1412
                processReadAborted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1413
            } else {
41010
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1414
                decodeImage();
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1415
                if (abortRequested()) {
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1416
                    processReadAborted();
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1417
                } else {
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1418
                    processImageComplete();
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1419
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1420
            }
41010
9824689edeb1 4924727: reader.abort() method does not work when called inside imageStarted for PNG
jdv
parents: 25859
diff changeset
  1421
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1422
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1423
            throw new IIOException("Error reading PNG image data", e);
1715
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1424
        } finally {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1425
            if (inf != null) {
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1426
                inf.end();
349c53487e78 6687968: PNGImageReader leaks native memory through an Inflater.
bae
parents: 2
diff changeset
  1427
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1428
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1429
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1430
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1431
    public int getNumImages(boolean allowSearch) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1432
        if (stream == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1433
            throw new IllegalStateException("No input source set!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1434
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1435
        if (seekForwardOnly && allowSearch) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1436
            throw new IllegalStateException
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1437
                ("seekForwardOnly and allowSearch can't both be true!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1438
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1439
        return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1440
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1441
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1442
    public int getWidth(int imageIndex) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1443
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1444
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1445
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1446
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1447
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1448
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1449
        return metadata.IHDR_width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1450
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1451
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1452
    public int getHeight(int imageIndex) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1453
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1454
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1455
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1456
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1457
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1458
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1459
        return metadata.IHDR_height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1460
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1461
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1462
    public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1463
      throws IIOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1464
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1465
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1466
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1467
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1468
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1469
        readHeader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1470
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1471
        ArrayList<ImageTypeSpecifier> l =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1472
            new ArrayList<ImageTypeSpecifier>(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1473
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1474
        ColorSpace rgb;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1475
        ColorSpace gray;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1476
        int[] bandOffsets;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1477
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1478
        int bitDepth = metadata.IHDR_bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1479
        int colorType = metadata.IHDR_colorType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1480
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1481
        int dataType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1482
        if (bitDepth <= 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1483
            dataType = DataBuffer.TYPE_BYTE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1484
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1485
            dataType = DataBuffer.TYPE_USHORT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1486
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1487
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1488
        switch (colorType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1489
        case PNG_COLOR_GRAY:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1490
            // Packed grayscale
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1491
            l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1492
                                                     dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1493
                                                     false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1494
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1495
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1496
        case PNG_COLOR_RGB:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1497
            if (bitDepth == 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1498
                // some standard types of buffered images
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1499
                // which can be used as destination
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1500
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1501
                          BufferedImage.TYPE_3BYTE_BGR));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1502
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1503
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1504
                          BufferedImage.TYPE_INT_RGB));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1505
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1506
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1507
                          BufferedImage.TYPE_INT_BGR));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1508
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1509
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1510
            // Component R, G, B
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1511
            rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1512
            bandOffsets = new int[3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1513
            bandOffsets[0] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1514
            bandOffsets[1] = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1515
            bandOffsets[2] = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1516
            l.add(ImageTypeSpecifier.createInterleaved(rgb,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1517
                                                       bandOffsets,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1518
                                                       dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1519
                                                       false,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1520
                                                       false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1521
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1522
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1523
        case PNG_COLOR_PALETTE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1524
            readMetadata(); // Need tRNS chunk
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1525
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1526
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1527
             * The PLTE chunk spec says:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1528
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1529
             * The number of palette entries must not exceed the range that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1530
             * can be represented in the image bit depth (for example, 2^4 = 16
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1531
             * for a bit depth of 4). It is permissible to have fewer entries
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1532
             * than the bit depth would allow. In that case, any out-of-range
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1533
             * pixel value found in the image data is an error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1534
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1535
             * http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.PLTE
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1536
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1537
             * Consequently, the case when the palette length is smaller than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1538
             * 2^bitDepth is legal in the view of PNG spec.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1539
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1540
             * However the spec of createIndexed() method demands the exact
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1541
             * equality of the palette lengh and number of possible palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1542
             * entries (2^bitDepth).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1543
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1544
             * {@link javax.imageio.ImageTypeSpecifier.html#createIndexed}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1545
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1546
             * In order to avoid this contradiction we need to extend the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1547
             * palette arrays to the limit defined by the bitDepth.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1548
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1549
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1550
            int plength = 1 << bitDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1551
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1552
            byte[] red = metadata.PLTE_red;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1553
            byte[] green = metadata.PLTE_green;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1554
            byte[] blue = metadata.PLTE_blue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1555
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1556
            if (metadata.PLTE_red.length < plength) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1557
                red = Arrays.copyOf(metadata.PLTE_red, plength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1558
                Arrays.fill(red, metadata.PLTE_red.length, plength,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1559
                            metadata.PLTE_red[metadata.PLTE_red.length - 1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1560
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1561
                green = Arrays.copyOf(metadata.PLTE_green, plength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1562
                Arrays.fill(green, metadata.PLTE_green.length, plength,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1563
                            metadata.PLTE_green[metadata.PLTE_green.length - 1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1564
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1565
                blue = Arrays.copyOf(metadata.PLTE_blue, plength);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1566
                Arrays.fill(blue, metadata.PLTE_blue.length, plength,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1567
                            metadata.PLTE_blue[metadata.PLTE_blue.length - 1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1568
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1569
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1570
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1571
            // Alpha from tRNS chunk may have fewer entries than
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1572
            // the RGB LUTs from the PLTE chunk; if so, pad with
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1573
            // 255.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1574
            byte[] alpha = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1575
            if (metadata.tRNS_present && (metadata.tRNS_alpha != null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1576
                if (metadata.tRNS_alpha.length == red.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1577
                    alpha = metadata.tRNS_alpha;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1578
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1579
                    alpha = Arrays.copyOf(metadata.tRNS_alpha, red.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1580
                    Arrays.fill(alpha,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1581
                                metadata.tRNS_alpha.length,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1582
                                red.length, (byte)255);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1583
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1584
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1585
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1586
            l.add(ImageTypeSpecifier.createIndexed(red, green,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1587
                                                   blue, alpha,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1588
                                                   bitDepth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1589
                                                   DataBuffer.TYPE_BYTE));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1590
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1591
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1592
        case PNG_COLOR_GRAY_ALPHA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1593
            // Component G, A
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1594
            gray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1595
            bandOffsets = new int[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1596
            bandOffsets[0] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1597
            bandOffsets[1] = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1598
            l.add(ImageTypeSpecifier.createInterleaved(gray,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1599
                                                       bandOffsets,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1600
                                                       dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1601
                                                       true,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1602
                                                       false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1603
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1604
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1605
        case PNG_COLOR_RGB_ALPHA:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1606
            if (bitDepth == 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1607
                // some standard types of buffered images
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1608
                // wich can be used as destination
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1609
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1610
                          BufferedImage.TYPE_4BYTE_ABGR));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1611
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1612
                l.add(ImageTypeSpecifier.createFromBufferedImageType(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1613
                          BufferedImage.TYPE_INT_ARGB));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1614
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1615
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1616
            // Component R, G, B, A (non-premultiplied)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1617
            rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1618
            bandOffsets = new int[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1619
            bandOffsets[0] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1620
            bandOffsets[1] = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1621
            bandOffsets[2] = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1622
            bandOffsets[3] = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1623
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1624
            l.add(ImageTypeSpecifier.createInterleaved(rgb,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1625
                                                       bandOffsets,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1626
                                                       dataType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1627
                                                       true,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1628
                                                       false));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1629
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1630
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1631
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1632
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1633
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1634
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1635
        return l.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1636
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1637
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1638
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1639
     * Super class implementation uses first element
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1640
     * of image types list as raw image type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1641
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1642
     * Also, super implementation uses first element of this list
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1643
     * as default destination type image read param does not specify
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1644
     * anything other.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1645
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1646
     * However, in case of RGB and RGBA color types, raw image type
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1647
     * produces buffered image of custom type. It causes some
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1648
     * performance degradation of subsequent rendering operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1649
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1650
     * To resolve this contradiction we put standard image types
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1651
     * at the first positions of image types list (to produce standard
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1652
     * images by default) and put raw image type (which is custom)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1653
     * at the last position of this list.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1654
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1655
     * After this changes we should override getRawImageType()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1656
     * to return last element of image types list.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1657
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1658
    public ImageTypeSpecifier getRawImageType(int imageIndex)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1659
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1660
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1661
        Iterator<ImageTypeSpecifier> types = getImageTypes(imageIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1662
        ImageTypeSpecifier raw = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1663
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1664
            raw = types.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1665
        } while (types.hasNext());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1666
        return raw;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1667
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1668
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1669
    public ImageReadParam getDefaultReadParam() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1670
        return new ImageReadParam();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1671
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1672
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1673
    public IIOMetadata getStreamMetadata()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1674
        throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1675
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1676
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1677
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1678
    public IIOMetadata getImageMetadata(int imageIndex) throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1679
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1680
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1681
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1682
        readMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1683
        return metadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1684
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1685
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1686
    public BufferedImage read(int imageIndex, ImageReadParam param)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1687
        throws IIOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1688
        if (imageIndex != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1689
            throw new IndexOutOfBoundsException("imageIndex != 0!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1690
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1691
47962
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1692
        try {
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1693
            readImage(param);
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1694
        } catch (IOException |
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1695
                 IllegalStateException |
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1696
                 IllegalArgumentException e)
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1697
        {
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1698
            throw e;
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1699
        } catch (Throwable e) {
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1700
            throw new IIOException("Caught exception during read: ", e);
99000fb68d0e 8190332: PngReader throws NegativeArraySizeException/OOM error when IHDR width is very large
jdv
parents: 47836
diff changeset
  1701
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1702
        return theImage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1703
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1704
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1705
    public void reset() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1706
        super.reset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1707
        resetStreamSettings();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1708
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1709
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1710
    private void resetStreamSettings() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1711
        gotHeader = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1712
        gotMetadata = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1713
        metadata = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1714
        pixelStream = null;
47972
18dbd2ae7eca 8191431: Reading multiple PNG images with unique IDAT chunk positions will cause IIOException
jdv
parents: 47962
diff changeset
  1715
        imageStartPosition = -1L;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1716
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1717
}