1

我正在尝试将 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);

谢谢。

4

2 回答 2

2

字体平滑适用于使用 Alpha 通道的部分透明度。的Transparent和的TransparentColor属性TBitmap因此不适用。

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

要让它工作,你需要将PixelFormat你的位图设置为pf32bit. 您可能还需要设置AlphaFormatafDefined.

如果你不能TBitmap做你需要的事情,那么你将不得不恢复到 GDI 命令来创建一个合适的HBITMAP. 您至少可以将其分配给Handlea 的属性,TBitmap并且通常从那里开始一切行为。

请注意,我不是 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;

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

在此处输入图像描述

我希望这会有所帮助,因为看起来你就快到了!

于 2011-03-14T10:40:54.467 回答
0

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

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

于 2014-11-04T09:07:48.933 回答