Recent

Author Topic: [Solved] [Verified] GPS to QR code (WMF stream)  (Read 3158 times)

PizzaProgram

  • Jr. Member
  • **
  • Posts: 53
  • ...developing Delphi apps since 25 years.
Re: [Solved] [Verified] GPS to QR code (WMF stream)
« Reply #15 on: August 11, 2020, 07:38:49 pm »
****************************************************
Final complete fixed DEMO of the EXE + DLL source can be downloaded here:
(including many comments)

It's a nice example for following 3 questions:
1.) How to generate QR code from GPS coordinates?
2.) How to convert WMF picture from a QR code?
3.) How to deliver a picture stream from a DLL to an EXE with iStream?

Edit2:
 - geo() function fixed.
« Last Edit: August 12, 2020, 05:53:22 pm by PizzaProgram »
x86_64-win64 --Win7 PRO 64bit HUN

wp

  • Hero Member
  • *****
  • Posts: 11833
Re: [Solved] [Verified] GPS to QR code (WMF stream)
« Reply #16 on: August 11, 2020, 10:57:18 pm »
Quote
Why? What is happening when they are Word? Why Int64 and not Integer?

Auto-scale not working if width > 25. Range check error.

vec.Width  := 25;   // inch   >> scaling: 25.6mm × 100 × width >> 26 would be too big for 65K (Word) >> will be scaled back

See: procedure PrepareScaling(...);
 and you'll understand.
Worked the last 16+ hours on this to debug. Now it's working fine.  O:-)
Thanks for finding this overflow bug (I wonder why fpc does not report it in spite of all checks being active...) But I don't like your solution because making the MaxX and MaxY the largest-possible integers only hides the issue that coordinates may overflow the 16-bit integer range - but wmf is ancient 16-bit technology, coordinates must be within -32768 and 32767.

I (hopefully) fixed the issue by using intermediate floating point variables (because the vec.Width is this type to avoid the Round() here). These intermediate variables now can safely be checked against the allowed maximum value (MAXINT16) and, as in the old code, can be used to reduce the scaling factor so that the real maximum stays below the limit.

Replace the following procedure in wmfVectorialWriter.pas (or use Lazarus trunk), and check whether the bug is fixed this way, too:

Code: Pascal  [Select][+][-]
  1. procedure TvWMFVectorialWriter.PrepareScaling(APage: TvVectorialPage);
  2. const
  3.   MAXINT16 = 32767;
  4. var
  5.   maxx, maxy: Double;
  6. begin
  7.   FScalingFactor := round(ONE_INCH * 100);   // 1 logical unit is 1/100 mm = 10 µm
  8.   maxx := APage.Width * FScalingFactor;
  9.   maxy := APage.Height * FScalingFactor;
  10.   // wmf is 16 bit only! --> reduce magnification if numbers get too big
  11.   if Max(maxx, maxy) > MAXINT16 then
  12.   begin
  13.     FScalingFactor := trunc(MAXINT16 / Max(APage.Width, APage.Height));
  14.     FLogicalMaxX := word(trunc(APage.Width * FScalingFactor));
  15.     FLogicalMaxY := word(trunc(APage.Height * FScalingFactor));
  16.   end else
  17.   begin
  18.     FLogicalMaxX := trunc(maxx);
  19.     FLogicalMaxY := trunc(maxy);
  20.   end;
  21. end;

 

TinyPortal © 2005-2018