handling Alpha channel

handling Alpha channel

Post by Rob » Wed, 12 May 2004 11:38:37


I'm trying to lighten images contained in an imagelist. The code I have
works fine for 24bit images but I can't, for the life of me, work out how to
handle 32 bit images. I know I'm probably being dense but I can't work out
how to change the R/G/B channels but ignore the alpha channel.

Thanks in advance
Rob

This is what I have so far:

Private Sub Command_Click()
Dim img As Long
Dim i As Long, j As Long

img = ImageList_Create(16, 16, ILC_COLOR32 Or ILC_MASK, 12, 0)

'// load imagelist with test images
Dim hIcon As Long
For i = 1 To 12
hIcon = LoadImage(0, App.Path & "\32." & 100 + i & ".ico", IMAGE_ICON,
16, 16, LR_LOADFROMFILE)
ImageList_ReplaceIcon img, -1, hIcon
DestroyIcon hIcon
Next i

'// draw the original images on the form
For i = 0 To ImageList_GetImageCount(img) - 1
ImageList_DrawEx img, i, Me.hDc, i * 24 + 8, 8, 16, 16, _
CLR_NONE, _
CLR_NONE, _
ILD_NORMAL
Next i

Dim ii As IMAGEINFO

ImageList_GetImageInfo img, 7, ii

Dim arrBmpBits() As Byte
Dim sa As SAFEARRAY2D
Dim bmp As BITMAP

GetObjectBitmap ii.hbmImage, LenB(bmp), bmp

'// point the safearray at the bitmap bits
With sa
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = bmp.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = bmp.bmWidthBytes
.pvData = bmp.bmBits
End With

CopyMemory ByVal VarPtrArray(arrBmpBits), VarPtr(sa), 4

'// apply formular to bitmap bits
Dim x As Long
For i = 0 To UBound(arrBmpBits, 1)
For j = 0 To UBound(arrBmpBits, 2)
x = arrBmpBits(i, j)
arrBmpBits(i, j) = x + (76 - Int((x + 32) / 64) * 19)
Next j
Next i

'// draw the lightend images below the originals
For i = 0 To ImageList_GetImageCount(img) - 1
ImageList_DrawEx img, i, hDc, i * 24 + 8, 32, 16, 16, _
CLR_NONE, _
CLR_NONE, _
ILD_NORMAL
Next i


ImageList_Destroy img

End Sub
 
 
 

handling Alpha channel

Post by Mike D Sut » Wed, 12 May 2004 21:20:13

> I'm trying to lighten images contained in an imagelist. The code I have
<code snipped>

I've not looked through the rest of your code, but try this loop instead:

'*** Warning; air code..
For j = 0 To UBound(arrBmpBits, 2)
For i = 0 To UBound(arrBmpBits, 1) Step 4
x = arrBmpBits(i, j)
arrBmpBits(i, j) = x + (76 - Int((x + 32) / 64) * 19)

x = arrBmpBits(i + 1, j)
arrBmpBits(i + 1, j) = x + (76 - Int((x + 32) / 64) * 19)

x = arrBmpBits(i + 2, j)
arrBmpBits(i + 2, j) = x + (76 - Int((x + 32) / 64) * 19)
Next i
Next j
'***

You could have an internal loop that goes through the three channels rather than pretty much the same code three times, but this is
slightly faster.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/

 
 
 

handling Alpha channel

Post by Rob » Wed, 12 May 2004 22:44:58

> I've not looked through the rest of your code, but try this loop instead:
rather than pretty much the same code three times, but this is

Mike

No go, I'm afraid. The actual images appear as expected but the background
comes out as pure white. Can you think of anything else that might be
causing this if it's not the loop?

Many thanks
Rob
 
 
 

handling Alpha channel

Post by Mike D Sut » Wed, 12 May 2004 23:10:35

> No go, I'm afraid. The actual images appear as expected but the background

Unfortunately you've caught me in a very busy week, hopefully someone else can jump in here otherwise I'll try and find some time
later on to have a better look through it.

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/
 
 
 

handling Alpha channel

Post by Schmid » Thu, 13 May 2004 17:32:11


"Rob" <none> schrieb im Newsbeitrag


background

Could you post your actual Loop-implementation?

Olaf
 
 
 

handling Alpha channel

Post by Rob » Thu, 13 May 2004 19:38:58


Here's the whole function: The bmBitsPixel = 32 version of the loop will
turn the background pure white.

Regards,
Rob

Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr"
(Ptr() As Any) As Long

Public Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type

Private Type SAFEARRAY2D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
Bounds(0 To 1) As SAFEARRAYBOUND
End Type

'// Purpose: Fade the images contained in an imagelist
'// Parameter: handle of imagelist containing 24 or 32 bit images
'//
Private Sub ImageList_Fade(ByVal himl As Long)
Dim ii As IMAGEINFO

