2016-05-15 13 views
-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-Ausnahme tritt bei PRGBArray (SDSt) [X]: = C im BilinearRescale Verfahren, aber es wahrscheinlich andere Probleme aufgrund von win64.Win64 Ausnahme, Win32 keine Ausnahme

+1

'sDst' eine ganze Zahl ist. Es muss eine 'NativeUInt' sein, um einen Zeiger wie' PRGBArray' zu verwenden. Außerdem müssen alle "Integer" -Stücke überprüft werden. –

+0

Ich versuche, ein echtes Problem mit echtem Code zu lösen, das mit Win32 aber nicht win64 gut funktioniert, also warum die unten Abstimmung? – Bill

+0

Sie müssen [lesen] (http://docwiki.embarcadero.com/RADStudio/Seattle/de/Converting_32-bit_Delphi_Applications_to_64-bit_Windows) (BTW, dies war keine Antwort auf Ihren vorherigen Kommentar, ich habe nicht DV) –

Antwort

3

Sie machen den Fehler zu denken, dass Integer und Zeiger die gleiche Sache sind.

Sie sind nicht und waren nie das Gleiche.

Ein Zeiger unterscheidet sich in der Größe abhängig vom adressierbaren Speicher in der CPU. Es ist von 16 Bits auf 20 Bits zu 32 Bits gegangen und ist jetzt 64 Bits (obwohl nur 48 Bits tatsächlich verwendet werden).

Eine ganze Zahl ist ebenfalls implementierungsabhängig, entspricht jedoch der Größe, mit der die CPU am einfachsten arbeiten kann.

Dies ist von 16 Bit auf 32 Bit gegangen und ist jetzt ... 32 Bit.

Es ist 32 Bit, weil das Bewegen von 32 Bit schneller ist als 64 Bit die ganze Zeit zu manipulieren.

Nimm niemals sizeof(integer) = sizeof(pointer) an, weil dein Code kaputt geht.

Um Dinge für Leute zu reparieren, die naiv annehmen, dass Zeiger und Integer irgendwie die gleiche Sache sind. Emba hat die NativeInt eingeführt, die als eine Ganzzahl definiert ist, die die gleiche Größe wie ein Zeiger hat.

Leider hilft und unterstützt der Compiler diese Torheit, indem Sie eine ganze Zahl auf einen Zeiger werfen können, auch wenn sie unterschiedliche Größen haben. Es sollte wirklich einen Compiler-Fehler erzeugen, wenn Sie das versuchen, aber das tut es nicht.

Sie müssen entweder alle gefälschte integer mit NativeInt ersetzen oder Ihre gefälschte integer mit pointer ersetzen und POINTERMATH aktivieren, indem Sie den {$PointerMath on} Compiler-Schalter.

Nie wieder davon ausgehen, dass Integer und Zeiger irgendwie verwandt sind.

Weiterführende Literatur:

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?

+0

Beachten Sie, dass es egal ist, ob Sie 'NativeUInt' oder' NativeInt' im Benutzermodus-Zeiger immer positiv verwenden. Im Kernel-Modus sind Zeiger immer negativ. Ja, ein weiteres Implementierungsdetail, auf das Sie sich nicht verlassen können und das nicht auf andere Architekturen portierbar ist (z. B. ARM). Deshalb bevorzuge ich die Verwendung von Zeigern, die von '{$ pintermath on}' ' – Johan

+0

unterstützt werden. Es bedeutet, dass Sie sagen, ein Zeiger ist 48 Bit. Es ist 64 Bits auf dem Win64 Delphi-Ziel. –

+0

Nur 48 dieser 64 Bits werden tatsächlich verwendet. Sie können nicht $ 7FFFFFFFFFFFFFFF ausdrücken, dass die Adresse nicht existiert und nicht existieren wird, wenn keine Änderungen in der x64-CPU vorgenommen werden. – Johan