LoadImage() with a transparent color
Posted: Sun Jul 31, 2016 4:39 pm
Similar to LoadImage(), but lets you specify an RGB color to use as transparent - all pixels of that color will then be set to Alpha channel value = 0, or more specifically, RGBA(0,0,0, 0)
This means you can provide transparency to formats such as tiny 8-bit BMP which doesn't natively support transparency. Can be used as a smaller alternative to the PNG decoder to provide transparency, although it only provides full transparency (like GIF), not variable gradient levels like PNG.
For flexibility you give it an existing imageID (eg from a LoadImage() or CreateImage()) rather than an image filename. The resulting image will of course be 32-bit, but the original image can be of any bit depth.
Supports everything: x86 + x64, Windows + Linux + OSX, and both RGB + BGR byte orders.
Ascii+Unicode both supported/irrelevant. Normal and ReversedY image row orders both supported/irrelevant.
Fast in-memory transform (no slow Point/Plot()'s) with purely 32-bit ops; no slow 8's.
This alternative version sets a color to transparent in an EXISTING IMAGE rather than creating a new one. The existing image must be 32bit (the procedure verifies this with a call to ImageDepth):
This means you can provide transparency to formats such as tiny 8-bit BMP which doesn't natively support transparency. Can be used as a smaller alternative to the PNG decoder to provide transparency, although it only provides full transparency (like GIF), not variable gradient levels like PNG.
For flexibility you give it an existing imageID (eg from a LoadImage() or CreateImage()) rather than an image filename. The resulting image will of course be 32-bit, but the original image can be of any bit depth.
Supports everything: x86 + x64, Windows + Linux + OSX, and both RGB + BGR byte orders.
Ascii+Unicode both supported/irrelevant. Normal and ReversedY image row orders both supported/irrelevant.
Fast in-memory transform (no slow Point/Plot()'s) with purely 32-bit ops; no slow 8's.
Code: Select all
EnableExplicit
Procedure ByteSwap32(addrLong)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rax, [p.v_addrLong]
!mov ecx, [rax]
!bswap ecx
!mov [rax], ecx
CompilerElse
!mov eax, [p.v_addrLong]
!mov ecx, [eax]
!bswap ecx
!mov [eax], ecx
CompilerEndIf
EndProcedure
Procedure.i LoadImageTransparent (hLoadImg, TransparentColorRGB.l) ;returns new image handle
Protected width,height,pitch,imgbase, x,y, hImg32, *RGBA.Long
width = ImageWidth(hLoadImg)
height = ImageHeight(hLoadImg)
hImg32 = CreateImage(#PB_Any, width, height, 32)
If hImg32 = 0: ProcedureReturn 0: EndIf
If StartDrawing(ImageOutput(hImg32)) = 0
FreeImage(hImg32): ProcedureReturn 0
EndIf
If DrawingBufferPixelFormat() & #PB_PixelFormat_32Bits_RGB
TransparentColorRGB | $FF000000 ;Linux & OSX
Else
ByteSwap32(@TransparentColorRGB) ;Windows
TransparentColorRGB = (TransparentColorRGB >> 8) | $FF000000
EndIf
DrawingMode(#PB_2DDrawing_Default)
DrawImage(ImageID(hLoadImg),0,0,width,height)
pitch = DrawingBufferPitch()
imgbase = DrawingBuffer()
width-1: height-1 ;to address from base 0
For y = 0 To height
*RGBA = imgbase + (y * pitch)
For x = 0 To width
If *RGBA\l = TransparentColorRGB
*RGBA\l = 0 ;= RGBA(0,0,0, 0) ;set Alpha channel to 0 (fully transparent)
EndIf
*RGBA+4
Next x
Next y
StopDrawing()
ProcedureReturn hImg32
EndProcedure
;### EXAMPLE ###########################################
Procedure TestImage()
Protected hImg = CreateImage(#PB_Any, 100,100, 24)
If StartDrawing(ImageOutput(hImg))
Box(0,0,50,50, RGB(200,20,10)) ;this Red box should show as transparent
Box(20,20,50,50, RGB(30,40,210))
EndIf
StopDrawing()
ProcedureReturn hImg
EndProcedure
Define hLoadImg = TestImage()
;Define hLoadImg = LoadImage(#PB_Any, "c:\test.bmp") ;eg. a tiny 8bit bmp that doesnt natively support transparency
Define TransparentColor.l = RGB(200,20,10)
Define hTransparentImg = LoadImageTransparent(hLoadImg, TransparentColor)
If hTransparentImg = 0
MessageRequester("Error","Couldnt convert bmp"): End
EndIf
FreeImage(hLoadImg)
OpenWindow(0,0,0,500,500,"Transparent Drawing",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ImageGadget(0,0,0,400,400, ImageID(hTransparentImg))
Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
Code: Select all
Procedure SetImageTransparent (hImg32, TransparentColorRGB.l) ;returns 1 on success, 0 on error/fail
Protected width,height,pitch,imgbase, x,y, *RGBA.Long
If ImageDepth(hImg32) <> 32: ProcedureReturn 0: Endif
width = ImageWidth(hImg32)
height = ImageHeight(hImg32)
If StartDrawing(ImageOutput(hImg32)) = 0
ProcedureReturn 0
EndIf
If DrawingBufferPixelFormat() & #PB_PixelFormat_32Bits_RGB
TransparentColorRGB | $FF000000 ;Linux & OSX
Else
ByteSwap32(@TransparentColorRGB) ;Windows
TransparentColorRGB = (TransparentColorRGB >> 8) | $FF000000
EndIf
DrawingMode(#PB_2DDrawing_Default)
pitch = DrawingBufferPitch()
imgbase = DrawingBuffer()
width-1: height-1
For y = 0 To height
*RGBA = imgbase + (y * pitch)
For x = 0 To width
If *RGBA\l = TransparentColorRGB
*RGBA\l = 0 ;= RGBA(0,0,0, 0) ;set Alpha channel to 0 (fully transparent)
EndIf
*RGBA+4
Next x
Next y
StopDrawing()
ProcedureReturn 1 ;SUCCESS
EndProcedure