Issues with transparent png's and fading

Hello wxPython-users! I'm realtively new to wxPython and am getting to
grips with image display one it at present. I'm hoping someone can
help me an issue relating to png's, transparency and alpha values.
As I understand it, the akpha value of a png controls it's
transparency and that by varying the alpha value (from 1.0 down to
0.0) you could in effect make an image fade out.

I've written a wx.Panel inheritor that displays an image within a
frame, and then after a few seconds, fades it out. This fading
nominally works, but the issue I'm getting is that my png fades out in
a rather luminescent shade of green,

This is the image once it's started it's fade out: http://i.imgur.com/O0Xyk.png
and this is the source .png: http://i.imgur.com/X1IxT.png

The core of the code I'm using to fade out is this:
<code>
def _RenderBitmap(self):
        self.image = wx.Image(self.path, wx.BITMAP_TYPE_ANY)
        self.image = self.image.AdjustChannels(1.0, 1.0, 1.0,
self.alpha)
        self.bitmap = self.image.ConvertToBitmap()
</code>

where self.alpha controls the fade amount (between 1.0 and 0.0). This
code is called by the original OnPaint(...) event and then again when
I want to re-render with self.Refresh() (on the wx.Panel subclass)

Does anyone have any experience with something like this? I've played
with the alpha channel in GIMP but even when setting a specific colour
as the alpha I still get the green coming through (http://i.imgur.com/
zDh1y.png)

This was a simple one to fix: there was code someone else had written
adding in a bright luminescent green background, commenting it out got
rid of that lurid green tone.
However the issue still remains - I can't get a png to fade out
without the background popping through. With the green suppressed, I
just get the standard gray background appearing instead.

As you might expect in flickering, I'm running Windows :slight_smile:

Windows 7
wx 2.8.11.0 (msw-unicode)
Python 2.7

The code I'm running in my fader class can be found here:

···

On Jul 18, 11:20 am, aodj <alexodonovanjo...@googlemail.com> wrote:

Hello wxPython-users! I'm realtively new to wxPython and am getting to
grips with image display one it at present. I'm hoping someone can
help me an issue relating to png's, transparency and alpha values.
As I understand it, the akpha value of a png controls it's
transparency and that by varying the alpha value (from 1.0 down to
0.0) you could in effect make an image fade out.

I've written a wx.Panel inheritor that displays an image within a
frame, and then after a few seconds, fades it out. This fading
nominally works, but the issue I'm getting is that my png fades out in
a rather luminescent shade of green,

This is the image once it's started it's fade out:http://i.imgur.com/O0Xyk.png
and this is the source .png:http://i.imgur.com/X1IxT.png

The core of the code I'm using to fade out is this:
<code>
def _RenderBitmap(self):
self.image = wx.Image(self.path, wx.BITMAP_TYPE_ANY)
self.image = self.image.AdjustChannels(1.0, 1.0, 1.0,
self.alpha)
self.bitmap = self.image.ConvertToBitmap()
</code>

where self.alpha controls the fade amount (between 1.0 and 0.0). This
code is called by the original OnPaint(...) event and then again when
I want to re-render with self.Refresh() (on the wx.Panel subclass)

Does anyone have any experience with something like this? I've played
with the alpha channel in GIMP but even when setting a specific colour
as the alpha I still get the green coming through (http://i.imgur.com/
zDh1y.png)

This was a simple one to fix: there was code someone else had written
adding in a bright luminescent green background, commenting it out got
rid of that lurid green tone.
However the issue still remains - I can't get a png to fade out
without the background popping through. With the green suppressed, I
just get the standard gray background appearing instead.

What are you expecting? The panel and whatever frame or other container you put it in are going to have their own backgrounds...

If you want it to fade away entirely and show only what is under the whole window (other windows or the desktop) then you can use SetTransparent on the frame that contains your image panel. There is an example here:

http://wiki.wxpython.org/Transparent%20Frames

