Ok…this seems like it ought be really easy…but the solution eludes me for days now. I have some PNG files that have an Alpha Channel – I need to be able to read that PNG file in (sample attached) display it on a canvas…and eventually save the picture without the alpha channel. Any transparent parts of the picture need to be opaque white. I thought I could do this with Christian’s PNGReaderMBS which has an option to strip the alpha channel. It doesn’t seem to matter if I use this option or not… according to runtime properties on my picture HasAlphaChannel = False.
This could be a byproduct of the PictureMBS.CopyPicture process?
My source image does appear to have a valid alpha channel.
dim f as folderitem = SpecialFolder.Resource("xojo_logo.png")
If f <> Nil Then
Var Currentin as PictureMBS = nil
Var pm as new PNGReaderMBS
if pm.OpenFile(f) then
'pm.StripAlpha = True
if pm.ApplyOptions(0) then
Currentin=new PictureMBS(pm.Width,pm.Height,PictureMBS.ImageFormatRGB)
Var i,c as Integer
c=pm.Height-1
for i=0 to c
Currentin.RowInFormat(i, PictureMBS.ImageFormatRGBA)=pm.ReadRow
next
end if
end if
Var p as Picture = Currentin.CopyPicture
Var p2 as New Picture(p.width,p.height,32)
Var g as Graphics = p2.Graphics
g.DrawPicture(p,0,0,p.Width,p.height)
Canvas1.Backdrop = p2
end
I was kinda hoping with the various libraries at my disposal this would be fairly easy.
Anybody care to contribute some guidance to a Xojo hobbyist? Much appreciated.
dim fIn as FolderItem = GetFolderItem("").child("xojoLogo.png")
dim p as picture = picture.Open(fIn)
' make a copy of the picture so we can edit it
dim p2 as new Picture(p.width,p.height)
p2.Graphics.DrawPicture(p,0,0)
dim rgb as RGBSurface = p2.RGBSurface
dim w as integer = p2.Width -1
dim h as integer = p2.height -1
for y as integer = 0 to h
for x as integer = 0 to w
dim c as color = rgb.Pixel(x,y)
' set the alpha channel to opaque
dim c2 as color = color.RGB(c.Red,c.Green,c.Blue,0)
rgb.Pixel(x,y) = c2
next
next
dim fOut as FolderItem = fIn.parent.child("xojoLogo-noalpha.png")
p2.Save(fOut, picture.Formats.PNG)
This works, but doesn’t do what you want. The problem is that the Xojo Logo image pixels are using black RGB (0,0,0) for the transparent sections, so if you wipe out the alpha channel, you get something that looks like this:
We can work around that by setting all transparent pixels to full white instead:
dim fIn as FolderItem = GetFolderItem("").child("xojoLogo.png")
dim p as picture = picture.Open(fIn)
' make a copy of the picture so we can edit it
dim p2 as new Picture(p.width,p.height)
p2.Graphics.DrawPicture(p,0,0)
dim rgb as RGBSurface = p2.RGBSurface
dim w as integer = p2.Width -1
dim h as integer = p2.height -1
for y as integer = 0 to h
for x as integer = 0 to w
dim c as color = rgb.Pixel(x,y)
' set the alpha channel to opaque, unless alpha was 255 (transparent) in which case set the RGB to full white
dim c2 as color = color.RGB(c.Red,c.Green,c.Blue,0)
if c.Alpha = 255 then
c2 = color.RGB(255,255,255,0)
end if
' set the color in the image
rgb.Pixel(x,y) = c2
next
next
dim fOut as FolderItem = fIn.parent.child("xojoLogo-noalpha.png")
p2.Save(fOut, picture.Formats.PNG)
A much simpler approach is to simply draw the original onto a while background, like this:
dim fIn as FolderItem = GetFolderItem("").child("xojoLogo.png")
dim p as picture = picture.Open(fIn)
' create a new picture, fill with white
dim p2 as new Picture(p.width,p.height)
p2.Graphics.DrawingColor = color.rgb(255,255,255,0)
p2.Graphics.FillRectangle(0,0,p2.Width,p2.Height)
' now draw the transparent picture onto the white one
p2.Graphics.DrawPicture(p,0,0)
'save the result
dim fOut as FolderItem = fIn.parent.child("xojoLogo-noalpha-v2.png")
p2.Save(fOut, picture.Formats.PNG)
Wow. Thanks Mike! Yes…shows how little (unfortunately) I know about working with graphics in Xojo. I’m going to pour over both these methods until I have a good understanding of both. I see what you did. I had found that my previous method worked on “some” PNG’s with an alpha channel… but did not work on others and I didn’t know why.
So I guess if the transparency property (alpha channel is set to 100% transparent…then the underlying RGB pixel values don’t really matter… but if you strip out the alpha channel…then the underlying RGB pixels become relevant. I’m guessing some people use Black 0,0,0 and some use white 255,255,255 – which is was why I got the desired result “sometimes”.
The idea of drawing the Picture with alpha on top of an opaque white backdrop may also be an option – which does certainly produce a better looking result. Thank you so much for being so helpful. One reason as a hobbyist I like the Xojo platform is the thoughtful and generous responses I receive from Pros when I post an issue on the forum. I always put forth my best effort before I ask the forum – but some times I’m just really stumped. I’ve read previous “Alpha Channel” questions and none of them really seemed to explain what my issue was or how to go about fixing it. Thank you so much.
You don’t want to strip the alpha channel as that will break the image.
What you want to do is flatten the source image onto a white background.
so… Load your image with the alpha channel into a picture, create a second picture and fill it white, draw the first picture into the second picture and then dispose of the first picture.