Steve Maughan 26 Posted February 14, 2020 In my mapping application I need to merge different layers together to create the map. Question: how do I merge a bitmap with anti-aliased text with a bitmap showing a multi-colored image? Is there a way to draw the anti-aliased text on a bitmap with the alpha channel enabled and then have the transparency preserved / respected when it is combined with the other bitmap? Here's a simple example that shows the problem (code attached to this message): procedure TForm2.FormPaint(Sender: TObject); var f: TBitmap; b: TBitmap; x, y: integer; xText: string; xWidth, xHeight: integer; begin //-- Size of image xWidth := Form2.Width; xHeight := Form2.Height; //-- Create the background bitmap f := TBitmap.Create; f.PixelFormat := pf32bit; f.SetSize(xWidth, xHeight); f.Canvas.Brush.Color := clFuchsia; f.Canvas.FillRect(f.Canvas.ClipRect); //-- Create the bitmap with the text b := TBitmap.Create; b.PixelFormat := pf32bit; b.Canvas.Brush.Color := clWhite; b.SetSize(xWidth, xHeight); b.Canvas.Font.Size := 32; b.Canvas.Font.Color := clBlack; b.Canvas.Font.Quality := TFontQuality.fqDefault; //-- Draw the text xText := 'Delphi 25th'; x := (b.Width - b.Canvas.TextWidth(xText)) div 2; y := (b.Height - b.Canvas.TextHeight(xText)) div 2; b.Canvas.TextOut(x, y, xText); //-- Transfer the text layer to the background TransparentBlt(f.Canvas.Handle, 0, 0, xWidth, xHeight, b.Canvas.Handle, 0, 0, xWidth, xHeight, clWhite); //-- Transfer to the form's canvas Form2.Canvas.CopyRect(Form2.Canvas.ClipRect, f.Canvas, f.Canvas.ClipRect); b.Free; f.Free; end; This results in the following screen (also attached to this message): https://ibb.co/GVWRZ6Y You can see the ugly white around the text due to the anti-aliasing. Currently I use non anti-aliased text, but that also looks blocky and ugly too. Thanks and Happy Delphi 25th! Steve Anti-Aliased-Text.zip Share this post Link to post
Vandrovnik 215 Posted February 14, 2020 Recently I have changed drawing to Direct2D, where transparency is not a problem. Share this post Link to post
Steve Maughan 26 Posted February 14, 2020 33 minutes ago, Vandrovnik said: Recently I have changed drawing to Direct2D, where transparency is not a problem. Interesting — how would you accomplish what I'd like to do using Direct2D? Thanks, Steve Share this post Link to post
Vandrovnik 215 Posted February 14, 2020 Please have a look at http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_the_Direct2D_Canvas Share this post Link to post
Steve Maughan 26 Posted February 14, 2020 Hi Vandrovnik — I'm aware of the basics of Difect2D, but how could I merge two Direct2D canvases and preserve the anti-aliasing of the text? If I'm not mistaken this isn't easy using Direct2D (but I'm far from being an expert on this). Thanks again, Steve Share this post Link to post
David Heffernan 2353 Posted February 14, 2020 In general you can't do this. Anti-aliasing requires knowledge of the background at the point where the text is rendered. If the original background is a single colour then it may be possible, but will require clever processing. What you ought to do is simply render the text again on the new background. 1 Share this post Link to post
Steve Maughan 26 Posted February 14, 2020 Just now, David Heffernan said: In general you can't do this. Anti-aliasing requires knowledge of the background at the point where the text is rendered. If the original background is a single colour then it may be possible, but will require clever processing. What you ought to do is simply render the text again on the new background. Thanks David — this is what is feared. I had hoped it would act like a PNG with transparency at the pixel level. Cheers, Steve Share this post Link to post
David Heffernan 2353 Posted February 14, 2020 There is transparency at the pixel level. PNGs have an alpha channel for that. Share this post Link to post
Anders Melander 1815 Posted February 14, 2020 I would just use Graphics32 but you can do it with regular TBitmap's - it's just more work. What you do is draw white text onto a black bitmap. Make sure ClearType anti aliasing is disabled or you will get artifacts. Use regular greyscale anti aliasing instead. This bitmap can now be merged (RGB only, there's no alpha) directly onto the destination bitmap or it can be used as an alpha mask to draw in any color or pattern. To use it as an alpha mask you just transfer any of the R, G or B values (they're the same) to the A channel and then reset the RGB to whatever color you want. Share this post Link to post
Vandrovnik 215 Posted February 14, 2020 2 hours ago, Steve Maughan said: Hi Vandrovnik — I'm aware of the basics of Difect2D, but how could I merge two Direct2D canvases and preserve the anti-aliasing of the text? If I'm not mistaken this isn't easy using Direct2D (but I'm far from being an expert on this). Thanks again, Steve Hello, as David already wrote - just render the text on the map, there is no need to render it to a bitmap and then merge bitmaps. Do you need to print the result? Because that was a pain with Direct2D and Delphi 😕 Share this post Link to post
Anders Melander 1815 Posted February 14, 2020 30 minutes ago, Vandrovnik said: just render the text on the map, there is no need to render it to a bitmap and then merge bitmaps. That will not preserve the alpha. Share this post Link to post
Steve Maughan 26 Posted February 14, 2020 2 hours ago, Anders Melander said: I would just use Graphics32 but you can do it with regular TBitmap's - it's just more work. What you do is draw white text onto a black bitmap. Make sure ClearType anti aliasing is disabled or you will get artifacts. Use regular greyscale anti aliasing instead. This bitmap can now be merged (RGB only, there's no alpha) directly onto the destination bitmap or it can be used as an alpha mask to draw in any color or pattern. To use it as an alpha mask you just transfer any of the R, G or B values (they're the same) to the A channel and then reset the RGB to whatever color you want. Hi Anders - this sound like what I need. Do you know of any code snippets? Thanks, Steve Share this post Link to post
Vandrovnik 215 Posted February 14, 2020 uses Direct2D; procedure TMainForm.PaintBox1Paint(Sender: TObject); var D2Canvas: TDirect2DCanvas; begin D2Canvas:=TDirect2DCanvas.Create(PaintBox1.Canvas, PaintBox1.ClientRect); try D2Canvas.BeginDraw; try D2Canvas.Brush.Style:=bsSolid; D2Canvas.Brush.Color:=clFuchsia; D2Canvas.FillRect(PaintBox1.ClientRect); D2Canvas.Font.Size:=32; D2Canvas.Font.Color:=clBlack; D2Canvas.TextOut(100, 100, 'Delphi 25th'); finally D2Canvas.EndDraw; end; finally FreeAndNil(D2Canvas); end; end; This is not OK? Share this post Link to post
Anders Melander 1815 Posted February 14, 2020 24 minutes ago, Steve Maughan said: Do you know of any code snippets? It's left as an exercise for the student 🙂 The only code I have is a 10 year old example I once made in the Graphics32 newsgroup to demonstrate why cleartype AA shouldn't be used with the technique I described. Code and executable attached. Note that the code probably requires a 10 year old version of Graphics32 to compile. Here's the screenshots that accompanied the example (Looks like Win XP 😞 Shows regular text output with no blending. ClearType artifacts are clearly visible because of scaling. This is expected. Shows text output with alpha blending. Alpha is calculated from a single channel. Alpha blended Gray Scale AA is identical to opaque Gray Scale AA. Alpha blended ClearType AA shows asymmetry. Shows text output with alpha blending. Alpha is calculated from all three channels. Alpha blended Gray Scale AA is identical to opaque Gray Scale AA. Alpha blended ClearType AA is symmetric, but lacks detail. amAAtest.zip AAtest.zip Share this post Link to post