GDI+ DrawImage() with transparent bitmap to a printer - windows

Does anybody have any pointers on how to successfully draw a bitmap that has
an alpha channel using Graphics::DrawImage() when the Graphics context is
created based on a printer HDC? The printer drivers don't generally support alpha blending - so is there an alternative to rendering everything to an offscreen bitmap and just sending that to the printer. This is often not feasible, especially for high res printing to large format printers.

What kind of printer is that? Regular printers don't print white. Create in-memory image and 'flatten' it (remove alpha channel) and then print the result.

Have you tried drawing a white rectangle to initialize the image before you call the DrawImage method?

The whole point is that I need the line-drawn graphics behind the image to be visible. I did try filling the rectangle first the with RGBA color of (255, 255, 255, 0) but this does not help. Pixels with an alpha value of zero do get printed as fully transparent but partially transparent pixels are drawn fully opaque.

Thanks for asking this question because I was just thinking of perhaps trying to use GDIplus to see whether it could get me around the problems I'm still facing getting patterned diamond shapes to print correctly. Although nowadays alpha-blending does appear to work on most printers, there are still some that draw black corners on the diamonds.
Aside from alpha-blending, I've also tried using diamond-shaped clip regions to surround the shape, but normally the printers that don't support alpha-blending don't seem to support polygonal clip-regions either. I've tried copying from the printer-dc into a bitmap to prime it before drawing the diamond on top, hoping that this will allow me to put back (in the corners) what was there before. This doesn't work either because it appears that the problem boils down to the fact that the printer driver doesn't actually know what is being printed on what part of the page.
In my case, my next plan is to try using a large bitmap brush for drawing the diamond fill directly to the printer hdc. I suspect there's a moderate chance that this too will fail for certain printers. It sounds like it may not be an option for what you were doing.

Related

HTML5 canvas - make a mono mask efficiently without antialiasing

I am using pixel colour inspection to detect collisions. I know there are other ways to achieve this but this is my use case.
I draw a shape cloned from the main canvas on to a second canvas switching the fill and stroke colours to pur black. I then use getImageData() to get an array of pixel colours and inspect them - if I see black I have a collision with something.
However, some pixels are shades of grey because the second canvas is applying antialiasing to the shape. I want only black or transparent pixels.
How can I get the second canvas to be composed of either transparent or black only?
I have achieved this long in the past with Windows GDI via compositing/xor combinations etc. However, GDI did not always apply antialiasing. I guess the answer lies in globalCompositeOperation or filter but I cannot see what settings/filters or sequence to apply.
I appreciate I have not provided sample code but I am hoping that someone can throw me a bone and I'll work up a snippet here which might become a standard cut & paste for posterity from that.

Generating fast color rectangles

I am designing a more powerful color picker for Qt and looking for some advice. How would one go about generating fast real-time color rectangles such as the ones found in Photoshop (for HSB and RGB). I was originally thinking of using QImage and scanline to calculate all the pixels individually but this would probably be too slow.
I was thinking it would be better to write an OpenGL shader. As I can recall you can assign colors to vertices and it would interpolate the changes for you. I just have no idea how this would be done in Qt or if this is even worth the effort.
I am using QGraphicsView to display the rectangle. Any advice would be appreciated.
Ok so looking into QGradients a bit more could you not use multiple QGradient to create the effect you need?
For the last of the 3 examples you could create a single gradient with multiple stops for the colours themselves then overlay this with a QGradient of black (alpha 0) to black (alpha 255) with apropriate stops to get the gradient to come in at the right point.

What can we use instead of blending in OpenGL ES?

I am doing my iPhone graphics using OpenGL. In one of my projects, I need to use an image, which I need to use as a texture in OpenGL. The .png image is 512 * 512 in size, its background is transparent, and the image has a thick blue line in its center.
When I apply my image to a polygon in OpenGL, the texture appears as if the transparent part in the image is black and the thick blue line is seen as itself. In order to remove the black part, I used blending:
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Then my black part of the texture in the polygon is removed. Now only the blue band is seen. Thus the problem is solved.
But I want to add many such images and make many objects in OpenGL. I am able to do that, but the frame rate is very low when I add more and more images to objects. But when I comment out blending, the frame rate is normal, but the images are not seen.
Since I do not have good fps, the graphics are a bit slow and I get a shaky effect.
So:
1) Is there any other method than blending to solve my problem?
2) How can I improve the frame rate of my OpenGL app? What all steps need to be taken in order to implement my graphics properly?
If you want to have transparent parts of an object, the only way is to blend to pixel data for the triangle with what is currently in the buffer (what you are currently doing). Normally, when using solid textures, the new pixel data for a triangle just overwrites what ever was in buffer (as long as it is closers, ie z-buffer). But with transparency, it has start looking at the transparency of that part of the texture, look at what is behind it, all the way back to something solid. Then has combine all of those over lapping layers of transparent stuff till you get the final image.
If all you are wanting your transparency for is something like a simple tree sprite, and removing the 'stuff' form the sides of the trunk etc. Then you may be better of providing more complex geometry that actually defines the shape of the trunk and thus not need to bother with transparency.
Sadly, I don't think there is much you can do to try to speed up your FPS, other then cut down the amount of transparency you are calculating. Maybe even adding some optimization that checks images to see if it can turn of alpha blending for this image or not. Depending on how much you are trying to push through, may save time in the long wrong.

