image32中有2种算法转换图像为svg,一种是按透明度计算找边缘,另一种是分析像素梯度找边缘,demo代码整理后如下:
unit uFrmImageToSVG; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Buttons, Vcl.ComCtrls, // Img32, uSvgWriter; type TfrmImageToSVG = class(TForm) OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; Panel1: TPanel; btnOpen: TSpeedButton; btnSaveAs: TSpeedButton; rbRasterImage: TRadioButton; rbRasterVectors: TRadioButton; rbSmoothedAndSimplified: TRadioButton; ckbHighlightVertices: TCheckBox; pnlSmooth: TPanel; lblSmooth: TLabel; lblSimplify: TLabel; TrackBar1: TTrackBar; TrackBar2: TTrackBar; PaintBox1: TPaintBox; StatusBar1: TStatusBar; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure PaintBox1Paint(Sender: TObject); procedure FormResize(Sender: TObject); procedure btnOpenClick(Sender: TObject); procedure TrackBarChange(Sender: TObject); procedure RadioOnClick(Sender: TObject); procedure ckbHighlightVerticesClick(Sender: TObject); procedure btnSaveAsClick(Sender: TObject); private masterImg, workImg: TImage32; hasTransparency: Boolean; // must be checked before resizing rawPaths, bezierPaths, smoothedPaths: TPathsD; function GetDisplaySize: TSize; procedure DisplayImage; public { Public declarations } end; var frmImageToSVG: TfrmImageToSVG; implementation {$R *.dfm} {$R Image2.res} uses Winapi.ShellAPI, System.Math, // Img32.Draw, Img32.Vector, Img32.Extra, Img32.Vectorizer, Img32.Fmt.BMP, Img32.Fmt.JPG, Img32.Fmt.PNG; const C_Margin = 20; function Count(const paths: TPathsD): integer; var i: integer; begin // 统计路径中有多少个点 Result := 0; for i := 0 to High(paths) do inc(Result, Length(paths[i])); end; procedure TfrmImageToSVG.btnOpenClick(Sender: TObject); begin // 打开图像 if not OpenDialog1.Execute then Exit; masterImg.LoadFromFile(OpenDialog1.FileName); hasTransparency := masterImg.hasTransparency; // 打开的图像是否透明. masterImg.ScaleToFit(1000, 1000); // 图像缩放到指定尺寸 DisplayImage; // 重新计算图像 end; procedure TfrmImageToSVG.btnSaveAsClick(Sender: TObject); begin // 保存为 SaveDialog1.InitialDir := OpenDialog1.InitialDir; SaveDialog1.FileName := ChangeFileExt(ExtractFileName(OpenDialog1.FileName), '.svg'); if not SaveDialog1.Execute then Exit; with TSimpleSvgWriter.Create(frEvenOdd) do // SVG 写对象 try AddPaths(smoothedPaths, false, $40000033, $FF000033, 1.2); // 后3个参数为 填充颜色,边线颜色,连线宽度 SaveToFile(SaveDialog1.FileName, 800, 600); // 保存 SVG,参数:文件名,最大宽度,最大高度,边缘宽度[不指定(默认20)] finally free; end; ShellExecute(0, 'open', PChar(SaveDialog1.FileName), nil, nil, SW_SHOW); // 保存完成后,使用默认程序打开 svg StatusBar1.Panels[1].Text := format(' %s saved.', [ExtractFileName(SaveDialog1.FileName)]); end; procedure TfrmImageToSVG.ckbHighlightVerticesClick(Sender: TObject); begin // 高亮显示顶点 变化 ,重新计算绘制 DisplayImage; end; procedure TfrmImageToSVG.DisplayImage; var i, j: integer; scale, simplifyTol: double; vectorBounds: TRect; // tmpColors: TArrayOfColor32; begin rawPaths := nil; bezierPaths := nil; smoothedPaths := nil; PaintBox1.Invalidate; if masterImg.IsEmpty then Exit; if rbRasterImage.Checked then //光栅图像 begin workImg.Assign(masterImg); // shows the raw image only with GetDisplaySize do workImg.ScaleToFit(cx - C_Margin * 2, cy - C_Margin * 2); // // otherwise, show as a monochrome image // tmpColors := GetColorMask(workImg, clBlack32, CompareRGB, $32); // Move(tmpColors[0], workImg.Pixels[0], Length(tmpColors) * SizeOf(TColor32)); StatusBar1.Panels[0].Text := ''; StatusBar1.Panels[1].Text := ' Raw raster image'; Exit; end; with GetDisplaySize do workImg.SetSize(cx, cy); if rbRasterVectors.Checked then //光栅矢量 simplifyTol := 0 else //平滑简化 simplifyTol := TrackBar2.Position * 0.5; //简化容差 (TrackBar2.Position 最大值为 10) // 1. Vectorize (now includes vector simplification):converts simple (2 color) raster images into vector images // 矢量化(现在包括矢量简化):将简单(2色)光栅图像转换为矢量图像 if hasTransparency then rawPaths := Vectorize(masterImg, $FF000000, CompareAlpha, $80, simplifyTol) //透明度对比 矢量化 $80:颜色容差 simplifyTol:简化容差 else rawPaths := Vectorize(masterImg, $FF000000, CompareRGB, $44, simplifyTol); //颜色值对比 矢量化 $44:颜色容差 simplifyTol:简化容差 vectorBounds := GetBounds(rawPaths); //获取路径区域 if vectorBounds.IsEmpty then Exit; // offset and scale the vector image 偏移和缩放矢量图像 rawPaths := TranslatePath(rawPaths, C_Margin - vectorBounds.Left, C_Margin - vectorBounds.Top); //平移图像(留出边缘距离) // 实际大小与显示大小,计算合适的缩放比 scale := Min((workImg.Width - C_Margin * 2) / RectWidth(vectorBounds), (workImg.Height - C_Margin * 2) / RectHeight(vectorBounds)); rawPaths := ScalePath(rawPaths, scale); //缩放路径 if rbRasterVectors.Checked then //光栅矢量 begin smoothedPaths := rawPaths; StatusBar1.Panels[0].Text := format(' Vertices: %d', [Count(rawPaths)]); StatusBar1.Panels[1].Text := ' Raw Vectors (no smoothing or simplification)'; end else begin //平滑简化 smoothedPaths := SmoothPaths(rawPaths, true, (10 - TrackBar1.Position) / 10, 0.25); //参数2:路径闭合 参数3:张力(决定平滑度) 参数4:形状公差 lblSmooth.Caption := format('Smooth'#10'Amount'#10'(%d)', [TrackBar1.Position]); //平滑度 TrackBar1最大值为10 lblSimplify.Caption := format('Simplify'#10'Amount'#10'(%d)', [TrackBar2.Position]); //差化容差 StatusBar1.Panels[0].Text := format(' Vertices: %d', [Count(smoothedPaths)]); StatusBar1.Panels[1].Text := ' Simplified & smoothed'; end; if ckbHighlightVertices.Checked then //高亮显示顶点 begin DrawPolygon(workImg, smoothedPaths, frEvenOdd, $20660000); //绘制多边开 DrawLine(workImg, smoothedPaths, DPIAware(2), clMaroon32, esPolygon); //绘制多边开连线 for i := 0 to High(smoothedPaths) do for j := 0 to High(smoothedPaths[i]) do DrawPoint(workImg, smoothedPaths[i][j], DPIAware(2.5), clNavy32); //绘制多边形顶点 end else begin DrawPolygon(workImg, smoothedPaths, frEvenOdd, $FF660033); //绘制多边开 end; end; procedure TfrmImageToSVG.FormCreate(Sender: TObject); begin self.BorderStyle := bsNone; // masterImg := TImage32.Create; masterImg.LoadFromResource('beetle', 'PNG'); // 从资源中加载图片. hasTransparency := masterImg.hasTransparency; // 是否透明 masterImg.ScaleToFit(1000, 1000); // 调整到指定尺寸 OpenDialog1.InitialDir := ExtractFilePath(paramStr(0)) + 'sample_images'; // 样办图片位置 ForceDirectories(OpenDialog1.InitialDir); OpenDialog1.FileName := 'book.bmp'; if hasTransparency then masterImg.CropTransparentPixels; // 裁剪透明像素 workImg := TImage32.Create; end; procedure TfrmImageToSVG.FormDestroy(Sender: TObject); begin masterImg.free; workImg.free; end; procedure TfrmImageToSVG.FormResize(Sender: TObject); begin if not(csDestroying in ComponentState) then begin Invalidate; DisplayImage; // 重新计算绘制 end; end; function TfrmImageToSVG.GetDisplaySize: TSize; begin Result.cx := PaintBox1.ClientWidth; // ClientWidth - pnlSmooth.Width; Result.cy := PaintBox1.ClientHeight; // ClientHeight - StatusBar1.Height; end; procedure TfrmImageToSVG.PaintBox1Paint(Sender: TObject); begin workImg.CopyToDc(PaintBox1.Canvas.Handle); // 绘制到 PaintBox end; procedure TfrmImageToSVG.RadioOnClick(Sender: TObject); begin // 切换不同的显示模式 pnlSmooth.Visible := Sender = rbSmoothedAndSimplified; if pnlSmooth.Visible then TrackBar1.SetFocus; DisplayImage; // 重新计算绘制 end; procedure TfrmImageToSVG.TrackBarChange(Sender: TObject); begin // 简化 及 平整 发生变化 DisplayImage; // 重新计算绘制 end; end.
效果如下:
标签:begin,workImg,end,Sender,SVG,delphi,TObject,Image32,procedure From: https://www.cnblogs.com/bluejade/p/18246947