Index: PNGFileFormat.java =================================================================== RCS file: /home/eclipse/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java,v retrieving revision 1.17 diff -u -r1.17 PNGFileFormat.java --- PNGFileFormat.java 1 Sep 2005 21:31:15 -0000 1.17 +++ PNGFileFormat.java 2 Feb 2006 06:34:11 -0000 @@ -136,8 +136,8 @@ } } void unloadIntoByteStream(ImageLoader loader) { - /* We do not currently support writing png. */ - SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT); + PngEncoder encoder = new PngEncoder(loader); + encoder.encode(outputStream); } boolean isFileFormat(LEDataInputStream stream) { try { Index: PngEncoder.java =================================================================== RCS file: PngEncoder.java diff -N PngEncoder.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ PngEncoder.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,364 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.internal.image; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.CRC32; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageLoader; +import org.eclipse.swt.graphics.RGB; + +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'}; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024); + CRC32 crc = new CRC32(); + + 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; + + writeInt(bytes, bufferLength); + bytes.write(tag, 0, 4); + crc.reset(); + crc.update(tag, 0, 4); + if (bufferLength != 0) { + bytes.write(buffer, 0, bufferLength); + crc.update(buffer, 0, bufferLength); + } + writeInt(bytes, (int) crc.getValue()); + +} + +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() { + + try { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + Deflater deflater = new Deflater(); + DeflaterOutputStream dos = new DeflaterOutputStream(baos, deflater); + + if (colorType == 3) { + + int[] lineData = new int[width]; + + for (int y = 0; y < height; y++) { + + byte filter[] = {0}; + dos.write(filter, 0, 1); + + data.getPixels(0, y, width, lineData, 0); + + for (int x = 0; x < lineData.length; x++) { + + dos.write((byte) lineData[x]); + + } + + } + + } + + else { + + int[] lineData = new int[width]; + byte[] 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; + + for (int y = 0; y < height; y++) { + + byte filter[] = {0}; + dos.write(filter, 0, 1); + + data.getPixels(0, y, width, lineData, 0); + + if (colorType == 6) { + data.getAlphas(0, y, width, alphaData, 0); + } + + for (int x = 0; x < lineData.length; x++) { + + int pixel = lineData[x]; + + 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; + + byte pixels[] = {(byte) r, (byte) g, (byte) b}; + dos.write(pixels, 0, 3); + + if (colorType == 6) { + + byte alpha[] = {alphaData[x]}; + dos.write(alpha, 0, 1); + + } + + } + + } + + } + + dos.close(); + + writeChunk(TAG_IDAT, baos.toByteArray()); + + deflater.finish(); + + } + + catch (IOException e) { + + SWT.error(SWT.ERROR_IO, e); + + } + +} + +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); + + } + +} + +}