Всем привет!
Есть такая функция (стырил на одном форуме)
Код:
procedure DrawPngRotate(const AOriginal: TPNGObject; ARotated: TPNGObject; const AAngle: single);
type
TRGBTripleArray = array [0..32767] of TRGBTriple;
pRGBTripleArray = ^TRGBTripleArray;
var
TmpPng: TPNGObject;
TmpX: Integer;
TmpY: Integer;
TmpXOrig: Integer;
TmpYOrig: Integer;
TmpXPrime: Integer;
TmpYPrime: Integer;
TmpDelta: single;
TmpDeltaCos: single;
TmpDeltaSin: single;
TmpWidth: Integer;
TmpHeight: Integer;
TmpRowRot : Integer;
TmpRowOrg : Integer;
TmpRowStart : Pointer;
TmpRowRotated: pRGBtripleArray;
TmpAlphaRot : Integer;
TmpAlphaOrg : Integer;
TmpAlphaStart : Pointer;
TmpAlphaRotated : pByteArray;
TmpTransparent: TRGBTriple;
TmpSubX: Integer;
TmpSubY: Integer;
TmpRotX: Integer;
TmpRotY: Integer;
// Diametr mod by angle
function Mod360(const AAngle: single): single;
begin
Result := Frac(AAngle / 360) * 360;
if Result < 0 then Result := Result + 360;
end;
begin
TmpDelta := -(2 * pi * Mod360(AAngle)) / 360;
TmpDeltaSin := Sin(TmpDelta);
TmpDeltaCos := Cos(TmpDelta);
TmpWidth := Abs(Round(AOriginal.Height * TmpDeltaSin))
+ Abs(Round(AOriginal.Width * TmpDeltaCos));
TmpHeight := Abs(Round(AOriginal.Width * TmpDeltaSin))
+ Abs(Round(AOriginal.Height * TmpDeltaCos));
// Rotate by zero
if (Abs(TmpDelta) * Max(AOriginal.Width, AOriginal.Height)) <= 1 then
begin
if ARotated <> AOriginal then ARotated.Assign(AOriginal);
Exit;
end;
// Rotate by non-zero
TmpPng := TPNGObject.CreateBlank(AOriginal.Header.ColorType, 8, TmpWidth, TmpHeight);
try
TmpRotY := Pred(TmpWidth);
TmpRotX := Pred(TmpHeight);
TmpSubY := Pred(AOriginal.Width);
TmpSubX := Pred(AOriginal.Height);
TmpRowRotated := TmpPng.Scanline[TmpRotX] ;
TmpRowStart := AOriginal.Scanline[0];
TmpRowRot := Integer(TmpPng.ScanLine[1]) - Integer(TmpPng.ScanLine[0]);
TmpRowOrg := Integer(AOriginal.ScanLine[1]) - Integer(AOriginal.ScanLine[0]);
TmpTransparent := pRGBtripleArray(AOriginal.Scanline[TmpSubX])[0];
// Check for transparency
if AOriginal.Header.ColorType in [COLOR_RGBALPHA] then
begin
TmpAlphaStart := AOriginal.AlphaScanline[0];
TmpAlphaRotated := TmpPng.AlphaScanline[TmpRotX];
TmpAlphaRot := Integer(TmpPng.AlphaScanline[1])
- Integer(TmpPng.AlphaScanline[0]);
TmpAlphaOrg := Integer(AOriginal.AlphaScanline[1])
- Integer(AOriginal.AlphaScanline[0]);
end else begin
TmpAlphaStart := nil;
TmpAlphaRotated := nil;
TmpAlphaRot := 0;
TmpAlphaOrg := 0;
end;
for TmpY := TmpRotX downto 0 do
begin
TmpYPrime := 2 * TmpY - TmpHeight + 1;
for TmpX := TmpRotY downto 0 do
begin
TmpXPrime := 2 * TmpX - TmpWidth + 1;
TmpXOrig := (Round(TmpXPrime * TmpDeltaCos - TmpYPrime * TmpDeltaSin)
+ TmpSubY) div 2;
// If inside
if (TmpXOrig >= 0) and (TmpXOrig <= TmpSubY) then
begin
TmpYOrig := (Round(TmpXPrime * TmpDeltaSin + TmpYPrime*TmpDeltaCos)
+ TmpSubX) div 2 ;
if (TmpYOrig >= 0) and (TmpYOrig <= TmpSubX) then
begin
TmpRowRotated[TmpX] := pRGBTripleArray(Integer(TmpRowStart)
+ (TmpYOrig * TmpRowOrg))[TmpXOrig];
if Assigned(TmpAlphaRotated) then
TmpAlphaRotated[TmpX] := pByteArray(Integer(TmpAlphaStart)
+ (TmpYOrig * TmpAlphaOrg))[TmpXOrig];
end else begin
//Set Transparency
if Assigned(TmpAlphaRotated) then TmpAlphaRotated[TmpX] := 0;
TmpRowRotated[TmpX] := TmpTransparent;
end;
end else begin
//Set Transparency
if Assigned(TmpAlphaRotated) then TmpAlphaRotated[TmpX] := 0;
TmpRowRotated[TmpX] := TmpTransparent;
end;
end;
Dec(Integer(TmpRowRotated), TmpRowRot);
if Assigned(TmpAlphaRotated) then Dec(Integer(TmpAlphaRotated), TmpAlphaRot);
end;
ARotated.Assign(TmpPng);
finally
FreeAndNil(TmpPng);
end;
end;
Когда я вызываю ее по таймеру
Код:
DrawPngRotate(FPNG,FPNG2,AAngle);
то происходит переполнение стека (stack overflow).
Подскажите, как можно решить эту проблему?
Создание, программирование и сопровождение сайтов любой сложности.
Изготовление программ на заказ.
Список услуг и портфолио на сайте
www.andreygrom.ru