ImageList_GetImageInfo himl, 7, ii

Dim arrBmpBits() As Byte
Dim sa As SAFEARRAY2D
Dim bmp As BITMAP

GetObjectBitmap ii.hbmImage, LenB(bmp), bmp

'// point the safearray at the bitmap bits
With sa
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = bmp.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = bmp.bmWidthBytes
.pvData = bmp.bmBits
End With

CopyMemory ByVal VarPtrArray(arrBmpBits), VarPtr(sa), 4

'// apply formular to bitmap bits
Dim x As Long, i As Long, j As Long

Dim t As String, c As String

If bmp.bmBitsPixel = 24 Then
For j = 0 To UBound(arrBmpBits, 2)
For i = 0 To UBound(arrBmpBits, 1)
x = arrBmpBits(i, j)
arrBmpBits(i, j) = x + (76 - Int((x + 32) / 64) * 19)
Next i
Next j
ElseIf bmp.bmBitsPixel = 32 Then
For j = 0 To UBound(arrBmpBits, 2)
For i = 0 To UBound(arrBmpBits, 1) Step 4
x = arrBmpBits(i, j)
arrBmpBits(i, j) = x + (76 - Int((x + 32) / 64) * 19)
x = arrBmpBits(i + 1, j)
arrBmpBits(i + 1, j) = x + (76 - Int((x + 32) / 64) * 19)
x = arrBmpBits(i + 2, j)
arrBmpBits(i + 2, j) = x + (76 - Int((x + 32) / 64) * 19)
Next i
Next j
End If
End Sub
 
 
 

handling Alpha channel

Post by Mike D Sut » Fri, 14 May 2004 07:03:56

> P.S. interesting:
<code snipped>

Ah yes, pre-multiplied alpha - Good idea, since AlphaBlend() is most likely used to render it. Another thing to bear in mind though
is that you're going to be dealing with pre-multiplied data coming _in_ as well as out so you really want to adjust just how much
you change the input pixel based on the current alpha. Unfortunately while pre-multiplication does make rendering of transparent
images faster, it does have the unfortunate side-effect of making data manipulation a bit of a pain since you never really know the
original colour values of anything other than completely opaque pixels.
Incidentally if you're just trying to lighten the image, why are you using such a complex calculation - Wouldn't a simple offset and
cap be sufficient? (And faster)
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/
 
 
 

handling Alpha channel

Post by Rob » Fri, 14 May 2004 10:13:04

Schmidt" < XXXX@XXXXX.COM > wrote in message
news:# XXXX@XXXXX.COM ...
VB-project).

Sorry. I use a typelib so was hoping you wouldn't need the API's :)

It's set up to load 12 icons from app.path called 101, 102, ..., 112
Copy code to form and set autoredraw = true

The icons are destined for a toolbar so I have no control over how they are
rendered.

Regards,
Rob

Option Explicit

Private Const CLR_NONE = &HFFFFFFFF
Private Const CLR_DEFAULT = &HFF000000
Private Const CLR_HILIGHT = CLR_DEFAULT

Private Type IMAGELISTDRAWPARAMS
cbSize As Long
hIml As Long
i As Long
hdcDst As Long
x As Long
y As Long
cx As Long
cy As Long
xBitmap As Long '// x offest from the upperleft of bitmap
yBitmap As Long '// y offset from the upperleft of bitmap
rgbBk As Long
rgbFg As Long
fStyle As ImageList_DrawStyles
dwRop As Long '// ternary raster flags (those used with
BitBlt)
End Type

Private Enum ImageList_CreateFlags
ILC_MASK = &H1
ILC_COLOR = &H0
ILC_COLORDDB = &HFE
ILC_COLOR4 = &H4
ILC_COLOR8 = &H8
ILC_COLOR16 = &H10
ILC_COLOR24 = &H18
ILC_COLOR32 = &H20
ILC_PALETTE = &H800 '// (not implemented)
End Enum

Private Enum ImageList_DrawStyles
ILD_NORMAL = &H0
ILD_TRANSPARENT = &H1
ILD_MASK = &H10
ILD_IMAGE = &H20
ILD_ROP = &H40
ILD_BLEND25 = &H2
ILD_BLEND50 = &H4
ILD_OVERLAYMASK = &HF00
ILD_SELECTED = ILD_BLEND50
ILD_FOCUS = ILD_BLEND25
ILD_BLEND = ILD_BLEND50
End Enum

'// used only in ImageList_Copy
Private Enum ImageList_CopyFlags
ILCF_MOVE = &H0
ILCF_SWAP = &H1
End Enum

