transparent part of advanced splash not working right

I feel like this must have been addressed but I couldn’t find it in the archive. I have a splash screen using AdvancedSplash that has some transparent parts. The bitmap is a GIF (made with GIMP…from a previous question, I was under the impression that making a .GIF would eliminate this sort of problem) that has an alpha channel for the transparent parts.

I’ve noticed that on XP, it looks good…unless I move other windows behind the splash while it is shown and in that case the transparent parts “pick up” parts of the other windows into them. On Windows 7, the transparent parts are just black the whole time.

What’s the right way to do this so the splash’s transparent parts are truly transparent and stay transparent, cross-platform?

(wx2.8.10, Python 2.5, WinXP or Win7…haven’t tried with Ubuntu yet)

Thanks,
Che

Hi Che,

I feel like this must have been addressed but I couldn't find it in the
archive. I have a splash screen using AdvancedSplash that has some
transparent parts. The bitmap is a GIF (made with GIMP...from a previous
question, I was under the impression that making a .GIF would eliminate this
sort of problem) that has an alpha channel for the transparent parts.

I've noticed that on XP, it looks good...unless I move other windows behind
the splash while it is shown and in that case the transparent parts "pick
up" parts of the other windows into them. On Windows 7, the transparent
parts are just black the whole time.

What's the right way to do this so the splash's transparent parts are truly
transparent and stay transparent, cross-platform?

As far as I know, the AdvancedSplash demo works on all the platforms
and it uses a PNG (if you look in the agw demo folder, under the
"bitmaps" folder there is an image called "advancedsplash.png").

That said, I have tried the AdvancedSplash demo on XP, Vista, 7 and
Ubuntu and it seems to me it is doing the right thing. Can you try
creating a PNG instead? If there something is not working, it can
either be a bug on AdvancedSplash or some issue on shaped-frames at
the wxWidgets level.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

···

On 9 July 2011 09:34, C M wrote:

Thanks, Andrea, but unfortunately saving it as a .PNG didn’t help–it has the same problem. I think I am creating the transparent parts incorrectly in GIMP or something, since on my computer your splash screen for the AdvancedSplash in the demo doesn’t have this problem (that is, when I move other windows under it, the transparent parts don’t become “dirty” with pixels from those other windows).

In GIMP, when I create my PNG, I start with an image, add an alpha channel, then select the regions I want to be transparent and Clear them (leaving the grey-on-grey checkerboard pattern there, indicating a transparent region), then I save it as a .PNG file (or, previously, a GIF file).

Should I be doing it some other way?

A while back, Robin had this to say about a possibly related problem I had:

“I suspect that what is happening is that your resized PNG is being saved with an 8-bit alpha channel instead of a 1-bit transparency
mask and so you are not getting a shaped region (other than something like a single rectangle for the whole image.) You can try fiddling with
the alpha-channel/mask in GIMP, or you can convert the alpha to a mask at runtime with wx.Image.”

Could this be the same issue here? If so, I think I need some help in carrying out those steps.

Thanks,
Che

···

On Sat, Jul 9, 2011 at 6:20 AM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi Che,

On 9 July 2011 09:34, C M wrote:

I feel like this must have been addressed but I couldn’t find it in the

archive. I have a splash screen using AdvancedSplash that has some

transparent parts. The bitmap is a GIF (made with GIMP…from a previous

question, I was under the impression that making a .GIF would eliminate this

sort of problem) that has an alpha channel for the transparent parts.

I’ve noticed that on XP, it looks good…unless I move other windows behind

the splash while it is shown and in that case the transparent parts "pick

up" parts of the other windows into them. On Windows 7, the transparent

parts are just black the whole time.

What’s the right way to do this so the splash’s transparent parts are truly

transparent and stay transparent, cross-platform?

As far as I know, the AdvancedSplash demo works on all the platforms

and it uses a PNG (if you look in the agw demo folder, under the

“bitmaps” folder there is an image called “advancedsplash.png”).

That said, I have tried the AdvancedSplash demo on XP, Vista, 7 and

Ubuntu and it seems to me it is doing the right thing. Can you try

creating a PNG instead? If there something is not working, it can

either be a bug on AdvancedSplash or some issue on shaped-frames at

the wxWidgets level.

Andrea.

I believe The Gimp works like Adobe Photoshop: When an area is selected in an image that has a transparency layer and then the key is pressed, that area is made 100% transparent (0% opaque). Transparency has values in [0…255]. This variable transparency is called “alpha”. Often the transparency channel / layer / plane is called the alpha channel / layer / plane.

