最近在做易宝支付接口,需要将后台生成的支付二维码图片传递给前端,采用的方案是后端对图片进行Base64编码后转递给前端(实现方式见:【Delphi + Vue】Web后端动态图片传递给前端),这样就有个需求就是图片满足扫描质量的前提下,数据越小越好。这样传输的数据就会少,减少网络时间。经过对比发现,同样质量下,PNG图片是最小的,依次是JPG和BMP,虽然以前也知道,但是这次实际测试后,感觉真是天壤之别!
一、测试数据:
https://u.wechat.com/MPfmfbn0X_TJzRmTEEAzVMU(我的微信二维码),将这个链接通过ZXingQRCode转换成二维码,逐次生成BMP,PNG,JPG图片,图片大小200X200,对比数据如下:
二、对比数据:
序号 | 图像格式 | 大小 |
1 | BMP(A2.bmp) | 160,054 字节(157K) |
2 | JPG(A4.jpg) | 23,093 字节(23K) |
3 | PNG(A3.png) | 1,058 字节(2K) |
从对比结果来看,大小相差非常大。所以以后后台想前端传递动态二维码图片,最好是选择PNG格式的。非常幸运的是Delphi 给我们提供了这几种格式的转换,注意早期的Delphi版本也许不支持PNG,10.1berlin是支持的。
三、Delphi函数实现(ZXingQRCode 生成 PNG图片)
需要引用的单元:
uses
DelphiZXingQRCode,
Vcl.Imaging.jpeg,
Vcl.Imaging.pngimage;
//CodeText 需要变成二维码的信息,W,H 分辨表示最终图片的像素大小,DestStream生成的png图片流数据
procedure TForm_Main.QR2PNG(CodeText: string; W, H: Word; DestStream: TStream);
var
QRCode : TDelphiZXingQRCode;
Row, Column: Integer;
Bitmap : TBitmap;
Rect : TRect;
ZoomBitmap : TBitmap; //缩放后的图片
PNG : TPNGImage; //转换成png图片
JPG : TJPEGImage;//转换成JPG图片
begin
QRCode := TDelphiZXingQRCode.Create;
Bitmap := TBitmap.Create;
ZoomBitmap := TBitmap.Create;
PNG := TPNGImage.Create;
JPG := TJPEGImage.Create;//转换成JPG图片
try
//1. 通过ZXingQRCode生成 bitmap 图像
QRCode.Data := CodeText;
QRCode.Encoding := TQRCodeEncoding(0);
QRCode.QuietZone := 1; // 四周空白区域大小
Bitmap.SetSize(QRCode.Rows, QRCode.Columns);
for Row := 0 to QRCode.Rows - 1 do begin
for Column := 0 to QRCode.Columns - 1 do begin
if (QRCode.IsBlack[Row, Column]) then begin
Bitmap.Canvas.Pixels[Column, Row] := clBlack;
end
else begin
Bitmap.Canvas.Pixels[Column, Row] := clWhite;
end;
end;
end;
//保存这张图片
Bitmap.SaveToFile('C:\www\A1.bmp');
//2. 对生成的bitmap进行缩放,因为 ZXingQRCode 生成的图片是 32X32的位图,所以W,H不能小于32,这里就不做判断,使用时注意就好
ZoomBitmap.Width := W;
ZoomBitmap.Height := H;
//2.1 设置缩放窗口
Rect.Left := 0;
Rect.Top := 0;
Rect.Right := W;
Rect.Bottom := H;
ZoomBitmap.Canvas.StretchDraw(Rect, Bitmap);
//2.2 保存缩放后的图片
ZoomBitmap.SaveToFile('C:\www\A2.bmp');
//3. 转换成 png
//ZoomBitmap.Monochrome := true; //转成黑白颜色,这里可以不需要
PNG.Assign(ZoomBitmap);
PNG.CompressionLevel := 9; //最高压缩率 0..9
PNG.SaveToFile('C:\www\A3.png');
PNG.SaveToStream(DestStream); //保存成 Stream ,以便可以传递给前端(Base64)
//4. 转换成 jpg, 主要是为了测试对比,实际应该使用PNG
JPG.PixelFormat := jf8bit; //对于delphi 只支持24位和8位位图,所以选择最低的8位
JPG.CompressionQuality := 90;
JPG.Assign(ZoomBitmap);
JPG.SaveToFile('C:\www\A4.jpg');
finally
QRCode.Free;
Bitmap.Free;
ZoomBitmap.Free;
PNG.Free;
JPG.Free;
end;
end;
procedure TForm_Main.Button_PNGClick(Sender: TObject);
var
M : TMemoryStream;
begin
M := TMemoryStream.Create;
QR2PNG('https://u.wechat.com/MPfmfbn0X_TJzRmTEEAzVMU',200,200,M);
//装载生成的图片
image1.Picture.LoadFromFile('C:\www\A3.png');
M.Free;
end;
使用本程序注意将图片文件的绝对地址更改成自己的目录,不然如果你机器上没有这个目录就出错了。