Skip to content

Commit 687c8a2

Browse files
vogellaakurtakov
authored andcommitted
[GTK] Fix loading 1 pixel wide RGB images with glycin
Since gdk-pixbuf delegates decoding to glycin, the rowstride of a pixbuf is no longer padded to 4 bytes, so a 1 pixel wide RGB image has a stride of 3. The loader passed that stride as scanline pad, and cloning the PNG ImageData then failed its minimum data length check, which assumes a 4 byte pad. Repack the rows to the standard 4 byte pad instead. Fixes #3545 Assisted-by: multiple AI agents and layers of automated tooling 🤖
1 parent 7c30c95 commit 687c8a2

3 files changed

Lines changed: 34 additions & 3 deletions

File tree

‎bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/NativeImageLoader.java‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,18 @@ private static ImageData pixbufToImageData(long pixbuf) {
225225
* width in bytes of the last row to copy raw pixbuf data.
226226
*/
227227
int lastRowWidth = width * ((n_channels * bits_per_sample + 7) / 8);
228-
byte[] srcData = new byte[stride * height];
229-
C.memmove(srcData, pixels, stride * (height - 1) + lastRowWidth);
228+
// The rowstride is not always 4-byte aligned (e.g. with glycin), but ImageData expects that
229+
int bytesPerLine = (lastRowWidth + 3) / 4 * 4;
230+
byte[] srcData = new byte[bytesPerLine * height];
231+
if (stride == bytesPerLine) {
232+
C.memmove(srcData, pixels, stride * (height - 1) + lastRowWidth);
233+
} else {
234+
byte[] row = new byte[lastRowWidth];
235+
for (int y = 0; y < height; y++) {
236+
C.memmove(row, pixels + (long) y * stride, lastRowWidth);
237+
System.arraycopy(row, 0, srcData, y * bytesPerLine, lastRowWidth);
238+
}
239+
}
230240
/*
231241
* Note: GdkPixbuf only supports 3/4 n_channels and 8 bits_per_sample, This
232242
* means all images are of depth 24 / depth 32. This means loading images will
@@ -236,7 +246,7 @@ private static ImageData pixbufToImageData(long pixbuf) {
236246
* See https://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html#PaletteData
237247
*/
238248
PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
239-
ImageData imgData = new ImageData(width, height, bits_per_sample * n_channels, palette, stride, srcData);
249+
ImageData imgData = new ImageData(width, height, bits_per_sample * n_channels, palette, 4, srcData);
240250
if (hasAlpha) {
241251
byte[] alphaData = imgData.alphaData = new byte[width * height];
242252
for (int y = 0, offset = 0, alphaOffset = 0; y < height; y++) {

‎tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_ImageLoader.java‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.eclipse.swt.graphics.ImageLoaderEvent;
3737
import org.eclipse.swt.graphics.ImageLoaderListener;
3838
import org.eclipse.swt.graphics.PaletteData;
39+
import org.eclipse.swt.graphics.RGB;
3940
import org.eclipse.swt.internal.DPIUtil.ElementAtZoom;
4041
import org.eclipse.swt.internal.NativeImageLoader;
4142
import org.eclipse.swt.widgets.Display;
@@ -246,6 +247,26 @@ public void test_loadSingleFrameGifReportedAsAnimation_bug3404() throws IOExcept
246247
}
247248
}
248249

250+
/**
251+
* Regression test for https://github.com/eclipse-platform/eclipse.platform.swt/issues/3545
252+
*
253+
* A one pixel wide RGB image has a row stride of 3 bytes when gdk-pixbuf decodes through glycin.
254+
*/
255+
@Test
256+
public void test_loadOnePixelWideRgbPng_bug3545() throws IOException {
257+
ImageData imageData;
258+
try (InputStream in = getClass().getResourceAsStream("rgb_1x3.png")) {
259+
assertNotNull(in, "Test resource rgb_1x3.png not found");
260+
imageData = new ImageData(in);
261+
}
262+
assertEquals(1, imageData.width);
263+
assertEquals(3, imageData.height);
264+
RGB[] expected = { new RGB(0x00, 0x35, 0x6a), new RGB(0x5b, 0x90, 0xc5), new RGB(0xb6, 0xeb, 0x20) };
265+
for (int y = 0; y < expected.length; y++) {
266+
assertEquals(expected[y], imageData.palette.getRGB(imageData.getPixel(0, y)), "Wrong pixel in row " + y);
267+
}
268+
}
269+
249270
/* custom */
250271
boolean loaderListenerCalled;
251272
}
77 Bytes
Loading

0 commit comments

Comments
 (0)