如何通过保持字体平滑度将 RichEdit 文本渲染到画布

发布于 2024-10-21 16:21:49 字数 1962 浏览 5 评论 0原文

我正在尝试将 RichEdit 渲染为位图。我想让背景透明。 我可以通过上面的代码实现这一点。问题是当我将位图设置为透明时 只有透明色才变得透明。有没有办法处理边缘的像素 它们与背景颜色不同,也与字体颜色不同。我的意思是制作像素 边缘半透明,视野平滑。

    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);

谢谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

〃温暖了心ぐ 2024-10-28 16:21:49

字体平滑使用 Alpha 通道与部分透明度配合使用。因此,TBitmapTransparentTransparentColor 属性不适用。

您还没有说明您正在使用哪个版本的 C++ Builder/VCL,但更现代的版本比一些旧版本对部分透明度有更好的支持。

要使其正常工作,您需要将位图的 PixelFormat 设置为 pf32bit。您可能还需要将 AlphaFormat 设置为 afDefined

如果您无法让 TBitmap 执行您需要的操作,那么您必须恢复到 GDI 命令来创建合适的 HBITMAP。您至少可以将其分配给 TBitmapHandle 属性,通常一切都会从那里开始。

请注意,我不是 C++ Builder 的用户,但了解 Delphi 的 VCL。

更新

我在 Delphi 中尝试了这一点,以下对我来说效果很好:

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;

输出看起来像这样,放大一些以查看抗锯齿:

在此处输入图像描述

我希望这会有所帮助,因为看起来您已经非常接近了!

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!

記柔刀 2024-10-28 16:21:49

正如 David 已经回答的那样,子像素抗锯齿需要了解背景颜色。 此答案对此进行了更详细的解释。本质上,当您进行子像素抗锯齿时,您将三个颜色通道视为具有不同的空间偏移(这就是分辨率明显增加的来源)。这意味着它们需要不同的 alpha 值,但当然只有一个 alpha 通道。

当然,您可以在透明背景上进行常规的全像素灰度抗锯齿。也许这已经足够好了?上面链接的问题中的一些其他答案提出了实现这一目标的方法。查看 LOGFONT 结构中的 ANTIALIASED_QUALITY(与 CLEARTYPE_QUALITY)。 (我没试过这个。)

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.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文