Here’s some conversions

wxBmap = wx.Bitmap( 'myGraphicsFile.PNG', wx.BITMAP_TYPE_ANY )

wxImg = wx.Image( 'myGraphicsFile.PNG', wx.BITMAP_TYPE_ANY )

You can then use :

wxBmap = wxImage.ConvertToBitmap()

wxImg = wx.ImageFromBitmap( wxBmap )

By the way, both types can be directly saved to disk files :

wxImg.SaveFile( 'myFilename.PNG', wx.BITMAP_TYPE_PNG )

and
wxBmap.SaveFile( ‘myFilename.PNG’, wx.BITMAP_TYPE_PNG )

Other file type constants are available.

Hope this helps.
Ray

This is how to convert alpha values into mask values.

import array
import wx

app = wx.App( redirect=False ) # No Frame or MainLoop, but can call all methods.

filename = ‘Toucan.PNG’
wxImg = wx.Image( filename, wx.BITMAP_TYPE_ANY )

hasMask = wxImg.HasMask()
hasAlpha = wxImg.HasAlpha()
print '---- hasMask, hasAlpha = ', hasMask, hasAlpha

Threshold the transparency layer values to [0, non-zero].

if hasAlpha : # Is always mutually exclusive with hasAlpha.

# Get the alpha values
alphaTransparencyString = wxImg.GetAlphaBuffer()
alphaTransparencyStringLen = len( alphaTransparencyString )

maskThreshhold = 128             # Use any suitable value [0..255].
maskTransparencyArray = array.array( 'B' )     # chr = unsigned int8
maskTransparencyArray.fromstring( alphaTransparencyString )

for index in xrange( alphaTransparencyStringLen ) :
   
    aTranspValue = maskTransparencyArray[ index ]
   
    if index > int( 0.99 * alphaTransparencyStringLen) :
        print 'alpha =', aTranspValue ,
   
    if (aTranspValue < maskThreshhold) :
        maskTransparencyArray[ index ] = 0
    else :
        maskTransparencyArray[ index ] = 255    # Can set to any value [1..255]
    #end if
   
    if index > int( 0.99 * alphaTransparencyStringLen) :
        print '-->', maskTransparencyArray[ index ]
   
#end for

maskTransparencyString = maskTransparencyArray.tostring()

#end if

newWxImg = wxImg
newWxImg.SetAlphaData( maskTransparencyString )
newWxImg.SaveFile( ‘Toucan_New_Image.PNG’, wx.BITMAP_TYPE_PNG )

newWximport array
import wx

app = wx.App( redirect=False ) # No Frame or MianLoop, but can call all methods.

filename = ‘Toucan.PNG’
wxImg = wx.Image( filename, wx.BITMAP_TYPE_ANY )

hasMask = wxImg.HasMask()
hasAlpha = wxImg.HasAlpha()
print '---- hasMask, hasAlpha = ', hasMask, hasAlpha

Threshold the transparency layer values to [0, non-zero].

if hasAlpha : # Is always mutually exclusive with hasAlpha.

# Get the alpha values
alphaTransparencyString = wxImg.GetAlphaBuffer()
alphaTransparencyStringLen = len( alphaTransparencyString )

maskThreshhold = 128             # Use any suitable value [0..255].
maskTransparencyArray = array.array( 'B' )     # chr = unsigned int8
maskTransparencyArray.fromstring( alphaTransparencyString )

for index in xrange( alphaTransparencyStringLen ) :
   
    aTranspValue = maskTransparencyArray[ index ]
   
    if index > int( 0.99 * alphaTransparencyStringLen) :
        print 'alpha =', aTranspValue ,
   
    if (aTranspValue < maskThreshhold) :
        maskTransparencyArray[ index ] = 0
    else :
        maskTransparencyArray[ index ] = 255    # Can set to any value [1..255]
    #end if
   
    if index > int( 0.99 * alphaTransparencyStringLen) :
        print '-->', maskTransparencyArray[ index ]
   
#end for

maskTransparencyString = maskTransparencyArray.tostring()

#end if

newWxImg = wxImg
newWxImg.SetAlphaData( maskTransparencyString )
newWxImg.SaveFile( ‘Toucan_New_Image.PNG’, wx.BITMAP_TYPE_PNG )

