in src/main/java/org/apache/commons/imaging/formats/png/PngImageParser.java [161:322]
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;
AbstractTransparencyFilter abstractTransparencyFilter = null;
final List<PngChunk> tRNSs = filterChunks(chunks, ChunkType.tRNS);
if (!tRNSs.isEmpty()) {
final PngChunk pngChunktRNS = tRNSs.get(0);
abstractTransparencyFilter = 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 && 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() || abstractTransparencyFilter != 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);
final AbstractScanExpediter abstractScanExpediter;
switch (pngChunkIHDR.getInterlaceMethod()) {
case NONE:
abstractScanExpediter = new ScanExpediterSimple(width, height, iis, result, pngColorType, bitDepth, bitsPerPixel, pngChunkPLTE, gammaCorrection,
abstractTransparencyFilter);
break;
case ADAM7:
abstractScanExpediter = new ScanExpediterInterlaced(width, height, iis, result, pngColorType, bitDepth, bitsPerPixel, pngChunkPLTE,
gammaCorrection, abstractTransparencyFilter);
break;
default:
throw new ImagingException("Unknown InterlaceMethod: " + pngChunkIHDR.getInterlaceMethod());
}
abstractScanExpediter.drive();
if (iccProfile != null) {
final boolean isSrgb = new IccProfileParser().isSrgb(iccProfile);
if (!isSrgb) {
final ICC_ColorSpace cs = new ICC_ColorSpace(iccProfile);
final ColorModel srgbCM = ColorModel.getRGBdefault();
final ColorSpace csSrgb = srgbCM.getColorSpace();
result = new ColorTools().convertBetweenColorSpaces(result, cs, csSrgb);
}
}
return result;
}
}