Jump to content
at3s

TBitmap to TBytes for ESC/POS Thermal Printer

Recommended Posts

Actually I'm looking for a function which could convert TBitmap to TBytes for printing in ESC/POS Thermal Printer.

I'm trying to make working a code from here, but also got an effect as on the author picture - white lines and not correct text on an image as well.

Has someone a working code?

Share this post


Link to post
22 hours ago, at3s said:

Actually I'm looking for a function which could convert TBitmap to TBytes

It really depends on the format that the ESC/POS is expecting.  It might be as simply as using TBitmap.SaveToStream() to save to a TBytesStream, and then using the stream's Bytes and Size properties.  Or it may be more complex, like having to extract the individual pixels, like that other code is doing.  You are going to have to provide more details about your particular situation.

Share this post


Link to post
14 hours ago, Remy Lebeau said:

It really depends on the format that the ESC/POS is expecting.  It might be as simply as using TBitmap.SaveToStream() to save to a TBytesStream, and then using the stream's Bytes and Size properties.  Or it may be more complex, like having to extract the individual pixels, like that other code is doing.  You are going to have to provide more details about your particular situation.

Here is my code. It's mostly the same as is in the sources here or here.

And I'm getting the same result with the horizontal blank lines as here.

 

uses
  System
  , System.SysUtils
  , System.UITypes
  , FMX.Graphics
  ;

type
  TRgbTriple = packed record
    // do not change the order of the fields, do not add any fields
    Blue: Byte;
    Green: Byte;
    Red: Byte;
  end;

// ---------------------------

procedure TThermalPrinter.SendString(AValue: String);
var
  SND: TBytes;
begin
  SND := TEncoding.ASCII.GetBytes(AValue);
  LSockect.SendData(SND); // send data to the printer
end;

procedure TThermalPrinter.DoSetLineSpacing(AValue : integer);
begin
 if (AValue = 0) then begin
   SendString(#$1B#$32{, false});  //Resetset to default
 end else begin
   SendString(#$1B#$33 + AnsiChar(AValue){, false});
 end;
end;

procedure TThermalPrinter.DoPrintBitmap(const ABitmap : TBitmap; const  BitsPerSlice : Byte);
const
 Threshhold = 127;
type
 TBitArray = array of boolean;
 TRGBTripleArray = ARRAY[Word] of TRGBTriple;
 pRGBTripleArray = ^TRGBTripleArray; // Use a PByteArray for pf8bit color.
var
 BMPData: TBitmapData;
 vCol : integer;
 vRow : integer;
 vIndex : integer;
 vSliceIndex : integer;
 vBytePos : integer;
 vBitPos : integer;
 vOffset : integer;
 vLuminance : integer;
 vLine: pRGBTripleArray;
  vPixel: TAlphaColor;
 vDots: TBitArray;
 vSlice : Byte;
 vBit : Byte;
 vTmpBit: Byte;
 vVal: boolean;
 vTempStr : string;
begin
 if not Assigned(ABitmap) then exit;

 ABitmap.Map(TMapAccess.Read, BMPData);
 try
    SetLength(vDots, (ABitmap.Height * ABitmap.Width));
    vIndex := 0;

    for vRow := 0 to ABitmap.Height-1 do
    begin
      for vCol := 0 to ABitmap.Width-1 do
      begin
        vPixel := BMPData.GetPixel(vCol, vRow);
        vLuminance := Trunc((TAlphaColorRec(vPixel).R * 0.3)  + (TAlphaColorRec(vPixel).G * 0.59) + (TAlphaColorRec(vPixel).B * 0.11));
        vDots[vIndex] := (vLuminance < 127);
        Inc(vIndex);
      end;
    end;

   DoSetLineSpacing(24);
   SendString(' ');

   vOffset := 0;
   while (vOffset < ABitmap.Height) do
   begin
    SendString(#$1B'*'#33 + AnsiChar(Lo(ABitmap.Width)) + AnsiChar(Hi(ABitmap.Width)){, false});

     vTempStr := '';
     for vCol := 0 to ABitmap.Width-1 do begin
       for vSliceIndex := 0 to 2 do begin // Remember, 24 dots = 24 bits = 3 bytes.
         vSlice := 0;
         for vBit := 0 to 7 do begin
           vBytePos := (((vOffset div 8) + vSliceIndex) * 8) + vBit;
           vBitPos := (vBytePos * ABitmap.Width) + vCol;

           vVal := false;
           if (vBitPos < Length(vDots)) then begin
             vVal := vDots[vBitPos];
           end;

           if vVal then
             vTmpBit := 1
           else
             vTmpBit := 0;
           vSlice := vSlice or (vTmpBit shl (7 - vBit));
         end;

         vTempStr := vTempStr + AnsiChar(vSlice);
       end;
     end;

     Inc(vOffset, 24);
     SendString(vTempStr + #13#10);
   end;

   DoSetLineSpacing(0);
   SendString(' ');
 finally
    vDots := nil;
    ABitmap.Unmap(BMPData);
 end;
end;

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×