Solved

TransparentBlt for DIBs (256 color)

Posted on 1998-05-21
19
1,016 Views
Last Modified: 2013-11-20
I need to paint DIBs transparently (by transparent color).
There is TransparentBlt for DDBs on www.codeguru.com but not for DIB. Can I convert DIB to DDB and then perform TransparentBlt? Will I lose right colors?
0
Comment
Question by:eugenem
  • 11
  • 7
19 Comments
 
LVL 23

Expert Comment

by:chensu
ID: 1313602
What you should do is to convert a DIB to a DDB so that you get the HBITMAP and HPALETTE and pass these two handles to the TransparentBlt. And process the WM_QUERYNEWPALETTE and WM_PALETTECHANGED message sent to the top-level window. Thus you won't lose right colors.
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313603
I've converted DIB to DDB using DIBToDDB function from codeguru. But now something strange happens with some colors: I set transparent color to RGB(150,255,255) but RGB(192,192,192) becames transparent. RGB(1,1,1) converts to RGB(0,0,0), but RGB(255,255,255) or RGB(128,128,128) don't convert.
I think something strange is happening in DIBToDDB.
0
 
LVL 23

Expert Comment

by:chensu
ID: 1313604
I think this problem relates to the palette. Do you pass the correct palette handle to TransparentBlt?
0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 3

Author Comment

by:eugenem
ID: 1313605
This doesn't matter because I use TransparentBlt with memory dc (that doesn't support palette).
0
 
LVL 1

Expert Comment

by:Blondie050798
ID: 1313606
There should be a new function to draw a transparent bitmap turning up at codeguru anytime now that is more efficient when blitting to memory dcs.
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313607
What new function? I use one from codeguru. I draw to memory dc to realize double-buffering.
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313608
Come on, guys! I need this thing to work.
0
 
LVL 23

Accepted Solution

by:
chensu earned 200 total points
ID: 1313609
Try the following function. No need to convert it to a DDB.

//
// draw a DIB bitmap treating the background color of the DC as transparent
//
int TransStretchDIBits(HDC hdc,
                       WORD DstX, WORD DstY, WORD DstDX, WORD DstDY,
                       WORD SrcX, WORD SrcY, WORD SrcDX, WORD SrcDY,
                       LPVOID lpBits, LPBITMAPINFO lpbi,
                       WORD wUsage, DWORD rop)
{
    struct {
        BITMAPINFOHEADER    bih;
        WORD                aw[256];
    }   biPal;

    struct {
        BITMAPINFOHEADER    bih;
        DWORD               argb[256];
    }   biRgb;

    WORD    FAR *pw;
    DWORD   FAR *prgb;
    COLORREF rgbBk;
    HPALETTE hpal;
    WORD     wPalBk;
    WORD     wPalBlack;
    WORD     wPalWhite;
    int      i;

    //
    // see if the device supports this call directly
    //
    // otherwise we need to simulate it.
    //
#ifndef WIN32
    if (GetDeviceCaps(hdc, CAPS1) & C1_TRANSPARENT)
    {
        WORD w;
        BOOL f;

        w = SetBkMode(hdc, NEWTRANSPARENT);

        f = StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
                              SrcX,SrcY,SrcDX,SrcDY,
                              lpBits, lpbi, wUsage, rop);
        SetBkMode(hdc, w);
        return f;
    }
#endif

    //
    //  we want to do the equivelent of a MaskBlt, but we dont have to
    //  create multiple masks and things, we just change the color
    //  table of DIB, (aren't DIBs great)
    //
    //  we will use the two pass MaskBlt()
    //
    //      AND the dest with a DIB that has '1' where the trans color is
    //      '0' otherwise
    //
    //      OR the dest with a DIB that has '0' where the trans color is
    //

    rgbBk = GetBkColor(hdc);

    if (wUsage == DIB_PAL_COLORS)
    {
      // get current palette.
        hpal = SelectPalette(hdc, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
      SelectPalette(hdc, hpal, FALSE);

        // get the index of the background color (and black)
        //
        //  NOTE it is *very* important that the palette has
        //  black and white in it (*real* black and white, not
        //  PC_RESERVED or PC_NOCOLAPSE) we are doing raster op's
        //  and assume black==00, and white==FF
        //
        wPalBk    = GetNearestPaletteIndex(hpal, rgbBk);
        wPalBlack = GetNearestPaletteIndex(hpal, rgbBlack);
        wPalWhite = GetNearestPaletteIndex(hpal, rgbWhite);

        //
        //  copy the given BITMAPINFO over and munge it, to make our mask.
        //  the usage is DIB_PAL_COLORS so we need to munge index's not
        //  RGBs
       //
        biPal.bih = lpbi->bmiHeader;
        pw = (WORD FAR *)lpbi->bmiColors;

        for (i=0; i < (int)biPal.bih.biClrUsed; i++)
        {
            if (pw[i] == wPalBk)
                biPal.aw[i] = wPalWhite;
            else
                biPal.aw[i] = wPalBlack;
        }

        StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
                          SrcX,SrcY,SrcDX,SrcDY,
                          lpBits, (LPBITMAPINFO)&biPal, wUsage, DSa);

        for (i=0; i < (int)biPal.bih.biClrUsed; i++)
        {
            if (pw[i] == wPalBk)
                biPal.aw[i] = wPalBlack;
            else
                biPal.aw[i] = pw[i];

        }

        StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
                          SrcX,SrcY,SrcDX,SrcDY,
                          lpBits, (LPBITMAPINFO)&biPal, wUsage, DSx);
    }
    else
    {
        //  the usage is DIB_RGB_COLORS so we need to munge rgb's not
        //  index's
        //
        biRgb.bih = lpbi->bmiHeader;
        prgb = (DWORD FAR *)lpbi->bmiColors;

        for (i=0; i < (int)biRgb.bih.biClrUsed; i++)
        {
            if (prgb[i] == RGBQ(rgbBk))
                biRgb.argb[i] = RGBQ(rgbWhite);
            else
                biRgb.argb[i] = RGBQ(rgbBlack);
        }

        StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
                          SrcX,SrcY,SrcDX,SrcDY,
                          lpBits, (LPBITMAPINFO)&biRgb, wUsage, DSa);

        for (i=0; i < (int)biRgb.bih.biClrUsed; i++)
        {
            if (prgb[i] == RGBQ(rgbBk))
                biRgb.argb[i] = RGBQ(rgbBlack);
            else
                biRgb.argb[i] = prgb[i];
        }

        StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
                          SrcX,SrcY,SrcDX,SrcDY,
                          lpBits, (LPBITMAPINFO)&biRgb, wUsage, DSx);
    }

    return TRUE;
}

