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