VSmolensky
asked on
Image transparency in Delphi under Windows XP
Hello,
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
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
ASKER
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.
V.S.
V.S.
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 :-)
Regards,
Hypoviax
Regards,
Hypoviax
Have you tried bitblt instead? This code may be of use to you:
procedure tform1.DrawTransparentBitm ap(DC: HDC; hBmp : HBITMAP ;
xStart: integer; yStart : integer; cTransparentColor : COLORREF);
var
bm: BITMAP;
cColor: COLORREF;
bmAndBack, bmAndObject, bmAndMem, bmSave: HBITMAP;
bmBackOld, bmObjectOld, bmMemOld, bmSaveOld: HBITMAP;
hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave: HDC;
ptSize: TPOINT;
begin
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,
SRCCOPY);
// 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,
NOTSRCCOPY);
// Copy the background of the main DC to the destination.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, dc, xStart, yStart,
SRCCOPY);
// 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,
SRCCOPY);
// 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.
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
end;
procedure TForm1.Button1Click(Sender : TObject);
begin
DrawTransparentBitmap(Form 1.Canvas.H andle, Image1.Picture.Bitmap.Hand le, 10, 10, clWhite);
end;
procedure tform1.DrawTransparentBitm
xStart: integer; yStart : integer; cTransparentColor : COLORREF);
var
bm: BITMAP;
cColor: COLORREF;
bmAndBack, bmAndObject, bmAndMem, bmSave: HBITMAP;
bmBackOld, bmObjectOld, bmMemOld, bmSaveOld: HBITMAP;
hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave: HDC;
ptSize: TPOINT;
begin
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,
bmSave := CreateCompatibleBitmap(dc,
// 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,
SRCCOPY);
// 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,
NOTSRCCOPY);
// Copy the background of the main DC to the destination.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, dc, xStart, yStart,
SRCCOPY);
// 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,
SRCCOPY);
// 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(
DeleteObject(SelectObject(
DeleteObject(SelectObject(
DeleteObject(SelectObject(
// Delete the memory DCs.
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
end;
procedure TForm1.Button1Click(Sender
begin
DrawTransparentBitmap(Form
end;
ASKER
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.
V.S.
V.S.
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?
Regards,
Hypoviax
Regards,
Hypoviax
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
YES!!!
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!
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!
As for the difference between 2000 and XP i am unsure, all i can reccomend is adjusting you image contrasts.
Best regards,
Hypoviax