newWxBmap = newWxImg.ConvertToBitmap()
newWxBmap.SaveFile( ‘Toucan_New_Bitmap.PNG’, wx.BITMAP_TYPE_PNG )
Bmap = newWxImg.ConvertToBitmap()
newWxBmap.SaveFile( ‘Toucan_New_Bitmap.PNG’, wx.BITMAP_TYPE_PNG )

···

#-----------------------

Ray

Here’s the test graphic file.

Toucan.PNG

The code and converted files.

Alpha2Mask.py (2.94 KB)

Toucan_New_Bitmap.png

Toucan_New_Image.png

[large code block deleted]

Thanks, Ray. But people, is it really necessary to go through all that just to get a PNG to have the proper transparency? It just doesn’t seem like this should be what one has to go through each time. Maybe I’m wrong, but it is hard to imagine that there isn’t an easier path to getting “correct” transparency. Maybe Robin can weigh in on this?

And Andrea, how did you make the PNG for use with the AdvancedSplash?

If this is the only way to do it, then I’ll give it a try of course. Thanks for your efforts, Ray.

Thanks again,
Che

···

On Sun, Jul 10, 2011 at 3:36 PM, Ray Pasco pascor22234@gmail.com wrote:

This is how to convert alpha values into mask values.

You can do it at runtime like this:

  img = wx.Image('imagefile.png')
  img.ConvertAlphaToMask()
  bmp = wx.BitmapFromImage(img)

···

On 7/11/11 10:27 AM, C M wrote:

On Sun, Jul 10, 2011 at 3:36 PM, Ray Pasco <pascor22234@gmail.com > <mailto:pascor22234@gmail.com>> wrote:

    This is how to convert alpha values into mask values.

[large code block deleted]

Thanks, Ray. But people, is it really necessary to go through all that
just to get a PNG to have the proper transparency? It just doesn't seem
like this should be what one has to go through each time. Maybe I'm
wrong, but it is hard to imagine that there isn't an easier path to
getting "correct" transparency. Maybe Robin can weigh in on this?

--
Robin Dunn
Software Craftsman

Thanks, Robin.

I try to use all images in applications stored using img2py, so in the first line, can I use wx.Image to create an image using the “Python” version of the image?

-Che

···

On Mon, Jul 11, 2011 at 1:44 PM, Robin Dunn robin@alldunn.com wrote:

On 7/11/11 10:27 AM, C M wrote:

On Sun, Jul 10, 2011 at 3:36 PM, Ray Pasco <pascor22234@gmail.com > > mailto:pascor22234@gmail.com> wrote:

This is how to convert alpha values into mask values.

[large code block deleted]

Thanks, Ray. But people, is it really necessary to go through all that

just to get a PNG to have the proper transparency? It just doesn’t seem

like this should be what one has to go through each time. Maybe I’m

wrong, but it is hard to imagine that there isn’t an easier path to

getting “correct” transparency. Maybe Robin can weigh in on this?

You can do it at runtime like this:

    img = wx.Image('imagefile.png')

    img.ConvertAlphaToMask()

    bmp = wx.BitmapFromImage(img)

Yes. Bytes are bytes, no matter where they came from originally.

···

On 7/11/11 11:01 AM, C M wrote:

On Mon, Jul 11, 2011 at 1:44 PM, Robin Dunn <robin@alldunn.com > <mailto:robin@alldunn.com>> wrote:

    On 7/11/11 10:27 AM, C M wrote:

        On Sun, Jul 10, 2011 at 3:36 PM, Ray Pasco > <pascor22234@gmail.com <mailto:pascor22234@gmail.com> > <mailto:pascor22234@gmail.com>__> > wrote:

            This is how to convert alpha values into mask values.

        [large code block deleted]

        Thanks, Ray. But people, is it really necessary to go through
        all that
        just to get a PNG to have the proper transparency? It just
        doesn't seem
        like this should be what one has to go through each time. Maybe I'm
        wrong, but it is hard to imagine that there isn't an easier path to
        getting "correct" transparency. Maybe Robin can weigh in on this?

    You can do it at runtime like this:

            img = wx.Image('imagefile.png')
            img.ConvertAlphaToMask()
            bmp = wx.BitmapFromImage(img)

Thanks, Robin.

I try to use all images in applications stored using img2py, so in the
first line, can I use wx.Image to create an image using the "Python"
version of the image?

--
Robin Dunn
Software Craftsman

Thanks. But tried it, and still getting the same problem as mentioned above (tested on XP).

Does anyone have a simple recipe to create a transparent image starting from scratch using free tools (like The GIMP) and which doesn’t have this problem?

Che

···

