ClearType ruins transparency - c++

I have a bitmap which background needs to be replaced with part of another bitmap. Everything works fine until I enable ClearFont on my WindowsXP.
In order to explain my problem better, let us label first bitmap as bmpDestination and second as bmpSource.
Here is how the bmpSource looks like :
Here is how bmpDestination looks like :
When ClearType is off, here is how the correct result looks like :
And here is the incorrect result of their combining when ClearType is on:
ClearType alters some parts of the text background color, so they aren't white anymore ( RGB( 255, 255, 255 ) ) but a combination of white and text color.
I am using BitBlt() and monochrome bitmap to create a mask, and to simulate transparency. I have tried using TransparentBlt() too, but got the same result.
How can I combine bmpSource and bmpDestination, when ClearType is enabled, so I can create correct result like above ?
Thank you for your help.
Best regards.

Render the treeview with black text on a white background. Use a font with grey-scale anti-aliasing. Don't use ClearType anti-aliasing. I'm moderately sure you can achieve this with one of the fdwQuality parameters to CreateFont, but I wouldn't swear to it.
Each pixel will have a shade of grey between white and black. You can interpret this as transparency. White is fully transparent; black is fully opaque. Use this information to create a bitmap with transparency. Render this transparent bitmap over your multi-coloured background.

Related

Draw/Create ID2D1RenderTarget with Transparent Color

I have a written a class which is able to display animated GIF files with Direct 2d as in this example from MSDN:
https://code.msdn.microsoft.com/windowsapps/Windows-Imaging-Component-65abbc6a/sourcecode?fileId=127204&pathId=969071766
The GIF which I display is a continuously growing/shrinking not filled blue circle. All other pixels are White / the Background is White.
Unlike the example posted I create a CWnd, without Caption and Border, with the size of the GIF, with a ID2D1RenderTarget filling the whole CWnd and place it above the Content of my MainFrame.
Since I never used Direct2d before I assumed I can simply apply SetLayerdWindow() on my CWnd to reach my goal of only displaying the blue Circle.
SetLayeredWindowAttributes(RGB(255,255,255), 204, LWA_ALPHA | LWA_COLORKEY);
This should result in a CWnd with no White Pixels + 80% Transparency. Unfortunately the resulting Window is 80% transparent but none of the WhitePixels where removed/ the white pixels are still drawn.
Why does LWA_COLORKEY not work in this case?
And how can I achieve that either my CWnd or ID2D1HwndRenderTarget will draw white as fully transparent?!
Note:
Besides that I've tried just for fun to draw a fully transparent background with the ID2D1HwndRenderTarget like:
m_pHwndRT->Clear(D2D1::ColorF(D2D1::ColorF::White, 0.0f));
With Microsoft stating: "The alpha value for the color to be constructed. An alpha channel value ranges from 0.0 to 1.0, where 0.0 represents a fully transparent color and 1.0 represents a fully opaque color. The default value is 1.0."
Which results in a fully white opaque window... Which made me wonder if this whole Transparency stuff is working at all

Qt Pixmap Manipulation

I'm attempting to create a process manager based on QPixmaps. These pixmaps are updated via a timer callback at 20Hz, so it appears like they're spinning.
Below is a screenshot of my current window.
The pixmap is a 2D array with [20][14] elements. 20 is the amount of time slices, 14 is the process status indicator. I know, there are only 13 displayed here on the screen.
I'm currently using the painter object and composition modes to add QImages together with the following code:
QImage textImage(mapIcon.size(), QImage::Format_ARGB32);
QImage resultImage(mapIcon.size(), QImage::Format_ARGB32);
QPainter textPainter(&textImage);
textPainter.setCompositionMode(QPainter::CompositionMode_Source);
textPainter.fillRect(mapIcon.rect(), Qt::black);
textPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
textPainter.setFont(QFont("Arial", 8, QFont::Bold));
textPainter.setPen(QPen(Qt::white));
textPainter.drawText(QRectF(0, 0, mapIcon.width(), mapIcon.height()),
Qt::AlignCenter, name);
textPainter.end();
QPainter resultPainter(&resultImage);
resultPainter.setCompositionMode(QPainter::CompositionMode_Source);
resultPainter.drawImage(0, 0, mapIcon);
resultPainter.setCompositionMode(QPainter::CompositionMode_Exclusion);
resultPainter.drawImage(0, 0, textImage);
resultPainter.setRenderHint(QPainter::SmoothPixmapTransform, true);
resultPainter.setRenderHint(QPainter::HighQualityAntialiasing, true);
runnerIcons[x][y] = QPixmap::fromImage(resultImage);
My question is this: I don't want the inverted color scheme seen on the green labels, I want that color black. The white on black is ok, but the magenta isn't my favorite.
Is this possible in Qt? Or maybe ya'll have some suggestions to alternative solutions?
Thanks in advance.
There are a couple things you can do. You might check out the QPainter::setCompositionMode (mode) method. Maybe one of the other composition modes would be useful to you? Particularly QPainter::CompositionMode_Exclusion or QPainter::RasterOp_SourceXorDestination.
You could also use a complimentary color for the text. Magenta (blue+red) is opposite green on the color wheel. If you made the text magenta, it would probably show up well against both black and green. (I'm not saying it will look great - just that it will show up well.) Or maybe you could make the text 50% gray so that there is contrast in the luminance as well as in the color?
Also, you only have 13 icons, not 14. Not sure if it makes any difference.

Colored border of the transparent color key around text written on the transparent window

I created a Transparent Layered window with a color key that I use to make the window transparent.
So far it works all fine.
Writing text on it - using GDI+ - works, too...
The problem I encounter is, that the text has a thin border of the colorkey-color around the letters...
What I do in the WM_PAINT is:
1. Clear the drawing area Graphics::Clear(ColorKey);
2. Draw the text on it.
Screenshot of what i mean: http://imageshack.us/photo/my-images/709/cutp.jpg/
Anyone knows about how to avoid this?
Try calling Graphics::SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit).