As you might expect in flickering, I'm running Windows :slight_smile:

Windows 7
wx 2.8.11.0 (msw-unicode)
Python 2.7

The code I'm running in my fader class can be found here:
wx fader - Pastebin.com

There are some other problems in this code:

* You are rebinding the timer event handlers without clearing out the old bindings first. Since you call Skip then you'll end up with each bound handler being called on each timer event. This results in redoing your fade out over and over again, even before the prior ones are finished. A better approach would be to precreate 2 timers, and only do the event binding once. You can then associate each handler with a specific timer by passing it to the Bind method.

* I added the use of a buffered paint DC and also self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) to eliminate flicker.

* The event.Skip in the paint event handler also probably contributed to the flicker. You should not call Skip if you "fully handle" an event, and when painting a window you do.

fade.py (2.47 KB)

···

On 7/18/11 9:23 AM, aodj wrote:

--
Robin Dunn
Software Craftsman

aodj wrote:

However the issue still remains - I can't get a png to fade out
without the background popping through. With the green suppressed, I
just get the standard gray background appearing instead.

Well, yes, that's exactly what it's supposed to do. When you specify an
alpha of 50%, that blends 50% of your image with 50% of the background.

If you simple want your image to fade to black, then you just need to
adjust the brightness of the image, not the alpha. You want the alpha
to stay at 100% but have the pixels go to 0.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

I took your suggestions on board, and this is where I'm at now:

I've three timers: fade in, show for duration and then fade out.

The main problem I've run into wasn't the colour shining through, as I
initially thought, but rather than when the panel flickered, the
background colour would conflict with the background image on the
panel behind it.

What I did was to handle this in the EVT_ERASE_BACKGROUND event, and
catch the background of the parent, and place it there instead of a
singular background colour.

This way, you don't see a grating colour appear when it flickers, and
the alpha fade out does so with respect to the 'proper' background
image in my application rather than a particular background colour.

With regards to your buffered DC, that actually seems to make the
flickering worse, and incidentally stops the fadeout to background
image I've set up.

I'm really grateful for all your ideas and guidelines, since wxPython
is new ground to me, and as you can probably tell from the code I
wrote, I've been hacking snippets of code I've found on the internet
just trying to get the basics to work :slight_smile:

···

On Jul 18, 5:29 pm, Robin Dunn <ro...@alldunn.com> wrote:

On 7/18/11 9:23 AM, aodj wrote:

> This was a simple one to fix: there was code someone else had written
> adding in a bright luminescent green background, commenting it out got
> rid of that lurid green tone.
> However the issue still remains - I can't get a png to fade out
> without the background popping through. With the green suppressed, I
> just get the standard gray background appearing instead.

What are you expecting? The panel and whatever frame or other container
you put it in are going to have their own backgrounds...

If you want it to fade away entirely and show only what is under the
whole window (other windows or the desktop) then you can use
SetTransparent on the frame that contains your image panel. There is an
example here:

http://wiki.wxpython.org/Transparent%20Frames

> As you might expect in flickering, I'm running Windows :slight_smile:

> Windows 7
> wx 2.8.11.0 (msw-unicode)
> Python 2.7

> The code I'm running in my fader class can be found here:
>wx fader - Pastebin.com

There are some other problems in this code:

* You are rebinding the timer event handlers without clearing out the
old bindings first. Since you call Skip then you'll end up with each
bound handler being called on each timer event. This results in redoing
your fade out over and over again, even before the prior ones are
finished. A better approach would be to precreate 2 timers, and only do
the event binding once. You can then associate each handler with a
specific timer by passing it to the Bind method.

* I added the use of a buffered paint DC and also
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) to eliminate flicker.

* The event.Skip in the paint event handler also probably contributed to
the flicker. You should not call Skip if you "fully handle" an event,
and when painting a window you do.

--
Robin Dunn
Software Craftsmanhttp://wxPython.org

fade.py
2KViewDownload