Recent

Author Topic: (Solved) Difference between FPC and Delphi  (Read 1336 times)

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
(Solved) Difference between FPC and Delphi
« on: March 05, 2021, 01:43:07 pm »
Hi, with FPC I generate the attached bitmap_string1.txt and with Delphi I generate bitmap_string2.txt.

The right output is the FPC one (bitmap_string1.txt) and the problem is in Delphi.

This is the faulty part:

I'm thinking it must be the data types or the Chr(). Any ideas on differences on Char between FPC and Delphi?

Code: Pascal  [Select][+][-]
  1. function TssESCPosPrintBitmap.RenderBitmap( const ABitmapFilename: string): string;
  2. var
  3.   LOffset     : Integer;
  4.   LX          : Integer;
  5.   LSlice      : Byte;
  6.   LB          : Integer;
  7.   LK          : Integer;
  8.   LY          : Integer;
  9.   LI          : Integer;
  10.   LV          : Boolean;
  11.   LVI         : Integer;
  12. begin
  13.   // *** load the Bitmap from the file
  14.   FBitmap.LoadFromFile( ABitmapFilename );
  15.   FBitmap.PixelFormat := pf24bit;
  16.   // *** Convert the bitmap to an array of B/W pixels
  17.   LoadBitmapData();
  18.   // *** Set the line spacing to 24 dots, the height of each "stripe" of the
  19.   // *** image that we're drawing
  20.   Result := #27'3'#24;
  21.   LOffset := 0;
  22.   while ( LOffset < FBitmapData.Height ) do
  23.    begin
  24.     Result := Result + #27;
  25.     Result := Result + '*'; // Bit image mode
  26.     Result := Result + #33; // 24-dot double density
  27.     Result := Result + Char( Lo( FBitmapData.Width ) );
  28.     Result := Result + Char( Hi( FBitmapData.Width ) );
  29.     for LX := 0 to FBitmapData.Width -1 do begin
  30.       for LK := 0 to 2 do begin
  31.         LSlice := 0;
  32.         for LB := 0 to 7 do begin
  33.           LY := ( ( ( LOffset div 8 ) + LK ) * 8 ) + LB;
  34.           LI := ( LY * FBitmapData.Width ) + LX;
  35.           LV := False;
  36.           if ( LI < Length( FBitmapData.Dots ) ) then
  37.             LV := FBitmapData.Dots[LI];
  38.           LVI := IfThen( LV, 1, 0 );
  39.           LSlice := LSlice or ( LVI shl ( 7 - LB ) );
  40.         end;
  41.         Result := Result + Chr( LSlice );
  42.       end;
  43.     end;
  44.     LOffset := LOffset + 24;
  45.     Result := Result + sLineBreak;
  46.    end;
  47.   // *** Restore the line spacing to the default of 30 dots
  48.   Result := Result + #27'3'#30 + sLineBreak + sLineBreak + sLineBreak;
  49. end;

This is the full code (for Delphi):

