Creating Alpha-Channel for PNG-Images with tRNS-Chunk
Posted: Tue Feb 02, 2010 2:25 am
Hi folks,
in THIS German Thread we find out, that PBs PNG-Decodes does not handle PNG Images correctly, which have stored the transparency information by using the tRNS-chunk (instead of by the sRGB way).
This is commonly done by small, icon-like Images with small amount of colors to save some Diskspace or to reduce the Download-Traffic.
So I've written a little routine to add the Alpha-channel to such an incorrect loaded Image - so you'll get the right transparency.
(Within the Code you will find an example and some more Infos how to use it:)
You can download the Demo-PNG you need for the included example-code: HERE
Maybe someone will find it usefull. (Feedback welcome.
)
[Remark:] Because I do not have other PNG-Sample Images with tRNS-Chunk i was not able to test it on other Images - so maybe I've fiddled around with the RGB-values a bit (could be BGR instead).
So if you find an Image where the Transparency will not restored correctly, please post a note and a link to the Image if possible.
Thanks and greets,
Albert.
(Sorry for my bad english. Here is the Link to this Thread in german Language.)
in THIS German Thread we find out, that PBs PNG-Decodes does not handle PNG Images correctly, which have stored the transparency information by using the tRNS-chunk (instead of by the sRGB way).
This is commonly done by small, icon-like Images with small amount of colors to save some Diskspace or to reduce the Download-Traffic.
So I've written a little routine to add the Alpha-channel to such an incorrect loaded Image - so you'll get the right transparency.
(Within the Code you will find an example and some more Infos how to use it:)
Code: Select all
EnableExplicit
Procedure CreateAlphaFromTRNSChunk(ImageNr,ImageFile.s,*ImageAdress=0)
Protected *ImageMemPos, FileNum, ReceivedBytes, Transcol.l, *TransColP.RGBQUAD, ImageCopy.l, x, y
; This Procedure creates the Alpha-Channel for a loaded PNG-Image where the Transpaent-Information
; is stored in a tRNS-Chunk instead of in the sRGB-Information.
;
; Parameters:
; ImageNR -> Number of the PureBasic-Image (not the ImageID)
; ImageFile.s -> If the Image was loaded from a file, place the Filename here - otherwise leave this blank (= "")
; *ImageAdress -> If you've catched the Image from Memory, put the Label-Adress in here and leave ImageFile.s blank (= "")
;
; How it works:
; The Procedure checks the first 50 Bytes of the File or the Memory-Position to check out
; - if it is a PGN File
; - if it has got the tRNS Chunk
; - if not, it will return without any Changes
; - it reads the transparent Color from the tRNS Chunk
; - creats a copy of the original Image
; - frees the old original Image and recreates a 32bit Alpha-Image with the same ImageNr.
; - copies the old RGB-Information back to the new created 32-bit Image
; - creates the Alpha-Channel from the Transparent Color which was read from the tRNS-Chunk
; - cleans up Memory and frees Backup-Image
;
; ReturnValue:
; It returns the ImageID of the new (or old, if not changed) Image
; Because it does NOT CHANGE the ImageNr. used by PB, there is no need to check the Result if you use PBs ImageNr.
; If you've used the ImageID (API-ImageID) of the Image before, you should use the ImageID which will be returned
;
; Examples of Usage:
;
; Using PBs ImageNumber and loading Image from File:
; - MyImage = LoadImage(#PB_Any, "C:\Temp\SpeakerOn.png")
; - Dummy = CreateAlphaFromTRNSChunk(MyImage,"C:\Temp\SpeakerOn.png")
;
; Using API ImageIDs and catching the Image from Memory:
; - ImageID = CatchImage(0, ?Image0)
; - ImageID = CreateAlphaFromTRNSChunk(0,"",?Image0)
If Len(ImageFile)
*ImageMemPos = AllocateMemory(50)
If Not *ImageMemPos : ProcedureReturn ImageID(ImageNr) : EndIf
Filenum = ReadFile(#PB_Any,ImageFile)
If Not Filenum : FreeMemory(*ImageMemPos) : ProcedureReturn ImageID(ImageNr) : EndIf
ReceivedBytes = ReadData(FileNum, *ImageMemPos, 50)
CloseFile(FileNum)
If ReceivedBytes < 49 : FreeMemory(*ImageMemPos) : ProcedureReturn ImageID(ImageNr) : EndIf
*ImageAdress = *ImageMemPos
ElseIf Not *ImageAdress
ProcedureReturn ImageID(ImageNr)
EndIf
If UCase(PeekS(*ImageAdress+1,3,#PB_Ascii)) = "PNG"
If UCase(PeekS(*ImageAdress+37,4,#PB_Ascii)) = "TRNS"
*TransColP = @Transcol
*TransColP\rgbBlue = PeekB(*ImageAdress+42)
*TransColP\rgbGreen = PeekB(*ImageAdress+44)
*TransColP\rgbRed = PeekB(*ImageAdress+46)
ImageCopy = CopyImage(ImageNr,#PB_Any)
FreeImage(ImageNr)
CreateImage(ImageNr,ImageWidth(ImageCopy), ImageHeight(ImageCopy),32)
If StartDrawing(ImageOutput(ImageNr))
DrawImage(ImageID(ImageCopy),0,0)
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0, 0, ImageWidth(ImageCopy), ImageHeight(ImageCopy), $FF000000)
; Setzen der Transparenten Punkte durch LANGSAME Point/Plot-Befehle
For x = 0 To ImageWidth(ImageCopy)-1
For y = 0 To ImageHeight(ImageCopy)-1
If (Point(x,y) & $FFFFFF) = Transcol
Plot(x,y,0)
EndIf
Next y
Next x
StopDrawing()
EndIf
FreeImage(ImageCopy)
EndIf
EndIf
If *ImageMemPos : FreeMemory(*ImageMemPos) : EndIf
ProcedureReturn ImageID(ImageNr)
EndProcedure
#ImageFileName = "C:\Temp\SpeakerOn.png" ; change this to fit your Image-File
UsePNGImageDecoder()
Global Image0=CatchImage(0, ?Image0)
Global Image1=CatchImage(1, ?Image0)
Global Image2=LoadImage(2, #ImageFileName)
Image1 = CreateAlphaFromTRNSChunk(1,"",?Image0)
CreateAlphaFromTRNSChunk(2,#ImageFileName)
DataSection
Image0:
IncludeBinary #ImageFileName
EndDataSection
If OpenWindow(0, 100,100,280,100, "Transparenz-Test",#PB_Window_SystemMenu | #PB_Window_TitleBar )
ImageGadget(0, 40, 20, 40, 35, Image0)
ImageGadget(1, 120, 20, 40, 35, Image1)
ImageGadget(2, 200, 20, 40, 35, ImageID(2))
Repeat
Define Event=WaitWindowEvent()
Until Event=#PB_Event_CloseWindow
EndIf
Maybe someone will find it usefull. (Feedback welcome.

[Remark:] Because I do not have other PNG-Sample Images with tRNS-Chunk i was not able to test it on other Images - so maybe I've fiddled around with the RGB-values a bit (could be BGR instead).
So if you find an Image where the Transparency will not restored correctly, please post a note and a link to the Image if possible.
Thanks and greets,
Albert.
(Sorry for my bad english. Here is the Link to this Thread in german Language.)