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

Josiah Bryan josiahbryan at gmail.com
Tue Mar 20 22:00:42 CET 2012


On Tue, Mar 20, 2012 at 4:22 PM, Christoph Feck <christoph at maxiom.de> wrote:

> 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
>
> Here
>
> https://projects.kde.org/projects/playground/artwork/smaragd/repository/revisions/c71af7bc12611e462426e75c3d5793a87b67f57e/diff
> 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.
>
>
Wonderful - seems to work so far in my basic testing - thank you for your
help!

I've updated my code example with your code:
http://www.jdbryanphotography.com/fullres/main.cpp

Thanks!


>  --
> Christoph Feck
> http://kdepepo.wordpress.com/
> KDE Quality Team
>



-- 
Josiah Bryan
765-215-0511
josiahbryan at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20120320/64054950/attachment.html>


More information about the Interest mailing list