Why would GDI+ colours vary based off whether a tooltip is visible?

I'm displaying a bitmap using GDI+. After loading the bitmap from a DLL resource I set the background colour (blue - #0000FF) to transparent using TransparentBlt. On Windows Vista and later this works as expected.
However, on a Windows XP system we're testing on this only works when any tooltip (e.g. the "title" property in IE, or Windows Explorer's tooltip shown when hovering the mouse over a file, etc) is displayed. The rest of the time the background colour is still blue.
Has anyone encountered this before, or know of a way to stop this occurring and for the blue to be properly made transparent?
Edit: After further investigation I found that setting colour depth in Windows XP to 16 bit colours instead of 32 bit colours caused TransparentBlt to start working normally again. Obviously this isn't an ideal solution, specifying what colour depth must be used, but does this give any hint to what might be happening?
Edit2: Code sample included.
m_pGDIBitmap = new Gdiplus::Bitmap(_Module.m_hInst, MAKEINTRESOURCE(lImageResource));
m_hMemDC = CreateCompatibleDC(hdc);
Gdiplus::Graphics myGraphics(m_hMemDC);
myGraphics.DrawImage(m_pGDIBitmap,
Gdiplus::Rect(0, 0, m_pGDIBitmap->GetWidth(), m_pGDIBitmap->GetHeight()),
0,
0,
m_pGDIBitmap->GetWidth(),
m_pGDIBitmap->GetHeight(),
Gdiplus::UnitPixel, &imAtt);
SetStretchBltMode(hdc, HALFTONE);
SetBrushOrgEx(hdc, rcBounds.left, rcBounds.top, NULL);
TransparentBlt(hdc, rcBounds.left, rcBounds.top, iScaledWidth, iScaledHeight, m_hMemDC, 0, 0, iBitmapWidth, iBitmapHeight, GetPixel(m_hMemDC, 0, 0));
You must show some sample code - the code that loads the bitmap and the code that blits it to display.
From the symptoms that you describe, my guess is that you load the bitmap not in its native format, but in the current display format. This means, that when the bit depth of the bitmap differs from the bit depth of the display, an automatic color space conversion is made. When this happens, the color that you provide to TransparentBlt is actually different from the color in the bitmap.
Possible alternative solutions:
Make sure that the bitmap is loaded in its native format without conversion.
Allow the conversion to take place, but instead of providing a hardcoded color value to TransparentBlt, make a GetPixel of a known "transparent" pixel of the bitmap (like top-left), and provide this value to the TransparentBlt.
What I ended up doing was more of a workaround, but it did work. I changed the background colour to black and added the following code before the DrawImage call:
Gdiplus::ImageAttributes imAtt;
imAtt.SetColorKey(Gdiplus::Color(0, 0, 0), Gdiplus::Color(0, 0, 0), Gdiplus::ColorAdjustTypeBitmap);
For some reason using this with blue as the background didn't work and using TransparentBlt on its own with either colour didn't work, but the combination applied the transparency correctly on the various OSes and colour depths that I tried.
If I had access to a paint program that supported bitmap files with an alpha channel, i.e. 32 bit bitmaps, I suspect making the background explicitly transparent and then using AlphaBlend would have worked as well but I didn't have the ability to try that at the time.

How can I draw a patternBrush with transparent backround (GDI)?

I can't draw a pattern with a transparent background. This is my snippet :
bitmap.CreateBitmap(8, 8, 1, 1, &bits)
brush.CreatePatternBrush(&bitmap)
hbrush = pCgrCurrentDC->SelectObject(&brush);
// set text color
TextCol = pCgrCurrentDC->SetTextColor(CgrColourPalRGB);
int oldBkgrdMode = pCgrCurrentDC->SetBkMode(TRANSPARENT);
//draw polygon
pCgrCurrentDC->Polygon(CgrBuffer, n);
The doc on msdn doesn't mention anything about transparency. I guess this mode could be used? Or is this a bug ?
Thanks!
Mode TRANSPARENT means that background will not be filled before your brush is drawn. But your brush does not contain any transparent pixels in it and it redraws background pixels anyway. Fourth argument in CreateBitmap was set to 1 in your sample. That means bitmap is monochrome.
You need to use 32-bit bitmap to use transparency in brushes. GDI supports transparency with some limits. Use GDI+ for full transparency support.