首页 文章

Win64异常,Win32没有例外

提问于
浏览
-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;

在BilinearRescale过程中PRGBArray(sDst)[X]:= C时会发生win64异常,但由于win64可能存在其他问题 .

1 回答

  • 3

    你错误认为整数和指针是一回事 .

    它们不是,也从来都不是同一个东西 .

    指针的大小取决于CPU中的可寻址内存 . 它已经从16位变为20位到32位,现在是64位(尽管实际上只使用了48位) .

    整数也取决于实现,但与CPU最容易使用的大小相匹配 .

    这已经从16位变为32位,现在是...... 32位 .

    它是32位,因为移动32位比一直操作64位更快 .

    永远不要假设 sizeof(integer) = sizeof(pointer) 因为你的代码会破坏 .

    为那些天真地认为指针和整数在某种程度上是同一件事的人解决问题 . Emba引入了 NativeInt ,它被定义为一个与指针大小相同的整数 .

    不幸的是,编译器通过允许您将一个整数强制转换为指针即使它们的大小不同也可以帮助和怂恿这种愚蠢 . 当你尝试这样做时,它应该真的会产生编译器错误,但事实并非如此 .

    你需要用 NativeInt 替换所有假 integer 或用 pointer 替换你的假 integer 并使用 {$PointerMath on} 编译器开关启用pointermath .

    再也不要假设整数和指针有某种关联 .

    进一步阅读:

    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?

相关问题