]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/internal/image/PngEncoder.java
Merge branch 'bug-623' into release/1.43.0
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / internal / image / PngEncoder.java
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 (file)
index 0000000..b00aa65
--- /dev/null
@@ -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);
+
+       }
+
+}
+
+}