On Mon, Jul 11, 2011 at 5:14 PM, Robin Dunn robin@alldunn.com wrote:

On 7/11/11 11:01 AM, C M wrote:

On Mon, Jul 11, 2011 at 1:44 PM, Robin Dunn <robin@alldunn.com > > mailto:robin@alldunn.com> wrote:

On 7/11/11 10:27 AM, C M wrote:







    On Sun, Jul 10, 2011 at 3:36 PM, Ray Pasco

    <pascor22234@gmail.com <mailto:pascor22234@gmail.com>

<mailto:pascor22234@gmail.com mailto:pascor22234@gmail.com>__>

    wrote:



        This is how to convert alpha values into mask values.





    [large code block deleted]



    Thanks, Ray.  But people, is it really necessary to go through

    all that

    just to get a PNG to have the proper transparency?  It just

    doesn't seem

    like this should be what one has to go through each time.  Maybe I'm

    wrong, but it is hard to imagine that there isn't an easier path to

    getting "correct" transparency.  Maybe Robin can weigh in on this?





You can do it at runtime like this:



        img = wx.Image('imagefile.png')

        img.ConvertAlphaToMask()

        bmp = wx.BitmapFromImage(img)

Thanks, Robin.

I try to use all images in applications stored using img2py, so in the

first line, can I use wx.Image to create an image using the “Python”

version of the image?

Yes. Bytes are bytes, no matter where they came from originally.

Creating transparency in wx usually requires work. It’s far easier to edit a PNG image in The Gimp or Photoshop to have binary (mask) transparency then bring it into your app. The transparent regions must be 100% transparent. That’s why I gave you that code. It creates a transparency mask (on/off) values from variable (alpha) values [0…255] using a thresholding value.

If you want to create transparent regions in a graphic using wx there are several ways to go:

  1. If all the regions to become transparent have the same unique color then you can designate that every pixel that has this color to be transparent. This is how a paletted-color GIF file works. See wx.Bitmap.SetMaskColor().

  2. You can create the mask layer/plane/channel yourself using wx and then apply that mask to the bitmap. Figuring out which pixels are to become transparent is the real trick. (No dc’s are involved). See wx.Bitmap.SetMask(). Note that the wx.Mask object is poorly documented, but I think it’s just a python “buffer”, which, again, is poorly documented, but, it’s just a python “string” of unsigned 8-bit values. Creating an array.array() with the values of type ‘B’ allows you to convert between string data and array data which can be easily read and written. See my code.

  3. My PIL <–> wx.Bitmap <–> wx.Image conversion module (ImgConv.py) and image mask manipulation l module (BitmapManip.py) eliminate the need to mess around with arrays and strings. It uses PIL to convert alpha transparency to mask transparency from either a disk file or a wx.Bitmap then supply a wx.Bitmap with the mask applied. PIL is only available for MSW platforms, but once the bitmap is masked properly it can be (re)written to a disk file which can be used on any platform without the need to use PIL again.

You can see that easily creating brand new transparency in a Bitmap with a reasonable amount of intelligence is not built into wx yet. I intend to rewrite my modules to eliminate the need for PIL by using pure Python array.array() like the code I attached earlier.

Ray

BitmapManip.py (22.6 KB)

ImgConv.py (7.99 KB)

Creating transparency in wx usually requires work. It's far easier to edit a
PNG image in The Gimp or Photoshop to have binary (mask) transparency then
bring it into your app.

That's just what I want to do. I want to create images in The GIMP
(with transparent regions), save them to the disk, convert them to
Python using img2py, and then use them with wxSplash or
AdvancedSplash. In fact, that is just what I have done, and yet I get
this problem as described in the thread.

What I'm doing in The GIMP is

a) Adding an alpha channel
b) cordoning off an area
c) Clearing that area (leaving the "checkerboard" region representing
transparency)
d) Saving a copy as a .GIF or a .PNG
e) Using img2py on that file (or not, it doesn't matter)
f) Using it as the bitmap for my splash screen.

If anyone would like to see what I mean, I am including a small
runnable sample and a.PNG image I am using, created as above other
than the img2py part. I'm also trying to use ConvertAlphaToMask() here
to no avail.

Notice what happens if you move other windows past the image in the
splash screen.

Note: to run this, put the chicken.PNG file on your desktop and
change the path to whatever path goes to your desktop (i.e., change
"user" to your name).

Thanks,
Che

The transparent regions must be 100% transparent.

transparent_problem.py (969 Bytes)

···

