Page 1 of 1

LoadImage() with a transparent color

Posted: Sun Jul 31, 2016 4:39 pm
by Keya
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.

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
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):

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

Re: LoadImage() with a transparent color

Posted: Wed Aug 03, 2016 12:57 pm
by minimy
Good Job! This can be interesting to make cartoon look or comic effects. :D
Thank for share!

Re: LoadImage() with a transparent color

Posted: Thu Aug 02, 2018 2:17 pm
by SeregaZ
i am create 32 bit image. paint some. then use SetImageTransparent for that image. next i want to repaint that image. i am make box(0, 0, to size of image) for fill old painting, them make some new paint, then use SetImageTransparent again... and it makes strange effect. first time it will shows some data, third time that image will full transparent. it need every time make free old transparent image, then create new one?

Re: LoadImage() with a transparent color

Posted: Fri Aug 03, 2018 6:33 pm
by Kwai chang caine
Works great :D
Thanks for sharing 8)

Re: LoadImage() with a transparent color

Posted: Sat Aug 04, 2018 1:08 am
by Dude
Alternative for transparent BMP images on Windows only (no conversion or swapping needed):

Code: Select all

; Note 1: It's a lot simpler just to use transparent PNG images! :)
; Note 2: Palette index 1 of the BMP file is the transparency color.

OpenWindow(0,200,200,320,120,"test",#PB_Window_SystemMenu)

hbitmap=LoadImage_(0,"C:\Image.bmp",#IMAGE_BITMAP,0,0,#LR_LOADFROMFILE|#LR_LOADTRANSPARENT|#LR_LOADMAP3DCOLORS)

ImageGadget(0,10,10,300,100,hbitmap)

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow