Discussion:
Alpha blending with Fl_PNG_Image
Chris Russ
2013-03-16 02:21:19 UTC
Permalink
I've been working on a widget that can show images zoomed in and out at arbitrary percentages, and that part works. Now, in the middle of my ::draw() function I want to overlay some RGBA PNG images -- these have transparency where I'd like the underlying image to show up.

I can make the images show up in the right places, but the alpha channel is being completely ignored in this little snippet:

void *baseaddr = (void *)(head->image_->data()[0]);
int imagew = head->image_->w();
int imageh = head->image_->h();
int imaged = head->image_->d();
fl_draw_image((const uchar *)baseaddr, x, y, imagew, imageh, imaged);

head->image_ in this case was an Fl_PNG_Image that should have 4 channels. It has been cast into an Fl_RGB_Image, which should be a compatible type.

But alpha blending isn't happening. I'm getting white where there should be transparency to the pixels previously drawn in the buffer. Instead, I should be getting a blend using the variable opacity in the A channel.

Upon further investigation, the documentation says that the only way to get transparency (and 100% transparency at that) is with an Fl_Pixmap (say, a GIF file), and that is definitely NOT RGB. Even so, would that work where this fails, albeit without the kinds of shadows I'm trying to cast in the PNGs?

The documentation also points out a function called fl_read_image() where I could copy out the area underneath where the PNG is destined to be drawn. Therefore I could do the alpha blend myself and then do a regular fl_draw_image() to put the blended image in place. Is this the only way it will work?

Please advise.

-Chris

P.S. I deeply appreciate your help earlier when I needed to split my Photoshop plug-in into a stub plug-in and then an .exe. Works like a champ.
Ian MacArthur
2013-03-16 08:04:04 UTC
Permalink
Post by Chris Russ
I've been working on a widget that can show images zoomed in and out at arbitrary percentages, and that part works. Now, in the middle of my ::draw() function I want to overlay some RGBA PNG images -- these have transparency where I'd like the underlying image to show up.
void *baseaddr = (void *)(head->image_->data()[0]);
int imagew = head->image_->w();
int imageh = head->image_->h();
int imaged = head->image_->d();
fl_draw_image((const uchar *)baseaddr, x, y, imagew, imageh, imaged);
head->image_ in this case was an Fl_PNG_Image that should have 4 channels. It has been cast into an Fl_RGB_Image, which should be a compatible type.
But alpha blending isn't happening. I'm getting white where there should be transparency to the pixels previously drawn in the buffer. Instead, I should be getting a blend using the variable opacity in the A channel.
Hi Chris,

I think this pretty much ought to work, at least with fltk-1.3.x.

What version are you using?

Anyway, take a look at the unittests demo from the test folder,one of the tabs there is about image blending and such (IIRC the tab is titled "drawing images".

Does that work on your system? ISTR it maybe only works on W32 and OSX, not sure about X11...

Anyway, the code for that tab is in the file unittest_images.cxx, so that might yeild some clues!
Ian MacArthur
2013-03-16 08:11:40 UTC
Permalink
Correction:

I hinted that the unittest_images demo did not work right on X11, but I just fired up a VM to check and it worked fine for me (Ubuntu-12.10 VM) with fltk-1.3.x-r9835
Greg Ercolano
2013-03-16 20:17:20 UTC
Permalink
Post by Chris Russ
But alpha blending isn't happening.
This technique works for me:
http://seriss.com/people/erco/fltk/#AlphaBlend
Albrecht Schlosser
2013-03-17 16:55:25 UTC
Permalink
This post might be inappropriate. Click to display it.
Chris Russ
2013-03-17 21:17:43 UTC
Permalink
Post by Albrecht Schlosser
As Ian and Greg pointed out already, alpha blending works with
FLTK 1.3 (and even with 1.1), but there are some restrictions.
Greg's method works like a champ and I actually found it about 1/2 hour after I posted this in the forum. Thanks!
Post by Albrecht Schlosser
Post by Chris Russ
Upon further investigation, the documentation says that the only way to get transparency (and 100% transparency at that) is with an Fl_Pixmap (say, a GIF file), and that is definitely NOT RGB. Even so, would that work where this fails, albeit without the kinds of shadows I'm trying to cast in the PNGs?
That's not up-to-date anymore, could you give a pointer where
you read it exactly? This documentation should better be updated,
but as I wrote before, the current state of image drawing was not
intended and should be more consistent across platforms. However,
it's not as easy to do it as it might seem, and somebody has to
do it. Patches always welcome...
Here's the link to the documentation that says it:

http://fltk.org/doc-1.3/drawing.html

Search on the page for the word "transparency"...

The documentation also strongly discourages people from using the ->draw() method of widgets.

My problem is solved, thank you. But the docs are, shall we say, confusing.
Albrecht Schlosser
2013-03-18 09:58:13 UTC
Permalink
Post by Chris Russ
Post by Albrecht Schlosser
Post by Chris Russ
Upon further investigation, the documentation says that the only way to get transparency (and 100% transparency at that) is with an Fl_Pixmap (say, a GIF file), and that is definitely NOT RGB. Even so, would that work where this fails, albeit without the kinds of shadows I'm trying to cast in the PNGs?
That's not up-to-date anymore, could you give a pointer where
you read it exactly? This documentation should better be updated,
but as I wrote before, the current state of image drawing was not
intended and should be more consistent across platforms. However,
it's not as easy to do it as it might seem, and somebody has to
do it. Patches always welcome...
http://fltk.org/doc-1.3/drawing.html
Search on the page for the word "transparency"...
Thanks for the link. I'll try to improve this later.
Post by Chris Russ
The documentation also strongly discourages people from using the ->draw() method of widgets.
Yes, and it is important not to call draw() from any callback,
be it a widget's callback or a timer update or any other.

However, if you are already within a draw() method of one widget,
then it is allowed and useful to use other widgets' draw() methods,
e.g. for a group or a complicated widget layout (draw the background
image, then a graph, then another Fl_Box with a bargraph on top of
it, similar to your case).
Post by Chris Russ
My problem is solved, thank you. But the docs are, shall we say, confusing.
Yep, you're right. The entire chapter needs some improvements
and probably some examples. I'll see what I can do when I can
find the time. Thanks for the heads-up.

Albrecht

Loading...