-5
var
  APoints: array [0 .. 3] of Integer;
  AptX, AptY: array [0 .. 3, 1 .. 32] of Integer;
  AptP, AptU: array [0 .. 3, 1 .. 32] of Single;
  AHistory: array [0 .. 3, Byte] of Integer;
  AMaxHistory: array [0 .. 3] of Integer;
  ALUT: array [0 .. 3, 0 .. 255] of Byte;
  APoint, AColorIndex: Integer;
  AImage, AIEBitmap: TIEBitmap;
  AImageLoaded: Boolean;
  ACurvesPath: String;

function CompareNatural(s1, s2: String): Integer;
  function ExtractNr(n: Integer; var Txt: String): Int64;
  begin
    while (n <= Length(Txt)) and (Txt[n] >= '0') and (Txt[n] <= '9') do
      n := n + 1;
    Result := StrToInt64Def(Copy(Txt, 1, n - 1), 0);
    Delete(Txt, 1, (n - 1));
  end;

var
  iB: Boolean;
begin
  Result := 0;
  s1 := LowerCase(s1);
  s2 := LowerCase(s2);
  if (s1 <> s2) and (s1 <> '') and (s2 <> '') then
  begin
    iB := False;
    while (not iB) do
    begin
      if ((s1[1] >= '0') and (s1[1] <= '9')) and
        ((s2[1] >= '0') and (s2[1] <= '9')) then
        Result := Sign(ExtractNr(1, s1) - ExtractNr(1, s2))
      else
        Result := Sign(Integer(s1[1]) - Integer(s2[1]));
      iB := (Result <> 0) or (Min(Length(s1), Length(s2)) < 2);
      if not iB then
      begin
        Delete(s1, 1, 1);
        Delete(s2, 1, 1);
      end;
    end;
  end;
  if Result = 0 then
  begin
    if (Length(s1) = 1) and (Length(s2) = 1) then
      Result := Sign(Integer(s1[1]) - Integer(s2[1]))
    else
      Result := Sign(Length(s1) - Length(s2));
  end;
end;

function SortMe(List: TStringList; i1, i2: Integer): Integer;
begin
  Result := CompareNatural(List[i1], List[i2]);
end;

function CalcImgSize(w, h, tw, th: Integer): TPoint;
begin
  Result := Point(0, 0);
  if (w = 0) or (h = 0) then
    Exit;
  if (w < tw) and (h < th) then
    Result := Point(w, h)
  else
  begin
    if w > h then
    begin
      if w < tw then
        tw := w;
      Result := Point(tw, Trunc(tw * h / w));
      if Result.Y > th then
        Result := Point(Trunc(th * w / h), th);
    end
    else
    begin
      if h < th then
        th := h;
      Result := Point(Trunc(th * w / h), th);
      if Result.X > tw then
        Result := Point(tw, Trunc(tw * h / w));
    end;
  end;
end;

function Blend(Color1, Color2: TColor; A: Byte): TColor;
var
  c1, c2: LongInt;
  R, G, B, v1, v2: Byte;
begin
  A := Round(2.56 * A);
  c1 := ColorToRGB(Color1);
  c2 := ColorToRGB(Color2);
  v1 := Byte(c1);
  v2 := Byte(c2);
  R := A * (v1 - v2) shr 8 + v2;
  v1 := Byte(c1 shr 8);
  v2 := Byte(c2 shr 8);
  G := A * (v1 - v2) shr 8 + v2;
  v1 := Byte(c1 shr 16);
  v2 := Byte(c2 shr 16);
  B := A * (v1 - v2) shr 8 + v2;
  Result := (B shl 16) + (G shl 8) + R;
end;

procedure BilinearRescale(Src, Dest: TIEBitmap);
var
  X, Y, px, py: Integer;
  i, x1, x2, z, z2, iz2: Integer;
  w1, w2, w3, w4: Integer;
  Ratio: Integer;
  sDst, sDstOff: Integer;
  PScanLine: array of PRGBArray;
  Src1, Src2: PRGBArray;
  C, c1, c2: TRGB24;
