使用TSVGIconImage导出SVG为位图时如何设置透明区域填充色
问题描述
我使用TSVGImageIcon读取SVG矢量图像,编写了如下函数实现将图像保存为指定尺寸的位图:
function SVG2Bitmap(Imatge: TBytes; x, y: integer): TBytes; var SVG: TSVGIconImage; Stream: TBytesStream; Bitmap: TBitmap; Resultat: TBytesStream; Form: TForm; begin try SVG := nil; Form := nil; Stream := nil; Bitmap := nil; Resultat := nil; Stream := TBytesStream.Create(Imatge); Stream.Position := 0; Form := TForm.Create(nil); // 不在Form内挂载的话SVGIconImage会抛出异常 SVG := TSVGIconImage.Create(Form); SVG.Parent := Form; SVG.Stretch := True; SVG.Proportional := True; SVG.LoadFromStream(Stream); SVG.Width := x; SVG.Height := y; Bitmap := TBitmap.Create; Bitmap.SetSize(x, y); SVG.PaintTo(Bitmap.Canvas, 0, 0); Resultat := TBytesStream.Create; Bitmap.SaveToStream(Resultat); Result := Resultat.Bytes; finally if Assigned(SVG) then try SVG.Free except end; if Assigned(Form) then try Form.Free except end; if Assigned(Bitmap) then try Bitmap.Free except end; if Assigned(Stream) then try Stream.Free except end; if Assigned(Resultat) then try Resultat.Free except end; end; end;
该代码运行正常,但导出的位图中透明区域会被填充为灰色,我希望将透明区域设置为白色。请问是否有方案可以在导出SVG为位图时直接设置透明区域的填充色,还是需要遍历位图将灰色像素修改为白色?
解决方案
不需要逐像素修改,你只需在绘制SVG到位图前预先填充白色背景即可,实现简单且运行效率更高。
出现灰色透明区域的原因是你创建TBitmap后没有手动初始化画布背景,SVG的透明区域绘制时会直接透底,空白画布导出时就会被默认填充为灰色。
你只需在原有代码的Bitmap.SetSize(x, y);语句之后、SVG.PaintTo调用之前,添加两行背景填充代码即可:
Bitmap.Canvas.Brush.Color := clWhite; Bitmap.Canvas.FillRect(Rect(0, 0, x, y));
如果编译时提示clWhite或Rect未定义,在单元的uses引用列表中添加Vcl.Graphics即可。
修改后的完整代码
function SVG2Bitmap(Imatge: TBytes; x, y: integer): TBytes; var SVG: TSVGIconImage; Stream: TBytesStream; Bitmap: TBitmap; Resultat: TBytesStream; Form: TForm; begin try SVG := nil; Form := nil; Stream := nil; Bitmap := nil; Resultat := nil; Stream := TBytesStream.Create(Imatge); Stream.Position := 0; Form := TForm.Create(nil); // 不在Form内挂载的话SVGIconImage会抛出异常 SVG := TSVGIconImage.Create(Form); SVG.Parent := Form; SVG.Stretch := True; SVG.Proportional := True; SVG.LoadFromStream(Stream); SVG.Width := x; SVG.Height := y; Bitmap := TBitmap.Create; Bitmap.SetSize(x, y); // 新增代码:预先填充白色背景 Bitmap.Canvas.Brush.Color := clWhite; Bitmap.Canvas.FillRect(Rect(0, 0, x, y)); SVG.PaintTo(Bitmap.Canvas, 0, 0); Resultat := TBytesStream.Create; Bitmap.SaveToStream(Resultat); Result := Resultat.Bytes; finally if Assigned(SVG) then try SVG.Free except end; if Assigned(Form) then try Form.Free except end; if Assigned(Bitmap) then try Bitmap.Free except end; if Assigned(Stream) then try Stream.Free except end; if Assigned(Resultat) then try Resultat.Free except end; end; end;
如果你后续需要保留透明通道而不是替换为白色,只需将Bitmap的PixelFormat设置为pf32bit即可,不需要修改其他逻辑。
内容的提问来源于stack exchange,提问作者Marc Guillot
相关产品推荐
相关产品推荐

