用delphi控制小票打印机打印图片
unit PosPrintBmp;
{***********************************************************************}
{ 单元名称:PosPrintBmp
小票打印机打印图片的类
}
{
}
{ 创建人:李红雷
}
{ 日期:2012.2
}
{ 修改人:
}
{ 日期:
}
{ 功能:GetDocument函数 得到图片的字节数组
}
{
属性ByteLen 得到字节数组的长度
}
{ 用法: PosPrintBmp := TPosPrintBmp.Create(FPicName);
}
{ try
}
{
PrintPic := PosPrintBmp.GetDocument;
}
{ gLen
:= PosPrintBmp.ByteLen;
}
{
WritePrinter(hprinter, @PrintPic, gLen, N);
}
{ finally
}
{
PosPrintBmp.Free;
}
{ end;
}
{***********************************************************************}
interface
uses
Windows, SysUtils, Classes, Graphics,
jpeg;
const
Nul: Char = #0;
FormFeed: Char = #12;
Escape: Char = #27;
Newline: Char = #10;
GroupSeparator: Char = #29;
HorizontalTab: Char = #9;
CarriageReturn: Char = #13;
Cancel: Char = #24;
DataLinkEscape: Char = #16;
EndOfTransmission: Char = #4;
FileSeparator: Char = #28;
Sat: Char = #64; //@
Sv: Char = #86; //V
S66: Char = #66;
S3: Char = #51;
Sx: Char = #42; //*
S24: Char = #24;
S33: Char = #33;
S30: Char = #30;
S3_1: Char = #3;
type
TData = packed record
Dots: array of
Boolean;
Height, Width:
Integer;
end;
TPosPrintBmp = class(TObject)
private
FLen: Integer;
FPicName: string;
function
GetBitmapData(PicName: string): TData;
procedure RenderLogo(out
fms: TMemoryStream);
public
constructor Create(const
AFileName: string);
function GetDocument:
TByteArray; //得到图片的字节数组
published
property ByteLen: Integer
read FLen; //字节数组的长度
end;
implementation
constructor TPosPrintBmp.Create(const AFileName: string);
begin
inherited Create;
FPicName := AFileName;
end;
function TPosPrintBmp.GetBitmapData(PicName: string): TData;
const
threshold: Integer = 127;
var
Bmp: TBitmap;
index, dimensions, x, y, luminance:
Integer;
dots: array of Boolean;
AData: TData;
RGB: TColor;
RC, GC, BC: Byte;
jpeg: TJPEGImage;
begin
index := 0;
Bmp := TBitmap.Create;
try
if
UpperCase(ExtractFileExt(PicName)) = '.JPG' then
begin
jpeg :=
TJPEGImage.Create;
try
jpeg.LoadFromFile(PicName);
Bmp.Assign(jpeg);
finally
jpeg.Free;
end
end else
Bmp.LoadFromFile(PicName);
dimensions := Bmp.Width *
Bmp.Height;
SetLength(dots,
dimensions);
for y := 0 to Bmp.Height -
1 do
begin
for x
:= 0 to Bmp.Width - 1 do
begin
RGB := Bmp.Canvas.Pixels[x, y];
RC := RGB and $FF;
GC := RGB and $FF00 shr 8;
BC := RGB and $FF0000 shr 16;
luminance := Round(RC * 0.3 + GC * 0.59 + BC *
0.11);
dots[index] := (luminance <
threshold);
Inc(index);
end;
end;
finally
AData.Height :=
Bmp.Height;
AData.Width :=
Bmp.Width;
SetLength(AData.Dots,
Length(dots));
Move(dots[0],
AData.Dots[0], Length(dots));
Bmp.Free;
end;
Result := AData;
end;
procedure TPosPrintBmp.RenderLogo(out fms: TMemoryStream);
var
Data: TData;
FDots: array of Boolean;
offset, I, K, b, x, y, tmpint, M:
Integer;
v: Boolean;
slice: Byte;
FWidth: array of Byte;
begin
Data := GetBitmapData(FPicName);
SetLength(FDots, Length(Data.Dots));
Move(Data.Dots[0], FDots[0],
Length(Data.Dots));
SetLength(FWidth, 4);
FWidth[0] := Data.Width and $FF;
FWidth[1] := Data.Width and $FF00 shr 8;
FWidth[2] := Data.Width and $FF0000 shr
16;
FWidth[3] := Data.Width and $FF000000 shr
24;
fms.Write(Newline, 1);
fms.Write(Escape, 1);
fms.Write(s3, 1);
fms.Write(S24, 1);
offset := 0;
OutputDebugString(PChar('offset=' +
IntToStr(offset)));
while (offset < Data.Height)
do
begin
fms.Write(Escape, 1);
fms.Write(Sx, 1);
// bit-image mode
fms.Write(S33, 1);
// 24-dot double-density
fms.Write(FWidth[0], 1);
// width low byte
fms.Write(FWidth[1], 1);
// width high byte
for x := 0 to data.Width -
1 do
begin
for K
:= 0 to 2 do
begin
slice := 0;
for b := 0 to 7 do
begin
y := (((offset div 8) + k) *
8) + b;
i := (y * data.Width) +
x;
v := False;
if (I <
Length(Data.Dots)) then
v :=
FDots[I];
tmpint := 7 - b;
if v then
M := 1 shl
tmpint
else
M := 0 shl
tmpint;
slice := slice or M;
end;
fms.Write(slice, 1);
end;
end;
Inc(offset, 24);
if offset <
Data.Height then // 去掉结束空行
fms.Write(Newline, 1);
end;
// Restore the line spacing to the default of
30 dots.
fms.Write(Escape, 1);
fms.Write(S3, 1);
fms.Write(S30, 1);
end;
function TPosPrintBmp.GetDocument: TByteArray;
var
ms: TMemoryStream;
TmpBA: TByteArray;
begin
ms := TMemoryStream.Create;
try
ms.Write(Escape, 1);
ms.Write(Sat, 1);
RenderLogo(ms);
//ms.Write(GroupSeparator,
1);
//ms.Write(Sv, 1);
//ms.Write(S66, 1);
//ms.Write(S3_1, 1);
ms.Write(Newline, 1);
ms.Position := 0;
FLen := ms.Size;
ms.ReadBuffer(TmpBA[0],
ms.Size);
finally
ms.Free;
end;
Result := TmpBA;
end;
end.