/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.imaging.formats.png;

import static org.apache.commons.imaging.common.BinaryFunctions.printCharQuad;
import static org.apache.commons.imaging.common.BinaryFunctions.read4Bytes;
import static org.apache.commons.imaging.common.BinaryFunctions.readAndVerifyBytes;
import static org.apache.commons.imaging.common.BinaryFunctions.readBytes;
import static org.apache.commons.imaging.common.BinaryFunctions.skipBytes;

import java.awt.Dimension;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.InflaterInputStream;

import org.apache.commons.imaging.ColorTools;
import org.apache.commons.imaging.ImageFormat;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImageInfo;
import org.apache.commons.imaging.ImageParser;
import org.apache.commons.imaging.ImagingException;
import org.apache.commons.imaging.bytesource.ByteSource;
import org.apache.commons.imaging.common.Allocator;
import org.apache.commons.imaging.common.GenericImageMetadata;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.common.XmpEmbeddable;
import org.apache.commons.imaging.common.XmpImagingParameters;
import org.apache.commons.imaging.formats.png.chunks.PngChunk;
import org.apache.commons.imaging.formats.png.chunks.PngChunkGama;
import org.apache.commons.imaging.formats.png.chunks.PngChunkIccp;
import org.apache.commons.imaging.formats.png.chunks.PngChunkIdat;
import org.apache.commons.imaging.formats.png.chunks.PngChunkIhdr;
import org.apache.commons.imaging.formats.png.chunks.PngChunkItxt;
import org.apache.commons.imaging.formats.png.chunks.PngChunkPhys;
import org.apache.commons.imaging.formats.png.chunks.PngChunkPlte;
import org.apache.commons.imaging.formats.png.chunks.PngChunkScal;
import org.apache.commons.imaging.formats.png.chunks.PngChunkText;
import org.apache.commons.imaging.formats.png.chunks.PngChunkZtxt;
import org.apache.commons.imaging.formats.png.chunks.PngTextChunk;
import org.apache.commons.imaging.formats.png.transparencyfilters.TransparencyFilter;
import org.apache.commons.imaging.formats.png.transparencyfilters.TransparencyFilterGrayscale;
import org.apache.commons.imaging.formats.png.transparencyfilters.TransparencyFilterIndexedColor;
import org.apache.commons.imaging.formats.png.transparencyfilters.TransparencyFilterTrueColor;
import org.apache.commons.imaging.icc.IccProfileParser;

public class PngImageParser extends ImageParser<PngImagingParameters>  implements XmpEmbeddable<PngImagingParameters> {

    private static final Logger LOGGER = Logger.getLogger(PngImageParser.class.getName());

    private static final String DEFAULT_EXTENSION = ImageFormats.PNG.getDefaultExtension();
    private static final String[] ACCEPTED_EXTENSIONS = ImageFormats.PNG.getExtensions();

    public static String getChunkTypeName(final int chunkType) {
        final StringBuilder result = new StringBuilder();
        result.append((char) (0xff & (chunkType >> 24)));
        result.append((char) (0xff & (chunkType >> 16)));
        result.append((char) (0xff & (chunkType >> 8)));
        result.append((char) (0xff & (chunkType >> 0)));
        return result.toString();
    }

