X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Finternal%2Fimage%2FPngEncoder.java;fp=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Finternal%2Fimage%2FPngEncoder.java;h=b00aa657ac1c6636f2c6bc15a29ec83f18bedab3;hb=db618b088560ad9a524dade82a3847f8d08bfb7c;hp=0000000000000000000000000000000000000000;hpb=930da66f9b2d7d1acba3e5dc805a323933abb780;p=simantics%2Fplatform.git diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngEncoder.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngEncoder.java new file mode 100644 index 000000000..b00aa657a --- /dev/null +++ b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngEncoder.java @@ -0,0 +1,382 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.internal.image; + +import java.io.*; +import java.util.zip.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; + +final class PngEncoder extends Object { + + static final byte SIGNATURE[] = {(byte) '\211', (byte) 'P', (byte) 'N', (byte) 'G', (byte) '\r', (byte) '\n', (byte) '\032', (byte) '\n'}; + static final byte TAG_IHDR[] = {(byte) 'I', (byte) 'H', (byte) 'D', (byte) 'R'}; + static final byte TAG_PLTE[] = {(byte) 'P', (byte) 'L', (byte) 'T', (byte) 'E'}; + static final byte TAG_TRNS[] = {(byte) 't', (byte) 'R', (byte) 'N', (byte) 'S'}; + static final byte TAG_IDAT[] = {(byte) 'I', (byte) 'D', (byte) 'A', (byte) 'T'}; + static final byte TAG_IEND[] = {(byte) 'I', (byte) 'E', (byte) 'N', (byte) 'D'}; + + static final int NO_COMPRESSION = 0; + static final int BEST_SPEED = 1; + static final int BEST_COMPRESSION = 9; + static final int DEFAULT_COMPRESSION = -1; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024); + PngChunk chunk; + + ImageLoader loader; + ImageData data; + int transparencyType; + + int width, height, bitDepth, colorType; + + int compressionMethod = 0; + int filterMethod = 0; + int interlaceMethod = 0; + +public PngEncoder(ImageLoader loader) { + + this.loader = loader; + this.data = loader.data[0]; + this.transparencyType = data.getTransparencyType(); + + this.width = data.width; + this.height = data.height; + + this.bitDepth = 8; + + this.colorType = 2; + + if (data.palette.isDirect) { + if (transparencyType == SWT.TRANSPARENCY_ALPHA) { + this.colorType = 6; + } + } + else { + this.colorType = 3; + } + + if (!(colorType == 2 || colorType == 3 || colorType == 6)) SWT.error(SWT.ERROR_INVALID_IMAGE); + +} + +void writeShort(ByteArrayOutputStream baos, int theShort) { + + byte byte1 = (byte) ((theShort >> 8) & 0xff); + byte byte2 = (byte) (theShort & 0xff); + byte[] temp = {byte1, byte2}; + baos.write(temp, 0, 2); + +} + +void writeInt(ByteArrayOutputStream baos, int theInt) { + + byte byte1 = (byte) ((theInt >> 24) & 0xff); + byte byte2 = (byte) ((theInt >> 16) & 0xff); + byte byte3 = (byte) ((theInt >> 8) & 0xff); + byte byte4 = (byte) (theInt & 0xff); + byte[] temp = {byte1, byte2, byte3, byte4}; + baos.write(temp, 0, 4); + +} + +void writeChunk(byte[] tag, byte[] buffer) { + + int bufferLength = (buffer != null) ? buffer.length : 0; + + chunk = new PngChunk(bufferLength); + + writeInt(bytes, bufferLength); + bytes.write(tag, 0, 4); + chunk.setType(tag); + if (bufferLength != 0) { + bytes.write(buffer, 0, bufferLength); + chunk.setData(buffer); + } + else { + chunk.setCRC(chunk.computeCRC()); + } + writeInt(bytes, chunk.getCRC()); + +} + +void writeSignature() { + + bytes.write(SIGNATURE, 0, 8); + +} + +void writeHeader() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(13); + + writeInt(baos, width); + writeInt(baos, height); + baos.write(bitDepth); + baos.write(colorType); + baos.write(compressionMethod); + baos.write(filterMethod); + baos.write(interlaceMethod); + + writeChunk(TAG_IHDR, baos.toByteArray()); + +} + +void writePalette() { + + RGB[] RGBs = data.palette.getRGBs(); + + if (RGBs.length > 256) SWT.error(SWT.ERROR_INVALID_IMAGE); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(RGBs.length); + + for (int i = 0; i < RGBs.length; i++) { + + baos.write((byte) RGBs[i].red); + baos.write((byte) RGBs[i].green); + baos.write((byte) RGBs[i].blue); + + } + + writeChunk(TAG_PLTE, baos.toByteArray()); + +} + +void writeTransparency() { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + switch (transparencyType) { + + case SWT.TRANSPARENCY_ALPHA: + + int pixelValue, alphaValue; + + byte[] alphas = new byte[data.palette.getRGBs().length]; + + for (int y = 0; y < height; y++) { + + for (int x = 0; x < width; x++) { + + pixelValue = data.getPixel(x, y); + alphaValue = data.getAlpha(x, y); + + alphas[pixelValue] = (byte) alphaValue; + + } + + } + + baos.write(alphas, 0, alphas.length); + + break; + + case SWT.TRANSPARENCY_PIXEL: + + int pixel = data.transparentPixel; + + if (colorType == 2) { + + int redMask = data.palette.redMask; + int redShift = data.palette.redShift; + int greenMask = data.palette.greenMask; + int greenShift = data.palette.greenShift; + int blueShift = data.palette.blueShift; + int blueMask = data.palette.blueMask; + + int r = pixel & redMask; + r = (redShift < 0) ? r >>> -redShift : r << redShift; + int g = pixel & greenMask; + g = (greenShift < 0) ? g >>> -greenShift : g << greenShift; + int b = pixel & blueMask; + b = (blueShift < 0) ? b >>> -blueShift : b << blueShift; + + writeShort(baos, r); + writeShort(baos, g); + writeShort(baos, b); + + } + + if (colorType == 3) { + + byte[] padding = new byte[pixel + 1]; + + for (int i = 0; i < pixel; i++) { + + padding[i] = (byte) 255; + + } + + padding[pixel] = (byte) 0; + + baos.write(padding, 0, padding.length); + + } + + break; + + } + + writeChunk(TAG_TRNS, baos.toByteArray()); + +} + +void writeImageData() throws IOException { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + OutputStream os = null; + switch (loader.compression) { + case 0: + os = new DeflaterOutputStream(baos, new Deflater(NO_COMPRESSION)); + break; + case 1: + os = new DeflaterOutputStream(baos, new Deflater(BEST_SPEED)); + break; + case 3: + os = new DeflaterOutputStream(baos, new Deflater(BEST_COMPRESSION)); + break; + default: + os = new DeflaterOutputStream(baos, new Deflater(DEFAULT_COMPRESSION)); + break; + } + + if (colorType == 3) { + + byte[] lineData = new byte[width]; + + for (int y = 0; y < height; y++) { + + int filter = 0; + os.write(filter); + + data.getPixels(0, y, width, lineData, 0); + + os.write(lineData); + + } + + } + + else { + + int[] lineData = new int[width]; + byte[] alphaData = null; + if (colorType == 6) { + alphaData = new byte[width]; + } + + int redMask = data.palette.redMask; + int redShift = data.palette.redShift; + int greenMask = data.palette.greenMask; + int greenShift = data.palette.greenShift; + int blueShift = data.palette.blueShift; + int blueMask = data.palette.blueMask; + + byte[] lineBytes = new byte[width * (colorType == 6 ? 4 : 3)]; + + for (int y = 0; y < height; y++) { + + int filter = 0; + os.write(filter); + + data.getPixels(0, y, width, lineData, 0); + + if (colorType == 6) { + data.getAlphas(0, y, width, alphaData, 0); + } + + int offset = 0; + for (int x = 0; x < lineData.length; x++) { + + int pixel = lineData[x]; + + int r = pixel & redMask; + lineBytes[offset++] = (byte) ((redShift < 0) ? r >>> -redShift + : r << redShift); + int g = pixel & greenMask; + lineBytes[offset++] = (byte) ((greenShift < 0) ? g >>> -greenShift + : g << greenShift); + int b = pixel & blueMask; + lineBytes[offset++] = (byte) ((blueShift < 0) ? b >>> -blueShift + : b << blueShift); + + if (colorType == 6) { + lineBytes[offset++] = alphaData[x]; + } + + } + + os.write(lineBytes); + + } + + } + + os.flush(); + os.close(); + + byte[] compressed = baos.toByteArray(); + if (os == baos) { + /* Use PngDeflater for J2ME. */ + PngDeflater deflater = new PngDeflater(); + compressed = deflater.deflate(compressed); + } + + writeChunk(TAG_IDAT, compressed); + +} + +void writeEnd() { + + writeChunk(TAG_IEND, null); + +} + +public void encode(LEDataOutputStream outputStream) { + + try { + + writeSignature(); + writeHeader(); + + if (colorType == 3) { + writePalette(); + } + + boolean transparencyAlpha = (transparencyType == SWT.TRANSPARENCY_ALPHA); + boolean transparencyPixel = (transparencyType == SWT.TRANSPARENCY_PIXEL); + boolean type2Transparency = (colorType == 2 && transparencyPixel); + boolean type3Transparency = (colorType == 3 && (transparencyAlpha || transparencyPixel)); + + if (type2Transparency || type3Transparency) { + writeTransparency(); + } + + writeImageData(); + writeEnd(); + + outputStream.write(bytes.toByteArray()); + + } + + catch (IOException e) { + + SWT.error(SWT.ERROR_IO, e); + + } + +} + +}