procedure draw2PxPoint(userid: string; bmp: TBitmap; isNet: Boolean; align: Integer);
var
PicNamearray: array[0..20] of Byte;
Send: string;
size: Integer;
data: array of Byte;
k, i, j, m, n, index: Integer;
canvas: TCanvas;
b: Byte;
temp: string;
color: TColor;
currentSum: Integer;
begin
try
//可以将图片压缩成指定大小,打印出来就是多大
size := bmp.Width * bmp.Height div 8 + 100;
canvas := bmp.Canvas;
SetLength(data, size);
//设置行距为0的指令
k := 0;
data[k] := $1B;
k := k + 1;
data[k] := $33;
k := k + 1;
data[k] := $00;
k := k + 1;
//居中打印
data[k] := $1B;
k := k + 1;
data[k] := $61;
k := k + 1;
case align of
0: data[k] := $00;
1: data[k] := $01;
2: data[k] := $02;
end;
k := k + 1;
//逐行打印
for j := 0 to (bmp.Height div 24 - 1) do
begin
data[k] := $1B;
k := k + 1;
data[k] := $2A;
k := k + 1;
data[k] := 33;
k := k + 1;
data[k] := bmp.Width mod 256;
k := k + 1;
data[k] := bmp.Width div 256;
k := k + 1;
//对于每一行,逐列打印
for i := 0 to bmp.Width - 1 do
begin
for m := 0 to 2 do
begin
currentSum := j * 24 + m * 8;
color := canvas.Pixels[i, currentSum];
if color = clWhite then
data[k] := 0
else
data[k] := 255;
k := k + 1;
end;
end;
data[k] := 10; //换行
k := k + 1;
end;
//打印命令在这里 上面是准备数据
for index := 0 to Length(data) - 1 do
begin
temp := temp + AnsiChar(strtoint('$' + IntToHex(data[index], 2)))
end;
Send := AnsiChar($1D) + AnsiChar($21) + AnsiChar($11);
Move(Send[1], PicNamearray, Length(Send));
frmMain.IdTCPClient_xy.Socket.Send(PicNamearray, Length(Send));
frmMain.IdTCPClient_xy.Writeln(temp);
finally
bmp.FreeImage;
end;
end;
if color = clWhite then
data[k] := 0
else
data[k] := 255;
出现这种黑块就是因为这一堆的255,我初步判断是底层封装的这个方法不可靠。
解决方案一:
color := GetPixel(canvas.Handle,i,currentSum); //WindowsAPI
用这行代码替代 color := canvas.Pixels[i, currentSum];
这两个一个是WindowsAPI提供的方法,一个是bitmap提供的方法,前者获取成功的准确度明显高于后者。
解决方案二:
Delphi提供了一种扫描线ScanLine方法是对图像的一行进行扫描,获取本行中各像素的内存地址。众所周知,内存操作肯定会比常规的像素点赋值速度快很多,所以将大大提高图像的处理速度。
procedure draw2PxPoint(userid: string; bmp: TBitmap; isNet: Boolean; align: Integer);
var
PicNamearray: array[0..20] of Byte;
Send: string;
size: Integer;
data: array of Byte;
k, i, j, m, n, index: Integer;
canvas: TCanvas;
b: Byte;
temp: string;
color: TColor;
currentSum: Integer;
imagePath:String;
Red,Green,Blue:Byte;
PColor:array of PByteArray;//像素数组
height,hindex,Gray:Integer;
begin
try
//可以将图片压缩成指定大小,打印出来就是多大
size := bmp.Width * bmp.Height div 8 + 100;
canvas := bmp.Canvas;
SetLength(data, size);
height:= bmp.Height;
SetLength(PColor,height);
for hindex:=0 to height-1 do
begin
PColor[hindex]:=bmp.ScanLine[hindex];//将图片所有像素值存入P
end;
//设置行距为0的指令
k := 0;
data[k] := $1B;
k := k + 1;
data[k] := $33;//选择24点双密度打印,分辨率达到200DPI。
k := k + 1;
data[k] := $00;
k := k + 1;
//居中打印
data[k] := $1B;
k := k + 1;
data[k] := $61;
k := k + 1;
case align of
0: data[k] := $00;
1: data[k] := $01;
2: data[k] := $02;
end;
k := k + 1;
//逐行打印
for j := 0 to (bmp.Height div 24 - 1) do
begin
data[k] := $1B;
k := k + 1;
data[k] := $2A;
k := k + 1;
data[k] := 33;
k := k + 1;
data[k] := bmp.Width mod 256;
k := k + 1;
data[k] := bmp.Width div 256;
k := k + 1;
for i := 0 to bmp.Width - 1 do
begin
for m := 0 to 2 do
begin
currentSum := j * 24 + m * 8;
//颜色值这个我确实不太懂,但是我发现Blue一直为255,而Green和Red 会在黑色和白色时分别为 0 和 255
// Blue:= PColor[i][currentSum];
// Green:= PColor[i][currentSum*3+1];
Red := PColor[i][currentSum*3+2];
// Gray:= Round(Blue * 0.3 +Green * 0.59 +Red * 0.11);
if Red = 0 then
// if Gray<128 then
data[k] := 255
else
data[k] := 0;
k := k + 1;
end;
end;
data[k] := 10; //换行
k := k + 1;
end;
//打印命令在这里 上面是准备数据
for index := 0 to Length(data) - 1 do
begin
temp := temp + AnsiChar(strtoint('$' + IntToHex(data[index], 2)))
end;
if isNet then
userQRData.Put(userid, temp);
//QRBitmapTemp:=temp;
Send := AnsiChar($1D) + AnsiChar($21) + AnsiChar($11);
Move(Send[1], PicNamearray, Length(Send));
frmMain.IdTCPClient_xy.Socket.Send(PicNamearray, Length(Send));
frmMain.IdTCPClient_xy.Writeln(temp);
finally
bmp.FreeImage;
end;
end;
至此,问题完全解决。
参考网址: