Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.02.2015, 19:39   #1
grominfo
Форумчанин
 
Аватар для grominfo
 
Регистрация: 30.05.2011
Сообщений: 651
По умолчанию Переполнение стека при вращении PNG

Всем привет!

Есть такая функция (стырил на одном форуме)

Код:
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
grominfo вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Переполнение стека при рекурсии (в бинарном дереве) LordJohn Помощь студентам 0 11.11.2012 18:28
Переполнение стека DeKot Общие вопросы Delphi 4 02.02.2012 01:28
переполнение стека при создании сообщений Miller-1981 Общие вопросы C/C++ 0 24.01.2011 10:49
при открытии Recordset'a возникает переполнение стека MrGB Microsoft Office Access 3 16.11.2010 20:15
Переполнение стека при передачи функциям массивов большой размерности graphoman Общие вопросы Delphi 2 07.01.2008 21:47