• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 845
  • Last Modified:

Image transparency in Delphi under Windows XP


I use TImage for writing text on its canvas with TextOut method. My images are all defined transparent, and when I work under Windows 2000, they do look transparent. However, when I run my application under Windows XP, only some parts of an image become transparent, namely those with text lines on them. All the remaining area of the image is white.

You can see the screenshots here:

http://www.susi.ru/kanji/kaze1.gif   (Windows 2000)
http://www.susi.ru/kanji/kaze2.gif   (Windows XP)

How can I solve this problem?

Vadim Smolensky,
St.Petersburg, Russia
  • 4
  • 3
1 Solution
Have you tried using a more contrasting colour for the transparency? In transparent images the more contrast in the image the better the transparency. With black text try a white background. Or a nother method is to use a colour which is similar too, but not the same as the text e.g. dark brown.

As for the difference between 2000 and XP i am unsure, all i can reccomend is adjusting you image contrasts.

Best regards,

VSmolenskyAuthor Commented:
Thank you for the suggestion, but your advice looks strange. Transparency isn't Alpha property, it can't be better or worse depending on contrasts. Tranparency either exists or not, it's a binary thing. And in my case, it obviously doesn't work properly at all.

I have found from experience with transparent forms that if you have a bitmap with a colour that is close to what you want remaining then you will get a better result. Similarly this will also work if the colour is strongly opposite (perhaps contrast was the wrong word). In your case i think you are right it is not a problem that could be solved using my method - you can but try though :-)


Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

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.

Have you tried bitblt instead? This code may be of use to you:

procedure tform1.DrawTransparentBitmap(DC: HDC; hBmp : HBITMAP ;
          xStart: integer; yStart : integer; cTransparentColor : COLORREF);
      bm:                                                  BITMAP;
      cColor:                                              COLORREF;
      bmAndBack, bmAndObject, bmAndMem, bmSave:            HBITMAP;
      bmBackOld, bmObjectOld, bmMemOld, bmSaveOld:         HBITMAP;
      hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave:        HDC;
      ptSize:                                              TPOINT;

   hdcTemp := CreateCompatibleDC(dc);
   SelectObject(hdcTemp, hBmp);   // Select the bitmap

   GetObject(hBmp, sizeof(BITMAP), @bm);
   ptSize.x := bm.bmWidth;            // Get width of bitmap
   ptSize.y := bm.bmHeight;           // Get height of bitmap
   DPtoLP(hdcTemp, ptSize, 1);        // Convert from device
                                      // to logical points

   // Create some DCs to hold temporary data.
   hdcBack   := CreateCompatibleDC(dc);
   hdcObject := CreateCompatibleDC(dc);
   hdcMem    := CreateCompatibleDC(dc);
   hdcSave   := CreateCompatibleDC(dc);

   // Create a bitmap for each DC. DCs are required for a number of
   // GDI functions.

   // Monochrome DC
   bmAndBack   := CreateBitmap(ptSize.x, ptSize.y, 1, 1, nil);

   // Monochrome DC
   bmAndObject := CreateBitmap(ptSize.x, ptSize.y, 1, 1, nil);

   bmAndMem    := CreateCompatibleBitmap(dc, ptSize.x, ptSize.y);
   bmSave      := CreateCompatibleBitmap(dc, ptSize.x, ptSize.y);

   // Each DC must select a bitmap object to store pixel data.
   bmBackOld   := SelectObject(hdcBack, bmAndBack);
   bmObjectOld := SelectObject(hdcObject, bmAndObject);
   bmMemOld    := SelectObject(hdcMem, bmAndMem);
   bmSaveOld   := SelectObject(hdcSave, bmSave);

   // Set proper mapping mode.
   SetMapMode(hdcTemp, GetMapMode(dc));

   // Save the bitmap sent here, because it will be overwritten.
   BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);

   // Set the background color of the source DC to the color.
   // contained in the parts of the bitmap that should be transparent
   cColor := SetBkColor(hdcTemp, cTransparentColor);

   // Create the object mask for the bitmap by performing a BitBlt
   // from the source bitmap to a monochrome bitmap.
   BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,

   // Set the background color of the source DC back to the original
   // color.
   SetBkColor(hdcTemp, cColor);

   // Create the inverse of the object mask.
   BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,

   // Copy the background of the main DC to the destination.
   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, dc, xStart, yStart,

   // Mask out the places where the bitmap will be placed.
   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);

   // Mask out the transparent colored pixels on the bitmap.
   BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);

   // XOR the bitmap with the background on the destination DC.
   BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);

   // Copy the destination to the screen.
   BitBlt(dc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,

   // Place the original bitmap back into the bitmap sent here.
        BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);

   // Delete the memory bitmaps.
   DeleteObject(SelectObject(hdcBack, bmBackOld));
   DeleteObject(SelectObject(hdcObject, bmObjectOld));
   DeleteObject(SelectObject(hdcMem, bmMemOld));
   DeleteObject(SelectObject(hdcSave, bmSaveOld));

   // Delete the memory DCs.

procedure TForm1.Button1Click(Sender: TObject);
DrawTransparentBitmap(Form1.Canvas.Handle, Image1.Picture.Bitmap.Handle, 10, 10, clWhite);
VSmolenskyAuthor Commented:
It's quite probable that this piece of code will work properly. But I wouldn't like to make my code too sophisticated. Under Windows 2K, it was enough to assign Trasparent:=True. I'm sure the solution for Windows XP must also be very simple. We just have to understand the difference between the two platforms.

You should still be able to assign Trasparent:=True in XP, i know i can. I'm using XP myself and i have not had problems such as yours since i have found the transparency to work fine if i adjust the transparent colour so i don't get the halo effect. Have you tested you app of another XP system? Also see what happens using a different image - do you get the same problem?



first try setting TransparentMode := tmFixed;
TransparentColor := yourTransparentColor;

also before calling TextOut

set Canvas.Brush.Color := yourTransparentColor;

it should help

another solution would be simply filling bitmap with bg color using FillRect
VSmolenskyAuthor Commented:

FillRect works perfectly well. Also, FloodFill gives the same effect. Looks like every pixel of the bitmap must be processed somehow to make the image truly transparent.

Thank you very much!

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

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

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now