Sign in to follow this  

Colour Blending

This topic is 3720 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I am making a simple game in Java using BufferedImage's as neon effect bricks (breakout style), where these images overlap I have written a routine to blend the colours, which looks fine but is not very efficient. Does anyone have any suggestions how to do this in a better, more efficient way, my code is as follows - (it basically takes in two colours (int's) mixes the two together and returns the blended colour). private int blendColours(int colour1, int colour2){ int n_red; int n_green; int n_blue; int i_red; int i_green; int i_blue; int s_red; int s_green; int s_blue; int s_alpha; s_red = (colour1 >> 16) & 255; s_green = (colour1 >> 8) & 255; s_blue = colour1 & 255; s_alpha = (colour2 >> 24)&255; i_red = (colour2 >> 16) & 255; i_green = (colour2 >> 8) & 255; i_blue = colour2 & 255; //apply on-screen blend n_red = 255 - ((255 - s_red)*(255-i_red)/255); n_green = 255 - ((255 - s_green)*(255-i_green)/255); n_blue = 255 - ((255 - s_blue)*(255-i_blue)/255); return n_blue | (n_green << 8) | (n_red << 16) | (s_alpha <<24); } Cheers Mark

Share this post


Link to post
Share on other sites
you can blend two colors together by a percentage, and I am guessing you are archiving for like a 50% blend.

So the method I like to use is this:

percent = 0.5; //what ever you want to use between 0.0 and 1.0

new_red = ((color1_red * percent) + (color2_red * (1.0f - percent)));
new_green = ((color1_green * percent) + (color2_green * (1.0f - percent)));
new_blue = ((color1_blue * percent) + (color2_blue * (1.0f - percent)));

So maybe this can help you.

Share this post


Link to post
Share on other sites
The speed problem is almost certainly not due to your blending function, but due to trying to grab every pixel to blend from each Image, one at a time, applying the function, and then writing back a colour value. In general (and I do mean *in general* - across multiple languages and UI/graphics toolkits/APIs), Image objects don't like you messing with their data manually: you can do things much faster by letting them do the work. It should be their responsibility, after all. (Specifically, per-pixel accessors/mutators tend to be a little slow, e.g. because of "locking"/"unlocking" resources in the underlying implementation, and that overhead adds up.)

In the case of the Java standard library, I think what you really want to do is much simpler: just get the Graphics of the "background" Image, and .drawImage the "foreground" Image on top at the appropriate location (possibly setting a clip first).

Share this post


Link to post
Share on other sites
Quote:
Original post by ZahlmanIn the case of the Java standard library, I think what you really want to do is much simpler: just get the Graphics of the "background" Image, and .drawImage the "foreground" Image on top at the appropriate location (possibly setting a clip first).


Yep...

A general overview of the Graphics2D operations.

Depending on how exactly you're doing this, you might need to create alpha masks and blend in several steps, but by now (java 1.6), all these operations should be done in hardware, so the cost should be quite low (and definitely much faster than per-pixel blend).

Enabling anti-aliasing may also improve the rendering.

Share this post


Link to post
Share on other sites
If you look at the code, he's multiplying the colors together (or, actually, multiplying their inverses and inversing the result). In order to do it using primitives, he'll need to be able to invert an image and multiple images. Are both of those supported in a java API?

Share this post


Link to post
Share on other sites
Quote:
Original post by Extrarius
If you look at the code, he's multiplying the colors together (or, actually, multiplying their inverses and inversing the result). In order to do it using primitives, he'll need to be able to invert an image and multiple images. Are both of those supported in a java API?


I did Java2D rendering last in Java 5.0, so I'm not up to date.

The overview of accelerated features suggests
Quote:
Composite
All 12 Porter-Duff rules defined by the AlphaComposite class can be accelerated by OpenGL. Likewise, if XOR mode is set, then we will use OpenGL's XOR logic operation to accelerate XOR rendering. For custom Composite implementations, we will fall back on our software pipelines to complete the operation.
that all AlphaComposite accelerations will be done using OGL (this is all still Java2D, not native openGL bindings via third-party libraries).

Last I checked, J6.0 improved on this.

Share this post


Link to post
Share on other sites
As far as the code he posted.. obviously one of the biggest dogs in it is his 3 divisions by 255 .. those 3 instructions are slower than all of the rest of them combined..

...change those divisions to shift rights by 8

Sacrificing that itty bitty bit of accuracy for the use of a low latency instruction, rather than using just about the worst instruction possible on a modern cpu

Share this post


Link to post
Share on other sites
Thanks to everyone who has replied, some of the suggestions have been a big help. The actual effect that I am using is described better here http://www.pegtop.net/delphi/articles/blendmodes/screen.htm it is like a Photoshop screen blend. I have posted an image of my program here http://www.codeaddict.co.uk/

The fps is really high but this is because the blend routine only occurs when a 'brick' is removed from the wall to refresh the remaining 'bricks'.

I realize that by changing each pixel in the image individually it is having a major impact on performance, but I cannot see any other way to achieve this effect without doing so. I guess that I could use openGL, perhaps via JOGL, but I was hoping that there was some simpler solution in Java - ideally using hardware acceleration.

Thanks

Mark

Share this post


Link to post
Share on other sites

This topic is 3720 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this