/* * $Id$ * * Copyright (c) 2008-2009 by Joel Uckelman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.tools.image; import java.io.DataInputStream; import java.io.IOException; /** * A (partial) PNG decoder. * * @author Joel Uckelman * @since 3.1.0 */ class PNGDecoder { protected PNGDecoder() {} // critical chunks static final int IHDR = 0x49484452; static final int PLTE = 0x504c5445; static final int IDAT = 0x49444154; static final int IEND = 0x49454e44; // ancillary chunks static final int bKGD = 0x624b4744; static final int cHRM = 0x6348524d; static final int gAMA = 0x67414d41; static final int hIST = 0x68495354; static final int iCCP = 0x69434350; static final int iTXt = 0x69545874; static final int pHYs = 0x70485973; static final int sBIT = 0x73424954; static final int sPLT = 0x73504c54; static final int sRGB = 0x73524742; static final int tEXt = 0x74455874; static final int tIME = 0x74494d45; static final int tRNS = 0x74524e53; static final int zTXt = 0x7a545874; static final long sig = 0x89504e470d0a1a0aL; public static boolean decodeSignature(DataInputStream in) throws IOException { // 5.2 return in.readLong() == sig; } public static Chunk decodeChunk(DataInputStream in) throws IOException { // 5.3 final int length = in.readInt(); // Length should not exceed 2^31-1. Since ints are signed, any value // greater than 2^31-1 will look negative to us. if (length < 0) { throw new IOException("chunk length out of range"); } final int type = in.readInt(); final byte[] data = new byte[length]; in.readFully(data); final long crc = in.readInt() & 0x0000000ffffffffL; /* final CRC32 crc32 = new CRC32(); crc32.update(type); crc32.update(data); if (crc != crc32.getValue()) throw new IOException("corrupted " + type + " chunk"); */ return new Chunk(type, data, crc); } public static class Chunk { public final int type; public final byte[] data; public final long crc; private Chunk(int type, byte[] data, long crc) { this.type = type; this.data = data; this.crc = crc; } } }