Re: ImageList_Draw and icons with alpha channel

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



The AND mask represents the "Alpha Channel".

Where the pixel is marked as "White", the pixel in the final
destination bitmap will be replaced by the background color
after application of the XOR and AND masks.

Using masks works for all bit depths and allows you to
create icons, cursors or use bitmaps that can be TransBlt
accross the screen. You don't have the option of fine
tuning the alpha channel for degree of opacity on a per
pixel basis.

If you want to define the degree of opacity
on a per pixel basis, you only have one option.

For the 32bpp case only, you may create the masks as follows:
1) Use a BITMAPV5HEADER and CreateDIBSection
to create an alpha channel canvas to draw your icon and text.
2) Use CreateBitmap to create an AND mask. You leave this
mask alone(i.e., don't set the bits on or off )
3) Use the pointer to the DIBSECTION bits to create the "AND"
mask. You use the same algorithm but operate on the alpha
channel only. You can refine the degree of opacity from 0 to 255
on a per pixel basis.
4) When your done, premultiply the alpha channel against the individual
colors.
5) Use the rest of your code to add the bitmap masks.

Keep in mind that normal Windows bitmaps are BI_RGB where
each pixel is formatted as 0x00BBGGRR. The alpha channel is
ignored.

An Alpha channel bitmap created by a BITMAPV5HEADER is
formatted as 0xAARRGGBB. If you premultiply the alpha channel
against the individual colors, you can ensure yourself that the
alpha channel will be preserved using Windows GDI calls.


