public BufferedImage getBufferedImage()

in src/main/java/org/apache/commons/imaging/formats/png/PngImageParser.java [681:856]


    public BufferedImage getBufferedImage(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        boolean verbose = ParamMap.getParamBoolean(params, PARAM_KEY_VERBOSE,
                false);

        if (params.containsKey(PARAM_KEY_VERBOSE))
            params.remove(PARAM_KEY_VERBOSE);

        // if (params.size() > 0) {
        // Object firstKey = params.keySet().iterator().next();
        // throw new ImageWriteException("Unknown parameter: " + firstKey);
        // }

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

        if ((chunks == null) || (chunks.size() < 1))
            throw new ImageReadException("PNG: no chunks");

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

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

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

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

        // -----

        List<PngChunk> IDATs = filterChunks(chunks, IDAT);
        if (IDATs.size() < 1)
            throw new ImageReadException("PNG missing image data");

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (int i = 0; i < IDATs.size(); i++)
        {
            PngChunkIdat pngChunkIDAT = (PngChunkIdat) IDATs.get(i);
            byte bytes[] = pngChunkIDAT.bytes;
            // System.out.println(i + ": bytes: " + bytes.length);
            baos.write(bytes);
        }

        byte compressed[] = baos.toByteArray();

        baos = null;

        TransparencyFilter transparencyFilter = null;

        List<PngChunk> tRNSs = filterChunks(chunks, tRNS);
        if (tRNSs.size() > 0)
        {
            PngChunk pngChunktRNS = tRNSs.get(0);
            transparencyFilter = getTransparencyFilter(pngChunkIHDR.colorType,
                    pngChunktRNS);
        }

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

            if (sRGBs.size() == 1)
            {
                // no color management neccesary.
                if (debug)
                    System.out.println("sRGB, no color management neccesary.");
            } else if (iCCPs.size() == 1)
            {
                if (debug)
                    System.out.println("iCCP.");

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

                icc_profile = ICC_Profile.getInstance(bytes);
            } else if (gAMAs.size() == 1)
            {
                PngChunkGama pngChunkgAMA = (PngChunkGama) gAMAs.get(0);
                double gamma = pngChunkgAMA.getGamma();

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

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

            }
        }

        {
            int width = pngChunkIHDR.width;
            int height = pngChunkIHDR.height;
            int colorType = pngChunkIHDR.colorType;
            int bitDepth = pngChunkIHDR.bitDepth;

            int bitsPerSample = bitDepth;

            if (pngChunkIHDR.filterMethod != 0)
                throw new ImageReadException("PNG: unknown FilterMethod: "
                        + pngChunkIHDR.filterMethod);

            int samplesPerPixel = samplesPerPixel(pngChunkIHDR.colorType);
            boolean isGrayscale = isGrayscale(pngChunkIHDR.colorType);

            int bitsPerPixel = bitsPerSample * samplesPerPixel;

            boolean hasAlpha = colorType == COLOR_TYPE_GREYSCALE_WITH_ALPHA
                    || colorType == COLOR_TYPE_TRUE_COLOR_WITH_ALPHA;

            BufferedImage result;
            if (isGrayscale)
                result = getBufferedImageFactory(params)
                        .getGrayscaleBufferedImage(width, height, hasAlpha);
            else
                result = getBufferedImageFactory(params).getColorBufferedImage(
                        width, height, hasAlpha);

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

            ScanExpediter scanExpediter;

            if (pngChunkIHDR.interlaceMethod == 0)
                scanExpediter = new ScanExpediterSimple(width, height, iis,
                        result, colorType, bitDepth, bitsPerPixel,
                        pngChunkPLTE, gammaCorrection, transparencyFilter);
            else if (pngChunkIHDR.interlaceMethod == 1)
                scanExpediter = new ScanExpediterInterlaced(width, height, iis,
                        result, colorType, bitDepth, bitsPerPixel,
                        pngChunkPLTE, gammaCorrection, transparencyFilter);
            else
                throw new ImageReadException("Unknown InterlaceMethod: "
                        + pngChunkIHDR.interlaceMethod);

            scanExpediter.drive();

            if (icc_profile != null)
            {
                Boolean is_srgb = new IccProfileParser().issRGB(icc_profile);
                if (is_srgb == null || !is_srgb.booleanValue())
                {
                    ICC_ColorSpace cs = new ICC_ColorSpace(icc_profile);

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

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

            return result;

        }

    }