Rendering Performance Issues

The first answer here is useful for copying an image:

I’m not using that method anymore, but you’re right that it’s useful. Thanks for finding it! I will keep it in mind if I ever use it some other time.

What is your point?

This draws a pixel-array onto another pixel-array. I get around 2200 fps on an i5

	public void draw(ArrayImage a, int xp, int yp) { //Draw a normal tile
		for (int y = 0; y < a.height; y++) {
			int yPixel = y + yp;
			if (yPixel < 0 || yPixel >= height) continue;

			for (int x = 0; x < a.width; x++) {
				int xPixel = x + xp;
				if (xPixel < 0 || xPixel >= width) continue;	

				int srcPixel = a.pixels[x + y * a.width];
				if (srcPixel < 0 /*if <0 srcPixel is meant to be transparent*/) pixels[xPixel + yPixel * width] = srcPixel;													
			}
		}
	}

Without knowning the dimensions of those pixel-arrays, it’s a meaningless statistic :slight_smile:

Yeah pardon, i forgot it reaches 2200 fps with nothing on the screen, just filling it with zeros every iteration :stuck_out_tongue:

Also its 640x500

I think I might scrap this whole thing and just invoke drawImage on the Graphics2D created by the BufferStrategy.

Does anyone know why BufferStrategy.drawImage is SO much faster than BufferedImage.drawImage?

Why not just use System.arraycopy to copy a region of your image?

	/**
	 * Quickly copies the specified pixels from the source image to the destination image.
	 * @param src the source image
	 * @param dst the destination image
	 * @param srcX the x position of the source image to start copying
	 * @param srcY the y position of the source image to start copying
	 * @param srcW the width of the section to copy from source
	 * @param srcH the height of the section to copy from source
	 * @param dstX the x position to place the copied pixels at on the destination image
	 * @param dstY the y position to place the copied pixels at on the destination image
	 */
	public void copyPixels(BufferedImage src, BufferedImage dst, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY) {
		int[] srcbuf = ((DataBufferInt)src.getRaster().getDataBuffer()).getData();
		int[] dstbuf = ((DataBufferInt)dst.getRaster().getDataBuffer()).getData();
		int srcOff = srcX + srcY * src.getWidth();
		int dstOff = dstX + dstY * dst.getWidth();
		for (int y=0; y<srcH; y++) { //copy every row of src starting at offset
			System.arraycopy(srcbuf, srcOff, dstbuf, dstOff, srcW);
			srcOff += src.getWidth();
			dstOff += dst.getWidth();
		}
	}

EDIT: If you’re loading images with ImageIO, they may not be TYPE_INT_ARGB. You can convert them easily like so:

		if (image.getType()!=BufferedImage.TYPE_INT_ARGB) {
			BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
			convertedImage.createGraphics().drawRenderedImage(image, null);
			image = convertedImage;
		}

Is that faster than just doing BufferStrategy.drawImage?

Not to mention it has nothing to do with drawing performance, that’s just looping through arrays and setting their values.

It’s like measuring how long a for loop takes.

int[] array = new array[1920*1080];

for (int i = 0; i < array.length; i++) {
array[i] = (int) System.currentTimeMillis();
}

Doing this loop 60 times takes about ~0.07 seconds. looping through 600 times ~0.6 seconds. looping through 1200 times ~1.2seconds.

The statistic is meaningless because it doesn’t really have anything to do with frames per second or drawing. Am I wrong?

[EDIT]
Also, I made a super awesome illustrative image of what happens to an image when you turn it into an array of ints! (Row major order)

Before: BufferedImage = new BufferedImage(width, height);

After: int[] array = new int[width*height];

In the end, rendering is nothing more or less than moving data around.

I would guess yes… Unless you’re copying huge sections, in which case drawImage might take advantage of OpenGL acceleration (assuming it’s enabled).

If this kind of performance is necessary, just benchmark it yourself.

Well my point is that if it takes less than a second to loop and alter 2 073 600 000 pixels ( 1000 * 1920 * 1080 ), performance is a non issue. :o

My fps dropped by around 250 frames when using your method as compared to just drawImage.

I pretty much answered this in my previous post on this thread (bearing in mind that BufferStrategy is most likely using VolatileImage)

Now you have. Before you didn’t mention that BufferStrategy most likely uses a VolatileImage.

My method wasn’t intended to be used every frame. It’s just a quick way to copy pixels from one image to another, without dealing with volatile images / video memory / etc.

You’ve changed your questions so many times that I’m no longer really sure what your current problem is or what you’re trying to accomplish…

What seems to be the problem here??

[quote]I’m trying to do pixel-by-pixel rendering to an image using for loops. I have an int array where pixel data is written to, and then, once per frame, that array is rendered to the BufferedImage.
[/quote]

BufferedImage image = new BufferedImage(WIDTH, HEIGHT,
			BufferedImage.TYPE_INT_RGB);
	int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer())
			.getData();
BufferStrategy s = getBufferStrategy();
		if (s == null) {
			createBufferStrategy(2);
		}

		for (int i = 0; i < pixels.length; i++) {
			pixels[i] = i + (int)System.currentTimeMilllis();
		}

                drawImageAt(10, 20, someImage);

		Graphics g = bs.getDrawGraphics();
		g.drawImage(image, 0, 0, null);
		g.dispose();
		bs.show();
public void drawImageAt(int x, int y, BufferedImage img) {
    int[] pixies = img.getRGB(0,0, img.getWidth(), img.getHeight(), null, 0, img.getWidth() );
    
    for (int yy = 0; yy < img.getHeight(); yy++) {
       for (int xx = 0 ; xx < img.getWidth(); xx++) {
           pixels[ (y+yy) * image.getWidth() + x + xx ] = pixies[y*img.getWidth() + x];
}
}
}

This statement doesn’t mean anything else than ‘it got slower’.

If the framerate dropped from 2500fps to 2250fps, that means it took 0.04ms
If the framerate dropped from 300fps to 50fps, that means it took 16.67ms