"Timo Kunze" <TKunze71216@xxxxxx> wrote in message
news:%235CZSZo2FHA.2364@xxxxxxxxxxxxxxxxxxxxxxx
> We're getting closer. :)
> With my (better: your) current code, the drag image contains the icon
> and the text (with correct colors) - on Windows XP SP2 as well as on
> Windows 2003 SP1. This is the first time I got this working with
> ILC_COLOR32. Looks like using CreateDIBSection is the key.
> However, the per-pixel alpha transparency still gets lost. I think it's
> because the AND mask tells GDI that these pixels are opaque and actually
> it should tell GDI that they're transparent, am I right? Then we'd need
> a way to read out each pixel's alpha channel in the for loops and set
> the AND mask's pixel to white if it is different than 255. Shouldn't be
> that difficult, but I'm too tired to try it right now.
>
> Here's the code I'm currently using:
>
> // create a memory DC
> WTL::CDC memoryDC;
> memoryDC.CreateCompatibleDC();
>
> // create a 32bpp DIB
> WTL::CBitmap dibBitmap32bpp;
> BITMAPINFO bitmapInfo = {0};
> bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
> bitmapInfo.bmiHeader.biWidth = 90;
> bitmapInfo.bmiHeader.biHeight = 50;
> bitmapInfo.bmiHeader.biPlanes = 1;
> bitmapInfo.bmiHeader.biBitCount = 32;
> bitmapInfo.bmiHeader.biCompression = BI_RGB;
> dibBitmap32bpp.CreateDIBSection(memoryDC, &bitmapInfo, DIB_RGB_COLORS,
> NULL, NULL, 0);
>
> // setup the memory DC
> WTL::CFontHandle font = (HFONT) SendMessage(WM_GETFONT, 0, 0);
> HFONT hPreviousFont = NULL;
> if(!font.IsNull()) {
> hPreviousFont = memoryDC.SelectFont(font);
> }
> HBITMAP hPreviousBitmap1 = memoryDC.SelectBitmap(dibBitmap32bpp);
> memoryDC.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
> memoryDC.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
>
> /* Fill the bitmap's background with an ugly magenta. Magenta pixels
> will become transparent. */
> COLORREF transparentColor = RGB(255, 0, 255);
> WTL::CBrush backgroundBrush;
> backgroundBrush.CreateSolidBrush(transparentColor);
> memoryDC.FillRect(WTL::CRect(0, 0, 90, 50), backgroundBrush);
>
> // draw content
> HICON hIcon = ::ImageList_ExtractIcon(NULL, hSourceImageList,
> item.iImage);
> memoryDC.DrawIcon(0, 0, hIcon);
> ::DestroyIcon(hIcon);
> memoryDC.DrawText(_T("Hello"), 5, WTL::CRect(40, 10, 80, 30),
> DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
>
> // create the masks that together build the drag image
> WTL::CBitmap xorMask;
> xorMask.CreateCompatibleBitmap(memoryDC, 90, 50);
> WTL::CDC xorMaskDC;
> xorMaskDC.CreateCompatibleDC();
> HBITMAP hPreviousBitmap2 = xorMaskDC.SelectBitmap(xorMask);
>
> WTL::CBitmap andMask;
> andMask.CreateBitmap(90, 50, 1, 1, NULL);
> WTL::CDC andMaskDC;
> andMaskDC.CreateCompatibleDC();
> HBITMAP hPreviousBitmap3 = andMaskDC.SelectBitmap(andMask);
>
> // draw the masks pixel by pixel
> for(DWORD x = 0; x < 90; x++) {
> for(DWORD y = 0; y < 50; y++) {
> if(memoryDC.GetPixel(x, y) == transparentColor) {
> andMaskDC.SetPixel(x, y, RGB(255, 255, 255));
> xorMaskDC.SetPixelV(x, y, RGB(0, 0, 0));
> } else {
> andMaskDC.SetPixel(x, y, RGB(0, 0, 0));
> xorMaskDC.SetPixel(x, y, memoryDC.GetPixel(x, y));
> }
> }
> }
> ::GdiFlush();
>
> // clean up
> memoryDC.SelectFont(hPreviousFont);
> memoryDC.SelectBitmap(hPreviousBitmap1);
> xorMaskDC.SelectBitmap(hPreviousBitmap2);
> andMaskDC.SelectBitmap(hPreviousBitmap3);
>
> // create the imagelist containing our drag image
> HIMAGELIST hDragImageList = ::ImageList_Create(90, 50, ILC_COLOR32 |
> ILC_MASK, 1, 0);
> ::ImageList_SetBkColor(hDragImageList, CLR_NONE);
> // add the drag image
> ::ImageList_Add(hDragImageList, xorMask, andMask);
>
> // ImageList_BeginDrag will be called with hDragImageList
>
> Timo
> --
> www.TimoSoft-Software.de - the home of ExplorerTreeView
> Stop software patents!


.



Relevant Pages

  • Re: Placement of pasted selections
    ... bits per channel per pixel (for RBG and ALPHA that is 8x4=32 bits per pixel). ...
    (comp.graphics.apps.gimp)
  • Re: Alphablending
    ... "paint" into the alpha channel.. ... Then you can use the rendered leaf as texture (with per pixel ... Its not diretcly a triangle, its a rectangle where only two sides are parallell and two are not. ... Barycentric coordinates, however, cannot. ...
    (alt.lang.asm)
  • Re: Alphablending
    ... A question more about those alpha channels, ... How can I do pixel shading in software, ... I used "virtual registers" and allocated real registers later.. ... Writing assembler is pain in the ass, if you dont have an assembler that is created to make it a blessed experience. ...
    (alt.lang.asm)
  • Re: AlphaBlending Question
    ... In order to save some calculations over a number of transparent png files, I was attempting to ignore the ... Interestingly enough, when I set the RGBs of zero alpha pixels to 0, the AlphaBlend function works fine. ... simply ignore the pre-multiplication if the alpha channel is 0, then I see the a white/grey color for those pixels. ... component and is simply combined with the inverse-alpha multiplication of the current pixel. ...
    (microsoft.public.vb.winapi.graphics)
  • Re: Discarding pixels by Alpha, Stencil, Depth test
    ... Alpha testing comes only after the pixel fragment has been evaluated, ... means it is just as slow as processing the pixel. ... Stencil is more expensive than depth because it requires both reading & ...
    (microsoft.public.win32.programmer.directx.graphics)