So micro optimizations that you can use when everything else is corrected.
You are calling pri.getHeight() six times in inner loop? It’s static and can be asked one time before both loops. Don’t compare against method call value in loop. Instead call against constant value. When somethin is changed you calculate this cx*pri.getHeight() + cy three times and when not two times. Pre calcualte it.
Make simple code that compiler and JIT can understand more easily and optimize it further. But before you do any of these work with higher level optimizations that are allready told.
And when you ask some about your code make it ready for the reviews. It’s lame excuse to say that there are some old copy paste buggers. Make it easy to other readers spot the right problem and fix everything that you know allready so time is not wasted.
A couple of corrections to things said earlier. There are some general misconceptions with managed images around here!
There are two methods called setRGB, and I’ve only ever seen the issue with images becoming unmanaged mentioned with regard to the other one (that takes an array). I’m not sure it’s still the case there either. It’s still the slower way to do this though.
If the OP is updating the image every frame (and only drawing it once) then there is absolutely no point in worrying about whether the image is managed or not. Drawing into a BufferedImage, even with Graphics2D, happens in software. The image is only synced to video memory when it’s been drawn a couple of times without modification.
If you need to update the pixel array of an image every frame, just grab the pixels array from the raster and stop worrying about whether it’s managed or not (unless you have to draw it lots of times, or rotated / scaled, in which case copying to a VolatileImage first may help).
If you ever need to update an image every frame with Graphics2D, then use a VolatileImage and you have a chance your drawing to (as well as rendering from) the image will be accelerated.
This is the current setup. I’m trying to create a subimage based on the intersection of the image and the master image but it’s still throwing RasterFormatExceptions.
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;
}
}
}
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;
}