Private Declare Function ImageList_Copy Lib "COMCTL32" (ByVal himlDst As
Long, ByVal iDst As Long, ByVal himlSrc As Long, ByVal iSrc As Long, ByVal
uFlags As Long) As Long
Private Declare Function ImageList_BeginDrag Lib "COMCTL32" (ByVal himlTrack
As Long, ByVal iTrack As Long, ByVal dxHotspot As Long, ByVal dyHotspot As
Long) As Long
Private Declare Sub ImageList_EndDrag Lib "COMCTL32" ()
Private Declare Function ImageList_DragEnter Lib "COMCTL32" (ByVal fLock As
Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function ImageList_DragLeave Lib "COMCTL32" (ByVal fLock As
Long) As Long
Private Declare Function ImageList_DragMove Lib "COMCTL32" (ByVal x As Long,
ByVal y As Long) As Long
Private Declare Function ImageList_SetDragCursorImage Lib "COMCTL32" (ByVal
himlDrag As Long, ByVal iDrag As Long, ByVal dxHotspot As Long, ByVal
dyHotspot As Long) As Long
Private Declare Function ImageList_DragShowNolock Lib "COMCTL32" (ByVal
fShow As Long) As Long
Private Declare Function ImageList_GetDragImage Lib "COMCTL32" (ppt As Any,
pptHotspot As Any) As Long
Private Declare Function ImageList_Create Lib "COMCTL32" (ByVal cx As Long,
ByVal cy As Long, ByVal Flags As Long, ByVal cInitial As Long, ByVal cGrow
As Long) As Long
Private Declare Function ImageList_Destroy Lib "COMCTL32" (ByVal hIml As
Long) As Long
Private Declare Function ImageList_GetImageCount Lib "COMCTL32" (ByVal hIml
As Long) As Long
Private Declare Function ImageList_SetImageCount Lib "COMCTL32" (ByVal hIml
As Long, ByVal uNewCount As Long) As Long
Private Declare Function ImageList_Add Lib "COMCTL32" (ByVal hIml, ByVal
hbmImage As Long, ByVal hbmMask As Long) As Long
Private Declare Function ImageList_ReplaceIcon Lib "COMC
 
 
 

handling Alpha channel

Post by Rob » Fri, 14 May 2004 10:28:51


such a complex calculation - Wouldn't a simple offset and

Mike

Sorry, bad description. It's more flatten than lighten. The lower the
value the more it gets "lightened".

Regards,
Rob
 
 
 

handling Alpha channel

Post by Schmid » Fri, 14 May 2004 23:24:11


"Rob" <none> schrieb im Newsbeitrag




Seems, that it was really the alpha-precalculation.
Try this version:

Private Sub ImageList_Fade(ByVal hIml As Long)
Dim ii As IMAGEINFO, B() As Byte, sa As SAFEARRAY2D, bmp As BITMAP
Dim x As Long, i As Long, j As Long, t As String, c As String, A#
Static LUT(255) As Byte

If LUT(255) = 0 Then 'calculate LUT (done at the first run only)
For i = 1 To 255: LUT(i) = i + (76 - Int((i + 32) / 64) * 19): Next
End If

ImageList_GetImageInfo hIml, 0, ii
GetObjectBitmap ii.hbmImage, LenB(bmp), bmp

'// point the safearray at the bitmap bits
sa.cbElements = 1
sa.cDims = 2
sa.Bounds(0).lLbound = 0
sa.Bounds(0).cElements = bmp.bmHeight
sa.Bounds(1).lLbound = 0
sa.Bounds(1).cElements = bmp.bmWidthBytes
sa.pvData = bmp.bmBits

CopyMemory ByVal VarPtrArray(B), VarPtr(sa), 4

'// apply formula to bitmap bits
On Error Resume Next
If bmp.bmBitsPixel = 24 Or bmp.bmBitsPixel = 32 Then
For j = 0 To UBound(B, 2)
For i = 0 To UBound(B, 1) Step bmp.bmBitsPixel \ 8
If bmp.bmBitsPixel = 24 Or B(i + 3, j) = 0 Then
B(i, j) = LUT(B(i, j))
B(i + 1, j) = LUT(B(i + 1, j))
B(i + 2, j) = LUT(B(i + 2, j))
Else
A = B(i + 3, j) / 255 'alpha-ratio
B(i, j) = LUT(B(i, j) / A) * A
B(i + 1, j) = LUT(B(i + 1, j) / A) * A
B(i + 2, j) = LUT(B(i + 2, j) / A) * A
End If
Next i
Next j
End If

CopyMemory ByVal VarPtrArray(B), 0&, 4 'Don't forget to cleanup
End Sub

Olaf
 
 
 

handling Alpha channel

Post by Rob » Sat, 15 May 2004 02:10:38

You've made my day. Thanks.