如何通过保持字体平滑度将 RichEdit 文本渲染到画布
我正在尝试将 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
字体平滑使用 Alpha 通道与部分透明度配合使用。因此,
TBitmap
的Transparent
和TransparentColor
属性不适用。您还没有说明您正在使用哪个版本的 C++ Builder/VCL,但更现代的版本比一些旧版本对部分透明度有更好的支持。
要使其正常工作,您需要将位图的
PixelFormat
设置为pf32bit
。您可能还需要将AlphaFormat
设置为afDefined
。如果您无法让
TBitmap
执行您需要的操作,那么您必须恢复到 GDI 命令来创建合适的HBITMAP
。您至少可以将其分配给TBitmap
的Handle
属性,通常一切都会从那里开始。请注意,我不是 C++ Builder 的用户,但了解 Delphi 的 VCL。
更新
我在 Delphi 中尝试了这一点,以下对我来说效果很好:
输出看起来像这样,放大一些以查看抗锯齿:
我希望这会有所帮助,因为看起来您已经非常接近了!
Font smoothing works with partial transparency using an alpha channel. The
Transparent
andTransparentColor
properties ofTBitmap
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 bepf32bit
. You may also need to setAlphaFormat
toafDefined
.If you can't get
TBitmap
to do what you need then you'll have to revert to GDI commands to create a suitableHBITMAP
. You can at least assign that to theHandle
property of aTBitmap
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:
The output looks like this, blown up somewhat to see the anti-aliasing:
I hope this helps, because it looks like you are very nearly there!
正如 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 theLOGFONT
structure. (I haven't tried this.)