Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 348919

Summary: getImageData() returns on Win7 BGR color-format instead of RGB
Product: [Eclipse Project] Platform Reporter: Missing name <eclipse>
Component: SWTAssignee: Platform-SWT-Inbox <platform-swt-inbox>
Status: RESOLVED NOT_ECLIPSE QA Contact:
Severity: normal    
Priority: P3 CC: eclipse.felipe
Version: 3.6.1   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description Missing name CLA 2011-06-09 11:32:04 EDT
Build Identifier: Build id: 20100917-0705

I'm trying this: Creating an image using the given image data:

ImageData imageData = new ImageData(m_width, m_height, 24, new PaletteData(0xff0000, 0xff00, 0xff));
imageData.type = SWT.BITMAP;

Then calling getImageData(). On this image data, on Win7 I have to use the BGR format while using setPixel(). On my linux it returns the RGB format. Both platform types ignore the given palette mask data in my first image data.

Reproducible: Always

Steps to Reproduce:
1. create an image with RGB palette
2. get an image data from that image
3. draw a pixel using RGB
4. create a new image from the given image data
5. the new image shows read and blue colors swapped!

If I create an ARGB image, I get the mirrored BGRA format using getImageData().

I think, this is a bug, because Win and Linux behave differently.
Comment 1 Felipe Heidrich CLA 2011-06-10 14:22:57 EDT
Works for me:

    public static void main(String[] args) {
        final Display display = new Display();
        Shell shell = new Shell(display);
        shell.setBounds(10,10,750,500);
        ImageData imageData = new ImageData(16, 16, 24, new	PaletteData(0xff0000, 0xff00, 0xff));
        for (int y = 0; y < 16; y++) {
        	for (int x = 0; x < 16; x++) {
        		imageData.setPixel(x, y, 0xff0000);
        	}
		}
        final Image image = new Image(display, imageData);
        shell.addListener(SWT.Paint, new Listener() {
			public void handleEvent(Event e) {
				e.gc.drawImage(image, 10, 10);
			}
		});

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }


please send a snippet that shows the problem.
Comment 2 Missing name CLA 2011-06-10 15:41:50 EDT
Hello Felipe, no, you didn't understand my problem :) I try to explain it better:

Replace in your code the following line:

ImageData imageData = new ImageData(16, 16, 24, new   
PaletteData(0xff0000, 0xff00, 0xff));

... with this ...

ImageData imageData = new ImageData(16, 16, 24, new   
PaletteData(0xff0000, 0xff00, 0xff));
Image tempImage = new Image(display, imageData);
imageData = tempImage.getImageData(); // should contain the same palette, but it doesn't
tempImage.dispose()

Now you have an image data that should be the same as the first one. But it isn't. On Windows now the palette defines a BGR format. Take a look in Image.getImageData() source code, you can find there code like this: = new PlaetteData(0xff, 0xff00, 0xff0000). This defines the "wrong" BGR format. It should be (0xff0000, 0xff00, 0xff) (RGB), or better, it should be the original palette, that was defined in the original image data. On linux, this code works correctly (I mean for RGB, I didn't try to use BGR on linux, maybe there is RGB hardcoded, which is wrong for palettes not equal to RGB).

I hope, you understand now, what I mean.
Comment 3 Felipe Heidrich CLA 2011-06-13 10:39:50 EDT
Image tempImage = new Image(display, imageData);
imageData = tempImage.getImageData(); // should contain the same palette, but
it doesn't


That is no true, sorry. We need to convert to an image data that the OS supports when creating an image.
Comment 4 Missing name CLA 2011-06-14 03:39:36 EDT
(In reply to comment #3)
> Image tempImage = new Image(display, imageData);
> imageData = tempImage.getImageData(); // should contain the same palette, but
> it doesn't
> 
> 
> That is no true, sorry. We need to convert to an image data that the OS
> supports when creating an image.

Yes, the internals are ok. But for the user it is a bit confusing.

I was confused doing this: I have an Image, that represents my buffer. It is painted in an own thread on the GUI. An another thread receives pixel data from the network and paints it on the image.

To do this, I need to append pixels on the buffer image. So, my first solution was to get the image data, draw the pixels, and rebuild the image. But this ends in swapping the RED and BLUE channels every frame.

You said, you need to convert to OS representation. Then why the returned image data has a BGR palette, but the image still needs RGB to be drawn correctly on the same OS?? Sorry, but this is a bug (or confusing feature that needs to be fixed) in my opinion.



Btw.: my next solution is to store the initial image data and modify it. Then always create an image from this initial image data. No mor calling getImageData() is needed. :) But this is only an improvement to my own code, no fix for the mentioned problem.
Comment 5 Felipe Heidrich CLA 2011-06-17 15:26:05 EDT
why don't change your code to use (and respect) the imagedata that is actually in the image instead of using the image data passed in the constructor ?


Besides, if you need to change an Image why not create a GC in it, draw on top, dispose the GC ?

Sorry, this is a bug in the application code, closing again.