Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (102)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (322)
Collections:
Other Resources:
JDK 11 java.desktop.jmod - Desktop Module
JDK 11 java.desktop.jmod is the JMOD file for JDK 11 Desktop module.
JDK 11 Desktop module compiled class files are stored in \fyicenter\jdk-11.0.1\jmods\java.desktop.jmod.
JDK 11 Desktop module compiled class files are also linked and stored in the \fyicenter\jdk-11.0.1\lib\modules JImage file.
JDK 11 Desktop module source code files are stored in \fyicenter\jdk-11.0.1\lib\src.zip\java.desktop.
You can click and view the content of each source code file in the list below.
✍: FYIcenter
⏎ com/sun/imageio/plugins/png/PNGImageWriter.java
/*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package com.sun.imageio.plugins.png;
import java.awt.Rectangle;
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.IOException;
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.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.ImageOutputStreamImpl;
final class CRC {
private static final 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;
}
}
}
CRC() {}
void reset() {
crc = 0xffffffff;
}
void update(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);
}
crc = c;
}
void update(int data) {
crc = crcTable[(crc ^ data) & 0xff] ^ (crc >>> 8);
}
int getValue() {
return crc ^ 0xffffffff;
}
}
final class ChunkStream extends ImageOutputStreamImpl {
private final ImageOutputStream stream;
private final long startPos;
private final CRC crc = new CRC();
ChunkStream(int type, ImageOutputStream stream) throws IOException {
this.stream = stream;
this.startPos = stream.getStreamPosition();
stream.writeInt(-1); // length, will backpatch
writeInt(type);
}
@Override
public int read() throws IOException {
throw new RuntimeException("Method not available");
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
throw new RuntimeException("Method not available");
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
crc.update(b, off, len);
stream.write(b, off, len);
}
@Override
public void write(int b) throws IOException {
crc.update(b);
stream.write(b);
}
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);
}
@Override
@SuppressWarnings("deprecation")
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 final byte[] chunkType = {
(byte)'I', (byte)'D', (byte)'A', (byte)'T'
};
private final ImageOutputStream stream;
private final int chunkLength;
private long startPos;
private final CRC crc = new CRC();
private final Deflater def;
private final byte[] buf = new byte[512];
// reused 1 byte[] array:
private final byte[] wbuf1 = new byte[1];
private int bytesRemaining;
IDATOutputStream(ImageOutputStream stream, int chunkLength,
int deflaterLevel) throws IOException
{
this.stream = stream;
this.chunkLength = chunkLength;
this.def = new Deflater(deflaterLevel);
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);
try {
stream.flushBefore(pos);
} catch (IOException e) {
/*
* If flushBefore() fails we try to access startPos in finally
* block of write_IDAT(). We should update startPos to avoid
* IndexOutOfBoundException while seek() is happening.
*/
this.startPos = stream.getStreamPosition();
throw e;
}
}
@Override
public int read() throws IOException {
throw new RuntimeException("Method not available");
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
throw new RuntimeException("Method not available");
}
@Override
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();
}
}
}
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;
}
}
@Override
public void write(int b) throws IOException {
wbuf1[0] = (byte)b;
write(wbuf1, 0, 1);
}
void finish() throws IOException {
try {
if (!def.finished()) {
def.finish();
while (!def.finished()) {
deflate();
}
}
finishChunk();
} finally {
def.end();
}
}
@Override
@SuppressWarnings("deprecation")
protected void finalize() throws Throwable {
// Empty finalizer (for improved performance; no need to call
// super.finalize() in this case)
}
}
final class PNGImageWriteParam extends ImageWriteParam {
/** Default quality level = 0.5 ie medium compression */
private static final float DEFAULT_QUALITY = 0.5f;
private static final String[] compressionNames = {"Deflate"};
private static final float[] qualityVals = { 0.00F, 0.30F, 0.75F, 1.00F };
private static final String[] qualityDescs = {
"High compression", // 0.00 -> 0.30
"Medium compression", // 0.30 -> 0.75
"Low compression" // 0.75 -> 1.00
};
PNGImageWriteParam(Locale locale) {
super();
this.canWriteProgressive = true;
this.locale = locale;
this.canWriteCompressed = true;
this.compressionTypes = compressionNames;
this.compressionType = compressionTypes[0];
this.compressionMode = MODE_DEFAULT;
this.compressionQuality = DEFAULT_QUALITY;
}
/**
* Removes any previous compression quality setting.
*
* <p> The default implementation resets the compression quality
* to <code>0.5F</code>.
*
* @exception IllegalStateException if the compression mode is not
* <code>MODE_EXPLICIT</code>.
*/
@Override
public void unsetCompression() {
super.unsetCompression();
this.compressionType = compressionTypes[0];
this.compressionQuality = DEFAULT_QUALITY;
}
/**
* Returns <code>true</code> since the PNG plug-in only supports
* lossless compression.
*
* @return <code>true</code>.
*/
@Override
public boolean isCompressionLossless() {
return true;
}
@Override
public String[] getCompressionQualityDescriptions() {
super.getCompressionQualityDescriptions();
return qualityDescs.clone();
}
@Override
public float[] getCompressionQualityValues() {
super.getCompressionQualityValues();
return qualityVals.clone();
}
}
/**
*/
public final class PNGImageWriter extends ImageWriter {
/** Default compression level = 4 ie medium compression */
private static final int DEFAULT_COMPRESSION_LEVEL = 4;
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);
}
@Override
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;
}
}
@Override
public ImageWriteParam getDefaultWriteParam() {
return new PNGImageWriteParam(getLocale());
}
@Override
public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
return null;
}
@Override
public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
ImageWriteParam param) {
PNGMetadata m = new PNGMetadata();
m.initialize(imageType, imageType.getSampleModel().getNumBands());
return m;
}
@Override
public IIOMetadata convertStreamMetadata(IIOMetadata inData,
ImageWriteParam param) {
return null;
}
@Override
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);
cs.writeInt(metadata.cHRM_whitePointY);
cs.writeInt(metadata.cHRM_redX);
cs.writeInt(metadata.cHRM_redY);
cs.writeInt(metadata.cHRM_greenX);
cs.writeInt(metadata.cHRM_greenY);
cs.writeInt(metadata.cHRM_blueX);
cs.writeInt(metadata.cHRM_blueY);
cs.finish();
}
}
private void write_gAMA() throws IOException {
if (metadata.gAMA_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.gAMA_TYPE, stream);
cs.writeInt(metadata.gAMA_gamma);
cs.finish();
}
}
private void write_iCCP() throws IOException {
if (metadata.iCCP_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.iCCP_TYPE, stream);
cs.writeBytes(metadata.iCCP_profileName);
cs.writeByte(0); // null terminator
cs.writeByte(metadata.iCCP_compressionMethod);
cs.write(metadata.iCCP_compressedProfile);
cs.finish();
}
}
private void write_sBIT() throws IOException {
if (metadata.sBIT_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.sBIT_TYPE, stream);
int colorType = metadata.IHDR_colorType;
if (metadata.sBIT_colorType != colorType) {
processWarningOccurred(0,
"sBIT metadata has wrong color type.\n" +
"The chunk will not be written.");
return;
}
if (colorType == PNGImageReader.PNG_COLOR_GRAY ||
colorType == PNGImageReader.PNG_COLOR_GRAY_ALPHA) {
cs.writeByte(metadata.sBIT_grayBits);
} else if (colorType == PNGImageReader.PNG_COLOR_RGB ||
colorType == PNGImageReader.PNG_COLOR_PALETTE ||
colorType == PNGImageReader.PNG_COLOR_RGB_ALPHA) {
cs.writeByte(metadata.sBIT_redBits);
cs.writeByte(metadata.sBIT_greenBits);
cs.writeByte(metadata.sBIT_blueBits);
}
if (colorType == PNGImageReader.PNG_COLOR_GRAY_ALPHA ||
colorType == PNGImageReader.PNG_COLOR_RGB_ALPHA) {
cs.writeByte(metadata.sBIT_alphaBits);
}
cs.finish();
}
}
private void write_sRGB() throws IOException {
if (metadata.sRGB_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.sRGB_TYPE, stream);
cs.writeByte(metadata.sRGB_renderingIntent);
cs.finish();
}
}
private void write_PLTE() throws IOException {
if (metadata.PLTE_present) {
if (metadata.IHDR_colorType == PNGImageReader.PNG_COLOR_GRAY ||
metadata.IHDR_colorType == PNGImageReader.PNG_COLOR_GRAY_ALPHA) {
// PLTE cannot occur in a gray image
processWarningOccurred(0,
"A PLTE chunk may not appear in a gray or gray alpha image.\n" +
"The chunk will not be written");
return;
}
ChunkStream cs = new ChunkStream(PNGImageReader.PLTE_TYPE, stream);
int numEntries = metadata.PLTE_red.length;
byte[] palette = new byte[numEntries*3];
int index = 0;
for (int i = 0; i < numEntries; i++) {
palette[index++] = metadata.PLTE_red[i];
palette[index++] = metadata.PLTE_green[i];
palette[index++] = metadata.PLTE_blue[i];
}
cs.write(palette);
cs.finish();
}
}
private void write_hIST() throws IOException, IIOException {
if (metadata.hIST_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.hIST_TYPE, stream);
if (!metadata.PLTE_present) {
throw new IIOException("hIST chunk without PLTE chunk!");
}
cs.writeChars(metadata.hIST_histogram,
0, metadata.hIST_histogram.length);
cs.finish();
}
}
private void write_tRNS() throws IOException, IIOException {
if (metadata.tRNS_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.tRNS_TYPE, stream);
int colorType = metadata.IHDR_colorType;
int chunkType = metadata.tRNS_colorType;
// Special case: image is RGB and chunk is Gray
// Promote chunk contents to RGB
int chunkRed = metadata.tRNS_red;
int chunkGreen = metadata.tRNS_green;
int chunkBlue = metadata.tRNS_blue;
if (colorType == PNGImageReader.PNG_COLOR_RGB &&
chunkType == PNGImageReader.PNG_COLOR_GRAY) {
chunkType = colorType;
chunkRed = chunkGreen = chunkBlue =
metadata.tRNS_gray;
}
if (chunkType != colorType) {
processWarningOccurred(0,
"tRNS metadata has incompatible color type.\n" +
"The chunk will not be written.");
return;
}
if (colorType == PNGImageReader.PNG_COLOR_PALETTE) {
if (!metadata.PLTE_present) {
throw new IIOException("tRNS chunk without PLTE chunk!");
}
cs.write(metadata.tRNS_alpha);
} else if (colorType == PNGImageReader.PNG_COLOR_GRAY) {
cs.writeShort(metadata.tRNS_gray);
} else if (colorType == PNGImageReader.PNG_COLOR_RGB) {
cs.writeShort(chunkRed);
cs.writeShort(chunkGreen);
cs.writeShort(chunkBlue);
} else {
throw new IIOException("tRNS chunk for color type 4 or 6!");
}
cs.finish();
}
}
private void write_bKGD() throws IOException {
if (metadata.bKGD_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.bKGD_TYPE, stream);
int colorType = metadata.IHDR_colorType & 0x3;
int chunkType = metadata.bKGD_colorType;
int chunkRed = metadata.bKGD_red;
int chunkGreen = metadata.bKGD_green;
int chunkBlue = metadata.bKGD_blue;
// Special case: image is RGB(A) and chunk is Gray
// Promote chunk contents to RGB
if (colorType == PNGImageReader.PNG_COLOR_RGB &&
chunkType == PNGImageReader.PNG_COLOR_GRAY) {
// Make a gray bKGD chunk look like RGB
chunkType = colorType;
chunkRed = chunkGreen = chunkBlue =
metadata.bKGD_gray;
}
// Ignore status of alpha in colorType
if (chunkType != colorType) {
processWarningOccurred(0,
"bKGD metadata has incompatible color type.\n" +
"The chunk will not be written.");
return;
}
if (colorType == PNGImageReader.PNG_COLOR_PALETTE) {
cs.writeByte(metadata.bKGD_index);
} else if (colorType == PNGImageReader.PNG_COLOR_GRAY ||
colorType == PNGImageReader.PNG_COLOR_GRAY_ALPHA) {
cs.writeShort(metadata.bKGD_gray);
} else { // colorType == PNGImageReader.PNG_COLOR_RGB ||
// colorType == PNGImageReader.PNG_COLOR_RGB_ALPHA
cs.writeShort(chunkRed);
cs.writeShort(chunkGreen);
cs.writeShort(chunkBlue);
}
cs.finish();
}
}
private void write_pHYs() throws IOException {
if (metadata.pHYs_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.pHYs_TYPE, stream);
cs.writeInt(metadata.pHYs_pixelsPerUnitXAxis);
cs.writeInt(metadata.pHYs_pixelsPerUnitYAxis);
cs.writeByte(metadata.pHYs_unitSpecifier);
cs.finish();
}
}
private void write_sPLT() throws IOException {
if (metadata.sPLT_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.sPLT_TYPE, stream);
cs.writeBytes(metadata.sPLT_paletteName);
cs.writeByte(0); // null terminator
cs.writeByte(metadata.sPLT_sampleDepth);
int numEntries = metadata.sPLT_red.length;
if (metadata.sPLT_sampleDepth == 8) {
for (int i = 0; i < numEntries; i++) {
cs.writeByte(metadata.sPLT_red[i]);
cs.writeByte(metadata.sPLT_green[i]);
cs.writeByte(metadata.sPLT_blue[i]);
cs.writeByte(metadata.sPLT_alpha[i]);
cs.writeShort(metadata.sPLT_frequency[i]);
}
} else { // sampleDepth == 16
for (int i = 0; i < numEntries; i++) {
cs.writeShort(metadata.sPLT_red[i]);
cs.writeShort(metadata.sPLT_green[i]);
cs.writeShort(metadata.sPLT_blue[i]);
cs.writeShort(metadata.sPLT_alpha[i]);
cs.writeShort(metadata.sPLT_frequency[i]);
}
}
cs.finish();
}
}
private void write_tIME() throws IOException {
if (metadata.tIME_present) {
ChunkStream cs = new ChunkStream(PNGImageReader.tIME_TYPE, stream);
cs.writeShort(metadata.tIME_year);
cs.writeByte(metadata.tIME_month);
cs.writeByte(metadata.tIME_day);
cs.writeByte(metadata.tIME_hour);
cs.writeByte(metadata.tIME_minute);
cs.writeByte(metadata.tIME_second);
cs.finish();
}
}
private void write_tEXt() throws IOException {
Iterator<String> keywordIter = metadata.tEXt_keyword.iterator();
Iterator<String> textIter = metadata.tEXt_text.iterator();
while (keywordIter.hasNext()) {
ChunkStream cs = new ChunkStream(PNGImageReader.tEXt_TYPE, stream);
String keyword = keywordIter.next();
cs.writeBytes(keyword);
cs.writeByte(0);
String text = textIter.next();
cs.writeBytes(text);
cs.finish();
}
}
private byte[] deflate(byte[] b) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(baos);
dos.write(b);
dos.close();
return baos.toByteArray();
}
private void write_iTXt() throws IOException {
Iterator<String> keywordIter = metadata.iTXt_keyword.iterator();
Iterator<Boolean> flagIter = metadata.iTXt_compressionFlag.iterator();
Iterator<Integer> methodIter = metadata.iTXt_compressionMethod.iterator();
Iterator<String> languageIter = metadata.iTXt_languageTag.iterator();
Iterator<String> translatedKeywordIter =
metadata.iTXt_translatedKeyword.iterator();
Iterator<String> textIter = metadata.iTXt_text.iterator();
while (keywordIter.hasNext()) {
ChunkStream cs = new ChunkStream(PNGImageReader.iTXt_TYPE, stream);
cs.writeBytes(keywordIter.next());
cs.writeByte(0);
Boolean compressed = flagIter.next();
cs.writeByte(compressed ? 1 : 0);
cs.writeByte(methodIter.next().intValue());
cs.writeBytes(languageIter.next());
cs.writeByte(0);
cs.write(translatedKeywordIter.next().getBytes("UTF8"));
cs.writeByte(0);
String text = textIter.next();
if (compressed) {
cs.write(deflate(text.getBytes("UTF8")));
} else {
cs.write(text.getBytes("UTF8"));
}
cs.finish();
}
}
private void write_zTXt() throws IOException {
Iterator<String> keywordIter = metadata.zTXt_keyword.iterator();
Iterator<Integer> methodIter = metadata.zTXt_compressionMethod.iterator();
Iterator<String> textIter = metadata.zTXt_text.iterator();
while (keywordIter.hasNext()) {
ChunkStream cs = new ChunkStream(PNGImageReader.zTXt_TYPE, stream);
String keyword = keywordIter.next();
cs.writeBytes(keyword);
cs.writeByte(0);
int compressionMethod = (methodIter.next()).intValue();
cs.writeByte(compressionMethod);
String text = textIter.next();
cs.write(deflate(text.getBytes("ISO-8859-1")));
cs.finish();
}
}
private void writeUnknownChunks() throws IOException {
Iterator<String> typeIter = metadata.unknownChunkType.iterator();
Iterator<byte[]> dataIter = metadata.unknownChunkData.iterator();
while (typeIter.hasNext() && dataIter.hasNext()) {
String type = typeIter.next();
ChunkStream cs = new ChunkStream(chunkType(type), stream);
byte[] data = dataIter.next();
cs.write(data);
cs.finish();
}
}
private static int chunkType(String typeString) {
char c0 = typeString.charAt(0);
char c1 = typeString.charAt(1);
char c2 = typeString.charAt(2);
char c3 = typeString.charAt(3);
int type = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
return type;
}
private void encodePass(ImageOutputStream os,
RenderedImage image,
int xOffset, int yOffset,
int xSkip, int ySkip) throws IOException {
int minX = sourceXOffset;
int minY = sourceYOffset;
int width = sourceWidth;
int height = sourceHeight;
// Adjust offsets and skips based on source subsampling factors
xOffset *= periodX;
xSkip *= periodX;
yOffset *= periodY;
ySkip *= periodY;
// Early exit if no data for this pass
int hpixels = (width - xOffset + xSkip - 1)/xSkip;
int vpixels = (height - yOffset + ySkip - 1)/ySkip;
if (hpixels == 0 || vpixels == 0) {
return;
}
// Convert X offset and skip from pixels to samples
xOffset *= numBands;
xSkip *= numBands;
// Create row buffers
int samplesPerByte = 8/metadata.IHDR_bitDepth;
int numSamples = width*numBands;
int[] samples = new int[numSamples];
int bytesPerRow = hpixels*numBands;
if (metadata.IHDR_bitDepth < 8) {
bytesPerRow = (bytesPerRow + samplesPerByte - 1)/samplesPerByte;
} else if (metadata.IHDR_bitDepth == 16) {
bytesPerRow *= 2;
}
IndexColorModel icm_gray_alpha = null;
if (metadata.IHDR_colorType == PNGImageReader.PNG_COLOR_GRAY_ALPHA &&
image.getColorModel() instanceof IndexColorModel)
{
// reserve space for alpha samples
bytesPerRow *= 2;
// will be used to calculate alpha value for the pixel
icm_gray_alpha = (IndexColorModel)image.getColorModel();
}
currRow = new byte[bytesPerRow + bpp];
prevRow = new byte[bytesPerRow + bpp];
filteredRows = new byte[5][bytesPerRow + bpp];
int bitDepth = metadata.IHDR_bitDepth;
for (int row = minY + yOffset; row < minY + height; row += ySkip) {
Rectangle rect = new Rectangle(minX, row, width, 1);
Raster ras = image.getData(rect);
if (sourceBands != null) {
ras = ras.createChild(minX, row, width, 1, minX, row,
sourceBands);
}
ras.getPixels(minX, row, width, 1, samples);
if (image.getColorModel().isAlphaPremultiplied()) {
WritableRaster wr = ras.createCompatibleWritableRaster();
wr.setPixels(wr.getMinX(), wr.getMinY(),
wr.getWidth(), wr.getHeight(),
samples);
image.getColorModel().coerceData(wr, false);
wr.getPixels(wr.getMinX(), wr.getMinY(),
wr.getWidth(), wr.getHeight(),
samples);
}
// Reorder palette data if necessary
int[] paletteOrder = metadata.PLTE_order;
if (paletteOrder != null) {
for (int i = 0; i < numSamples; i++) {
samples[i] = paletteOrder[samples[i]];
}
}
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) {
byte val = scale0[samples[s]];
tmp = (tmp << bitDepth) | val;
if ((pos++ & mask) == mask) {
currRow[count++] = (byte)tmp;
tmp = 0;
pos = 0;
}
}
// Left shift the last byte
if ((pos & mask) != 0) {
tmp <<= ((8/bitDepth) - pos)*bitDepth;
currRow[count++] = (byte)tmp;
}
break;
case 8:
if (numBands == 1) {
for (int s = xOffset; s < numSamples; s += xSkip) {
currRow[count++] = scale0[samples[s]];
if (icm_gray_alpha != null) {
currRow[count++] =
scale0[icm_gray_alpha.getAlpha(0xff & samples[s])];
}
}
} else {
for (int s = xOffset; s < numSamples; s += xSkip) {
for (int b = 0; b < numBands; b++) {
currRow[count++] = scale[b][samples[s + b]];
}
}
}
break;
case 16:
for (int s = xOffset; s < numSamples; s += xSkip) {
for (int b = 0; b < numBands; b++) {
currRow[count++] = scaleh[b][samples[s + b]];
currRow[count++] = scalel[b][samples[s + b]];
}
}
break;
}
// Perform filtering
int filterType = rowFilter.filterRow(metadata.IHDR_colorType,
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;
pixelsDone += hpixels;
processImageProgress(100.0F*pixelsDone/totalPixels);
// If write has been aborted, just return;
// processWriteAborted will be called later
if (abortRequested()) {
return;
}
}
}
// Use sourceXOffset, etc.
private void write_IDAT(RenderedImage image, int deflaterLevel)
throws IOException
{
IDATOutputStream ios = new IDATOutputStream(stream, 32768,
deflaterLevel);
try {
if (metadata.IHDR_interlaceMethod == 1) {
for (int i = 0; i < 7; i++) {
encodePass(ios, image,
PNGImageReader.adam7XOffset[i],
PNGImageReader.adam7YOffset[i],
PNGImageReader.adam7XSubsampling[i],
PNGImageReader.adam7YSubsampling[i]);
if (abortRequested()) {
break;
}
}
} else {
encodePass(ios, image, 0, 0, 1, 1);
}
} finally {
ios.finish();
}
}
private void writeIEND() throws IOException {
ChunkStream cs = new ChunkStream(PNGImageReader.IEND_TYPE, stream);
cs.finish();
}
// Check two int arrays for value equality, always returns false
// if either array is null
private boolean equals(int[] s0, int[] s1) {
if (s0 == null || s1 == null) {
return false;
}
if (s0.length != s1.length) {
return false;
}
for (int i = 0; i < s0.length; i++) {
if (s0[i] != s1[i]) {
return false;
}
}
return true;
}
// Initialize the scale/scale0 or scaleh/scalel arrays to
// hold the results of scaling an input value to the desired
// output bit depth
private void initializeScaleTables(int[] sampleSize) {
int bitDepth = metadata.IHDR_bitDepth;
// If the existing tables are still valid, just return
if (bitDepth == scalingBitDepth &&
equals(sampleSize, this.sampleSize)) {
return;
}
// Compute new tables
this.sampleSize = sampleSize;
this.scalingBitDepth = bitDepth;
int maxOutSample = (1 << bitDepth) - 1;
if (bitDepth <= 8) {
scale = new byte[numBands][];
for (int b = 0; b < numBands; b++) {
int maxInSample = (1 << sampleSize[b]) - 1;
int halfMaxInSample = maxInSample/2;
scale[b] = new byte[maxInSample + 1];
for (int s = 0; s <= maxInSample; s++) {
scale[b][s] =
(byte)((s*maxOutSample + halfMaxInSample)/maxInSample);
}
}
scale0 = scale[0];
scaleh = scalel = null;
} else { // bitDepth == 16
// Divide scaling table into high and low bytes
scaleh = new byte[numBands][];
scalel = new byte[numBands][];
for (int b = 0; b < numBands; b++) {
int maxInSample = (1 << sampleSize[b]) - 1;
int halfMaxInSample = maxInSample/2;
scaleh[b] = new byte[maxInSample + 1];
scalel[b] = new byte[maxInSample + 1];
for (int s = 0; s <= maxInSample; s++) {
int val = (s*maxOutSample + halfMaxInSample)/maxInSample;
scaleh[b][s] = (byte)(val >> 8);
scalel[b][s] = (byte)(val & 0xff);
}
}
scale = null;
scale0 = null;
}
}
@Override
public void write(IIOMetadata streamMetadata,
IIOImage image,
ImageWriteParam param) throws IIOException {
if (stream == null) {
throw new IllegalStateException("output == null!");
}
if (image == null) {
throw new IllegalArgumentException("image == null!");
}
if (image.hasRaster()) {
throw new UnsupportedOperationException("image has a Raster!");
}
RenderedImage im = image.getRenderedImage();
SampleModel sampleModel = im.getSampleModel();
this.numBands = sampleModel.getNumBands();
// Set source region and subsampling to default values
this.sourceXOffset = im.getMinX();
this.sourceYOffset = im.getMinY();
this.sourceWidth = im.getWidth();
this.sourceHeight = im.getHeight();
this.sourceBands = null;
this.periodX = 1;
this.periodY = 1;
if (param != null) {
// Get source region and subsampling factors
Rectangle sourceRegion = param.getSourceRegion();
if (sourceRegion != null) {
Rectangle imageBounds = new Rectangle(im.getMinX(),
im.getMinY(),
im.getWidth(),
im.getHeight());
// Clip to actual image bounds
sourceRegion = sourceRegion.intersection(imageBounds);
sourceXOffset = sourceRegion.x;
sourceYOffset = sourceRegion.y;
sourceWidth = sourceRegion.width;
sourceHeight = sourceRegion.height;
}
// Adjust for subsampling offsets
int gridX = param.getSubsamplingXOffset();
int gridY = param.getSubsamplingYOffset();
sourceXOffset += gridX;
sourceYOffset += gridY;
sourceWidth -= gridX;
sourceHeight -= gridY;
// Get subsampling factors
periodX = param.getSourceXSubsampling();
periodY = param.getSourceYSubsampling();
int[] sBands = param.getSourceBands();
if (sBands != null) {
sourceBands = sBands;
numBands = sourceBands.length;
}
}
// Compute output dimensions
int destWidth = (sourceWidth + periodX - 1)/periodX;
int destHeight = (sourceHeight + periodY - 1)/periodY;
if (destWidth <= 0 || destHeight <= 0) {
throw new IllegalArgumentException("Empty source region!");
}
// Compute total number of pixels for progress notification
this.totalPixels = destWidth*destHeight;
this.pixelsDone = 0;
// Create metadata
IIOMetadata imd = image.getMetadata();
if (imd != null) {
metadata = (PNGMetadata)convertImageMetadata(imd,
ImageTypeSpecifier.createFromRenderedImage(im),
null);
} else {
metadata = new PNGMetadata();
}
// reset compression level to default:
int deflaterLevel = DEFAULT_COMPRESSION_LEVEL;
if (param != null) {
switch(param.getCompressionMode()) {
case ImageWriteParam.MODE_DISABLED:
deflaterLevel = Deflater.NO_COMPRESSION;
break;
case ImageWriteParam.MODE_EXPLICIT:
float quality = param.getCompressionQuality();
if (quality >= 0f && quality <= 1f) {
deflaterLevel = 9 - Math.round(9f * quality);
}
break;
default:
}
// Use Adam7 interlacing if set in write param
switch (param.getProgressiveMode()) {
case ImageWriteParam.MODE_DEFAULT:
metadata.IHDR_interlaceMethod = 1;
break;
case ImageWriteParam.MODE_DISABLED:
metadata.IHDR_interlaceMethod = 0;
break;
// MODE_COPY_FROM_METADATA should already be taken care of
// MODE_EXPLICIT is not allowed
default:
}
}
// Initialize bitDepth and colorType
metadata.initialize(new ImageTypeSpecifier(im), numBands);
// Overwrite IHDR width and height values with values from image
metadata.IHDR_width = destWidth;
metadata.IHDR_height = destHeight;
this.bpp = numBands*((metadata.IHDR_bitDepth == 16) ? 2 : 1);
// Initialize scaling tables for this image
initializeScaleTables(sampleModel.getSampleSize());
clearAbortRequest();
processImageStarted(0);
if (abortRequested()) {
processWriteAborted();
} else {
try {
write_magic();
write_IHDR();
write_cHRM();
write_gAMA();
write_iCCP();
write_sBIT();
write_sRGB();
write_PLTE();
write_hIST();
write_tRNS();
write_bKGD();
write_pHYs();
write_sPLT();
write_tIME();
write_tEXt();
write_iTXt();
write_zTXt();
writeUnknownChunks();
write_IDAT(im, deflaterLevel);
if (abortRequested()) {
processWriteAborted();
} else {
// Finish up and inform the listeners we are done
writeIEND();
processImageComplete();
}
} catch (IOException e) {
throw new IIOException("I/O error writing PNG file!", e);
}
}
}
}
⏎ com/sun/imageio/plugins/png/PNGImageWriter.java
Or download all of them as a single archive file:
File name: java.desktop-11.0.1-src.zip File size: 7974380 bytes Release date: 2018-11-04 Download
⇒ JDK 11 java.instrument.jmod - Instrument Module
2022-08-06, ≈577🔥, 5💬
Popular Posts:
Apache Log4j 1.2 Bridge allows applications coded to use Log4j 1.2 API to use Log4j 2 instead. Bytec...
JLayer is a library that decodes/plays/converts MPEG 1/2/2.5 Layer 1/2/3 (i.e. MP3) in real time for...
JDK 11 java.base.jmod is the JMOD file for JDK 11 Base module. JDK 11 Base module compiled class fil...
JDK 17 java.compiler.jmod is the JMOD file for JDK 17 Compiler module. JDK 17 Compiler module compil...
maven-model-builder-3.8. 6.jaris the JAR file for Apache Maven 3.8.6 Model Builder module. Apache Ma...