HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Drawing a bufferedimage into another

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
bufferedimageintodrawinganother

Problem

For what I'm doing, I need to be able to draw a buffered image directly into a larger buffered image. I've searched around a little and still have failed to find a better way, but my current way is extremely inefficient and I would like a better way if it's possible. Any improvements onto this design would also be great, even if it's not a totally separate way.

public static final void drawOntoBI(final BufferedImage on, final BufferedImage draw, final int x, final int y)
{
    // Calls method instead of needing to call them every loop
    final int width = draw.getWidth(), height = draw.getHeight(), onwidth = on.getWidth(), onheight = on.getHeight();
    // Stores temporary variables so they wont be recalculated
    int x3, y3;
    // Goes through all of the pixels in the drawn image to copy them
    for(int x2 = 0; x2  onwidth - 1 || x3  onheight - 1 || y3 < 1) break;
            // Draws the pixel on the image where it needs to be from the x and y looped in the image
            on.setRGB(x3, y3, draw.getRGB(x2, y2));
        }
    }
}


This is the second biggest bottleneck on my program, so it really is important to be improved. It's called all the time, and is rather slow. Memory isn't an issue, so memory-using methods can be considered.

Solution

Java Native Solution

The solution Java offers for adding two BufferedImages should be faster than anything that you will program yourself:

/**
  * prints the contents of buff2 on buff1 with the given opaque value.
  */
 private void addImage(BufferedImage buff1, BufferedImage buff2,
         float opaque, int x, int y) {
     Graphics2D g2d = buff1.createGraphics();
     g2d.setComposite(
             AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opaque));
     g2d.drawImage(buff2, x, y, null);
     g2d.dispose();
 }


Your Code

As I said, if you remove the unnecessary x3 checks, you would at least save two comparisons for each loop of y2 (and those can really add up).

You can also move the onheight - 1 and onwidth - 1 computations outside the loop.

If most of the time the smaller image does fit into the larger image, you can also remove the bounds check completely. Create two new methods. One for when the image fits - no bound checks necessary - and one for when it does not fit (here you obviously still need the check). Then in your main method, you check once if the image would fit and use the quicker method without bounds check. If it does not fit, you use the method with bounds check.

If the smaller image does not fit most of the time, you could also first crop the smaller image (if it does not fit), so that it does always fit. I doubt that it will be faster, but it is worth a try.

Code Snippets

/**
  * prints the contents of buff2 on buff1 with the given opaque value.
  */
 private void addImage(BufferedImage buff1, BufferedImage buff2,
         float opaque, int x, int y) {
     Graphics2D g2d = buff1.createGraphics();
     g2d.setComposite(
             AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opaque));
     g2d.drawImage(buff2, x, y, null);
     g2d.dispose();
 }

Context

StackExchange Code Review Q#58067, answer score: 4

Revisions (0)

No revisions yet.