Code: Pascal  [Select][+][-]
  1. {******************************************************************************}
  2. {                                                                              }
  3. {  Unit: ssESCPosPrintBitmap.pas                                               }
  4. {  Summerswell Core                                                            }
  5. {                                                                              }
  6. {  Copyright (C) 2015 Summerswell                                              }
  7. {                                                                              }
  8. {  Author     : bvonfintel                                                     }
  9. {  Original   : 2015/01/06 11:12:30 AM                                         }
  10. {                                                                              }
  11. {******************************************************************************}
  12. {
  13.   This is based on the class provided by:
  14.   http://nicholas.piasecki.name/blog/2009/12/sending-a-bit-image-to-an-epson-tm-t88iii-receipt-printer-using-c-and-escpos/
  15.   The Delphi translation provided (http://nicholas.piasecki.name/blog/wp-content/uploads/2009/12/Delphi-Version.txt.txt)
  16.   did not print to the Epson TM T70
  17. {}
  18. unit ssESCPosPrintBitmap;
  19. interface
  20. uses
  21.  Soap.EncdDecd;
  22. type
  23.   // *** -------------------------------------------------------------------------
  24.   // *** INTERFACE: IssESCPosPrintBitmap
  25.   // *** -------------------------------------------------------------------------
  26.   IssESCPosPrintBitmap = interface( IInterface )
  27.     ['{3F279585-6D2E-451F-AF97-76F0E07A70DF}']
  28.     function RenderBitmap( const ABitmapFilename: string ): string;
  29.     function RenderBitmapBase64(const base64data: string): string;
  30.   end;
  31.   function _ESCPosPrintBitmap(): IssESCPosPrintBitmap;
  32. implementation
  33. uses
  34.   Windows,
  35.   Math,Classes,Graphics, SysUtils, Dialogs,System.NetEncoding;
  36. type
  37.   TRGBTripleArray = ARRAY[Word] of TRGBTriple;
  38.   pRGBTripleArray = ^TRGBTripleArray; // Use a PByteArray for pf8bit color.
  39.   // *** -------------------------------------------------------------------------
  40.   // *** RECORD:  TBitmapData
  41.   // *** -------------------------------------------------------------------------
  42.   TBitmapData = record
  43.     Dots      : array of Boolean;
  44.     Height    : Integer;
  45.     Width     : Integer;
  46.   end;
  47.   // *** -------------------------------------------------------------------------
  48.   // *** CLASS: TssESCPosPrintBitmap
  49.   // *** -------------------------------------------------------------------------
  50.   TssESCPosPrintBitmap = class( TInterfacedObject, IssESCPosPrintBitmap )
  51.     private
  52.       FLumThreshold : Integer;
  53.       FBitmap       : TBitmap;
  54.       FBitmapData   : TBitmapData;
  55.       procedure LoadBitmapData();
  56.     public
  57.       constructor Create();
  58.       destructor Destroy; override;
  59.       function RenderBitmap( const ABitmapFilename: string ): string;
  60.       function RenderBitmapBase64(const base64data: string): string;
  61.   end;
  62. const
  63.   C_DEFAULT_THRESHOLD = 127;
  64. function _ESCPosPrintBitmap(): IssESCPosPrintBitmap;
  65. begin
  66.   Result := TssESCPosPrintBitmap.Create();
  67. end;
  68. { TssESCPosPrintBitmap }
  69. {-------------------------------------------------------------------------------
  70.   Procedure: TssESCPosPrintBitmap.Create
  71.   Author:    bvonfintel
  72.   DateTime:  2015.01.06
  73.   Arguments: None
  74.   Result:    None
  75. -------------------------------------------------------------------------------}
  76. constructor TssESCPosPrintBitmap.Create;
  77. begin
  78.   inherited;
  79.   FBitmap       := TBitmap.Create();
  80.   FLumThreshold := C_DEFAULT_THRESHOLD;
  81. end;
  82. function BitmapFromBase64(const base64: string): TBitmap;
  83. var
  84.   Input: TStringStream;
  85.   Output: TBytesStream;
  86. begin
  87.   Input := TStringStream.Create(base64, TEncoding.ASCII);
  88.   try
  89.     Output := TBytesStream.Create;
  90.     try
  91.       Soap.EncdDecd.DecodeStream(Input, Output);
  92.       Output.Position := 0;
  93.       Result := TBitmap.Create;
  94.       try
  95.         Result.LoadFromStream(Output);
  96.       except
  97.         Result.Free;
  98.         raise;
  99.       end;
  100.     finally
  101.       Output.Free;
  102.     end;
  103.   finally
  104.     Input.Free;
  105.   end;
  106. end;
  107. {-------------------------------------------------------------------------------
  108.   Procedure: TssESCPosPrintBitmap.Destroy
  109.   Author:    bvonfintel
  110.   DateTime:  2015.01.06
  111.   Arguments: None
  112.   Result:    None
  113. -------------------------------------------------------------------------------}
  114. destructor TssESCPosPrintBitmap.Destroy;
  115. begin
  116.   FBitmap.Free();
  117.   inherited;
  118. end;
  119. {-------------------------------------------------------------------------------
  120.   Procedure: TssESCPosPrintBitmap.LoadBitmapData
  121.   Author:    bvonfintel
  122.   DateTime:  2015.01.06
  123.   Arguments: None
  124.   Result:    None
  125. -------------------------------------------------------------------------------}
  126. procedure TssESCPosPrintBitmap.LoadBitmapData;
  127. var
  128.   LIndex : Integer;
  129.   LX     : Integer;
  130.   LY     : Integer;
  131.   LLine  : pRGBTripleArray;
  132.   LPixel : TRGBTriple;
  133.   LLum   : Integer;
  134. begin
  135.   LIndex := 0;
  136.   FBitmapData.Height := FBitmap.Height;
  137.   FBitmapData.Width  := FBitmap.Width;
  138.   SetLength( FBitmapData.Dots, FBitmap.Width * FBitmap.Height );
  139.   for LY := 0 to FBitmap.Height - 1 do
  140.   begin
  141.     LLine := FBitmap.ScanLine[LY];
  142.     for LX := 0 to FBitmap.Width - 1 do
  143.     begin
  144.       LPixel := LLine[LX];
  145.       LLum   := Trunc( ( LPixel.rgbtRed * 0.3 ) + ( LPixel.rgbtGreen  * 0.59 ) + ( LPixel.rgbtBlue * 0.11 ) );
  146.       FBitmapData.Dots[LIndex] := ( LLum < FLumThreshold );
  147.       Inc( LIndex );
  148.     end;
  149.   end;
  150. end;
  151. function TssESCPosPrintBitmap.RenderBitmapBase64(const base64data: string): string;
  152. var
  153.   LOffset     : Integer;
  154.   LX          : Integer;
  155.   LSlice      : Byte;
  156.   LB          : Integer;
  157.   LK          : Integer;
  158.   LY          : Integer;
  159.   LI          : Integer;
  160.   LV          : Boolean;
  161.   LVI         : Integer;
  162.   bmp: TBitmap;
  163. begin
  164.   bmp := TBitmap.Create;
  165.   bmp := BitmapFromBase64(base64data);
  166.   //bmp.SaveToFile('D:\PosBASE64.bmp');
  167.   FBitmap:=bmp;
  168.   //FBitmap.SaveToFile('D:\Pos2BASE64.bmp');
  169.   LoadBitmapData();
  170.   Result := #27'3'#24;
  171.   LOffset := 0;
  172.   while ( LOffset < FBitmapData.Height ) do begin
  173.     Result := Result + #27;
  174.     Result := Result + '*'; // Bit image mode
  175.     Result := Result + #33; // 24-dot double density
  176.     Result := Result + Char( Lo( FBitmapData.Width ) );
  177.     Result := Result + Char( Hi( FBitmapData.Width ) );
  178.     for LX := 0 to FBitmapData.Width -1 do begin
  179.       for LK := 0 to 2 do begin
  180.         LSlice := 0;
  181.         for LB := 0 to 7 do begin
  182.           LY := ( ( ( LOffset div 8 ) + LK ) * 8 ) + LB;
  183.           LI := ( LY * FBitmapData.Width ) + LX;
  184.           LV := False;
  185.           if ( LI < Length( FBitmapData.Dots ) ) then
  186.             LV := FBitmapData.Dots[LI];
  187.           LVI := IfThen( LV, 1, 0 );
  188.           LSlice := LSlice or ( LVI shl ( 7 - LB ) );
  189.         end;
  190.         Result := Result + Chr( LSlice );
  191.       end;
  192.     end;
  193.     LOffset := LOffset + 24;
  194.     Result := Result + sLineBreak;
  195.   end;
  196.   // *** Restore the line spacing to the default of 30 dots
  197.   Result := Result + #27'3'#30 + sLineBreak + sLineBreak + sLineBreak;
  198. end;
  199. {-------------------------------------------------------------------------------
  200.   Procedure: TssESCPosPrintBitmap.RenderBitmap
  201.   Author:    bvonfintel
  202.   DateTime:  2015.01.06
  203.   Arguments: const ABitmapFilename: string
  204.   Result:    string
  205. -------------------------------------------------------------------------------}
  206. function TssESCPosPrintBitmap.RenderBitmap( const ABitmapFilename: string): string;
  207. var
  208.   LOffset     : Integer;
  209.   LX          : Integer;
  210.   LSlice      : Byte;
  211.   LB          : Integer;
  212.   LK          : Integer;
  213.   LY          : Integer;
  214.   LI          : Integer;
  215.   LV          : Boolean;
  216.   LVI         : Integer;
  217. begin
  218.   // *** load the Bitmap from the file
  219.   FBitmap.LoadFromFile( ABitmapFilename );
  220.   FBitmap.PixelFormat := pf24bit;
  221.   // *** Convert the bitmap to an array of B/W pixels
  222.   LoadBitmapData();
  223.   // *** Set the line spacing to 24 dots, the height of each "stripe" of the
  224.   // *** image that we're drawing
  225.   Result := #27'3'#24;
  226.   LOffset := 0;
  227.   while ( LOffset < FBitmapData.Height ) do
  228.    begin
  229.     Result := Result + #27;
  230.     Result := Result + '*'; // Bit image mode
  231.     Result := Result + #33; // 24-dot double density
  232.     Result := Result + Char( Lo( FBitmapData.Width ) );
  233.     Result := Result + Char( Hi( FBitmapData.Width ) );
  234.     for LX := 0 to FBitmapData.Width -1 do begin
  235.       for LK := 0 to 2 do begin
  236.         LSlice := 0;
  237.         for LB := 0 to 7 do begin
  238.           LY := ( ( ( LOffset div 8 ) + LK ) * 8 ) + LB;
  239.           LI := ( LY * FBitmapData.Width ) + LX;
  240.           LV := False;
  241.           if ( LI < Length( FBitmapData.Dots ) ) then
  242.             LV := FBitmapData.Dots[LI];
  243.           LVI := IfThen( LV, 1, 0 );
  244.           LSlice := LSlice or ( LVI shl ( 7 - LB ) );
  245.         end;
  246.         Result := Result + Chr( LSlice );
  247.       end;
  248.     end;
  249.     LOffset := LOffset + 24;
  250.     Result := Result + sLineBreak;
  251.    end;
  252.   // *** Restore the line spacing to the default of 30 dots
  253.   Result := Result + #27'3'#30 + sLineBreak + sLineBreak + sLineBreak;
  254. end;
  255. end.
« Last Edit: March 05, 2021, 02:56:40 pm by lainz »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Difference between FPC and Delphi
« Reply #1 on: March 05, 2021, 01:53:19 pm »
In Delphi Char = WideChar?

Bart

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Difference between FPC and Delphi
« Reply #2 on: March 05, 2021, 01:57:10 pm »
In D2009 char=widechar in D2007- char=ansichar.

If you mean a bytesized char, always use ansichar.

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
Re: Difference between FPC and Delphi
« Reply #3 on: March 05, 2021, 02:32:53 pm »
Thanks =)

Thaddy

  • Hero Member
  • *****
  • Posts: 14213
  • Probably until I exterminate Putin.
Re: Difference between FPC and Delphi
« Reply #4 on: March 05, 2021, 02:35:55 pm »
In D2009 char=widechar in D2007- char=ansichar.

If you mean a bytesized char, always use ansichar.
In D2009 or higher. And D2007 or lower.
In this case there are two solutions:
1: replace the char casts to AnsiChar casts
2: use byte as you correctly remark.
This code is sloppy and needs byte....
Probably due to C'ism complex.
« Last Edit: March 05, 2021, 02:37:54 pm by Thaddy »
Specialize a type, not a var.

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
Re: Difference between FPC and Delphi
« Reply #5 on: March 05, 2021, 02:56:30 pm »
Code: Pascal  [Select][+][-]
  1. Result := Result + ansichar(chr(LSlice));

Using that solves the problem.

Many thanks =)

 

TinyPortal © 2005-2018