It is currently Sat Dec 14, 2019 5:35 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: LoadImage() with a transparent color
PostPosted: Sun Jul 31, 2016 4:39 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jun 04, 2015 7:10 am
Posts: 1673
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:
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:
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

_________________
Thankyou to all the coders who generously helped & encouraged me in the nearly 2yrs when i was welcome here,
it was a tremendous privilege. I learned a lot. I wish you and your families all the best and success for the future.


Top
 Profile  
Reply with quote  
 Post subject: Re: LoadImage() with a transparent color
PostPosted: Wed Aug 03, 2016 12:57 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Jul 08, 2013 8:43 pm
Posts: 243
Good Job! This can be interesting to make cartoon look or comic effects. :D
Thank for share!

_________________
If translation=Error: reply="Sorry, Im Spanish": Endif


Top
 Profile  
Reply with quote  
 Post subject: Re: LoadImage() with a transparent color
PostPosted: Thu Aug 02, 2018 2:17 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Feb 20, 2009 9:24 am
Posts: 559
Location: Almaty (Kazakhstan)
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?


Top
 Profile  
Reply with quote  
 Post subject: Re: LoadImage() with a transparent color
PostPosted: Fri Aug 03, 2018 6:33 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 4545
Location: Lyon - France
Works great :D
Thanks for sharing 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
Reply with quote  
 Post subject: Re: LoadImage() with a transparent color
PostPosted: Sat Aug 04, 2018 1:08 am 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1904
Alternative for transparent BMP images on Windows only (no conversion or swapping needed):

Code:
; 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


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye