Seite 1 von 1

Erzeugen eines Alpha-Channels für ein PNG-Image mit tRNS-Chu

Verfasst: 02.02.2010 02:56
von PureLust
Moin zusammen,

angeregt durch DIESEN Thread, in dem sich heraus gestellt hat, dass der PNG-Decoder von PB die Transparenz-Informationen eines PGN-Images mit tRNS-Chunks nicht korrekt auswertet, hab ich mich mal hingesetzt um in dieser Beziehung Abhilfe zu schaffen.

Solltet Ihr also mal ein PNG-Bild haben, welches zwar eigentlich Transparenz-Informationen enthält, es aber dennoch unter PB nicht mit Transparenz dargestelt wird, so könnte es sich um ein solches PNG-Bild handeln, welches die Transparenzinformationen per tRNS-Cunk gespeichert hat (dies wird z.B. gerne bei Icons und kleinen Grafiken mit wenigen Farben gemacht um Speicherplatz zu sparen).

Um auch bei solchen PNG-Bildern einen PB-tauglichen Alpha-Channel zu erhalten habe ich mal eine kleine Routine geschrieben:
(Anwendung und Beschreibung: siehe Remarks im Code.)

Code: Alles auswählen

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
Das für das enthaltene Beispiel benötigte PNG-Image könnt Ihr HIER runter laden.

Hoffe es kann jemand gebrauchen (Feedback welcome :mrgreen: ).

Grüße, PL

PS: Ach ja ... mangels anderer Beispielbilder bin ich mir nicht sicher, ob ich beim Auslesen der Transparenzfarbe nicht evtl. doch irgendwie R,G und B durcheinander gewürfelt habe (beim Beispielbild sind R,G und B alle gleich (RGB=$ffffff)).
Sollte also jemand irgendwann einmal auf ein PNG-Bild mit tRNS-Chunk treffen bei dem die Transparenz nicht korrekt rekonstruiert wird -> bitte hier 'na Nachricht schreiben und am Besten einen Link zum Image posten.

Re: Erzeugen eines Alpha-Channels für ein PNG-Image mit tRNS-Chu

Verfasst: 02.02.2010 11:01
von 7x7
:allright:

Spitze! Da hast du dich ja ganz schön reingehängt! Und das Nachts um 02:00 :lol:
Funktioniert prima.

Den Code verstehe ich nicht. Gut, muss ich auch nicht unbedingt. Aber an welcher Stelle im Code kann ich den mit SaveImage()
das geänderte Image abspeichern? Habe fachmännisch( :mrgreen: ) einfach mal sämtliche IDs probiert; jedesmal kommt eine Fehlermeldung
"Das angegebene #Image ist nicht initialisiert"

PureLust: "Ach ja ... mangels anderer Beispielbilder bin ich mir nicht sicher, ob ich beim Auslesen der Transparenzfarbe nicht
evtl. doch irgendwie R,G und B durcheinander gewürfelt habe"

Passt schon. Wo ein "SpeakerOn.png" Bildist, ist auch ein "SpeakerOff.png" Bildund andere. Die Farben sind korrekt zugeordnet. Die Bilder erzeuge
ich mit CorelPaint. Corel bietet mir gar nicht die Möglichkeit, PNG-Dateien "PB-geeignet" mit 32Bit zu speichern. Habe 24 oder 48 Bit zur
Auswahl. Mit beidem kommt PB nicht klar.

Die Probleme des PB UsePNGImageDecoder() sind nicht mehr als Schwäche, sondern als Bug zu bezeichen. Hier in meinem Firefox oder
auch im IE werden die Images korrekt dargestellt. Werde im int.Forum mal eine Meldung machen.

Re: Erzeugen eines Alpha-Channels für ein PNG-Image mit tRNS-Chu

Verfasst: 02.02.2010 17:48
von Thorium
7x7 hat geschrieben:Die Bilder erzeuge
ich mit CorelPaint. Corel bietet mir gar nicht die Möglichkeit, PNG-Dateien "PB-geeignet" mit 32Bit zu speichern. Habe 24 oder 48 Bit zur
Die schlechte Formatunterstützung von Corel ist traditionell. Das hat noch mit ner Reihe anderer Formate Probleme. Ich würde dir raten auf ein anderes Programm umzusteigen, kann auch was freies wie GIMP sein.

Re: Erzeugen eines Alpha-Channels für ein PNG-Image mit tRNS-Chu

Verfasst: 02.02.2010 18:51
von 7x7
Thorium: "Die schlechte Formatunterstützung von Corel ist traditionell. Das hat noch mit ner Reihe anderer Formate Probleme."
Kann ich nach mehr als 10 Jahren Corel-Erfahrung nicht bestätigen.

Aber was mir tierisch auf den Sack ging: Habe mir mal "Corel Paint Photo Pro X2" gekauft. Diese Dreckssoftware konnte nicht einmal mit dem hauseigenen CPT-Format umgehen. Habs umgehend deinstalliert und die CD geschreddert. :evil:

Re: Erzeugen eines Alpha-Channels für ein PNG-Image mit tRNS-Chu

Verfasst: 02.02.2010 19:11
von Thorium
7x7 hat geschrieben:Thorium: "Die schlechte Formatunterstützung von Corel ist traditionell. Das hat noch mit ner Reihe anderer Formate Probleme."
Kann ich nach mehr als 10 Jahren Corel-Erfahrung nicht bestätigen.
Z.B. Paletten in .bmp Dateien hat Corel PhotoPaint falsch gespeichert. Bis zur letzten Version die ich benutzt hatte, das war Version 9. Davor hatte ich die Versionen 6-8 genutzt die alle die gleichen Bugs hatten.