summaryrefslogtreecommitdiffstats
path: root/bundles/org.eclipse.swt/Eclipse SWT
diff options
context:
space:
mode:
authorCarolyn MacLeod <carolyn>2005-09-01 21:31:15 +0000
committerCarolyn MacLeod <carolyn>2005-09-01 21:31:15 +0000
commitff32f7578b312ab2cf7bee31c19161e45b3b344c (patch)
tree9fb601ce6e9ce8617db17bb9e6ace9a7c6b9063f /bundles/org.eclipse.swt/Eclipse SWT
parent553d7364f85189cde07e065aaa5ba7380f0c1418 (diff)
downloadeclipse.platform.swt-ff32f7578b312ab2cf7bee31c19161e45b3b344c.tar.gz
eclipse.platform.swt-ff32f7578b312ab2cf7bee31c19161e45b3b344c.tar.xz
eclipse.platform.swt-ff32f7578b312ab2cf7bee31c19161e45b3b344c.zip
bug 46387
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT')
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java5
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java167
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java3
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/OS2BMPFileFormat.java3
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java3
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/TIFFFileFormat.java5
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java3
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java13
9 files changed, 160 insertions, 72 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java
index 15b4d79e96..d3677ff3ba 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java
@@ -23,16 +23,17 @@ import org.eclipse.swt.internal.image.*;
* <p>
* Currently supported image formats are:
* </p><ul>
- * <li>BMP (Windows Bitmap)</li>
+ * <li>BMP (Windows or OS/2 Bitmap)</li>
* <li>ICO (Windows Icon)</li>
* <li>JPEG</li>
* <li>GIF</li>
* <li>PNG</li>
+ * <li>TIFF</li>
* </ul>
* <code>ImageLoaders</code> can be used to:
* <ul>
* <li>load/save single images in all formats</li>
- * <li>load/save multiple images (GIF/ICO)</li>
+ * <li>load/save multiple images (GIF/ICO/TIFF)</li>
* <li>load/save animated GIF images</li>
* <li>load interlaced GIF/PNG images</li>
* <li>load progressive JPEG images</li>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java
index ed93f2b414..792bf2755c 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java
@@ -25,14 +25,6 @@ public abstract class FileFormat {
ImageLoader loader;
int compression;
-byte[] bitInvertData(byte[] data, int startIndex, int endIndex) {
- // Destructively bit invert data in the given byte array.
- for (int i = startIndex; i < endIndex; i++) {
- data[i] = (byte)(255 - data[i - startIndex]);
- }
- return data;
-}
-
/**
* Return whether or not the specified input stream
* represents a supported file format.
@@ -51,6 +43,10 @@ public ImageData[] loadFromStream(LEDataInputStream stream) {
}
}
+/**
+ * Read the specified input stream using the specified loader, and
+ * return the device independent image array represented by the stream.
+ */
public static ImageData[] load(InputStream is, ImageLoader loader) {
FileFormat fileFormat = null;
LEDataInputStream stream = new LEDataInputStream(is);
@@ -75,13 +71,15 @@ public static ImageData[] load(InputStream is, ImageLoader loader) {
return fileFormat.loadFromStream(stream);
}
+/**
+ * Write the device independent image array stored in the specified loader
+ * to the specified output stream using the specified file format.
+ */
public static void save(OutputStream os, int format, ImageLoader loader) {
if (format < 0 || format >= FORMATS.length) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
if (FORMATS[format] == null) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+ if (loader.data == null || loader.data.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- /* We do not currently support writing multi-image files,
- * so we use the first image data in the loader's array. */
- ImageData data = loader.data[0];
LEDataOutputStream stream = new LEDataOutputStream(os);
FileFormat fileFormat = null;
try {
@@ -91,20 +89,20 @@ public static void save(OutputStream os, int format, ImageLoader loader) {
SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
}
if (format == SWT.IMAGE_BMP_RLE) {
- switch (data.depth) {
+ switch (loader.data[0].depth) {
case 8: fileFormat.compression = 1; break;
case 4: fileFormat.compression = 2; break;
}
}
- fileFormat.unloadIntoStream(data, stream);
+ fileFormat.unloadIntoStream(loader, stream);
}
-abstract void unloadIntoByteStream(ImageData image);
+abstract void unloadIntoByteStream(ImageLoader loader);
-public void unloadIntoStream(ImageData image, LEDataOutputStream stream) {
+public void unloadIntoStream(ImageLoader loader, LEDataOutputStream stream) {
try {
outputStream = stream;
- unloadIntoByteStream(image);
+ unloadIntoByteStream(loader);
outputStream.flush();
} catch (Exception e) {
try {outputStream.flush();} catch (Exception f) {}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java
index 3523c61b3f..d303a6353c 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java
@@ -420,31 +420,129 @@ final class GIFFileFormat extends FileFormat {
return new PaletteData(colors);
}
- /**
- * Write the specified device independent image
- * to the output stream.
- */
- void unloadIntoByteStream(ImageData image) {
- if (!((image.depth == 1) || (image.depth == 4) || (image.depth == 8))) {
+ void unloadIntoByteStream(ImageLoader loader) {
+
+ /* Step 1: Acquire GIF parameters */
+ ImageData[] data = loader.data;
+ int frameCount = data.length;
+ boolean multi = frameCount > 1;
+ ImageData firstImage = data[0];
+ int logicalScreenWidth = multi ? loader.logicalScreenWidth : firstImage.width;
+ int logicalScreenHeight = multi ? loader.logicalScreenHeight : firstImage.height;
+ int backgroundPixel = loader.backgroundPixel;
+ int depth = firstImage.depth;
+ PaletteData palette = firstImage.palette;
+ RGB[] colors = palette.getRGBs();
+ short globalTable = 1;
+
+ /* Step 2: Check for validity and global/local color map */
+ if (!(depth == 1 || depth == 4 || depth == 8)) {
SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
}
- byte bitField = (byte)((0x80 & 0xF8 & 0xF7 & 0x8F) + (image.depth - 1) + ((image.depth - 1) * 16));
+ for (int i=0; i<frameCount; i++) {
+ if (data[i].palette.isDirect) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ if (multi) {
+ if (!(data[i].height <= logicalScreenHeight && data[i].width <= logicalScreenWidth && data[i].depth == depth)) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ if (globalTable == 1) {
+ RGB rgbs[] = data[i].palette.getRGBs();
+ if (rgbs.length != colors.length) {
+ globalTable = 0;
+ } else {
+ for (int j=0; j<colors.length; j++) {
+ if (!(rgbs[j].red == colors[j].red &&
+ rgbs[j].green == colors[j].green &&
+ rgbs[j].blue == colors[j].blue))
+ globalTable = 0;
+ }
+ }
+ }
+ }
+ }
+
try {
- outputStream.write(new byte[] { (byte)'G', (byte)'I', (byte)'F' });
- outputStream.write(new byte[] { (byte)'8', (byte)'9', (byte)'a' });
- outputStream.writeShort((short)image.width);
- outputStream.writeShort((short)image.height);
- outputStream.writeByte(bitField);
- outputStream.writeByte((byte)0);
+ /* Step 3: Write the GIF89a Header and Logical Screen Descriptor */
+ int bits = globalTable*128 + (depth-1)*16 + depth-1;
+ outputStream.write("GIF89a".getBytes());
+ outputStream.writeShort((short)logicalScreenWidth);
+ outputStream.writeShort((short)logicalScreenHeight);
+ outputStream.writeByte((byte)bits);
+ outputStream.writeByte((byte)backgroundPixel);
outputStream.writeByte((byte)0);
} catch (IOException e) {
SWT.error(SWT.ERROR_IO, e);
}
- writePalette(image.palette, image.depth);
- if (image.transparentPixel != -1 || image.disposalMethod != 0 || image.delayTime != 0) {
- writeGraphicsControlBlock(image);
+
+ /* Step 4: Write Global Color Table if applicable */
+ if (globalTable == 1) {
+ writePalette(palette, depth);
}
- writeImageBlock(image);
+
+ /* Step 5: Write Application Extension if applicable */
+ if (multi) {
+ int repeatCount = loader.repeatCount;
+ try {
+ outputStream.write(GIF_EXTENSION_BLOCK_ID);
+ outputStream.write(GIF_APPLICATION_EXTENSION_BLOCK_ID);
+ outputStream.write((byte)11); // Eleven bytes following
+ outputStream.write("NETSCAPE2.0".getBytes());
+ outputStream.write((byte)3); // Three bytes following
+ outputStream.writeByte((byte)1);
+ outputStream.write((byte) repeatCount & 0xFF);
+ outputStream.write((byte) (repeatCount >> 8) & 0xFF);
+ outputStream.writeByte((byte)0);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+
+ for (int frame=0; frame<frameCount; frame++) {
+
+ /* Step 6: Write Graphics Control Block for each frame if applicable */
+ if (multi || data[frame].transparentPixel != -1) {
+ writeGraphicsControlBlock(data[frame]);
+ }
+
+ /* Step 7: Write Image Header for each frame */
+ int x = data[frame].x;
+ int y = data[frame].y;
+ int width = data[frame].width;
+ int height = data[frame].height;
+ try {
+ outputStream.write(GIF_IMAGE_BLOCK_ID); // 0x2C
+ byte[] block = new byte[9];
+ block[0] = (byte)(x & 0xFF);
+ block[1] = (byte)((x >> 8) & 0xFF);
+ block[2] = (byte)(y & 0xFF);
+ block[3] = (byte)((y >> 8) & 0xFF);
+ block[4] = (byte)(width & 0xFF);
+ block[5] = (byte)((width >> 8) & 0xFF);
+ block[6] = (byte)(height & 0xFF);
+ block[7] = (byte)((height >> 8) & 0xFF);
+ block[8] = (byte)(globalTable == 0 ? (depth-1) | 0x80 : 0x00);
+ outputStream.write(block);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+
+ /* Step 8: Write Local Color Table for each frame if applicable */
+ if (globalTable == 0) {
+ writePalette(data[frame].palette, depth);
+ }
+
+ /* Step 9: Write the actual data for each frame */
+ try {
+ outputStream.write(depth); // minimum LZW Code size: 3 for 1 bit per pixel images and usually the number of bits per pixel plus 1 for other images.
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ new LZWCodec().encode(outputStream, data[frame]);
+ }
+
+ /* Step 10: Write GIF terminator */
try {
outputStream.write(0x3B);
} catch (IOException e) {
@@ -462,18 +560,16 @@ final class GIFFileFormat extends FileFormat {
outputStream.write(GIF_GRAPHICS_CONTROL_BLOCK_ID);
outputStream.write(0x04); // size of block
byte[] gcBlock = new byte[4];
- gcBlock[0] = (byte)0xFD;
+ gcBlock[0] = 0;
gcBlock[1] = 0;
gcBlock[2] = 0;
gcBlock[3] = 0;
- if (image.transparentPixel == -1) {
- gcBlock[0] = (byte)(gcBlock[0] & 0xFE);
- } else {
- gcBlock[0] = (byte)(gcBlock[0] | 0x01);
+ if (image.transparentPixel != -1) {
+ gcBlock[0] = (byte)0x01;
gcBlock[3] = (byte)image.transparentPixel;
}
if (image.disposalMethod != 0) {
- gcBlock[0] = (byte)(gcBlock[0] | ((image.disposalMethod & 0x07) << 2));
+ gcBlock[0] |= (byte)((image.disposalMethod & 0x07) << 2);
}
if (image.delayTime != 0) {
gcBlock[1] = (byte)(image.delayTime & 0xFF);
@@ -487,31 +583,6 @@ final class GIFFileFormat extends FileFormat {
}
/**
- * Write the specified device independent image
- * to the current position in the output stream.
- */
- void writeImageBlock(ImageData image) {
- try {
- outputStream.write(GIF_IMAGE_BLOCK_ID);
- byte[] block = new byte[9];
- block[0] = (byte)(image.x & 0xFF);
- block[1] = (byte)((image.x >> 8) & 0xFF);
- block[2] = (byte)(image.y & 0xFF);
- block[3] = (byte)((image.y >> 8) & 0xFF);
- block[4] = (byte)(image.width & 0xFF);
- block[5] = (byte)((image.width >> 8) & 0xFF);
- block[6] = (byte)(image.height & 0xFF);
- block[7] = (byte)((image.height >> 8) & 0xFF);
- block[8] = 0; // no interlace, no sort, no local palette
- outputStream.write(block);
- outputStream.write(image.depth);
- } catch (IOException e) {
- SWT.error(SWT.ERROR_IO, e);
- }
- new LZWCodec().encode(outputStream, image);
- }
-
- /**
* Write the specified palette to the output stream.
*/
void writePalette(PaletteData palette, int depth) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java
index c3fa2bd47c..3c2c5a18b7 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java
@@ -1771,7 +1771,8 @@ void storeData(int[] dataUnit, int iComp, int xmcu, int ymcu, int hi, int ihi, i
destIndex += compWidth;
}
}
-void unloadIntoByteStream(ImageData image) {
+void unloadIntoByteStream(ImageLoader loader) {
+ ImageData image = loader.data[0];
if (!new JPEGStartOfImage().writeToStream(outputStream)) {
SWT.error(SWT.ERROR_IO);
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/OS2BMPFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/OS2BMPFileFormat.java
index a7123c0145..ade4460aa2 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/OS2BMPFileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/OS2BMPFileFormat.java
@@ -201,7 +201,8 @@ int unloadData(ImageData image, OutputStream out) {
* Unload a DeviceIndependentImage using Windows .BMP format into the given
* byte stream.
*/
-void unloadIntoByteStream(ImageData image) {
+void unloadIntoByteStream(ImageLoader loader) {
+ ImageData image = loader.data[0];
byte[] rgbs;
int numCols;
if (!((image.depth == 1) || (image.depth == 4) || (image.depth == 8) ||
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java
index 6973c56745..dc49c29908 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java
@@ -135,7 +135,8 @@ void readNextChunk(PngChunkReader chunkReader) {
}
}
}
-void unloadIntoByteStream(ImageData p1) {
+void unloadIntoByteStream(ImageLoader loader) {
+ /* We do not currently support writing png. */
SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
}
boolean isFileFormat(LEDataInputStream stream) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/TIFFFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/TIFFFileFormat.java
index dd48276e5f..21ef7a43d0 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/TIFFFileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/TIFFFileFormat.java
@@ -64,7 +64,10 @@ ImageData[] loadFromByteStream() {
return images;
}
-void unloadIntoByteStream(ImageData image) {
+void unloadIntoByteStream(ImageLoader loader) {
+ /* We do not currently support writing multi-page tiff,
+ * so we use the first image data in the loader's array. */
+ ImageData image = loader.data[0];
TIFFDirectory directory = new TIFFDirectory(image);
try {
directory.writeToStream(outputStream);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java
index df0261df5c..63cc665694 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java
@@ -569,7 +569,8 @@ int unloadDataNoCompression(ImageData image, OutputStream out) {
* Unload a DeviceIndependentImage using Windows .BMP format into the given
* byte stream.
*/
-void unloadIntoByteStream(ImageData image) {
+void unloadIntoByteStream(ImageLoader loader) {
+ ImageData image = loader.data[0];
byte[] rgbs;
int numCols;
if (!((image.depth == 1) || (image.depth == 4) || (image.depth == 8) ||
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java
index b19aaa2f06..1fd3d62eba 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java
@@ -17,6 +17,14 @@ import java.io.*;
final class WinICOFileFormat extends FileFormat {
+byte[] bitInvertData(byte[] data, int startIndex, int endIndex) {
+ // Destructively bit invert data in the given byte array.
+ for (int i = startIndex; i < endIndex; i++) {
+ data[i] = (byte)(255 - data[i - startIndex]);
+ }
+ return data;
+}
+
static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
if (pad == newPad) return data;
int stride = (width * depth + 7) / 8;
@@ -252,7 +260,10 @@ void unloadIconHeader(ImageData i) {
SWT.error(SWT.ERROR_IO, e);
}
}
-void unloadIntoByteStream(ImageData image) {
+void unloadIntoByteStream(ImageLoader loader) {
+ /* We do not currently support writing multi-image ico,
+ * so we use the first image data in the loader's array. */
+ ImageData image = loader.data[0];
if (!isValidIcon(image))
SWT.error(SWT.ERROR_INVALID_IMAGE);
try {