package com.fr.third.JAI; /* * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduct the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that Software is not designed,licensed or intended for use in * the design, construction, operation or maintenance of any nuclear facility. */ import java.awt.image.IndexColorModel; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.io.ByteArrayOutputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; class CRC { private static int[] crcTable = new int[256]; static { // Initialize CRC table for (int n = 0; n < 256; n++) { int c = n; for (int k = 0; k < 8; k++) { if ((c & 1) == 1) { c = 0xedb88320 ^ (c >>> 1); } else { c >>>= 1; } crcTable[n] = c; } } } public static int updateCRC(int crc, byte[] data, int off, int len) { int c = crc; for (int n = 0; n < len; n++) { c = crcTable[(c ^ data[off + n]) & 0xff] ^ (c >>> 8); } return c; } } class ChunkStream extends OutputStream implements DataOutput { private String type; private ByteArrayOutputStream baos; private DataOutputStream dos; public ChunkStream(String type) throws IOException { this.type = type; this.baos = new ByteArrayOutputStream(); this.dos = new DataOutputStream(baos); } public void write(byte[] b) throws IOException { dos.write(b); } public void write(byte[] b, int off, int len) throws IOException { dos.write(b, off, len); } public void write(int b) throws IOException { dos.write(b); } public void writeBoolean(boolean v) throws IOException { dos.writeBoolean(v); } public void writeByte(int v) throws IOException { dos.writeByte(v); } public void writeBytes(String s) throws IOException { dos.writeBytes(s); } public void writeChar(int v) throws IOException { dos.writeChar(v); } public void writeChars(String s) throws IOException { dos.writeChars(s); } public void writeDouble(double v) throws IOException { dos.writeDouble(v); } public void writeFloat(float v) throws IOException { dos.writeFloat(v); } public void writeInt(int v) throws IOException { dos.writeInt(v); } public void writeLong(long v) throws IOException { dos.writeLong(v); } public void writeShort(int v) throws IOException { dos.writeShort(v); } public void writeUTF(String str) throws IOException { dos.writeUTF(str); } public void writeToStream(DataOutputStream output) throws IOException { byte[] typeSignature = new byte[4]; typeSignature[0] = (byte)type.charAt(0); typeSignature[1] = (byte)type.charAt(1); typeSignature[2] = (byte)type.charAt(2); typeSignature[3] = (byte)type.charAt(3); dos.flush(); baos.flush(); byte[] data = baos.toByteArray(); int len = data.length; output.writeInt(len); output.write(typeSignature); output.write(data, 0, len); int crc = 0xffffffff; crc = CRC.updateCRC(crc, typeSignature, 0, 4); crc = CRC.updateCRC(crc, data, 0, len); output.writeInt(crc ^ 0xffffffff); } } class IDATOutputStream extends FilterOutputStream { private static final byte[] typeSignature = {(byte)'I', (byte)'D', (byte)'A', (byte)'T'}; private int bytesWritten = 0; private int segmentLength; byte[] buffer; public IDATOutputStream(OutputStream output, int segmentLength) { super(output); this.segmentLength = segmentLength; this.buffer = new byte[segmentLength]; } public void close() throws IOException { flush(); } private void writeInt(int x) throws IOException { out.write(x >> 24); out.write((x >> 16) & 0xff); out.write((x >> 8) & 0xff); out.write(x & 0xff); } public void flush() throws IOException { // Length writeInt(bytesWritten); // 'IDAT' signature out.write(typeSignature); // Data out.write(buffer, 0, bytesWritten); int crc = 0xffffffff; crc = CRC.updateCRC(crc, typeSignature, 0, 4); crc = CRC.updateCRC(crc, buffer, 0, bytesWritten); // CRC writeInt(crc ^ 0xffffffff); // Reset buffer bytesWritten = 0; } public void write(byte[] b) throws IOException { this.write(b, 0, b.length); } public void write(byte[] b, int off, int len) throws IOException { while (len > 0) { int bytes = Math.min(segmentLength - bytesWritten, len); System.arraycopy(b, off, buffer, bytesWritten, bytes); off += bytes; len -= bytes; bytesWritten += bytes; if (bytesWritten == segmentLength) { flush(); } } } public void write(int b) throws IOException { buffer[bytesWritten++] = (byte)b; if (bytesWritten == segmentLength) { flush(); } } } /** * An ImageEncoder for the PNG file format. * */ public class PNGImageEncoder extends ImageEncoderImpl { private static final int PNG_COLOR_GRAY = 0; private static final int PNG_COLOR_RGB = 2; private static final int PNG_COLOR_PALETTE = 3; private static final int PNG_COLOR_GRAY_ALPHA = 4; private static final int PNG_COLOR_RGB_ALPHA = 6; private static final byte[] magic = { (byte)137, (byte) 80, (byte) 78, (byte) 71, (byte) 13, (byte) 10, (byte) 26, (byte) 10 }; private PNGEncodeParam param; private RenderedImage image; private int width; private int height; private int bitDepth; private int bitShift; private int numBands; private int colorType; private int bpp; // bytes per pixel, rounded up private boolean skipAlpha = false; private boolean compressGray = false; private boolean interlace; private byte[] redPalette = null; private byte[] greenPalette = null; private byte[] bluePalette = null; private byte[] alphaPalette = null; private DataOutputStream dataOutput; public PNGImageEncoder(OutputStream output, PNGEncodeParam param) { super(output, param); if (param != null) { this.param = (PNGEncodeParam)param; } this.dataOutput = new DataOutputStream(output); } private void writeMagic() throws IOException { dataOutput.write(magic); } private void writeIHDR() throws IOException { ChunkStream cs = new ChunkStream("IHDR"); cs.writeInt(width); cs.writeInt(height); cs.writeByte((byte)bitDepth); cs.writeByte((byte)colorType); cs.writeByte((byte)0); cs.writeByte((byte)0); cs.writeByte(interlace ? (byte)1 : (byte)0); cs.writeToStream(dataOutput); } private byte[] prevRow = null; private byte[] currRow = null; private byte[][] filteredRows = null; private static int clamp(int val, int maxValue) { return (val > maxValue) ? maxValue : val; } private void encodePass(OutputStream os, Raster ras, int xOffset, int yOffset, int xSkip, int ySkip) throws IOException { int minX = ras.getMinX(); int minY = ras.getMinY(); int width = ras.getWidth(); int height = ras.getHeight(); xOffset *= numBands; xSkip *= numBands; int samplesPerByte = 8/bitDepth; int numSamples = width*numBands; int[] samples = new int[numSamples]; int pixels = (numSamples - xOffset + xSkip - 1)/xSkip; int bytesPerRow = pixels*numBands; if (bitDepth < 8) { bytesPerRow = (bytesPerRow + samplesPerByte - 1)/samplesPerByte; } else if (bitDepth == 16) { bytesPerRow *= 2; } if (bytesPerRow == 0) { return; } currRow = new byte[bytesPerRow + bpp]; prevRow = new byte[bytesPerRow + bpp]; filteredRows = new byte[5][bytesPerRow + bpp]; int maxValue = (1 << bitDepth) - 1; for (int row = minY + yOffset; row < minY + height; row += ySkip) { ras.getPixels(minX, row, width, 1, samples); if (compressGray) { int shift = 8 - bitDepth; for (int i = 0; i < width; i++) { samples[i] >>= shift; } } int count = bpp; // leave first 'bpp' bytes zero int pos = 0; int tmp = 0; switch (bitDepth) { case 1: case 2: case 4: // Image can only have a single band int mask = samplesPerByte - 1; for (int s = xOffset; s < numSamples; s += xSkip) { int val = clamp(samples[s] >> bitShift, maxValue); tmp = (tmp << bitDepth) | val; if ((pos++ & mask) == mask) { currRow[count++] = (byte)tmp; tmp = 0; } } // Left shift the last byte if ((pos & mask) != 0) { tmp <<= ((8/bitDepth) - pos)*bitDepth; currRow[count++] = (byte)tmp; } break; case 8: for (int s = xOffset; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { currRow[count++] = (byte)clamp(samples[s + b] >> bitShift, maxValue); } } break; case 16: for (int s = xOffset; s < numSamples; s += xSkip) { for (int b = 0; b < numBands; b++) { int val = clamp(samples[s + b] >> bitShift, maxValue); currRow[count++] = (byte)(val >> 8); currRow[count++] = (byte)(val & 0xff); } } break; } // Perform filtering int filterType = param.filterRow(currRow, prevRow, filteredRows, bytesPerRow, bpp); os.write(filterType); os.write(filteredRows[filterType], bpp, bytesPerRow); // Swap current and previous rows byte[] swap = currRow; currRow = prevRow; prevRow = swap; } } private void writeIDAT() throws IOException { IDATOutputStream ios = new IDATOutputStream(dataOutput, 8192); DeflaterOutputStream dos = new DeflaterOutputStream(ios, new Deflater(9)); // Future work - don't convert entire image to a Raster Raster ras = image.getData(); if (skipAlpha) { int numBands = ras.getNumBands() - 1; int[] bandList = new int[numBands]; for (int i = 0; i < numBands; i++) { bandList[i] = i; } ras = ras.createChild(0, 0, ras.getWidth(), ras.getHeight(), 0, 0, bandList); } if (interlace) { // Interlacing pass 1 encodePass(dos, ras, 0, 0, 8, 8); // Interlacing pass 2 encodePass(dos, ras, 4, 0, 8, 8); // Interlacing pass 3 encodePass(dos, ras, 0, 4, 4, 8); // Interlacing pass 4 encodePass(dos, ras, 2, 0, 4, 4); // Interlacing pass 5 encodePass(dos, ras, 0, 2, 2, 4); // Interlacing pass 6 encodePass(dos, ras, 1, 0, 2, 2); // Interlacing pass 7 encodePass(dos, ras, 0, 1, 1, 2); } else { encodePass(dos, ras, 0, 0, 1, 1); } dos.finish(); ios.flush(); } private void writeIEND() throws IOException { ChunkStream cs = new ChunkStream("IEND"); cs.writeToStream(dataOutput); } private static final float[] srgbChroma = { 0.31270F, 0.329F, 0.64F, 0.33F, 0.3F, 0.6F, 0.15F, 0.06F }; private void writeCHRM() throws IOException { if (param.isChromaticitySet() || param.isSRGBIntentSet()) { ChunkStream cs = new ChunkStream("cHRM"); float[] chroma; if (!param.isSRGBIntentSet()) { chroma = param.getChromaticity(); } else { chroma = srgbChroma; // SRGB chromaticities } for (int i = 0; i < 8; i++) { cs.writeInt((int)(chroma[i]*100000)); } cs.writeToStream(dataOutput); } } private void writeGAMA() throws IOException { if (param.isGammaSet() || param.isSRGBIntentSet()) { ChunkStream cs = new ChunkStream("gAMA"); float gamma; if (!param.isSRGBIntentSet()) { gamma = param.getGamma(); } else { gamma = 1.0F/2.2F; // SRGB gamma } cs.writeInt((int)(gamma*100000)); cs.writeToStream(dataOutput); } } private void writeICCP() throws IOException { if (param.isICCProfileDataSet()) { ChunkStream cs = new ChunkStream("iCCP"); byte[] ICCProfileData = param.getICCProfileData(); cs.write(ICCProfileData); cs.writeToStream(dataOutput); } } private void writeSBIT() throws IOException { if (param.isSignificantBitsSet()) { ChunkStream cs = new ChunkStream("sBIT"); int[] significantBits = param.getSignificantBits(); int len = significantBits.length; for (int i = 0; i < len; i++) { cs.writeByte(significantBits[i]); } cs.writeToStream(dataOutput); } } private void writeSRGB() throws IOException { if (param.isSRGBIntentSet()) { ChunkStream cs = new ChunkStream("sRGB"); int intent = param.getSRGBIntent(); cs.write(intent); cs.writeToStream(dataOutput); } } private void writePLTE() throws IOException { if (redPalette == null) { return; } ChunkStream cs = new ChunkStream("PLTE"); for (int i = 0; i < redPalette.length; i++) { cs.writeByte(redPalette[i]); cs.writeByte(greenPalette[i]); cs.writeByte(bluePalette[i]); } cs.writeToStream(dataOutput); } private void writeBKGD() throws IOException { if (param.isBackgroundSet()) { ChunkStream cs = new ChunkStream("bKGD"); switch (colorType) { case PNG_COLOR_GRAY: case PNG_COLOR_GRAY_ALPHA: int gray = ((PNGEncodeParam.Gray)param).getBackgroundGray(); cs.writeShort(gray); break; case PNG_COLOR_PALETTE: int index = ((PNGEncodeParam.Palette)param).getBackgroundPaletteIndex(); cs.writeByte(index); break; case PNG_COLOR_RGB: case PNG_COLOR_RGB_ALPHA: int[] rgb = ((PNGEncodeParam.RGB)param).getBackgroundRGB(); cs.writeShort(rgb[0]); cs.writeShort(rgb[1]); cs.writeShort(rgb[2]); break; } cs.writeToStream(dataOutput); } } private void writeHIST() throws IOException { if (param.isPaletteHistogramSet()) { ChunkStream cs = new ChunkStream("hIST"); int[] hist = param.getPaletteHistogram(); for (int i = 0; i < hist.length; i++) { cs.writeShort(hist[i]); } cs.writeToStream(dataOutput); } } private void writeTRNS() throws IOException { if (param.isTransparencySet() && (colorType != PNG_COLOR_GRAY_ALPHA) && (colorType != PNG_COLOR_RGB_ALPHA)) { ChunkStream cs = new ChunkStream("tRNS"); if (param instanceof PNGEncodeParam.Palette) { byte[] t = ((PNGEncodeParam.Palette)param).getPaletteTransparency(); for (int i = 0; i < t.length; i++) { cs.writeByte(t[i]); } } else if (param instanceof PNGEncodeParam.Gray) { int t = ((PNGEncodeParam.Gray)param).getTransparentGray(); cs.writeShort(t); } else if (param instanceof PNGEncodeParam.RGB) { int[] t = ((PNGEncodeParam.RGB)param).getTransparentRGB(); cs.writeShort(t[0]); cs.writeShort(t[1]); cs.writeShort(t[2]); } cs.writeToStream(dataOutput); } else if (colorType == PNG_COLOR_PALETTE) { int lastEntry = Math.min(255, alphaPalette.length - 1); int nonOpaque; for (nonOpaque = lastEntry; nonOpaque >= 0; nonOpaque--) { if (alphaPalette[nonOpaque] != (byte)255) { break; } } if (nonOpaque >= 0) { ChunkStream cs = new ChunkStream("tRNS"); for (int i = 0; i <= nonOpaque; i++) { cs.writeByte(alphaPalette[i]); } cs.writeToStream(dataOutput); } } } private void writePHYS() throws IOException { if (param.isPhysicalDimensionSet()) { ChunkStream cs = new ChunkStream("pHYs"); int[] dims = param.getPhysicalDimension(); cs.writeInt(dims[0]); cs.writeInt(dims[1]); cs.writeByte((byte)dims[2]); cs.writeToStream(dataOutput); } } private void writeSPLT() throws IOException { if (param.isSuggestedPaletteSet()) { ChunkStream cs = new ChunkStream("sPLT"); System.out.println("sPLT not supported yet."); cs.writeToStream(dataOutput); } } private void writeTIME() throws IOException { if (param.isModificationTimeSet()) { ChunkStream cs = new ChunkStream("tIME"); Date date = param.getModificationTime(); TimeZone gmt = TimeZone.getTimeZone("GMT"); GregorianCalendar cal = new GregorianCalendar(gmt); cal.setTime(date); int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH); int day = cal.get(Calendar.DAY_OF_MONTH); int hour = cal.get(Calendar.HOUR_OF_DAY); int minute = cal.get(Calendar.MINUTE); int second = cal.get(Calendar.SECOND); cs.writeShort(year); cs.writeByte(month + 1); cs.writeByte(day); cs.writeByte(hour); cs.writeByte(minute); cs.writeByte(second); cs.writeToStream(dataOutput); } } private void writeTEXT() throws IOException { if (param.isTextSet()) { String[] text = param.getText(); for (int i = 0; i < text.length/2; i++) { byte[] keyword = text[2*i].getBytes(); byte[] value = text[2*i + 1].getBytes(); ChunkStream cs = new ChunkStream("tEXt"); cs.write(keyword, 0, Math.min(keyword.length, 79)); cs.write(0); cs.write(value); cs.writeToStream(dataOutput); } } } private void writeZTXT() throws IOException { if (param.isCompressedTextSet()) { String[] text = param.getCompressedText(); for (int i = 0; i < text.length/2; i++) { byte[] keyword = text[2*i].getBytes(); byte[] value = text[2*i + 1].getBytes(); ChunkStream cs = new ChunkStream("zTXt"); cs.write(keyword, 0, Math.min(keyword.length, 79)); cs.write(0); cs.write(0); DeflaterOutputStream dos = new DeflaterOutputStream(cs); dos.write(value); dos.finish(); cs.writeToStream(dataOutput); } } } private void writePrivateChunks() throws IOException { int numChunks = param.getNumPrivateChunks(); for (int i = 0; i < numChunks; i++) { String type = param.getPrivateChunkType(i); char char3 = type.charAt(3); byte[] data = param.getPrivateChunkData(i); ChunkStream cs = new ChunkStream(type); cs.write(data); cs.writeToStream(dataOutput); } } /** * Analyzes a set of palettes and determines if it can be expressed * as a standard set of gray values, with zero or one values being * fully transparent and the rest being fully opaque. If it * is possible to express the data thusly, the method returns * a suitable instance of PNGEncodeParam.Gray; otherwise it * returns null. */ private PNGEncodeParam.Gray createGrayParam(byte[] redPalette, byte[] greenPalette, byte[] bluePalette, byte[] alphaPalette) { PNGEncodeParam.Gray param = new PNGEncodeParam.Gray(); int numTransparent = 0; int grayFactor = 255/((1 << bitDepth) - 1); int entries = 1 << bitDepth; for (int i = 0; i < entries; i++) { byte red = redPalette[i]; if ((red != i*grayFactor) || (red != greenPalette[i]) || (red != bluePalette[i])) { return null; } // All alphas must be 255 except at most 1 can be 0 byte alpha = alphaPalette[i]; if (alpha == (byte)0) { param.setTransparentGray(i); ++numTransparent; if (numTransparent > 1) { return null; } } else if (alpha != (byte)255) { return null; } } return param; } public void encode(RenderedImage im) throws IOException { this.image = im; this.width = image.getWidth(); this.height = image.getHeight(); SampleModel sampleModel = image.getSampleModel(); int[] sampleSize = sampleModel.getSampleSize(); // Set bitDepth to a sentinel value this.bitDepth = -1; this.bitShift = 0; // Allow user to override the bit depth of gray images if (param instanceof PNGEncodeParam.Gray) { PNGEncodeParam.Gray paramg = (PNGEncodeParam.Gray)param; if (paramg.isBitDepthSet()) { this.bitDepth = paramg.getBitDepth(); } if (paramg.isBitShiftSet()) { this.bitShift = paramg.getBitShift(); } } // Get bit depth from image if not set in param if (this.bitDepth == -1) { // Get bit depth from channel 0 of the image this.bitDepth = sampleSize[0]; // Ensure all channels have the same bit depth for (int i = 1; i < sampleSize.length; i++) { if (sampleSize[i] != bitDepth) { throw new RuntimeException(); } } // Round bit depth up to a power of 2 if (bitDepth > 2 && bitDepth < 4) { bitDepth = 4; } else if (bitDepth > 4 && bitDepth < 8) { bitDepth = 8; } else if (bitDepth > 8 && bitDepth < 16) { bitDepth = 16; } else if (bitDepth > 16) { throw new RuntimeException(); } } this.numBands = sampleModel.getNumBands(); this.bpp = numBands*((bitDepth == 16) ? 2 : 1); ColorModel colorModel = image.getColorModel(); if (colorModel instanceof IndexColorModel) { if (bitDepth < 1 || bitDepth > 8) { throw new RuntimeException(); } if (sampleModel.getNumBands() != 1) { throw new RuntimeException(); } IndexColorModel icm = (IndexColorModel)colorModel; int size = icm.getMapSize(); redPalette = new byte[size]; greenPalette = new byte[size]; bluePalette = new byte[size]; alphaPalette = new byte[size]; icm.getReds(redPalette); icm.getGreens(greenPalette); icm.getBlues(bluePalette); icm.getAlphas(alphaPalette); this.bpp = 1; if (param == null) { param = createGrayParam(redPalette, greenPalette, bluePalette, alphaPalette); } // If param is still null, it can't be expressed as gray if (param == null) { param = new PNGEncodeParam.Palette(); } if (param instanceof PNGEncodeParam.Palette) { // If palette not set in param, create one from the ColorModel. PNGEncodeParam.Palette parami = (PNGEncodeParam.Palette)param; if (parami.isPaletteSet()) { int[] palette = parami.getPalette(); size = palette.length/3; int index = 0; for (int i = 0; i < size; i++) { redPalette[i] = (byte)palette[index++]; greenPalette[i] = (byte)palette[index++]; bluePalette[i] = (byte)palette[index++]; alphaPalette[i] = (byte)255; } } this.colorType = PNG_COLOR_PALETTE; } else if (param instanceof PNGEncodeParam.Gray) { redPalette = greenPalette = bluePalette = alphaPalette = null; this.colorType = PNG_COLOR_GRAY; } else { throw new RuntimeException(); } } else if (numBands == 1) { if (param == null) { param = new PNGEncodeParam.Gray(); } this.colorType = PNG_COLOR_GRAY; } else if (numBands == 2) { if (param == null) { param = new PNGEncodeParam.Gray(); } if (param.isTransparencySet()) { skipAlpha = true; numBands = 1; if ((sampleSize[0] == 8) && (bitDepth < 8)) { compressGray = true; } bpp = (bitDepth == 16) ? 2 : 1; this.colorType = PNG_COLOR_GRAY; } else { if (this.bitDepth < 8) { this.bitDepth = 8; } this.colorType = PNG_COLOR_GRAY_ALPHA; } } else if (numBands == 3) { if (param == null) { param = new PNGEncodeParam.RGB(); } this.colorType = PNG_COLOR_RGB; } else if (numBands == 4) { if (param == null) { param = new PNGEncodeParam.RGB(); } if (param.isTransparencySet()) { skipAlpha = true; numBands = 3; bpp = (bitDepth == 16) ? 6 : 3; this.colorType = PNG_COLOR_RGB; } else { this.colorType = PNG_COLOR_RGB_ALPHA; } } interlace = param.getInterlacing(); writeMagic(); writeIHDR(); writeCHRM(); writeGAMA(); writeICCP(); writeSBIT(); writeSRGB(); writePLTE(); writeHIST(); writeTRNS(); writeBKGD(); writePHYS(); writeSPLT(); writeTIME(); writeTEXT(); writeZTXT(); writePrivateChunks(); writeIDAT(); writeIEND(); dataOutput.flush(); dataOutput.close(); } // public static void main(String[] args) { // try { // SeekableStream stream = new FileSeekableStream(args[0]); // String[] names = ImageCodec.getDecoderNames(stream); // ImageDecoder dec = // ImageCodec.createImageDecoder(names[0], stream, null); // RenderedImage im = dec.decodeAsRenderedImage(); // OutputStream output = new FileOutputStream(args[1]); // PNGEncodeParam param = null; // Object o = im.getProperty("encode_param"); // if ((o != null) && (o instanceof PNGEncodeParam)) { // param = (PNGEncodeParam)o; // } else { // param = PNGEncodeParam.getDefaultEncodeParam(im); // } // if (param instanceof PNGEncodeParam.RGB) { // int[] rgb = { 50, 100, 150 }; // ((PNGEncodeParam.RGB)param).setBackgroundRGB(rgb); // } // param.setChromaticity(0.32270F, 0.319F, // 0.65F, 0.32F, // 0.31F, 0.58F, // 0.16F, 0.04F); // param.setGamma(3.5F); // int[] sbits = { 8, 8, 8 }; // param.setSignificantBits(sbits); // param.setSRGBIntent(0); // String[] text = new String[4]; // text[0] = "Title"; // text[1] = "PNG Test Image"; // text[2] = "Author"; // text[3] = "Daniel Rice"; // param.setText(text); // String[] ztext = new String[2]; // ztext[0] = "Description"; // ztext[1] = "A really incredibly long-winded description of extremely little if any substance whatsoever."; // param.setCompressedText(ztext); // ImageEncoder enc = new PNGImageEncoder(output, param); // enc.encode(im); // } catch (Exception e) { // e.printStackTrace(); // System.exit(1); // } // } }