Project: SWT
Bug 88133 Slow rendering with images with transparancy bit set
Reported: 2005-03-15 18:01:03 | Status: resolved fixed

I have come across a severe performance issue when dealing with copying lots of images with transparency bit set to an Image used in a double buffer type painting strategy. This code is straight out of "The definitive guide to SWT and JFace" by Robert Warner with the addition of the loop to draw my tiles. If I use the images t1 and t2 as they are (without setting a transparancy bit) then performance is great. But if I extract the ImageData and set transparentPixel then performance drops off to an unacceptable level. Even if I extract the ImageData and create an new image from that without even setting transparentPixel performance is notably reduced. Here is the main class with the paint event etc.: import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; public class DoubleDoppleGanger { private static final int IMAGE_WIDTH = 100; // The timer interval in milliseconds private static final int TIMER_INTERVAL = 10; private ImageManager im; // The location of the "ball" private int x = 0; private int y = 0; // The direction the "floating image" is moving private int directionX = 1; private int directionY = 1; // We draw everything on this canvas private Canvas canvas; /** * Runs the application */ public void run() { final Display display = new Display(); Shell shell = new Shell(display); shell.setText("Animator Double Buffer"); im = new ImageManager(display); createContents(shell); shell.open(); // Set up the timer for the animation Runnable runnable = new Runnable() { public void run() { animate(); display.timerExec(TIMER_INTERVAL, this); } }; // Launch the timer display.timerExec(TIMER_INTERVAL, runnable); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } // Kill the timer display.timerExec(-1, runnable); display.dispose(); } private void createContents(final Shell shell) { shell.setLayout(new FillLayout()); canvas = new Canvas(shell, SWT.NO_BACKGROUND); canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent event) { // Create the image to fill the canvas Image image = new Image(shell.getDisplay(), canvas.getBounds()); // Set up the offscreen gc GC gcImage = new GC(image); // Draw the background gcImage.setBackground(event.gc.getBackground()); gcImage.fillRectangle(image.getBounds()); int lx = 0; int ly = 0; int i; int j; boolean indent = false; for (i = 0; i < 30; i++) { if (indent) { lx = 32; indent = false; } else { lx = 0; indent = true; } for (j = 0; j < 14; j++) { gcImage.drawImage(ImageManager.t1, lx, ly); lx += 64; } ly += 16; } gcImage.drawImage(ImageManager.t2, x, y); event.gc.drawImage(image, 0, 0); image.dispose(); gcImage.dispose(); } }); } /** * Animates the next frame */ public void animate() { // Determine the ball's location x += directionX; y += directionY; // Determine out of bounds Rectangle rect = canvas.getClientArea(); if (x < 0) { x = 0; directionX = 1; } else if (x > rect.width - IMAGE_WIDTH) { x = rect.width - IMAGE_WIDTH; directionX = -1; } if (y < 0) { y = 0; directionY = 1; } else if (y > rect.height - IMAGE_WIDTH) { y = rect.height - IMAGE_WIDTH; directionY = -1; } // Force a redraw canvas.redraw(); } } And my very simple image management class. tiles_test.png is a large image with several isometric (64x32) tiles on it on a purple background (rgb 127,0,127) which is the transparent bit. import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.graphics.ImageData; public class ImageManager { private Image blob; static Image t1; static Image t2; ImageManager(Display display) { blob = new Image(display, "tiles_test.png"); Image xt1 = new Image(display, 64, 32); ImageData tData = xt1.getImageData(); int purplePixel = tData.palette.getPixel(new RGB(127,0,127)); tData.transparentPixel = purplePixel; t1 = new Image(display, tData); Image xt2 = new Image(display, 64, 32); ImageData tData2 = xt2.getImageData(); tData2.transparentPixel = purplePixel; t2 = new Image(display, tData2); GC dest = new GC(t1); dest.drawImage(blob, 65, 0, 64, 32, 0, 0, 64, 32); GC dest2 = new GC(t2); dest2.drawImage(blob, 0, 0, 64, 32, 0, 0, 64, 32); } } I am not very savy with SWT or Java for that matter and posted this question to eclipse.platform.swt and subsequently asked to post it to the bug list. So my apologies if I am doing something really stupid here. Builder Chad

Files changed in fix:
bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java