Winapi 如何通过保持字体平滑度将RichEdit文本渲染到画布
我正在尝试将RichEdit渲染为位图。我想做一个返校家长。 我可以通过上面的代码实现这一点。问题是,当我将位图设置为tranparent时 只有透明颜色变为透明。有没有办法处理边缘上的像素 它们既不同于背景色,也不同于字体颜色。我是说制作像素 边缘上的半投影,形成平滑视图Winapi 如何通过保持字体平滑度将RichEdit文本渲染到画布,winapi,bitmap,gdi,vcl,richedit,Winapi,Bitmap,Gdi,Vcl,Richedit,我正在尝试将RichEdit渲染为位图。我想做一个返校家长。 我可以通过上面的代码实现这一点。问题是,当我将位图设置为tranparent时 只有透明颜色变为透明。有没有办法处理边缘上的像素 它们既不同于背景色,也不同于字体颜色。我是说制作像素 边缘上的半投影,形成平滑视图 Graphics::TBitmap *bitmap = new Graphics::TBitmap(); bitmap->Width = RichEdit1->Width ; bitmap
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.字体平滑使用alpha通道与部分透明度一起工作。因此,
TBitmap
的Transparent
和TransparentColor
属性不适用
<>你没有说你使用的是哪个版本的C++ Builder/VCL,但是更多的现代版本比部分旧版本更好地支持了部分透明性。
要使其工作,您需要将位图的PixelFormat
设置为pf32bit
。您可能还需要将AlphaFormat
设置为afDefined
如果您无法获得TBitmap
来执行您需要的操作,那么您必须返回到GDI命令来创建合适的HBITMAP
。您至少可以将其分配给TBitmap
的Handle
属性,并且通常从该属性开始,一切都会正常运行
注意,我不是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;
输出如下所示,放大一些以查看抗锯齿:
我希望这能有所帮助,因为看起来你就快到了 正如David已经回答的那样,亚像素抗锯齿需要了解背景颜色。这将在中进行更详细的解释。本质上,当您进行亚像素消除混叠时,您会将三个颜色通道视为具有不同的空间偏移(这就是分辨率明显提高的原因)。这意味着它们需要不同的alpha值,但当然只有一个alpha通道
当然,您可以在透明背景上执行常规的全像素灰度消除混叠。也许这就足够了?上述问题中的其他一些答案提出了实现这一目标的方法。查看
LOGFONT
结构中的抗锯齿质量
(与CLEARTYPE\u质量
)。(我还没试过。)谢谢你的回答。我使用C++ Builder 2010。将PixelFormat设置为FP32位,将AlphaFormat设置为afDefined不会更改输出。你能提供更多关于如何通过GDI commads创建合适位图的信息吗?背景是透明的还是图片中的白色。使用背景色渲染时,会保留抗锯齿。如果我们尝试在不使用bachground的情况下进行渲染(指定位图透明、透明颜色属性),则会出现问题。好的,现在我将更清楚地说明这一点。如果没有背景色,则无法使用antialias。算法在很大程度上取决于这一点。你到底想做什么?我想通过保留字体的平滑曲线,从richedit的文本中选择一个透明位图。我认为这可以通过部分培训支持来实现。我会把那个位图画到我不知道它的颜色的地方。@tutalia实际上这是做不到的。字体抗锯齿渲染算法需要知道背景颜色。