[Interest] The "Proper" Way to Mix/Cross-Fade Images

Christoph Feck christoph at maxiom.de
Tue Mar 20 21:22:33 CET 2012

On Tuesday 20 March 2012 14:17:49 Josiah Bryan wrote:
> I may be crazy, or just aiming for something unrealistic. But here
> goes:
> - I want to cross-fade two images over a background. (Simple,
> right?)
> Well, not really. Forgot the "Cross-fading" part - lets just take
> one point in time, a 50/50 opacity (e.g. the two images we're
> cross fading each is at 50% opacity.) What would that look like if
> you just did this straight-forward? (Paint background, paint 1st
> image at .5 opac, paint 2nd image at .5 opac)
> Well, it would look like this:
> http://www.jdbryanphotography.com/fullres/fadetest-bg-renderout.png
> (200px by 200px PNG image)
> (For those who don't want to click - the blue background with the
> word "(bg)" on it is visible through the partial-opacity "B"
> behind the partial-opacity "A")
> This would be coded like:
>     double opac = .5;
>     p.setOpacity(1.0-opac);
>     p.drawImage(0,0,image1);
>     p.setOpacity(opac);
>     p.drawImage(0,0,image2);
>  // render this image now over the background and you get the above
> link's image
> But I don't think the background should show thru - if each image
> is exactly 50% opac, in my (simple) mind, that should "add up to"
> 100% opacity - This is what I want to see:
> http://www.jdbryanphotography.com/fullres/output-goal.png (200px by
> 200px PNG image)
> (No clicky? Solid red background with partial-opacity A over
> partial opacity B)
> However, the "best" so far that I can come up with (without
> cheating) is this:
> http://www.jdbryanphotography.com/fullres/output-bestsofar.png
> (200px by 200px PNG image)
> (No clicky? 75% red bg with same partial-opacity letters.)
> Here's the source of the example (self-contained, 116 lines of
> cpp): http://www.jdbryanphotography.com/fullres/main.cpp
> Using the following images as source:
> http://www.jdbryanphotography.com/fullres/fadetest-A.png
> http://www.jdbryanphotography.com/fullres/fadetest-B.png
> http://www.jdbryanphotography.com/fullres/fadetest-bg.png
> (Basically, I render the image as above, then I create another
> image to use as the alpha channel, extract the alpha channels of
> the first two images (image1 and image2), then render them the
> same way (1.0-opac, draw, opac, draw), then I set the alpha
> channel image as the alpha channel on the first rendered image)
> ** The main problem I can't figure out **
> My main.cpp example linked here would work perfectly for my
> problem, EXCEPT that even when mixing the alpha chan properly, the
> resultant image is 25% darker than it should be - e.g. the solid
> red areas in "-bestsofar.png" are 189 red instead of 255 red.
> Shouldn't 50% of red from fadetest-A.png at pixel X,Y mixed with
> 50% red from fadetest-B.png at the same pixel X,Y be 100% red in
> the output image?
> (Well, I can "force" it to render how I want - just render the
> first image with 100% opacity - see the comment about "Want to
> cheat?" in the main.cpp. But if I cheat, that wouldn't work for
> images that have different areas with different opacities - say
> trying to crossfade between two words (100% opacity) rendered on a
> 30% black background.)
> ** The other (side) problem **
> This method is dog-slow - 4ms for me just to render and set the
> alpha channel (not to mention the 4ms to render the initial mixed
> image.) And thats with a 200x200 image - I'm talking about doing
> this with 1024x768px-sized images - which would (if I extrapolate
> correctly) be about 20-50ms a frame - ouch.
> So it all boils down to this:
> Is there any way to force QPainter (or, heck, just do it on a raw
> OpenGL surface and skip QPainter/QImage all together) to blend
> things where 50% opacity + 50% opacity = 100% opacity in the
> resultant image?
> Or, as some might say, am I just waayyyy off base here? Perhaps the
> mere mention of this idea is causing Porter and/or Duff to want to
> smack me with a stick...I don't know. Any thoughts?
> Anyway, thanks for your thoughts and feedback. Cheers!
> -Josiah

is the code change I did in Smaragd when I faced the same problem.

From what you can see in the deleted code, I tried to render one image 
with "1 - a" and the other image with "a" opacity, but that did not 
work as you noticed. The added helper function solved the issue, but 
it does not handle images of different sizes.

Christoph Feck
KDE Quality Team

More information about the Interest mailing list