params.remove(PngConstants.PARAM_KEY_PNG_TEXT_CHUNKS);
}
params.remove(ImagingConstants.PARAM_KEY_PIXEL_DENSITY);
if (!params.isEmpty()) {
final Object firstKey = params.keySet().iterator().next();
throw new ImageWriteException("Unknown parameter: " + firstKey);
}
params = rawParams;
final int width = src.getWidth();
final int height = src.getHeight();
final boolean hasAlpha = new PaletteFactory().hasTransparency(src);
if (verbose) {
Debug.debug("hasAlpha: " + hasAlpha);
}
// int transparency = new PaletteFactory().getTransparency(src);
boolean isGrayscale = new PaletteFactory().isGrayscale(src);
if (verbose) {
Debug.debug("isGrayscale: " + isGrayscale);
}
ColorType colorType;
{
final boolean forceIndexedColor = Boolean.TRUE.equals(params.get(PngConstants.PARAM_KEY_PNG_FORCE_INDEXED_COLOR));
final boolean forceTrueColor = Boolean.TRUE.equals(params.get(PngConstants.PARAM_KEY_PNG_FORCE_TRUE_COLOR));
if (forceIndexedColor && forceTrueColor) {
throw new ImageWriteException(
"Params: Cannot force both indexed and true color modes");
} else if (forceIndexedColor) {
colorType = ColorType.INDEXED_COLOR;
} else if (forceTrueColor) {
colorType = (hasAlpha ? ColorType.TRUE_COLOR_WITH_ALPHA : ColorType.TRUE_COLOR);
isGrayscale = false;
} else {
colorType = ColorType.getColorType(hasAlpha, isGrayscale);
}
if (verbose) {
Debug.debug("colorType: " + colorType);
}
}
final byte bitDepth = getBitDepth(colorType, params);
if (verbose) {
Debug.debug("bitDepth: " + bitDepth);
}
int sampleDepth;
if (colorType == ColorType.INDEXED_COLOR) {
sampleDepth = 8;
} else {
sampleDepth = bitDepth;
}
if (verbose) {
Debug.debug("sampleDepth: " + sampleDepth);
}
{
PngConstants.PNG_SIGNATURE.writeTo(os);
}
{
// IHDR must be first
final byte compressionMethod = PngConstants.COMPRESSION_TYPE_INFLATE_DEFLATE;
final byte filterMethod = PngConstants.FILTER_METHOD_ADAPTIVE;
final InterlaceMethod interlaceMethod = InterlaceMethod.NONE;
final ImageHeader imageHeader = new ImageHeader(width, height, bitDepth,
colorType, compressionMethod, filterMethod, interlaceMethod);
writeChunkIHDR(os, imageHeader);
}
//{
// sRGB No Before PLTE and IDAT. If the sRGB chunk is present, the
// iCCP chunk should not be present.
// charles
//}
Palette palette = null;
if (colorType == ColorType.INDEXED_COLOR) {
// PLTE No Before first IDAT
final int maxColors = hasAlpha ? 255 : 256;
final PaletteFactory paletteFactory = new PaletteFactory();
palette = paletteFactory.makeQuantizedRgbPalette(src, maxColors);
// Palette palette2 = new PaletteFactory().makePaletteSimple(src,
// maxColors);
// palette.dump();
if (hasAlpha) {
palette = new TransparentPalette(palette);
writeChunkPLTE(os, palette);
writeChunkTRNS(os, new SimplePalette(new int[] { 0x00000000 }));
} else {
writeChunkPLTE(os, palette);
}
}
final Object pixelDensityObj = params.get(ImagingConstants.PARAM_KEY_PIXEL_DENSITY);
if (pixelDensityObj instanceof PixelDensity) {
final PixelDensity pixelDensity = (PixelDensity) pixelDensityObj;
if (pixelDensity.isUnitless()) {
writeChunkPHYS(os, (int) Math.round(pixelDensity
.getRawHorizontalDensity()),
(int) Math.round(pixelDensity.getRawVerticalDensity()),
(byte) 0);
} else {
writeChunkPHYS(os, (int) Math.round(pixelDensity
.horizontalDensityMetres()),
(int) Math.round(pixelDensity.verticalDensityMetres()),
(byte) 1);
}
}
if (params.containsKey(ImagingConstants.PARAM_KEY_XMP_XML)) {
final String xmpXml = (String) params.get(ImagingConstants.PARAM_KEY_XMP_XML);
writeChunkXmpiTXt(os, xmpXml);
}
if (params.containsKey(PngConstants.PARAM_KEY_PNG_TEXT_CHUNKS)) {
final List<?> outputTexts = (List<?>) params.get(PngConstants.PARAM_KEY_PNG_TEXT_CHUNKS);
for (Object outputText : outputTexts) {
final PngText text = (PngText) outputText;
if (text instanceof PngText.Text) {
writeChunktEXt(os, (PngText.Text) text);
} else if (text instanceof PngText.Ztxt) {
writeChunkzTXt(os, (PngText.Ztxt) text);
} else if (text instanceof PngText.Itxt) {
writeChunkiTXt(os, (PngText.Itxt) text);
} else {
throw new ImageWriteException(
"Unknown text to embed in PNG: " + text);
}
}
}