On Tue, Jul 12, 2011 at 2:46 PM, Ray Pasco <pascor22234@gmail.com> wrote:

That's why I gave you that code. It creates a transparency mask (on/off)
values from variable (alpha) values [0..255] using a thresholding value.

If you want to create transparent regions in a graphic using wx there are
several ways to go:

1) If all the regions to become transparent have the same unique color then
you can designate that every pixel that has this color to be transparent.
This is how a paletted-color GIF file works. See wx.Bitmap.SetMaskColor().

2) You can create the mask layer/plane/channel yourself using wx and then
apply that mask to the bitmap. Figuring out which pixels are to become
transparent is the real trick. (No dc's are involved). See
wx.Bitmap.SetMask(). Note that the wx.Mask object is poorly documented, but
I think it's just a python "buffer", which, again, is poorly documented,
but, it's just a python "string" of unsigned 8-bit values. Creating an
array.array() with the values of type 'B' allows you to convert between
string data and array data which can be easily read and written. See my
code.

3) My PIL <--> wx.Bitmap <--> wx.Image conversion module (ImgConv.py) and
image mask manipulation l module (BitmapManip.py) eliminate the need to mess
around with arrays and strings. It uses PIL to convert alpha transparency to
mask transparency from either a disk file or a wx.Bitmap then supply a
wx.Bitmap with the mask applied. PIL is only available for MSW platforms,
but once the bitmap is masked properly it can be (re)written to a disk file
which can be used on any platform without the need to use PIL again.

You can see that easily creating brand new transparency in a Bitmap with a
reasonable amount of intelligence is not built into wx yet. I intend to
rewrite my modules to eliminate the need for PIL by using pure Python
array.array() like the code I attached earlier.

Ray

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

     def AddSplash(self):
         img = wx.Image(u'C:/Documents and Settings/user/Desktop/chicken.png')
         img.ConvertAlphaToMask()
         bmp = wx.BitmapFromImage(img)

The image is fine and your manipulation of it is correct.

         frame = wx.SplashScreen(bmp,
           wx.SPLASH_CENTRE_ON_SCREEN| wx.SPLASH_TIMEOUT,
         10000, self, -1, wx.DefaultPosition, wx.DefaultSize,
             wx.NO_BORDER);

The problem is that you are using wx.SplashScreen, which does *not* support using a shaped window, instead of wx.lib.agw.advancedsplash, which does. Try this:

     def AddSplash(self):
         img = wx.Image(u'chicken.png')
         img.ConvertAlphaToMask()
         bmp = wx.BitmapFromImage(img)

         import wx.lib.agw.advancedsplash as splash
         sp = splash.AdvancedSplash(self, bitmap=bmp, timeout=10000)

···

On 7/12/11 12:13 PM, C M wrote:

--
Robin Dunn
Software Craftsman

D'oh! I had been using AdvancedSplash, somehow thought it wasn't
working, tried to simplify down to just a regular wxSplashScreen and
in many intervening months where I forgot about this issue I also
forgot the whole value add of the AS. Now it is working fine, with
either a .PNG or a .GIF. I had been thinking I had to make the
transparent image in some special way, but no--just use the right
widget!

Sorry, Andrea, for casting any doubt on the AdvancedSplash--just my flub!

And thanks, Robin.

Che

···

On Tue, Jul 12, 2011 at 6:19 PM, Robin Dunn <robin@alldunn.com> wrote:

On 7/12/11 12:13 PM, C M wrote:

def AddSplash\(self\):
    img = wx\.Image\(u&#39;C:/Documents and

Settings/user/Desktop/chicken.png')
img.ConvertAlphaToMask()
bmp = wx.BitmapFromImage(img)

The image is fine and your manipulation of it is correct.

    frame = wx\.SplashScreen\(bmp,
      wx\.SPLASH\_CENTRE\_ON\_SCREEN| wx\.SPLASH\_TIMEOUT,
    10000, self, \-1, wx\.DefaultPosition, wx\.DefaultSize,
        wx\.NO\_BORDER\);

The problem is that you are using wx.SplashScreen, which does *not* support
using a shaped window, instead of wx.lib.agw.advancedsplash, which does.
Try this:

def AddSplash(self):
img = wx.Image(u'chicken.png')
img.ConvertAlphaToMask()
bmp = wx.BitmapFromImage(img)

   import wx\.lib\.agw\.advancedsplash as splash
   sp = splash\.AdvancedSplash\(self, bitmap=bmp, timeout=10000\)