Search code examples
canvasswt

Get Image from Canvas after drawing shapes in SWT


I´m trying to get an Image object based on a Canvas in SWT, first I´m drawing some random shapes to fill the canvas, then I try to get the image and read the image pixels like this:

canvas.addPaintListener(new PaintListener() {
        public void paintControl(PaintEvent e) {
            // Draw 100 random shapes
            for(int a=0; a<100; a++) {
                e.gc.setBackground(randomColor());
                e.gc.fillOval(randomPosition(), randomPosition(), randomSize(), randomSize());
            }
                    
            // Create image based on canvas
            Image img = new Image(display, canvas.getBounds());
            GC imageGC = new GC(img);
            canvas.print(imageGC);
            imageGC.dispose();

            ImageData imageData = img.getImageData();

            int width = imageData.width;
            int height = imageData.height;

            // Get pixels
            int[] pixels = new int[width * height];
            imageData.getPixels(0, 0, width * height, pixels, 0);

            // Display RGB values of each pixel
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int pixelValue = pixels[y * width + x];
                    
                    int red = pixelValue & 0xFF;
                    int blue= (pixelValue >> 16) & 0xFF;
                    int green = (pixelValue >> 8) & 0xFF;

                    System.out.println("Color of pixel (" + x + ", " + y + "): RGB(" + red + ", " + green + ", " + blue + ")");
                }
            }
        }
    });

But it always displays the following as if the Canvas was empty:

Color of pixel (0, 0): RGB(0, 0, 0)
Color of pixel (1, 0): RGB(0, 0, 0)
Color of pixel (2, 0): RGB(0, 0, 0)
Color of pixel (3, 0): RGB(0, 0, 0)
Color of pixel (4, 0): RGB(0, 0, 0)
...

Does anyone knows why the Canvas seems to be empty even if I can see the shapes in the screen?


Solution

  • A paint listener should only paint the control. Exactly when the drawing is written to the control is not defined and may vary between platforms. You should assume that it is not done until the code returns from the paint listener.

    As an example of the variations in behaviour your code produces a stack overflow on macOS because the paint event is called recursively by the print call.

    So the print and the code to extra the data should be done separately from the paint.