Transparency to text in GDI

i have created a Bitmap using GDI+.I am drawing text on to that bitmap using GDI Drawtext.Using Drawtext i am unable to apply tranparency.
Any help or code will be appreciated.
If you want to draw text without a background fill, SetBkMode(hdc,TRANSPARENT) will tell GDI to leave the background when drawing text.
To actually render the foreground color of the text with alpha... is going to be more complicated. GDI does not actually support alpha channels all that widely in its APIs. Outside of AlphaBlend actually all it does is preserve the channel. Its actually not valid to set the upper bits of a COLOREF to alpha values as the high byte is actually used for flags to indicate whether the COLOREF is (rather than an RGB value) a palette entry.
So, unfortunately, your only real way forward is to:
Create a 32bit DIBSection. (CreateDIBSection). This gives you an HBITMAP that is guaranteed to be able to hold alpha information. If you create a bitmap via one of the other bitmap creation functions its going to be at the device colordepth that might not be 32bpp.
DrawText onto the DIBSection.
When you created the DIBSection you got a pointer to the actual memory. At this point you need to go through the memory and set the alpha values. I don't think that DrawText is going to do anything to the alpha channel by itself at all. Im thinking a simple check of the RGB components of each DWORD of the bitmap - if theyre the forground color, rewrite the DWORD with a 50% (or whatever) alpha in the alpha byte, if theyre the background color, rewrite with a 100% alpha in the alpha byte. *
AlphaBlend the bitmap onto the final destination. AlphaBlend requires the alpha channel in the source to be pre-multiplied.
*
It might be sufficient to simply memset the DIBSection with a 50% alpha before doing the DrawText, and ensure that the BKColor is black. I don't know what DrawText might do to the alpha channel though. Some experimentation is called for.
SIMPLE and EASY solution:)
Had this problem, i tried to change alpha values and premultiply, but there was another problem - antialiased and cleartype fonts where not shown correctly (ugly edges). So what i did...
Compose your scene (bitmaps, graphics, etc.)
BitBlt required rectangle from this scene (same as your text rectangle, from the place where you want your text to be) to memory DC with compatible bitmap selected at 0,0 destination coordinates
Draw Your text to that rectangle in memory DC.
Now AlphaBlend that rectangle without AC_SRC_ALPHA in the BLENDFUNCTION and with desired SourceConstantAlpha from this memory DC back to your scene DC.
I think You got it :)
Hmmmm - trying to do same here - wondering - I see that when you create a dib section youi specify the "masks" that is a R,G,B (and alpha) mask.
IF and thats a big if it really does not alter the alpha chhannel, then you might specify the mask differently for two bitmap headers. ONe specifies thr RGB in the proper places, the other makes them all have their bits assigned to the alpha channel. (set the text color to white in this case) then render in two passes, one to load the color values, the other to load the alpha values.
???? anyway just musing :)
While this question is about making text semi-transparent, I had the opposite problem.
DrawText was making the text in my layered window (UpdateLayeredWindow) semi-transparent ... and I didn't want it to be.
Take a look at this other question ... since in the other question I post some code that you could easily modify ... and is almost exactly what Chris Becke suggests in his answer.
A limited answer for a specific situation:
If you have a graphic with alpha channel and you want to draw opaque text over a locally opaque background, first prepare your 32 bit bitmap with 32 bit brushes created with CreateDIBPatternBrushPt. Then scan through the bitmap bits inverting the alpha channel, draw your text as you normally would (including SetBkMode to TRANSPARENT), then invert the alpha in the bitmap again. You can skip the first inversion if you invert the alpha of your brushes.

How do I create a bitmap with an alpha channel on the fly using GDI?

I am using layered windows and drawing a rounded rectangle on the screen. However, I'd like to smooth out the jagged edges. I think that I'll need alpha blending for this. Is there a way I can do this with GDI?
CreateDIBSection. Fill in the BITMAPINFOHEADER with 32bpp. Fill in the alpha channel with pre-multiplied alpha and youre good to go.
AlphaBlend is the API to actually blit 32 bpp bitmaps with an aplha channel.
You can do this in C# using the LockBits method of the BitMap class (see this question for an explanation). You definitely don't want to use GetPixel and SetPixel for this, as they are hideously slow (even though you'd just be manipulating the edges and not the entire bitmap).
Any chance of using GDI+ instead of GDI? It supports antialiasing and transparency right out of the box.
There isn't an easy way to do such drawing with just GDI calls. What you want isn't just alpha blending: you want anti-aliasing. That usually involves drawing what you want at a larger resolution and then scaling down.
What I've done in the past for similar problems is to use an art program to draw whatever shape I want (e.g. a rounded corner) much larger than I needed it in black and white. When I wanted to draw it I would scale the black and white bitmap to whatever size I wanted (using a variant of a scaling class from Code Project). This gives me a grayscale image that I can use as an alpha channel, which I'd then use for alpha blending, either by calling the Win32 function AlphaBlend, or by using a DIBSection and manually changing the appropriate pixels.
Another variation of this approach would be to allocate a DIBSection about four times larger than you wanted the final result, draw into that, and then use the above scaling class to scale it down: the scaling from a larger image will give the appropriate smoothing effect.
If all this sounds like quite a lot of work: well, it is.
EDIT: To answer the title of this question: you can create a bitmap with an alpha channel by calling CreateDIBSection. That won't on its own do what you want though, I think.

Resources