pixel = array of ARGB pixelsoffset = position of pixel in array to blendsource = color in ARGB format to blend with destination (pixel[offset])alpha = alpha to take into account while blending (between 0-255)

the problem is that sometimes it doesn't blend the alpha properly and instead just replaces the destination alpha with source alpha, can anyone see why this happens?

This bit looks wrong. Assuming your alpha value is in the range 0..255, then that needs to be shifted down.

eg.

1

srcA = (srcA * alpha) >> 8;

In my code I'm also doing the equivalent of

1

srcA = (srcA * (alpha + 1)) >> 8;

which seems to be more accurate.

The second issue may be that Porter-Duff algorithms expect pre-multiplied colour data. You haven't mentioned whether the data is pre-multiplied or not (I'd recommend doing so, as it makes a lot of things easier for both you and the CPU).

If your data isn't pre-multiplied then I'd also change the code above to be

This bit looks wrong. Assuming your alpha value is in the range 0..255, then that needs to be shifted down.

This should be right, as I'm doing a >> 8 shift after, to move it back into the range of a byte.

eg.

1

srcA = (srcA * alpha) >> 8;

In my code I'm also doing the equivalent of

1

srcA = (srcA * (alpha + 1)) >> 8;

which seems to be more accurate.

I will try this, thanks for spotting that.

The second issue may be that Porter-Duff algorithms expect pre-multiplied colour data. You haven't mentioned whether the data is pre-multiplied or not (I'd recommend doing so, as it makes a lot of things easier for both you and the CPU).

If your data isn't pre-multiplied then I'd also change the code above to be

no need to mask it when you know that the left 24 bits will always be zero, same thing applies to srcA.

Nice catch! Must have been a bit too quick on the copy, paste, replace there.

There's a few other potential optimisations too - the immediate one that comes to mind is to replace the 3 checks for alpha==255 with a single if statement. In fact, I'd done that in the first Add composite but none of the others. I must go back to this class and do some tidy up - I haven't looked at it for a while - was just glad it worked at all!

Incidentally, what are you writing a software renderer for? A project of its own or something bigger?

And I know I mentioned it before, but I'd really recommend moving to premultiplied data throughout - it's easier and better performing - trust me, I found out the hard way!

I wasn't happy with the performance of Java2D, especially in regards to colorizing images on the fly; therefore I had to devise something much faster.

Now that I have switched to a software renderer, I get the following benefits:

Able to use any blendmode I want for brushes (Add, Multiply, Over, Overlay, Screen, Darken, etc)

Able to save the state of any pixels I modify without doing a scan beforehand (VERY useful for undo states)

Able to colorize brush pixels on the fly using a simple OR operation: (source << 24) | color, previously in Java2D I had to create a new image, get a graphics context, set alphacomposite, set color and call drawLine(x,y,x,y) for each pixel I wanted to recolor. INSANE speed increase in brush rendering once I made the switch.

Uses much less memory, each brush image (with colors, etc) took about 4kb memory before, and about 1000 would be created for a single stroke, equal to 4MB. With my new software renderer, it is able to use a constant 400kb per brush (for 100 sizes)

overall, the software renderer is about 15x faster than Java2D and also supports blendmodes, state saving, etc, its a win-win situation.

I might switch to TYPE_ARGB_PRE later, if required, but I've actually tried it before and it results in weird artifacts when I zoom in, i'll save it for investigation on another day

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org