0
 
LVL 3

Author Comment

by:eugenem
ID: 1313610
How do I choose transparent color? Is it background of DC?
How do I know if I should use DIB_PAL_COLORS or DIB_RGB_COLORS?
What should be rop parameter? What's with these PS_RESERVED and PC_NOCOLLAPSE (should I make first and last 10 colors PC_NOCOLLAPSE and other zeros when I load the palette)?
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313611
May be we can switch to e-mail. It will be faster.
My is mednikov@netvision.net.il.
0
 
LVL 23

Expert Comment

by:chensu
ID: 1313612
>How do I choose transparent color? Is it background of DC?
Yes, use SetBkColor to set the background color of DC.

>How do I know if I should use DIB_PAL_COLORS or DIB_RGB_COLORS?
It depends on the DIB. It is the same as the parameter of StretchDIBits. It is usually DIB_RGB_COLORS.

>What should be rop parameter?
It is the same as the parameter of StretchDIBits and BitBlt. It is used only in 16-bit version. I forgot to tell you that:
#define DSa  0x008800C6L
#define DSx  0x00660046L
#define rgbBlack RGB(0,0,0)
#define rgbWhite RGB(255,255,255)

>What's with these PS_RESERVED and PC_NOCOLLAPSE (should I make first and last 10 colors PC_NOCOLLAPSE and other zeros when I load the palette)?
Normally, you need to do nothing.

>May be we can switch to e-mail. It will be faster.
Sorry, I prefer using Experts Exchange so that we can keep all the comments here.

0
 
LVL 3

Author Comment

by:eugenem
ID: 1313613
Are DSa SRCAND and DSx SRCPAINT?
I need to use this function with memory dc so should I provide palette as a parameter?
What is RGBQ? Same as RGB?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1313614
>Are DSa SRCAND and DSx SRCPAINT?
Actually, DSa is the same as SRCAND and DSx is the same as SRCINVERT.

>I need to use this function with memory dc so should I provide palette as a parameter?
You should select the palette of the DIB into the DC and realize it before calling this function. You should always do so when you handle a DIB.

>What is RGBQ? Same as RGB?
#define RGBQ(rgb)   RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb))
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313615
How can I realize palette in memoryDC if it doesn't support palettes?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1313616
If it doesn't, don't do it.
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313617
But is it true that memory dc doesn't support palette?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1313618
It depends. When you create the memory DC by using CDC::CreateCompatibleDC, it is compatible with the system display. You can always select and realize a palette no matter whether it supports or not. If it does not, simply no effect.
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313619
It works great. Just need to replace
        for (i=0; i < (int)biRgb.bih.biClrUsed; i++)
        {
            if (prgb[i] == RGBQ(rgbBk))
                biRgb.argb[i] = RGBQ(rgbWhite);
            else
                biRgb.argb[i] = RGBQ(rgbBlack);
        }
to
      int size = 1 << lpbi->bmiHeader.biBitCount;

        for (i=0; i < size; i++)
        {
            if (prgb[i] == RGBQ(rgbBk) )
                biRgb.argb[i] = RGBQ(rgbWhite);
            else
                biRgb.argb[i] = RGBQ(rgbBlack);
        }
Thanks a lot!
0
 
LVL 3

Author Comment

by:eugenem
ID: 1313620
It works great. Just need to replace
        for (i=0; i < (int)biRgb.bih.biClrUsed; i++)
        {
            if (prgb[i] == RGBQ(rgbBk))
                biRgb.argb[i] = RGBQ(rgbWhite);
            else
                biRgb.argb[i] = RGBQ(rgbBlack);
        }
to
      int size = 1 << lpbi->bmiHeader.biBitCount;

        for (i=0; i < size; i++)
        {
            if (prgb[i] == RGBQ(rgbBk) )
                biRgb.argb[i] = RGBQ(rgbWhite);
            else
                biRgb.argb[i] = RGBQ(rgbBlack);
        }
Thanks a lot!
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Question regarding Copy/Paste 16 96
Installing Microsoft R server on REDHAT or SUSE Linux 4 147
Separate files macro - Errors on larger data set 18 73
string initialization in java 11 115
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli‚Ķ
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question