Модераторы: Snowy, Alexeis, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как повернуть Image на определенный угол 
:(
    Опции темы
falcon39
Дата 15.10.2004, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 21.6.2004

Репутация: нет
Всего: 0



Как повернуть Image на определенный угол. (например 10 градусов)
--------------------
PM MAIL   Вверх
p0s0l
Дата 16.10.2004, 00:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 16
Всего: 112



2 примера из DRKB:
Код
Как повернуть Bitmap на любой угол
Previous  Top  Next  

Const PixelMax = 32768;
Type
 pPixelArray  =  ^TPixelArray;
 TPixelArray  =  Array[0..PixelMax-1] Of TRGBTriple;

Procedure RotateBitmap_ads(
 SourceBitmap   : TBitmap;
 out DestBitmap : TBitmap;
 Center         : TPoint;
 Angle          : Double);
Var
 cosRadians          : Double;
 inX                 : Integer;
 inXOriginal         : Integer;
 inXPrime            : Integer;
 inXPrimeRotated     : Integer;
 inY                 : Integer;
 inYOriginal         : Integer;
 inYPrime            : Integer;
 inYPrimeRotated     : Integer;
 OriginalRow         : pPixelArray;
 Radians             : Double;
 RotatedRow          : pPixelArray;
 sinRadians          : Double;
begin
 DestBitmap.Width    := SourceBitmap.Width;
 DestBitmap.Height   := SourceBitmap.Height;
 DestBitmap.PixelFormat := pf24bit;
 Radians             := -(Angle) * PI / 180;
 sinRadians          := Sin(Radians);
 cosRadians          := Cos(Radians);
 For inX             := DestBitmap.Height-1 Downto 0 Do
 Begin
   RotatedRow        := DestBitmap.Scanline[inX];
   inXPrime          := 2*(inX - Center.y) + 1;
   For inY           := DestBitmap.Width-1 Downto 0 Do
   Begin
     inYPrime        := 2*(inY - Center.x) + 1;
     inYPrimeRotated := Round(inYPrime * CosRadians - inXPrime * sinRadians);
     inXPrimeRotated := Round(inYPrime * sinRadians + inXPrime * cosRadians);
     inYOriginal     := (inYPrimeRotated - 1) Div 2 + Center.x;
     inXOriginal     := (inXPrimeRotated - 1) Div 2 + Center.y;
     If
       (inYOriginal  >= 0)                    And
       (inYOriginal  <= SourceBitmap.Width-1) And
       (inXOriginal  >= 0)                    And
       (inXOriginal  <= SourceBitmap.Height-1)
     Then
     Begin
       OriginalRow   := SourceBitmap.Scanline[inXOriginal];
       RotatedRow[inY]  := OriginalRow[inYOriginal]
     End
     Else
     Begin
       RotatedRow[inY].rgbtBlue  := 255;
       RotatedRow[inY].rgbtGreen := 0;
       RotatedRow[inY].rgbtRed   := 0
     End;
   End;
 End;
End;

{Usage:}
procedure TForm1.Button1Click(Sender: TObject);
Var
 Center : TPoint;
 Bitmap : TBitmap;
begin
 Bitmap := TBitmap.Create;
 Try
   Center.y := (Image.Height  div 2)+20;
   Center.x := (Image.Width div 2)+0;
   RotateBitmap_ads(
     Image.Picture.Bitmap,  
     Bitmap,  
     Center,  
     Angle);
   Angle := Angle + 15;
   Image2.Picture.Bitmap.Assign(Bitmap);
 Finally
   Bitmap.Free;
 End;
end;

Взято с Исходников.ru http://www.sources.ru


--------------------------------------------------------------------------------

procedure RotateBitmap(Bitmap: TBitmap; Angle: Double; BackColor: TColor);
type TRGB = record
      B, G, R: Byte;
    end;
    pRGB = ^TRGB;
    pByteArray = ^TByteArray;
    TByteArray = array[0..32767] of Byte;
    TRectList = array [1..4] of TPoint;

var x, y, W, H, v1, v2: Integer;
   Dest, Src: pRGB;
   VertArray: array of pByteArray;
   Bmp: TBitmap;

 procedure SinCos(AngleRad: Double; var ASin, ACos: Double);
 begin
   ASin := Sin(AngleRad);
   ACos := Cos(AngleRad);
 end;

 function RotateRect(const Rect: TRect; const Center: TPoint; Angle: Double): TRectList;
 var DX, DY: Integer;
     SinAng, CosAng: Double;
   function RotPoint(PX, PY: Integer): TPoint;
   begin
     DX := PX - Center.x;
     DY := PY - Center.y;
     Result.x := Center.x + Round(DX * CosAng - DY * SinAng);
     Result.y := Center.y + Round(DX * SinAng + DY * CosAng);
   end;
 begin
   SinCos(Angle * (Pi / 180), SinAng, CosAng);
   Result[1] := RotPoint(Rect.Left, Rect.Top);
   Result[2] := RotPoint(Rect.Right, Rect.Top);
   Result[3] := RotPoint(Rect.Right, Rect.Bottom);
   Result[4] := RotPoint(Rect.Left, Rect.Bottom);
 end;

 function Min(A, B: Integer): Integer;
 begin
   if A < B then Result := A
            else Result := B;
 end;

 function Max(A, B: Integer): Integer;
 begin
   if A > B then Result := A
            else Result := B;
 end;

 function GetRLLimit(const RL: TRectList): TRect;
 begin
   Result.Left := Min(Min(RL[1].x, RL[2].x), Min(RL[3].x, RL[4].x));
   Result.Top := Min(Min(RL[1].y, RL[2].y), Min(RL[3].y, RL[4].y));
   Result.Right := Max(Max(RL[1].x, RL[2].x), Max(RL[3].x, RL[4].x));
   Result.Bottom := Max(Max(RL[1].y, RL[2].y), Max(RL[3].y, RL[4].y));
 end;

 procedure Rotate;
 var x, y, xr, yr, yp: Integer;
     ACos, ASin: Double;
     Lim: TRect;
 begin
   W := Bmp.Width;
   H := Bmp.Height;
   SinCos(-Angle * Pi/180, ASin, ACos);
   Lim := GetRLLimit(RotateRect(Rect(0, 0, Bmp.Width, Bmp.Height), Point(0, 0), Angle));
   Bitmap.Width := Lim.Right - Lim.Left;
   Bitmap.Height := Lim.Bottom - Lim.Top;
   Bitmap.Canvas.Brush.Color := BackColor;
   Bitmap.Canvas.FillRect(Rect(0, 0, Bitmap.Width, Bitmap.Height));
   for y := 0 to Bitmap.Height - 1 do begin
     Dest := Bitmap.ScanLine[y];
     yp := y + Lim.Top;
     for x := 0 to Bitmap.Width - 1 do begin
       xr := Round(((x + Lim.Left) * ACos) - (yp * ASin));
       yr := Round(((x + Lim.Left) * ASin) + (yp * ACos));
       if (xr > -1) and (xr < W) and (yr > -1) and (yr < H) then begin
         Src := Bmp.ScanLine[yr];
         Inc(Src, xr);
         Dest^ := Src^;
       end;
       Inc(Dest);
     end;
   end;
 end;

begin
 Bitmap.PixelFormat := pf24Bit;
 Bmp := TBitmap.Create;
 try
   Bmp.Assign(Bitmap);
   W := Bitmap.Width - 1;
   H := Bitmap.Height - 1;
   if Frac(Angle) <> 0.0
     then Rotate
     else
   case Trunc(Angle) of
     -360, 0, 360, 720: Exit;
     90, 270: begin
       Bitmap.Width := H + 1;
       Bitmap.Height := W + 1;
       SetLength(VertArray, H + 1);
       v1 := 0;
       v2 := 0;
       if Angle = 90.0 then v1 := H
                       else v2 := W;
       for y := 0 to H do VertArray[y] := Bmp.ScanLine[Abs(v1 - y)];
       for x := 0 to W do begin
         Dest := Bitmap.ScanLine[x];
         for y := 0 to H do begin
           v1 := Abs(v2 - x)*3;
           with Dest^ do begin
             B := VertArray[y, v1];
             G := VertArray[y, v1+1];
             R := VertArray[y, v1+2];
           end;
           Inc(Dest);
         end;
       end
     end;
     180: begin
       for y := 0 to H do begin
         Dest := Bitmap.ScanLine[y];
         Src := Bmp.ScanLine[H - y];
         Inc(Src, W);
         for x := 0 to W do begin
           Dest^ := Src^;
           Dec(Src);
           Inc(Dest);
         end;
       end;
     end;
     else Rotate;
   end;
 finally
   Bmp.Free;
 end;
end;

// Использование
RotateBitmap(Image1.Picture.Bitmap, StrToInt(Edit1.Text), clWhite);

Взято из http://delphiworld.narod.ru
Если не разберешься как юзать (мало ли) - спрашивай smile.gif



--------------------
С уважением, г-н Посол.
PM   Вверх
maxim1000
Дата 16.10.2004, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 1
Всего: 110



в WindowsAPI есть такая функция SetWorldTransform - с помощью нее можно задать любое афинное преобразование, которое будет автоматически накладываться на выводимую информацию

что касается алгоритма поворота, есть еще один:
поворот представляется в виде трех "скашиваний", т.е. преобразований типа: (x,y)->(x,y+ax) или (x+by,y) (a и b подбираются так, чтобы композиция давала нужную матрицу преобразования)
плюс заключается в том, что если кучу раз делать вращение туда-обратно, то рисунок не исказится, а кроме того все точки останутся - просто поменяют местоположение


--------------------
qqq
PM WWW   Вверх
DonPager
Дата 16.10.2004, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Колдырь
**


Профиль
Группа: Участник
Сообщений: 327
Регистрация: 28.3.2003
Где: Воронеж

Репутация: нет
Всего: 2



есть вариант - использовать компонент с таким свойством (например из Raize) smile.gif
... но если хочется всё самому.... см. выше


--------------------
кодер + лодырь = колдырь
PM MAIL ICQ Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.0541 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.