Page 1 of 1

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

Posted: Thu Sep 11, 2008 12:14 am
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

Posted: Thu Sep 11, 2008 12:40 am
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.

Posted: Thu Sep 11, 2008 4:32 pm
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 (...)

Posted: Sun Sep 14, 2008 4:43 pm
by eddy
PB destroys the new icon resource.

I made a test : Freeimage fails after I change 'icon' by zero.

Posted: Mon Sep 15, 2008 12:10 am
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.