Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXi Yan2019-04-02 16:30:10 -0400
committerXi Yan2019-04-03 12:12:48 -0400
commit79f8e3fa02f3f0995dcbf8f04ef8696ffd498411 (patch)
tree204e88cf858982bf0fe9756312cab50a8ec34559
parent58cbb11130181f062aef553ee21bcb21bc968945 (diff)
downloadeclipse.platform.swt-79f8e3fa02f3f0995dcbf8f04ef8696ffd498411.tar.gz
eclipse.platform.swt-79f8e3fa02f3f0995dcbf8f04ef8696ffd498411.tar.xz
eclipse.platform.swt-79f8e3fa02f3f0995dcbf8f04ef8696ffd498411.zip
Bug 546035 - [GTK3][regression] Some icons aren't rendered properly
anymore Caused by ImageLoader#save not working properly when ImageData.data we want to save in RGBA channel but ImageData is in RGB channel. Fix is to iterate over each pixel and fix the byte ordering to get a good pixel data buffer to pass to gdk_pixbuf_new. Tested with child Eclipse on X11 and Wayland with hover icons. Tested with ImageAnalyzer: loading any format image and saving it as PNG should work. Load JPEG file (in RGB), add Alpha mask to it, then saving it as PNG should work. Change-Id: I60dd32e313276ebb0dc35a5646beb4b57691e665 Signed-off-by: Xi Yan <xixiyan@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java83
1 files changed, 61 insertions, 22 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java
index b283bb63d2..a7542f5fd7 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/ImageLoader.java
@@ -424,24 +424,6 @@ static long gdk_pixbuf_new_from_file(String filename) {
}
/**
- * Convert java object ImageData to a new GdkPixbuf for saving
- * @param imgData
- * @return
- */
-static long imageDataToPixbuf(ImageData imgData) {
- int colorspace = GDK.GDK_COLORSPACE_RGB;
- boolean has_alpha = imgData.alphaData != null;
- int width = imgData.width;
- int height = imgData.height;
- int rowstride = imgData.scanlinePad;
- long buffer_ptr = OS.g_malloc(imgData.data.length);
- C.memmove(buffer_ptr, imgData.data, imgData.data.length);
- long pixbuf = GDK.gdk_pixbuf_new_from_data (buffer_ptr, colorspace, has_alpha, 8, width, height, rowstride, 0, 0);
- OS.g_free(buffer_ptr);
- return pixbuf;
-}
-
-/**
* Saves the image data in this ImageLoader to the specified stream.
* The format parameter can have one of the following values:
* <dl>
@@ -476,11 +458,60 @@ static long imageDataToPixbuf(ImageData imgData) {
public void save(OutputStream stream, int format) {
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (format == -1) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
- long pixbuf = imageDataToPixbuf(this.data[0]);
- if (pixbuf == 0) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (this.data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ ImageData imgData = this.data [0];
+ int colorspace = GDK.GDK_COLORSPACE_RGB;
+ boolean has_alpha = imgData.alphaData != null;
+ int width = imgData.width;
+ int height = imgData.height;
+ int n_channels = imgData.bytesPerLine / width; // original n_channels 3 or 4
+ int bytes_per_pixel = imgData.bytesPerLine / width; // n_channels for original ImageData (width * height * bytes_per_pixel) = imgData.length
+
+ if (has_alpha && bytes_per_pixel == 3) {
+ // Original is RGB -> we want RGBA
+ bytes_per_pixel += 1;
+ }
+ int oa, or, og, ob;
+ if (OS.BIG_ENDIAN) {
+ oa = 0; or = 1; og = 2; ob = 3;
+ } else {
+ oa = 3; or = 2; og = 1; ob = 0;
+ }
+ byte[] srcData = new byte[(width * height * bytes_per_pixel)];
+
+ if (has_alpha) {
+ for (int y = 0, offset = 0, new_offset = 0, alphaOffset = 0; y < height; y++) {
+ for (int x = 0; x < width; x++, offset += n_channels, new_offset += bytes_per_pixel) {
+ byte a = imgData.alphaData[alphaOffset++];
+ int offset_alpha = n_channels == 4 ? 1 : 0;
+ byte r = imgData.data[offset + offset_alpha + 0];
+ byte g = imgData.data[offset + offset_alpha + 1];
+ byte b = imgData.data[offset + offset_alpha + 2];
+
+ srcData[new_offset + ob] = b;
+ srcData[new_offset + og] = g;
+ srcData[new_offset + or] = r;
+ srcData[new_offset + oa] = a;
+ }
+ }
+ } else {
+ srcData = imgData.data;
+ }
+
+ // Get GdkPixbuf from pixel data buffer
+ long buffer_ptr = OS.g_malloc(srcData.length);
+ C.memmove(buffer_ptr, srcData, srcData.length);
+ int rowstride = srcData.length / height;
+ long pixbuf = GDK.gdk_pixbuf_new_from_data (buffer_ptr, colorspace, has_alpha, 8, width, height, rowstride, 0, 0);
+ if (pixbuf == 0) {
+ OS.g_free(buffer_ptr);
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+
// Write pixbuf to byte array and then to OutputStream
String typeStr = "";
switch (format) {
+ case SWT.IMAGE_BMP_RLE: typeStr = "bmp"; break;
case SWT.IMAGE_BMP: typeStr = "bmp"; break;
case SWT.IMAGE_GIF: typeStr = "gif"; break;
case SWT.IMAGE_ICO: typeStr = "ico"; break;
@@ -488,18 +519,26 @@ public void save(OutputStream stream, int format) {
case SWT.IMAGE_PNG: typeStr = "png"; break;
case SWT.IMAGE_TIFF: typeStr = "tiff"; break;
}
- byte[] type = Converter.wcsToMbcs(typeStr, true);
+
+ byte [] type = Converter.wcsToMbcs(typeStr, true);
+
long [] buffer = new long [1];
+ if (type == null || typeStr == "") {
+ OS.g_free(buffer_ptr);
+ SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+ }
long [] len = new long [1];
- if (type == null) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
GDK.gdk_pixbuf_save_to_bufferv(pixbuf, buffer, len, type, null, null, null);
byte[] byteArray = new byte[(int) len[0]];
C.memmove(byteArray, buffer[0], byteArray.length);
try {
stream.write(byteArray);
} catch (IOException e) {
+ OS.g_free(buffer_ptr);
SWT.error(SWT.ERROR_IO);
}
+ // must free buffer_ptr last otherwise we get half/corrupted image
+ OS.g_free(buffer_ptr);
}
/**

Back to the top