Code: Select all
Structure ICONIMAGE
icHeader.BITMAPINFOHEADER
StructureUnion
icColors.RGBQUAD[0]
icXOR.b[0]
icAND.b[0]
EndStructureUnion
EndStructureCode: Select all
Structure ICONDIR
idReserved.w ; // Reserved (must be 0)
idType.w ; // Resource type (1 for icons)
idCount.w ; // How many images?
idEntries.ICONHEADER[0] ; // The entries for each image
EndStructure
Declare GetMask(image)
Structure ICONIMAGE_MSDN
icHeader.BITMAPINFOHEADER ; // DIB header
icColors.RGBQUAD[0] ; // Color table
Array icXOR.b(0) ; // DIB bits for XOR mask
Array icAND.b(0) ; // DIB bits for AND mask
EndStructure
ii.ICONIMAGE_MSDN
; Make an image to test with
CreateImage(0, 32,32,32,#PB_Image_Transparent)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0,0,16,16,RGBA(255,0,0,255))
Box(16,16,16,16,RGBA(0,0,255,255))
StopDrawing()
; Make a mask for it (at 32bpp for now)
Mask = GetMask(0)
; Start by getting the icXOR bits for the icon's color image
hdcSrc = CreateCompatibleDC_(0)
*bmi.BITMAPINFO = AllocateMemory(SizeOf(BITMAPINFO)+SizeOf(RGBQUAD)*256)
With *bmi
\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
\bmiHeader\biWidth = 32
\bmiHeader\biHeight = 32
\bmiHeader\biPlanes = 1
\bmiHeader\biBitCount = 32
EndWith
GetDIBits_(hdcSrc, ImageID(0), 0, 32, #Null, *bmi, #DIB_RGB_COLORS)
sz_color = *bmi\bmiHeader\biSizeImage
ReDim ii\icXOR(sz_color)
GetDIBits_(hdcSrc, ImageID(0), 0, 32, @ii\icXOR(0), *bmi, #DIB_RGB_COLORS)
FreeMemory(*bmi)
; Then we have to get the 1bpp Mask bits
*bmiMask.BITMAPINFO = AllocateMemory(SizeOf(BITMAPINFO)+SizeOf(RGBQUAD)*256)
With *bmiMask
\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
\bmiHeader\biWidth = 32
\bmiHeader\biHeight = 32
\bmiHeader\biPlanes = 1
\bmiHeader\biBitCount = 1
EndWith
GetDIBits_(hdcSrc, ImageID(Mask), 0, 32, #Null, *bmiMask, #DIB_PAL_COLORS)
sz_mask_1bpp = *bmiMask\bmiHeader\biSizeImage
ReDim ii\icAND(sz_mask_1bpp)
GetDIBits_(hdcSrc, ImageID(Mask), 0, 32, @ii\icAND(0), *bmiMask, #DIB_PAL_COLORS)
FreeMemory(*bmiMask)
DeleteDC_(hdcSrc)
; All is ready, we can write this stuff out to a memory block
*file = AllocateMemory(SizeOf(ICONDIR) + SizeOf(ICONHEADER) + SizeOf(BITMAPINFOHEADER) + sz_color + sz_mask_1bpp)
*dir.ICONDIR = *file
With *dir
\idCount = 1
\idType = 1
EndWith
*ih.ICONHEADER = *file+SizeOf(ICONDIR)
With *ih
\bWidth = 32
\bHeight = 32
\wPlanes = 1
\wBitCount = 32
\dwBytesInRes = SizeOf(BITMAPINFOHEADER) + sz_color + sz_mask_1bpp
\dwBytesOffset = SizeOf(ICONDIR) + SizeOf(ICONHEADER)
EndWith
*iimage.ICONIMAGE = *file + *ih\dwBytesOffset
With *iimage\icHeader
\biSize = SizeOf(BITMAPINFOHEADER)
\biWidth = 32
\biHeight = 32 * 2
\biPlanes = 1
\biBitCount = 32
\biSizeImage = sz_color
EndWith
*color = *file + *ih\dwBytesOffset + SizeOf(BITMAPINFOHEADER)
*mask = *color + sz_color
CopyMemory(@ii\icXOR(0), *color, sz_color)
CopyMemory(@ii\icAND(0), *mask, sz_mask_1bpp)
; Now dump it to a file and see how we did
; If a window comes up with two transparent icons on a "purebasic yellow" background, we succeeded.
If CreateFile(0, "test.ico")
WriteData(0, *file, MemorySize(*file))
CloseFile(0)
EndIf
; Test it, did it make an icon?
ExtractIconEx_("test.ico", 0, @large.i, @small.i, 1)
OpenWindow(0,0,0,640,480,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
SetWindowColor(0, RGB(255,255,223))
ImageGadget(0,10,10,0,0,large)
ImageGadget(1,100,10,0,0,small)
Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
;===============================================
; PROCEDURES
;===============================================
Procedure GetMask(image)
Dim maskcolors.b(ImageWidth(image)-1, ImageHeight(image)-1)
mask = CreateImage(#PB_Any, ImageWidth(image), ImageHeight(image), ImageDepth(image), #Black)
StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AlphaChannel)
For j=0 To ImageHeight(image)-1
For i=0 To ImageWidth(image)-1
If Alpha(Point(i,j)) = 0
maskcolors(i,j) = 1
Else
maskcolors(i,j) = 0
EndIf
Next
Next
StopDrawing()
StartDrawing(ImageOutput(mask))
For j=0 To ImageHeight(mask)-1
For i=0 To ImageWidth(mask)-1
If maskcolors(i,j)
Plot(i, j, #White)
Else
Plot(i, j, #Black)
EndIf
Next
Next
StopDrawing()
ProcedureReturn mask
EndProcedure