begin
  if (Dest.Width < 2) or (Dest.Height < 2) then
  begin
    Dest.Assign(Src);
    Exit;
  end;
  SetLength(PScanLine, Src.Height);
  PScanLine[0] := (Src.Scanline[0]);
  i := Integer(Src.Scanline[1]) - Integer(PScanLine[0]);
  for Y := 1 to Src.Height - 1 do
    PScanLine[Y] := PRGBArray(Integer(PScanLine[Y - 1]) + i);
  sDst := Integer(Dest.Scanline[0]);
  sDstOff := Integer(Dest.Scanline[1]) - sDst;
  Ratio := ((Src.Width - 1) shl 15) div Dest.Width;
  py := 0;
  for Y := 0 to Dest.Height - 1 do
  begin
    i := py shr 15;
    if i > Src.Height - 1 then
      i := Src.Height - 1;
    Src1 := PScanLine[i];
    if i < Src.Height - 1 then
      Src2 := PScanLine[i + 1]
    else
      Src2 := Src1;
    z2 := py and $7FFF;
    iz2 := $8000 - z2;
    px := 0;
    for X := 0 to Dest.Width - 1 do
    begin
      x1 := px shr 15;
      x2 := x1 + 1;
      c1 := Src1[x1];
      c2 := Src2[x1];
      z := px and $7FFF;
      w2 := (z * iz2) shr 15;
      w1 := iz2 - w2;
      w4 := (z * z2) shr 15;
      w3 := z2 - w4;
      C.R := (c1.R * w1 + Src1[x2].R * w2 + c2.R * w3 + Src2[x2].R * w4) shr 15;
      C.G := (c1.G * w1 + Src1[x2].G * w2 + c2.G * w3 + Src2[x2].G * w4) shr 15;
      C.B := (c1.B * w1 + Src2[x2].B * w2 + c2.B * w3 + Src2[x2].B * w4) shr 15;
      PRGBArray(sDst)[X] := C;
      Inc(px, Ratio);
    end;
    sDst := sDst + sDstOff;
    Inc(py, Ratio);
  end;
  SetLength(PScanLine, 0);
end;

function PtInCircle(cx, cy, X, Y, radius: Integer): Boolean;
begin
  Result := ((cx - X) * (cx - X)) + ((cy - Y) * (cy - Y)) <= radius * radius;
end;

procedure WuLine(Src: TBitmap; x1, y1, x2, y2: Integer; Color: TColor);
var
  C: Cardinal;
  R, G, B: Byte;
  i, dx, dy, X, Y, w, h, a1, a2: Integer;
  dxi, dyi, iGradient: Integer;
  iLine: array of PRGBArray;
  function BlendPixel(X, Y, A: Integer): TRGB24;
  begin
    Result.R := A * (R - iLine[Y][X].R) shr 8 + iLine[Y][X].R;
    Result.G := A * (G - iLine[Y][X].G) shr 8 + iLine[Y][X].G;
    Result.B := A * (B - iLine[Y][X].B) shr 8 + iLine[Y][X].B;
  end;
begin
  C := ColorToRGB(Color);
  R := C and 255;
  G := (C shr 8) and 255;
  B := (C shr 16) and 255;
  w := Src.Width;
  h := Src.Height;
  if (x1 = x2) or (y1 = y2) then
  begin
    Src.Canvas.Pen.Color := Color;
    Src.Canvas.MoveTo(x1, y1);
    Src.Canvas.LineTo(x2, y2);
    Exit;
  end;
  // make an array of source scanlines to speed up the rendering
  SetLength(iLine, Src.Height);
  iLine[0] := (Src.Scanline[0]);
  i := Integer(Src.Scanline[1]) - Integer(iLine[0]);
  for Y := 1 to Src.Height - 1 do
    iLine[Y] := PRGBArray(Integer(iLine[Y - 1]) + i);
  dx := abs(x2 - x1);
  dy := abs(y2 - y1);
  if dx > dy then
  begin // horizontal or vertical
    if y2 > y1 then
      dy := -dy;
    iGradient := dy shl 8 div dx;
    if x2 < x1 then
    begin
      i := x1;
      x1 := x2;
      x2 := i;
      dyi := y2 shl 8;
    end
    else
    begin
      dyi := y1 shl 8;
      iGradient := -iGradient;
    end;
    if x1 >= w then
      x2 := w - 1;
    for X := x1 to x2 do
    begin
      Y := dyi shr 8;
      if (X < 0) or (Y < 0) or (Y > h - 2) then
        Inc(dyi, iGradient)
      else
      begin
        a1 := dyi - Y shl 8;
        a2 := 256 - a1;
        iLine[Y][X] := BlendPixel(X, Y, a1);
        iLine[Y + 1][X] := BlendPixel(X, Y + 1, a2);
        Inc(dyi, iGradient);
      end;
    end;
  end
  else
  begin
    if x2 > x1 then
      dx := -dx;
    iGradient := dx shl 8 div dy;
    if y2 < y1 then
    begin
      i := y1;
      y1 := y2;
      y2 := i;
      dxi := x2 shl 8;
    end
    else
    begin
      dxi := x1 shl 8;
      iGradient := -iGradient;
    end;
    if y2 >= h then
      y2 := h - 1;
    for Y := y1 to y2 do
    begin
      X := dxi shr 8;
      if (Y < 0) or (X < 0) or (X > w - 2) then
        Inc(dxi, iGradient)
      else
      begin
        a1 := dxi - X shl 8;
        a2 := 256 - a1;
        iLine[Y][X] := BlendPixel(X, Y, a2);
        iLine[Y][X + 1] := BlendPixel(X + 1, Y, a1);
        Inc(dxi, iGradient);
      end;
    end;
  end;
