1

i am trying to render RichEdit to a bitmap. I want to make backgrond tranparent. I could achieve that by the code above. The problem is that when i set bitmap as tranparent only the transparent color becomes transparent. Is there any way to handle the pixels on the edge which are diffrent from background color and also different from font color. i mean making the pixels semi-tranparent on the edge which makes a smooth view.

    Graphics::TBitmap *bitmap = new Graphics::TBitmap();
    bitmap->Width = RichEdit1->Width ;
    bitmap->Height = RichEdit1->Height ;


    TRect BoundingBox(0,0,RichEdit1->Width, RichEdit1->Height) ;

    // Render RichEdit to bitmap
    TFormatRange formatRange;
    int twipsPerPixel = 1440 / Screen->PixelsPerInch;

    formatRange.hdc = bitmap->Canvas->Handle;
    formatRange.hdcTarget = bitmap->Canvas->Handle;
    formatRange.chrg.cpMin = 0;
    formatRange.chrg.cpMax = -1;

    formatRange.rc.top = 2 * twipsPerPixel;
    formatRange.rc.bottom = (BoundingBox.Height() - 4) * twipsPerPixel + formatRange.rc.top;
    formatRange.rc.left = 2 * twipsPerPixel;
    formatRange.rc.right = (BoundingBox.Width() - 4) * twipsPerPixel;

    // Measure text's height.
    RichEdit1->Perform(EM_FORMATRANGE, 0, 0);
    RichEdit1->Perform(EM_FORMATRANGE, 0, (LPARAM) &formatRange);

    formatRange.rc.bottom = (BoundingBox.Height() - 4) * twipsPerPixel + formatRange.rc.top;
    formatRange.rc.left = 2 * twipsPerPixel;
    formatRange.rc.right = (BoundingBox.Width() - 4) * twipsPerPixel;

    formatRange.rcPage = formatRange.rc;


    /**
    * Draw..
    **************************************************************************/
    RichEdit1->Perform(EM_FORMATRANGE, 1, (LPARAM) &formatRange);
    RichEdit1->Perform(EM_FORMATRANGE, 0, 0);


   // Draw background
   // Use different background color to see the trasparency problem
   this->Canvas->Brush->Color = clRed ;
   this->Canvas->Rectangle(0,0,RichEdit1->Width , RichEdit1->Height );

   // Draw the transparent bitmap
   bitmap->Transparent = true ;
   bitmap->TransparentColor = RichEdit1->Color ;
   this->Canvas->Draw(0,0,bitmap);

Thanx.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
tutalia
  • 285
  • 3
  • 16

2 Answers2

2

Font smoothing works with partial transparency using an alpha channel. The Transparent and TransparentColor properties of TBitmap are therefore not applicable.

You haven't said which version of the C++ Builder/VCL you are using, but more modern versions have better support for partial transparency than some of the older ones.

To get this to work you will need to set the PixelFormat of your bitmap to be pf32bit. You may also need to set AlphaFormat to afDefined.

If you can't get TBitmap to do what you need then you'll have to revert to GDI commands to create a suitable HBITMAP. You can at least assign that to the Handle property of a TBitmap and usually from there everything behaves.

Note that I am not a user of C++ Builder but do know the VCL from Delphi.

UPDATE

I tried this out in Delphi and the following worked fine for me:

procedure TForm4.Button1ClickBMP(Sender: TObject);
var
  BMP: TBitmap;
  fmtRange: TFormatRange;
  intPPI, Flags: Integer;
begin
  BMP := TBitmap.Create;
  Try
    BMP.PixelFormat := pf32bit;
    BMP.SetSize(RichEdit1.Width, RichEdit1.Height);

    FillChar(fmtRange, SizeOf(fmtRange), 0);
    with fmtRange do begin
      hDC := BMP.Canvas.Handle;
      hdcTarget := hDC;
      intPPI := Screen.PixelsPerInch;
      rc := Rect(
        0,
        0,
        RichEdit1.Width*1440 div intPPI,
        RichEdit1.Height*1440 div intPPI
      );
      rcPage := rc;
      chrg.cpMin := 0;
      chrg.cpMax := -1;
    end;
    Flags := 1;
    RichEdit1.Perform(EM_FORMATRANGE, Flags, Longint(@fmtRange));
    RichEdit1.Perform(EM_FORMATRANGE, 0, 0);
    BMP.SaveToFile('c:\desktop\test.bmp');
  Finally
    FreeAndNil(BMP);
  End;
end;

The output looks like this, blown up somewhat to see the anti-aliasing:

enter image description here

I hope this helps, because it looks like you are very nearly there!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks for your answer. I use C++ Builder 2010. Setting the PixelFormat to fp32bit and AlphaFormat to afDefined didn't change output. Could you give more information about how to create suitable bitmap by GDI commads. – tutalia Mar 14 '11 at 12:20
  • Is backgound transparent or white in the picture. Anti-aliasing is kept when rendering with background color. If we try to render without bachground (assigning Bitmaps Transparent, TransparentColor property)that problem appears. – tutalia Mar 15 '11 at 08:24
  • ok now I'm getting it clearer. You can't antialias without a background colour. The algorithm depends crucially on that. What are you actually trying to do? – David Heffernan Mar 15 '11 at 08:27
  • i am trying to optain a transparent bitmap from richedit's text by preserving the font's smooth curves. i think it can be done by partial tranparency support. i will draw that bitmap onto somewhere which i don't know its color. – tutalia Mar 15 '11 at 09:05
  • @tutalia Actually it cannot be done. Font anti-aliasing rendering algorithms need to know the background colour. – David Heffernan Mar 15 '11 at 09:19
  • BitmapFontGenerator software (http://www.angelcode.com/products/bmfont/) can produce anti-alised font images with transparent background, an example is here : http://img835.imageshack.us/i/smoothfonttransparentba.png/), i think it can be possible in same way. – tutalia Mar 15 '11 at 09:43
  • @tutalia that's not how the rich edit control does it though is it? – David Heffernan Mar 15 '11 at 10:17
  • no it is not,it only gives idea to provide smoothness by partial tranparency. – tutalia Mar 15 '11 at 10:26
0

As David has answered already, sub-pixel antialiasing requires knowledge of the background colour. This is explained in more detailed in this answer. In essence, when you do sub-pixel anti-aliasing you treat the three colour channels as having different spatial offsets (which is where the apparent increase in resolution comes from). This means they need different alpha values, but of course there is only one alpha channel.

You can of course do regular full-pixel grayscale antialiasing over a transparent background. Perhaps this would be good enough? Some of the other answers in the question linked above suggest ways to achieve this. Have a look at ANTIALIASED_QUALITY (vs. CLEARTYPE_QUALITY) in the LOGFONT structure. (I haven't tried this.)

Community
  • 1
  • 1
Ian Goldby
  • 5,609
  • 1
  • 45
  • 81