📄 pngimagewriter.java
字号:
/* * @(#)PNGImageWriter.java 1.37 07/09/12 * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.imageio.plugins.png;import java.awt.Rectangle;import java.awt.image.ColorModel;import java.awt.image.IndexColorModel;import java.awt.image.Raster;import java.awt.image.WritableRaster;import java.awt.image.RenderedImage;import java.awt.image.SampleModel;import java.io.ByteArrayOutputStream;import java.io.DataOutput;import java.io.IOException;import java.io.OutputStream;import java.util.Iterator;import java.util.Locale;import java.util.zip.Deflater;import java.util.zip.DeflaterOutputStream;import javax.imageio.IIOException;import javax.imageio.IIOImage;import javax.imageio.ImageTypeSpecifier;import javax.imageio.ImageWriteParam;import javax.imageio.ImageWriter;import javax.imageio.metadata.IIOMetadata;import javax.imageio.metadata.IIOMetadata;import javax.imageio.spi.ImageWriterSpi;import javax.imageio.stream.ImageOutputStream;import javax.imageio.stream.ImageOutputStreamImpl;class CRC { private static int[] crcTable = new int[256]; private int crc = 0xffffffff; 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 CRC() {} public void reset() { crc = 0xffffffff; } public void update(byte[] data, int off, int len) { for (int n = 0; n < len; n++) { crc = crcTable[(crc ^ data[off + n]) & 0xff] ^ (crc >>> 8); } } public void update(int data) { crc = crcTable[(crc ^ data) & 0xff] ^ (crc >>> 8); } public int getValue() { return crc ^ 0xffffffff; }}final class ChunkStream extends ImageOutputStreamImpl { private ImageOutputStream stream; private long startPos; private CRC crc = new CRC(); public ChunkStream(int type, ImageOutputStream stream) throws IOException { this.stream = stream; this.startPos = stream.getStreamPosition(); stream.writeInt(-1); // length, will backpatch writeInt(type); } public int read() throws IOException { throw new RuntimeException("Method not available"); } public int read(byte[] b, int off, int len) throws IOException { throw new RuntimeException("Method not available"); } public void write(byte[] b, int off, int len) throws IOException { crc.update(b, off, len); stream.write(b, off, len); } public void write(int b) throws IOException { crc.update(b); stream.write(b); } public void finish() throws IOException { // Write CRC stream.writeInt(crc.getValue()); // Write length long pos = stream.getStreamPosition(); stream.seek(startPos); stream.writeInt((int)(pos - startPos) - 12); // Return to end of chunk and flush to minimize buffering stream.seek(pos); stream.flushBefore(pos); } protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) }}// Compress output and write as a series of 'IDAT' chunks of// fixed length.final class IDATOutputStream extends ImageOutputStreamImpl { private static byte[] chunkType = { (byte)'I', (byte)'D', (byte)'A', (byte)'T' }; private ImageOutputStream stream; private int chunkLength; private long startPos; private CRC crc = new CRC(); Deflater def = new Deflater(Deflater.BEST_COMPRESSION); byte[] buf = new byte[512]; private int bytesRemaining; public IDATOutputStream(ImageOutputStream stream, int chunkLength) throws IOException { this.stream = stream; this.chunkLength = chunkLength; startChunk(); } private void startChunk() throws IOException { crc.reset(); this.startPos = stream.getStreamPosition(); stream.writeInt(-1); // length, will backpatch crc.update(chunkType, 0, 4); stream.write(chunkType, 0, 4); this.bytesRemaining = chunkLength; } private void finishChunk() throws IOException { // Write CRC stream.writeInt(crc.getValue()); // Write length long pos = stream.getStreamPosition(); stream.seek(startPos); stream.writeInt((int)(pos - startPos) - 12); // Return to end of chunk and flush to minimize buffering stream.seek(pos); stream.flushBefore(pos); } public int read() throws IOException { throw new RuntimeException("Method not available"); } public int read(byte[] b, int off, int len) throws IOException { throw new RuntimeException("Method not available"); } public void write(byte[] b, int off, int len) throws IOException { if (len == 0) { return; } if (!def.finished()) { def.setInput(b, off, len); while (!def.needsInput()) { deflate(); } } } public void deflate() throws IOException { int len = def.deflate(buf, 0, buf.length); int off = 0; while (len > 0) { if (bytesRemaining == 0) { finishChunk(); startChunk(); } int nbytes = Math.min(len, bytesRemaining); crc.update(buf, off, nbytes); stream.write(buf, off, nbytes); off += nbytes; len -= nbytes; bytesRemaining -= nbytes; } } public void write(int b) throws IOException { byte[] wbuf = new byte[1]; wbuf[0] = (byte)b; write(wbuf, 0, 1); } public void finish() throws IOException { if (!def.finished()) { def.finish(); while (!def.finished()) { deflate(); } } finishChunk(); } protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) }}class PNGImageWriteParam extends ImageWriteParam { public PNGImageWriteParam(Locale locale) { super(); this.canWriteProgressive = true; this.locale = locale; }}/** * @version 0.5 */public class PNGImageWriter extends ImageWriter { ImageOutputStream stream = null; PNGMetadata metadata = null; // Factors from the ImageWriteParam int sourceXOffset = 0; int sourceYOffset = 0; int sourceWidth = 0; int sourceHeight = 0; int[] sourceBands = null; int periodX = 1; int periodY = 1; int numBands; int bpp; RowFilter rowFilter = new RowFilter(); byte[] prevRow = null; byte[] currRow = null; byte[][] filteredRows = null; // Per-band scaling tables // // After the first call to initializeScaleTables, either scale and scale0 // will be valid, or scaleh and scalel will be valid, but not both. // // The tables will be designed for use with a set of input but depths // given by sampleSize, and an output bit depth given by scalingBitDepth. // int[] sampleSize = null; // Sample size per band, in bits int scalingBitDepth = -1; // Output bit depth of the scaling tables // Tables for 1, 2, 4, or 8 bit output byte[][] scale = null; // 8 bit table byte[] scale0 = null; // equivalent to scale[0] // Tables for 16 bit output byte[][] scaleh = null; // High bytes of output byte[][] scalel = null; // Low bytes of output int totalPixels; // Total number of pixels to be written by write_IDAT int pixelsDone; // Running count of pixels written by write_IDAT public PNGImageWriter(ImageWriterSpi originatingProvider) { super(originatingProvider); } public void setOutput(Object output) { super.setOutput(output); if (output != null) { if (!(output instanceof ImageOutputStream)) { throw new IllegalArgumentException("output not an ImageOutputStream!"); } this.stream = (ImageOutputStream)output; } else { this.stream = null; } } private static int[] allowedProgressivePasses = { 1, 7 }; public ImageWriteParam getDefaultWriteParam() { return new PNGImageWriteParam(getLocale()); } public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { PNGMetadata m = new PNGMetadata(); m.initialize(imageType, imageType.getSampleModel().getNumBands()); return m; } public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { // TODO - deal with imageType if (inData instanceof PNGMetadata) { return (PNGMetadata)((PNGMetadata)inData).clone(); } else { return new PNGMetadata(inData); } } private void write_magic() throws IOException { // Write signature byte[] magic = { (byte)137, 80, 78, 71, 13, 10, 26, 10 }; stream.write(magic); } private void write_IHDR() throws IOException { // Write IHDR chunk ChunkStream cs = new ChunkStream(PNGImageReader.IHDR_TYPE, stream); cs.writeInt(metadata.IHDR_width); cs.writeInt(metadata.IHDR_height); cs.writeByte(metadata.IHDR_bitDepth); cs.writeByte(metadata.IHDR_colorType); if (metadata.IHDR_compressionMethod != 0) { throw new IIOException("Only compression method 0 is defined in PNG 1.1"); } cs.writeByte(metadata.IHDR_compressionMethod); if (metadata.IHDR_filterMethod != 0) { throw new IIOException("Only filter method 0 is defined in PNG 1.1"); } cs.writeByte(metadata.IHDR_filterMethod); if (metadata.IHDR_interlaceMethod < 0 || metadata.IHDR_interlaceMethod > 1) { throw new IIOException("Only interlace methods 0 (node) and 1 (adam7) are defined in PNG 1.1"); } cs.writeByte(metadata.IHDR_interlaceMethod); cs.finish(); } private void write_cHRM() throws IOException { if (metadata.cHRM_present) { ChunkStream cs = new ChunkStream(PNGImageReader.cHRM_TYPE, stream); cs.writeInt(metadata.cHRM_whitePointX);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -