Create Alphachannel-Masked Image & Icon (32bits colors)

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Create Alphachannel-Masked Image & Icon (32bits colors)

Post by eddy »

1) create 32bits transaprent image
- use alphachannel (256 colors image)
- use maskcolor (if no alphachannel)
2) convert standard image to icon image


Here is my "animated icon titlebar" example :

Code: Select all


ProcedureDLL ConvertToIconImage(image) ; Convert PB Image to PB Icon Image
   ;Check if image source is valid
   If Not IsImage(image) : ProcedureReturn : EndIf
   If ImageWidth(image)<>ImageHeight(image) : ProcedureReturn : EndIf
   Select ImageWidth(image)
      Case 16, 32, 48, 72, 128, 256
      Default : ProcedureReturn
   EndSelect
   
   ;Create 32-bits-color Icon
   Protected empty=CreateImage(#PB_Any, ImageWidth(image), ImageWidth(image), 1)
   Protected ICONINFO.ICONINFO
   ICONINFO\fIcon=1
   ICONINFO\hbmMask=ImageID(empty)
   ICONINFO\hbmColor=ImageID(image)
   Protected icon=CreateIconIndirect_(@ICONINFO)
   FreeImage(empty)
   ;Update PB Image
   Protected *Bitmap.Long=IsImage(image) : DeleteObject_(*Bitmap\l)
   *Bitmap\l=icon
   
   
   
   
   ProcedureReturn image
EndProcedure
ProcedureDLL SetImageMaskColor(color) ; Set color to use as maskcolor
   Global ImageMaskColorForCreateAlphaImage
   ImageMaskColorForCreateAlphaImage=color
EndProcedure
ProcedureDLL CreateAlphaImage(image, alphachannel=0) ; Create alpha image or masked image (32 bits)
   ;Create 32-bits-color image
   Protected w=ImageWidth(image)
   Protected h=ImageHeight(image)
   Protected paint=CreateImage(#PB_Any, w, h, 32)
   StartDrawing(ImageOutput(paint))
      DrawImage(ImageID(image), 0, 0)
   StopDrawing()
   
   ;Extract 32-bits-color bitmap
   Protected i, j
   Protected *rgba.RGBQUAD
   Protected bmp.BITMAP
   GetObject_(ImageID(paint), SizeOf(BITMAP), bmp)
   
   ;Apply Mask or Alpha layer
   If Not IsImage(alphachannel)
      Global ImageMaskColorForCreateAlphaImage
      Protected maskR=Red(ImageMaskColorForCreateAlphaImage)
      Protected maskG=Green(ImageMaskColorForCreateAlphaImage)
      Protected maskB=Blue(ImageMaskColorForCreateAlphaImage)
      
      For i=0 To bmp\bmHeight-1
         For j=0 To bmp\bmWidthBytes-1 Step 4
            *rgba=bmp\bmBits+bmp\bmWidthBytes*i+j
            *rgba\rgbReserved=$FF
            *rgba\rgbReserved*(#True XOr (*rgba\rgbBlue=maskB And *rgba\rgbGreen=maskG And *rgba\rgbRed=maskR))
         Next
      Next
   Else
      StartDrawing(ImageOutput(alphachannel))
         For i=0 To bmp\bmHeight-1
            For j=0 To bmp\bmWidthBytes-1 Step 4
               *rgba=bmp\bmBits+bmp\bmWidthBytes*i+j
               *rgba\rgbReserved=Point(j/4, i) & $FF
            Next
         Next
      StopDrawing()
   EndIf
   
   ;Redraw image
   CompilerIf 1
      FreeImage(image)
      CopyImage(paint, image)
   CompilerElse
      CreateImage(image, w, h, 32)
      StartDrawing(ImageOutput(image))
         DrawAlphaImage(ImageID(paint), 0, 0)
      StopDrawing()
   CompilerEndIf
   FreeImage(paint)
   
   ProcedureReturn image
EndProcedure

;********************
;EXAMPLE
;********************
For ico=1 To 32
   ;COLORS ( + MASKED COLOR )
   CreateImage(ico, 32, 32, 24)
   StartDrawing(ImageOutput(ico))
      FrontColor(#Black)
      Box(0, 0, 32, 32)
      
      FrontColor(#Red)
      For a=0 To 360 Step 20
         r=Random(14) : Box(16+r*Cos(a), 16+r*Sin(a), 3, 3)
      Next
   StopDrawing()
   ;//// CREATE MASKED ICON
   SetImageMaskColor(#Black)
   CreateAlphaImage(ico)
   ConvertToIconImage(ico)
   
   ;COLORS
   icoAlpha=ico+32
   CreateImage(icoAlpha, 32, 32, 24)
   StartDrawing(ImageOutput(icoAlpha))
      FrontColor(#Blue)
      Box(0, 0, 32, 32)
   StopDrawing()
   ;ALPHACHANNEL
   alphachannel=CreateImage(#PB_Any, 32, 32, 8)
   StartDrawing(ImageOutput(alphachannel))
      FrontColor(#Black)
      Box(0, 0, 32, 32)
      
      For a=0 To 360 Step 20
         r=Random(14)
         If r>5
            FrontColor(256-256*r/16)
         Else
            FrontColor(255)
         EndIf
         Box(16.0+r*Cos(a), 16.0+r*Sin(a), 5, 5)
      Next
   StopDrawing()
   ;//// CREATE ALPHACHANNEL ICON
   CreateAlphaImage(icoAlpha, alphachannel)
   ConvertToIconImage(icoAlpha)
   FreeImage(alphachannel)
Next

win=OpenWindow(1, 0, 0, 300, 300, "Animated Transparent Icon by eddy")
CreateGadgetList(win)
ButtonImageGadget(11, 5, 5, 100, 100, ImageID(1))
ButtonImageGadget(12, 110, 5, 100, 100, ImageID(1))
AddSysTrayIcon(111, win, ImageID(1))

Repeat
   event=WaitWindowEvent(200)
   
   If EventGadget()=11
      ShowIconMode=0
   ElseIf EventGadget()=12
      ShowIconMode=1
   EndIf
   
   If Not event
      anim=(anim+1)%32
      
      iconMasked=ImageID(anim+1)
      SetGadgetAttribute(11, #PB_Button_Image, iconMasked)
      
      iconAlpha=ImageID(anim+33)
      SetGadgetAttribute(12, #PB_Button_Image, iconAlpha)
      
      If ShowIconMode
         SendMessage_(win, #WM_SETICON, 0, iconAlpha)
         ChangeSysTrayIcon(111, iconAlpha)
      Else
         SendMessage_(win, #WM_SETICON, 0, iconMasked)
         ChangeSysTrayIcon(111, iconMasked)
      EndIf
   EndIf 
Until event=#PB_Event_CloseWindow
Last edited by eddy on Wed Oct 01, 2008 4:59 pm, edited 2 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

This will be helpful.

One shortcoming in your code, your methods leak resources. You never destory the icons you create nor do you provide their handles so that they can be destroyed by the user when the user is finished with them.

I mentioned this in your previous thread here.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

Do you have an example to check this leak ?

You're right, I didn't check if PB can free the modified image object.
Perhaps, the icon converter is not a good idea.
I need this function to change systray icon.

I can replace it by : ChangeSystrayIconFromImage (...)
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

PB destroys the new icon resource.

I made a test : Freeimage fails after I change 'icon' by zero.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

eddy wrote:PB destroys the new icon resource.

I made a test : Freeimage fails after I change 'icon' by zero.
I'm glad to hear it.

I was trying to verify that information also, as well as discover an alternative method. If I find some conclusive and independently verifiable examples I'll post it.

I appreciate the graphics methods you've posted that use API, including those involving sprites. I'm just trying to be a sounding board to weed out any problems that might hinder the results.
Post Reply