    @Override
    public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource)
            throws ImagingException, IOException {
        final ImageInfo imageInfo = getImageInfo(byteSource);
        if (imageInfo == null) {
            return false;
        }

        imageInfo.toString(pw, "");

        final List<PngChunk> chunks = readChunks(byteSource, null, false);
        final List<PngChunk> IHDRs = filterChunks(chunks, ChunkType.IHDR);
        if (IHDRs.size() != 1) {
            if (LOGGER.isLoggable(Level.FINEST)) {
                LOGGER.finest("PNG contains more than one Header");
            }
            return false;
        }
        final PngChunkIhdr pngChunkIHDR = (PngChunkIhdr) IHDRs.get(0);
        pw.println("Color: " + pngChunkIHDR.getPngColorType().name());

        pw.println("chunks: " + chunks.size());

        if ((chunks.isEmpty())) {
            return false;
        }

        for (int i = 0; i < chunks.size(); i++) {
            final PngChunk chunk = chunks.get(i);
            printCharQuad(pw, "\t" + i + ": ", chunk.getChunkType());
        }

        pw.println("");

        pw.flush();

        return true;
    }

    private List<PngChunk> filterChunks(final List<PngChunk> chunks, final ChunkType type) {
        final List<PngChunk> result = new ArrayList<>();

        for (final PngChunk chunk : chunks) {
            if (chunk.getChunkType() == type.value) {
                result.add(chunk);
            }
        }

        return result;
    }

    @Override
    protected String[] getAcceptedExtensions() {
        return ACCEPTED_EXTENSIONS.clone();
    }

    @Override
    protected ImageFormat[] getAcceptedTypes() {
        return new ImageFormat[] { ImageFormats.PNG, //
        };
    }

    // private final static int tRNS = CharsToQuad('t', 'R', 'N', 's');

    @Override
    public BufferedImage getBufferedImage(final ByteSource byteSource, final PngImagingParameters params)
            throws ImagingException, IOException {

        final List<PngChunk> chunks = readChunks(byteSource, new ChunkType[] {
                ChunkType.IHDR,
                ChunkType.PLTE,
                ChunkType.IDAT,
                ChunkType.tRNS,
                ChunkType.iCCP,
                ChunkType.gAMA,
                ChunkType.sRGB,
            }, false);

        if (chunks.isEmpty()) {
            throw new ImagingException("PNG: no chunks");
        }

        final List<PngChunk> IHDRs = filterChunks(chunks, ChunkType.IHDR);
        if (IHDRs.size() != 1) {
            throw new ImagingException("PNG contains more than one Header");
        }

        final PngChunkIhdr pngChunkIHDR = (PngChunkIhdr) IHDRs.get(0);

        final List<PngChunk> PLTEs = filterChunks(chunks, ChunkType.PLTE);
        if (PLTEs.size() > 1) {
            throw new ImagingException("PNG contains more than one Palette");
        }

        PngChunkPlte pngChunkPLTE = null;
        if (PLTEs.size() == 1) {
            pngChunkPLTE = (PngChunkPlte) PLTEs.get(0);
        }

        final List<PngChunk> IDATs = filterChunks(chunks, ChunkType.IDAT);
        if (IDATs.isEmpty()) {
            throw new ImagingException("PNG missing image data");
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (final PngChunk IDAT : IDATs) {
            final PngChunkIdat pngChunkIDAT = (PngChunkIdat) IDAT;
            final byte[] bytes = pngChunkIDAT.getBytes();
            // System.out.println(i + ": bytes: " + bytes.length);
            baos.write(bytes);
        }

        final byte[] compressed = baos.toByteArray();

        baos = null;

        TransparencyFilter transparencyFilter = null;

        final List<PngChunk> tRNSs = filterChunks(chunks, ChunkType.tRNS);
        if (!tRNSs.isEmpty()) {
            final PngChunk pngChunktRNS = tRNSs.get(0);
            transparencyFilter = getTransparencyFilter(pngChunkIHDR.getPngColorType(), pngChunktRNS);
        }

        ICC_Profile iccProfile = null;
        GammaCorrection gammaCorrection = null;
        {
            final List<PngChunk> sRGBs = filterChunks(chunks, ChunkType.sRGB);
            final List<PngChunk> gAMAs = filterChunks(chunks, ChunkType.gAMA);
            final List<PngChunk> iCCPs = filterChunks(chunks, ChunkType.iCCP);
            if (sRGBs.size() > 1) {
                throw new ImagingException("PNG: unexpected sRGB chunk");
            }
            if (gAMAs.size() > 1) {
                throw new ImagingException("PNG: unexpected gAMA chunk");
            }
            if (iCCPs.size() > 1) {
                throw new ImagingException("PNG: unexpected iCCP chunk");
            }

            if (sRGBs.size() == 1) {
                // no color management necessary.
                if (LOGGER.isLoggable(Level.FINEST)) {
                    LOGGER.finest("sRGB, no color management necessary.");
                }
            } else if (iCCPs.size() == 1) {
                if (LOGGER.isLoggable(Level.FINEST)) {
                    LOGGER.finest("iCCP.");
                }

                final PngChunkIccp pngChunkiCCP = (PngChunkIccp) iCCPs.get(0);
                final byte[] bytes = pngChunkiCCP.getUncompressedProfile();

                try {
                    iccProfile = ICC_Profile.getInstance(bytes);
                } catch (final IllegalArgumentException iae) {
                    throw new ImagingException("The image data does not correspond to a valid ICC Profile", iae);
                }
            } else if (gAMAs.size() == 1) {
                final PngChunkGama pngChunkgAMA = (PngChunkGama) gAMAs.get(0);
                final double gamma = pngChunkgAMA.getGamma();

                // charles: what is the correct target value here?
                // double targetGamma = 2.2;
                final double targetGamma = 1.0;
                final double diff = Math.abs(targetGamma - gamma);
                if (diff >= 0.5) {
                    gammaCorrection = new GammaCorrection(gamma, targetGamma);
                }

                if (gammaCorrection != null) {
                    if (pngChunkPLTE != null) {
                        pngChunkPLTE.correct(gammaCorrection);
                    }
                }

            }
        }

        {
            final int width = pngChunkIHDR.getWidth();
            final int height = pngChunkIHDR.getHeight();
            final PngColorType pngColorType = pngChunkIHDR.getPngColorType();
            final int bitDepth = pngChunkIHDR.getBitDepth();

            if (pngChunkIHDR.getFilterMethod() != 0) {
                throw new ImagingException("PNG: unknown FilterMethod: " + pngChunkIHDR.getFilterMethod());
            }

            final int bitsPerPixel = bitDepth * pngColorType.getSamplesPerPixel();

            final boolean hasAlpha = pngColorType.hasAlpha() || transparencyFilter != null;

            BufferedImage result;
            if (pngColorType.isGreyscale()) {
                result = getBufferedImageFactory(params).getGrayscaleBufferedImage(width, height, hasAlpha);
            } else {
                result = getBufferedImageFactory(params).getColorBufferedImage(width, height, hasAlpha);
            }

            final ByteArrayInputStream bais = new ByteArrayInputStream(compressed);
            final InflaterInputStream iis = new InflaterInputStream(bais);

            ScanExpediter scanExpediter;

            switch (pngChunkIHDR.getInterlaceMethod()) {
                case NONE:
                    scanExpediter = new ScanExpediterSimple(width, height, iis,
                            result, pngColorType, bitDepth, bitsPerPixel,
                            pngChunkPLTE, gammaCorrection, transparencyFilter);
                    break;
                case ADAM7:
                    scanExpediter = new ScanExpediterInterlaced(width, height, iis,
                            result, pngColorType, bitDepth, bitsPerPixel,
                            pngChunkPLTE, gammaCorrection, transparencyFilter);
                    break;
                default:
                    throw new ImagingException("Unknown InterlaceMethod: " + pngChunkIHDR.getInterlaceMethod());
            }

            scanExpediter.drive();

            if (iccProfile != null) {
                final boolean is_srgb = new IccProfileParser().issRGB(iccProfile);
                if (!is_srgb) {
                    final ICC_ColorSpace cs = new ICC_ColorSpace(iccProfile);

                    final ColorModel srgbCM = ColorModel.getRGBdefault();
                    final ColorSpace cs_sRGB = srgbCM.getColorSpace();

                    result = new ColorTools().convertBetweenColorSpaces(result, cs, cs_sRGB);
                }
            }

            return result;

        }

    }

    /**
     * @param is PNG image input stream
     * @return List of String-formatted chunk types, ie. "tRNs".
     * @throws ImagingException if it fail to read the PNG chunks
     * @throws IOException if it fails to read the input stream data
     */
    public List<String> getChunkTypes(final InputStream is)
            throws ImagingException, IOException {
        final List<PngChunk> chunks = readChunks(is, null, false);
        final List<String> chunkTypes = Allocator.arrayList(chunks.size());
        for (final PngChunk chunk : chunks) {
            chunkTypes.add(getChunkTypeName(chunk.getChunkType()));
        }
        return chunkTypes;
    }

    @Override
    public String getDefaultExtension() {
        return DEFAULT_EXTENSION;
    }

    @Override
    public PngImagingParameters getDefaultParameters() {
        return new PngImagingParameters();
    }

    @Override
    public byte[] getICCProfileBytes(final ByteSource byteSource, final PngImagingParameters params)
            throws ImagingException, IOException {
        final List<PngChunk> chunks = readChunks(byteSource, new ChunkType[] { ChunkType.iCCP },
                true);

        if (chunks.isEmpty()) {
            return null;
        }

        if (chunks.size() > 1) {
            throw new ImagingException(
                    "PNG contains more than one ICC Profile ");
        }

        final PngChunkIccp pngChunkiCCP = (PngChunkIccp) chunks.get(0);

        return (pngChunkiCCP.getUncompressedProfile());// TODO should this be a clone?
    }

    @Override
    public ImageInfo getImageInfo(final ByteSource byteSource, final PngImagingParameters params)
            throws ImagingException, IOException {
        final List<PngChunk> chunks = readChunks(byteSource, new ChunkType[] {
                ChunkType.IHDR,
                ChunkType.pHYs,
                ChunkType.sCAL,
                ChunkType.tEXt,
                ChunkType.zTXt,
                ChunkType.tRNS,
                ChunkType.PLTE,
                ChunkType.iTXt,
            }, false);

        if (chunks.isEmpty()) {
            throw new ImagingException("PNG: no chunks");
        }

        final List<PngChunk> IHDRs = filterChunks(chunks, ChunkType.IHDR);
        if (IHDRs.size() != 1) {
            throw new ImagingException("PNG contains more than one Header");
        }

        final PngChunkIhdr pngChunkIHDR = (PngChunkIhdr) IHDRs.get(0);

        boolean transparent = false;

        final List<PngChunk> tRNSs = filterChunks(chunks, ChunkType.tRNS);
        if (!tRNSs.isEmpty()) {
            transparent = true;
        } else {
            // CE - Fix Alpha.
            transparent = pngChunkIHDR.getPngColorType().hasAlpha();
            // END FIX
        }

        PngChunkPhys pngChunkpHYs = null;

        final List<PngChunk> pHYss = filterChunks(chunks, ChunkType.pHYs);
        if (pHYss.size() > 1) {
            throw new ImagingException("PNG contains more than one pHYs: "
                    + pHYss.size());
        }
        if (pHYss.size() == 1) {
            pngChunkpHYs = (PngChunkPhys) pHYss.get(0);
        }

        PhysicalScale physicalScale = PhysicalScale.UNDEFINED;

        final List<PngChunk> sCALs = filterChunks(chunks, ChunkType.sCAL);
        if (sCALs.size() > 1) {
            throw new ImagingException("PNG contains more than one sCAL:"
                    + sCALs.size());
        }
        if (sCALs.size() == 1) {
            final PngChunkScal pngChunkScal = (PngChunkScal) sCALs.get(0);
            if (pngChunkScal.getUnitSpecifier() == 1) {
                physicalScale = PhysicalScale.createFromMeters(pngChunkScal.getUnitsPerPixelXAxis(),
                      pngChunkScal.getUnitsPerPixelYAxis());
            } else {
                physicalScale = PhysicalScale.createFromRadians(pngChunkScal.getUnitsPerPixelXAxis(),
                      pngChunkScal.getUnitsPerPixelYAxis());
            }
        }

        final List<PngChunk> tEXts = filterChunks(chunks, ChunkType.tEXt);
        final List<PngChunk> zTXts = filterChunks(chunks, ChunkType.zTXt);
        final List<PngChunk> iTXts = filterChunks(chunks, ChunkType.iTXt);

        final int chunkCount = tEXts.size() + zTXts.size() + iTXts.size();
        final List<String> comments = Allocator.arrayList(chunkCount);
        final List<PngText> textChunks = Allocator.arrayList(chunkCount);

        for (final PngChunk tEXt : tEXts) {
            final PngChunkText pngChunktEXt = (PngChunkText) tEXt;
            comments.add(pngChunktEXt.getKeyword() + ": " + pngChunktEXt.getText());
            textChunks.add(pngChunktEXt.getContents());
        }
        for (final PngChunk zTXt : zTXts) {
            final PngChunkZtxt pngChunkzTXt = (PngChunkZtxt) zTXt;
            comments.add(pngChunkzTXt.getKeyword() + ": " + pngChunkzTXt.getText());
            textChunks.add(pngChunkzTXt.getContents());
        }
        for (final PngChunk iTXt : iTXts) {
            final PngChunkItxt pngChunkiTXt = (PngChunkItxt) iTXt;
            comments.add(pngChunkiTXt.getKeyword() + ": " + pngChunkiTXt.getText());
            textChunks.add(pngChunkiTXt.getContents());
        }

        final int bitsPerPixel = pngChunkIHDR.getBitDepth() * pngChunkIHDR.getPngColorType().getSamplesPerPixel();
        final ImageFormat format = ImageFormats.PNG;
        final String formatName = "PNG Portable Network Graphics";
        final int height = pngChunkIHDR.getHeight();
        final String mimeType = "image/png";
        final int numberOfImages = 1;
        final int width = pngChunkIHDR.getWidth();
        final boolean progressive = pngChunkIHDR.getInterlaceMethod().isProgressive();

        int physicalHeightDpi = -1;
        float physicalHeightInch = -1;
        int physicalWidthDpi = -1;
        float physicalWidthInch = -1;

        // if (pngChunkpHYs != null)
        // {
        // System.out.println("\t" + "pngChunkpHYs.UnitSpecifier: " +
        // pngChunkpHYs.UnitSpecifier );
        // System.out.println("\t" + "pngChunkpHYs.PixelsPerUnitYAxis: " +
        // pngChunkpHYs.PixelsPerUnitYAxis );
        // System.out.println("\t" + "pngChunkpHYs.PixelsPerUnitXAxis: " +
        // pngChunkpHYs.PixelsPerUnitXAxis );
        // }
        if ((pngChunkpHYs != null) && (pngChunkpHYs.getUnitSpecifier() == 1)) { // meters
            final double metersPerInch = 0.0254;

            physicalWidthDpi = (int) Math.round(pngChunkpHYs.getPixelsPerUnitXAxis() * metersPerInch);
            physicalWidthInch = (float) (width / (pngChunkpHYs.getPixelsPerUnitXAxis() * metersPerInch));
            physicalHeightDpi = (int) Math.round(pngChunkpHYs.getPixelsPerUnitYAxis() * metersPerInch);
            physicalHeightInch = (float) (height / (pngChunkpHYs.getPixelsPerUnitYAxis() * metersPerInch));
        }

        boolean usesPalette = false;

        final List<PngChunk> PLTEs = filterChunks(chunks, ChunkType.PLTE);
        if (!PLTEs.isEmpty()) {
            usesPalette = true;
        }

        ImageInfo.ColorType colorType;
        switch (pngChunkIHDR.getPngColorType()) {
            case GREYSCALE:
            case GREYSCALE_WITH_ALPHA:
                colorType = ImageInfo.ColorType.GRAYSCALE;
                break;
            case TRUE_COLOR:
            case INDEXED_COLOR:
            case TRUE_COLOR_WITH_ALPHA:
                colorType = ImageInfo.ColorType.RGB;
                break;
            default:
                throw new ImagingException("Png: Unknown ColorType: " + pngChunkIHDR.getPngColorType());
        }

        final String formatDetails = "Png";
        final ImageInfo.CompressionAlgorithm compressionAlgorithm = ImageInfo.CompressionAlgorithm.PNG_FILTER;

        return new PngImageInfo(formatDetails, bitsPerPixel, comments,
                format, formatName, height, mimeType, numberOfImages,
                physicalHeightDpi, physicalHeightInch, physicalWidthDpi,
                physicalWidthInch, width, progressive, transparent,
                usesPalette, colorType, compressionAlgorithm, textChunks,
                physicalScale);
    }

    @Override
    public Dimension getImageSize(final ByteSource byteSource, final PngImagingParameters params)
            throws ImagingException, IOException {
        final List<PngChunk> chunks = readChunks(byteSource, new ChunkType[] { ChunkType.IHDR, }, true);

        if (chunks.isEmpty()) {
            throw new ImagingException("Png: No chunks");
        }

        if (chunks.size() > 1) {
            throw new ImagingException("PNG contains more than one Header");
        }

        final PngChunkIhdr pngChunkIHDR = (PngChunkIhdr) chunks.get(0);

        return new Dimension(pngChunkIHDR.getWidth(), pngChunkIHDR.getHeight());
    }

    @Override
    public ImageMetadata getMetadata(final ByteSource byteSource, final PngImagingParameters params)
            throws ImagingException, IOException {
        final List<PngChunk> chunks = readChunks(byteSource, new ChunkType[] { ChunkType.tEXt, ChunkType.zTXt, ChunkType.iTXt }, false);

        if (chunks.isEmpty()) {
            return null;
        }

        final GenericImageMetadata result = new GenericImageMetadata();

        for (final PngChunk chunk : chunks) {
            final PngTextChunk textChunk = (PngTextChunk) chunk;

            result.add(textChunk.getKeyword(), textChunk.getText());
        }

        return result;
    }

    @Override
    public String getName() {
        return "Png-Custom";
    }

    private TransparencyFilter getTransparencyFilter(final PngColorType pngColorType, final PngChunk pngChunktRNS)
            throws ImagingException, IOException {
        switch (pngColorType) {
            case GREYSCALE: // 1,2,4,8,16 Each pixel is a grayscale sample.
                return new TransparencyFilterGrayscale(pngChunktRNS.getBytes());
            case TRUE_COLOR: // 8,16 Each pixel is an R,G,B triple.
                return new TransparencyFilterTrueColor(pngChunktRNS.getBytes());
            case INDEXED_COLOR: // 1,2,4,8 Each pixel is a palette index;
                return new TransparencyFilterIndexedColor(pngChunktRNS.getBytes());
            case GREYSCALE_WITH_ALPHA: // 8,16 Each pixel is a grayscale sample,
            case TRUE_COLOR_WITH_ALPHA: // 8,16 Each pixel is an R,G,B triple,
            default:
                throw new ImagingException("Simple Transparency not compatible with ColorType: " + pngColorType);
        }
    }

    @Override
    public String getXmpXml(final ByteSource byteSource, final XmpImagingParameters<PngImagingParameters> params)
            throws ImagingException, IOException {

        final List<PngChunk> chunks = readChunks(byteSource, new ChunkType[] { ChunkType.iTXt }, false);

        if (chunks.isEmpty()) {
            return null;
        }

        final List<PngChunkItxt> xmpChunks = new ArrayList<>();
        for (final PngChunk chunk : chunks) {
            final PngChunkItxt itxtChunk = (PngChunkItxt) chunk;
            if (!itxtChunk.getKeyword().equals(PngConstants.XMP_KEYWORD)) {
                continue;
            }
            xmpChunks.add(itxtChunk);
        }

        if (xmpChunks.isEmpty()) {
            return null;
        }
        if (xmpChunks.size() > 1) {
            throw new ImagingException(
                    "PNG contains more than one XMP chunk.");
        }

        final PngChunkItxt chunk = xmpChunks.get(0);
        return chunk.getText();
    }

    // TODO: I have been too casual about making inner classes subclass of
    // BinaryFileParser
    // I may not have always preserved byte order correctly.

    public boolean hasChunkType(final ByteSource byteSource, final ChunkType chunkType)
            throws ImagingException, IOException {
        try (InputStream is = byteSource.getInputStream()) {
            readSignature(is);
            final List<PngChunk> chunks = readChunks(is, new ChunkType[] { chunkType }, true);
            return !chunks.isEmpty();
        }
    }

    private boolean keepChunk(final int chunkType, final ChunkType[] chunkTypes) {
        // System.out.println("keepChunk: ");
        if (chunkTypes == null) {
            return true;
        }

        for (final ChunkType chunkType2 : chunkTypes) {
            if (chunkType2.value == chunkType) {
                return true;
            }
        }
        return false;
    }

    private List<PngChunk> readChunks(final ByteSource byteSource, final ChunkType[] chunkTypes,
            final boolean returnAfterFirst) throws ImagingException, IOException {
        try (InputStream is = byteSource.getInputStream()) {
            readSignature(is);
            return readChunks(is, chunkTypes, returnAfterFirst);
        }
    }

    private List<PngChunk> readChunks(final InputStream is, final ChunkType[] chunkTypes,
            final boolean returnAfterFirst) throws ImagingException, IOException {
        final List<PngChunk> result = new ArrayList<>();

        while (true) {
            final int length = read4Bytes("Length", is, "Not a Valid PNG File", getByteOrder());
            if (length < 0) {
                throw new ImagingException("Invalid PNG chunk length: " + length);
            }
            final int chunkType = read4Bytes("ChunkType", is, "Not a Valid PNG File", getByteOrder());

            if (LOGGER.isLoggable(Level.FINEST)) {
                printCharQuad("ChunkType", chunkType);
                debugNumber("Length", length, 4);
            }
            final boolean keep = keepChunk(chunkType, chunkTypes);

            byte[] bytes = null;
            if (keep) {
                bytes = readBytes("Chunk Data", is, length,
                        "Not a Valid PNG File: Couldn't read Chunk Data.");
            } else {
                skipBytes(is, length, "Not a Valid PNG File");
            }

            if (LOGGER.isLoggable(Level.FINEST)) {
                if (bytes != null) {
                    debugNumber("bytes", bytes.length, 4);
                }
            }

            final int crc = read4Bytes("CRC", is, "Not a Valid PNG File", getByteOrder());

            if (keep) {
                if (chunkType == ChunkType.iCCP.value) {
                    result.add(new PngChunkIccp(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.tEXt.value) {
                    result.add(new PngChunkText(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.zTXt.value) {
                    result.add(new PngChunkZtxt(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.IHDR.value) {
                    result.add(new PngChunkIhdr(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.PLTE.value) {
                    result.add(new PngChunkPlte(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.pHYs.value) {
                    result.add(new PngChunkPhys(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.sCAL.value) {
                    result.add(new PngChunkScal(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.IDAT.value) {
                    result.add(new PngChunkIdat(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.gAMA.value) {
                    result.add(new PngChunkGama(length, chunkType, crc, bytes));
                } else if (chunkType == ChunkType.iTXt.value) {
                    result.add(new PngChunkItxt(length, chunkType, crc, bytes));
                } else {
                    result.add(new PngChunk(length, chunkType, crc, bytes));
                }

                if (returnAfterFirst) {
                    return result;
                }
            }

            if (chunkType == ChunkType.IEND.value) {
                break;
            }

        }

        return result;

    }

    public void readSignature(final InputStream is) throws ImagingException,
            IOException {
        readAndVerifyBytes(is, PngConstants.PNG_SIGNATURE,
                "Not a Valid PNG Segment: Incorrect Signature");

    }

    @Override
    public void writeImage(final BufferedImage src, final OutputStream os, final PngImagingParameters params)
            throws ImagingException, IOException {
        new PngWriter().writeImage(src, os, params, null);
    }

}