end;

A win64 exception occurs at PRGBArray(sDst)[X] := C in the BilinearRescale procedure, but there probably other problems due to win64.

Johan
  • 74,508
  • 24
  • 191
  • 319
Bill
  • 2,993
  • 5
  • 37
  • 71
  • 1
    `sDst` is an integer. It needs to be a `NativeUInt` to fit a pointer like `PRGBArray`. Also all `Integer` casts needs to be looked over as well. – LU RD May 15 '16 at 18:53
  • I am trying to resolve a real problem with real code that works just fine with Win32 but not win64 so why the down vote? – Bill May 15 '16 at 19:05
  • You need to [read this](http://docwiki.embarcadero.com/RADStudio/Seattle/en/Converting_32-bit_Delphi_Applications_to_64-bit_Windows) (BTW, this was not an answer to your previous comment, I did not DV) – Tom Brunberg May 15 '16 at 19:06
  • Your Integer casts are still wrong. You need to slow down and learn a bit about 64 but. Make a mcve. It's disappointing that you didn't tell us what the error is. – David Heffernan May 15 '16 at 19:09
  • A few more links: [Data types](http://docwiki.embarcadero.com/RADStudio/Berlin/en/64-bit_Windows_Data_Types_Compared_to_32-bit_Windows_Data_Types) and [General](http://docwiki.embarcadero.com/RADStudio/Berlin/en/64-bit_Windows_Application_Development) – Tom Brunberg May 15 '16 at 19:21
  • Thanks Tom and David. – Bill May 15 '16 at 19:22
  • 3
    BTW you are being downvoted because you're presenting a wall of code in your question and did not narrow down the issue. That's considered laziness and bad form on SO. I didn't downvote because you're already at -2, but if you'd be at +1 I would, just to make clear that this is not a good way of presenting a question. – Johan May 15 '16 at 19:31
  • It almost seems that you have up before debugging. Strip it down to a MCVE. Then debug it. – David Heffernan May 15 '16 at 19:33
  • @Bill, I'm not sure why my comment was taken as a down vote? – LU RD May 15 '16 at 20:21

1 Answers1

3

You are making the error to think that integers and pointers are the same thing.

They are not and have never been the same thing.

A pointer differs in size depending on the addressable memory in the CPU. It has gone from 16bits to 20 bits to 32bits and is now 64bits (although only 48 bits are actually in use).

An integer is also implementation dependent, but matches the size the CPU can most easily work with.

This has gone from 16 bit to 32 bits and is now ... 32 bit.

It is 32 bit, because moving 32 bit around is faster than manipulating 64 bits all the time.

Never assume sizeof(integer) = sizeof(pointer) because your code will break.

To fix things for people who naively assume that pointer and integer are somehow the same thing. Emba has introduced the NativeInt which is defined as an integer that is the same size as a pointer.

Unfortunately the compiler aids and abets this folly by allowing you to cast an integer to a pointer even when they are different sizes. It should really generate a compiler error when you're trying to do that, but it does not.

You need to either replace all fake integer with NativeInt or replace your fake integer with pointer and enable pointermath by using the {$PointerMath on} compiler switch.

Never again assume that integer and pointer are somehow related.

Further reading:

Converting 32-bit Delphi Applications to 64-bit Windows

Pointer Math (Delphi)

A hidden feature of $POINTERMATH directive in Delphi 2009

When can ((Pointer)(P)+1)^ work?

Community
  • 1
  • 1
Johan
  • 74,508
  • 24
  • 191
  • 319
  • Note that it does not matter if you use `NativeUInt` or `NativeInt` in user mode pointer are always positive. In kernel mode pointers are always negative. Yes another implementation detail you cannot rely on and which will not be portable to other architectures (e.g. ARM). Which is why I prefer using pointers everywhere supported by `{$pointermath on}` – Johan May 15 '16 at 19:41
  • It appalls me that you say a pointer is 48 bits. It is 64 bits on the Win64 Delphi target. – David Heffernan May 15 '16 at 20:46
  • Only 48 of those 64 bits are actually in use. You cannot express $7FFFFFFFFFFFFFFF that address does not exist and will not exist barring changes in the x64 CPU. – Johan May 15 '16 at 21:02
  • That's a detail of implementation. The instruction set has 64 bits and you could readily make a chip that went beyond the 48 bits. Properly written code would be fine. Code that assumed 48 bits would not. You are making the same mistaken of assumption as the asker. What is sizeof(pointer)? – David Heffernan May 15 '16 at 21:05