If I create a wx.Image with all the pixels set to a fully transparent colour (alpha=0) and call its HasAlpha() method, it returns True (as I would expect).
If I then convert the image to a bitmap, copy the bitmap to the clipboard, get the bitmap back from the clipboard and convert it back to a wx.Image, then its HasAlpha() method returns False!
The same thing happens if I set some of the pixels in the image to any fully opaque colour (alpha=255) and perform the same operations.
However, if I set at least one of the pixels in the original image to any semi-transparent colour (alpha=1 through 254) and perform the same operations, then the final image’s HasAlpha() does return True.
I have evaluated this issue on the following setups with the same results:
- Python 3.6.9, wxPython 4.0.1 gtk3 (phoenix), Linux Mint 19.3
- Python 3.8.2, wxPython 4.0.7 gtk3 (phoenix) wxWidgets 3.0.4, Linux Mint 20.
The code below produces the following output:
incl_transparent_pixel = False
start_image.HasAlpha() = True
clipboard_image.HasAlpha() = False
incl_transparent_pixel = True
start_image.HasAlpha() = True
clipboard_image.HasAlpha() = True
Why does the clipboard discard the alpha channel for images that don’t contain any partially transparent pixels? Is this a bug or intended behaviour or am I doing something wrong?
import wx
def copyImageToClipboard(image):
if not wx.TheClipboard.IsOpened():
wx.TheClipboard.Open()
bitmap = wx.Bitmap(image)
data_object = wx.BitmapDataObject()
data_object.SetBitmap(bitmap)
success = wx.TheClipboard.SetData(data_object)
wx.TheClipboard.Close()
else:
success = False
return success
def getBlankImage(width, height, colour):
r, g, b, a = colour.Get(includeAlpha=True)
data = bytearray((r, g, b) * width * height)
alpha = bytearray((a,) * height * width)
image = wx.Image(width, height, data, alpha)
return image
def getClipboardImage():
bitmap = None
if not wx.TheClipboard.IsOpened():
data_obj = wx.BitmapDataObject()
wx.TheClipboard.Open()
success = wx.TheClipboard.GetData(data_obj)
wx.TheClipboard.Close()
if success:
bitmap = data_obj.GetBitmap()
if bitmap is not None:
return bitmap.ConvertToImage()
return None
def runTest(incl_transparent_pixel=False):
print("incl_transparent_pixel =", incl_transparent_pixel)
bg_colour = wx.Colour(255, 255, 255, 0)
start_image = getBlankImage(16, 16, bg_colour)
if incl_transparent_pixel:
# Set one pixel to any transparent colour
x, y = 0, 0
start_image.SetRGB(x, y, 255, 0, 0)
start_image.SetAlpha(x, y, 128)
print("start_image.HasAlpha() =", start_image.HasAlpha())
success = copyImageToClipboard(start_image)
assert success
clipboard_image = getClipboardImage()
assert clipboard_image.IsOk()
print("clipboard_image.HasAlpha() =", clipboard_image.HasAlpha())
def main():
_app = wx.App()
runTest()
print()
runTest(True)
if __name__ == '__main__':
main()