views:

334

answers:

2

Hi,

I'm designing a Canvas object which is been used to draw a BufferedImage of size 228x262 pixels.

That image is been drawn using Graphics2D.drawImage(...) method. I'm doing a pixel basis color manipulation within given offset ranges. A sample of the code below:

for( int i = frameOffset; i < colorClock; i++ ) {  
    rgb[i] = new Color(this.colorBK).getRGB();  
    }

Where rbg is set to that bufferedimage I'm changing in.
The problem is that code is painting slow.

I'm creating the image using GraphicsConfiguration.createCompatibleImage, and I'm using double buffering via Buffer Strategy.

Any lights please?

Thanks on adv.

A: 

Don't create a new Color just to extract an RGB integer for every pixel in your image. The only single parameter constructor I can find for Color is one that takes an int RGB - can you not just use colorBK directly?

Also, if you are doing this conversion on every paint that will be slow; you should only need to do the conversion once.

Software Monkey
Hi Monkey, thank you for replying. Actually, I should change the color of certain pixels after a piece of code is executed. The color constructor I'm using to do the conversion is really this one which takes the int RGB but I made some changes and now I can use directly. As long as getRGB() under the hood do some shifts in the bits of the color components, it returns a different value than that one I pass to the constructor. But after minor code changes, I now can do it straight. Thank you. But still, no performance gain.
Leonardo
@Leonardo: The only "change" made by that constructor is to make the alpha value fully opaque: `value = 0xff000000 | rgb;`. This is something you could have easily done without creating a temp object.
Software Monkey
Easy man, you are right. As I said before: "But after minor code changes, I now can do it straight.". I meant that I managed to do it without any temp object. Sorry for my lack of expression abilities.My point thereafter is that, even without the temps I'm still getting performance issues. It's a not big 262x228 BufferedImage, but it's taking time sufficient as for me to see the lines been squashed down at time of drawing. Thank you for the replies.
Leonardo
+1  A: 

If you run the loop every time you draw the image, the loop might be the bottleneck. There is an completely unnecessary object allocation which will make the garbage collector to run quite often.

I'm assuming that colorBK is int. If this is the case, you just create and initialize a Color object and ask it to return a rgb value that is assigned to rgb array. What actually happens is that you assign the value of colorBK in the rgb array. So, equivalent and more efficient implementation would be rgb[i] = colorBK.

To optimize this even more, you could assign the value of colorBK to a final local variable. This would avoid fetching the value of the field over and over again. So the loop could look like this:

final int color = colorBK;
for( int i = frameOffset; i < colorClock; i++ ) {
    rgb[i] = color;
}

To get even more performance gain, you should think that if there is completely different ways of doing this. As the above example just changes some pixels to certain color, I could assume that this could be done with an image and a couple of fillRects.

So you would fill a rect behind the image with the color you want (in this case colorBK). If the image has transparent pixels in those areas the above loop changes they remain unchanged in the canvas and the same effect is gained. This might be more efficient as the graphics methods are better optimized and does not involve heavy array usage.

Lauri
And as others have pointed out in this thread, if the color is constant then this has to be done only once when the image is loaded and not during every paint.
Lauri
Hi Lauri. In fact, graphics methods should be better, but I've already tried it with fillRects before and it was far slower. But as the code is equally far different now than that time, I did fillRects in place of BufferedImage drawing but the performance remained unchanged. Though, I have not tried the behind fillRect trick and I will check it out. Thank you. Probably I have to rethink the whole drawing system.
Leonardo