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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 21.06.2009, 17:12   #1
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
Печаль поворот изображения

прошу помощи, нашел два кода:
1)
Код:
var B:TBitMap;
procedure TForm2.FormCreate(Sender: TObject);
var M:TXFORM;
    a:Double;
    HDC:THandle;
begin
   B := TBitMap.Create;
   B.LoadFromFile('logo.bmp');

   hDc := image1.Canvas.Handle;
   SetGraphicsMode(hDc, GM_ADVANCED);

   M.eM11 := 1;
   M.eM12 := 0;
   M.eM21 := 0;
   M.eM22 := 1;
   M.eDx := -B.Width div 2;
   M.eDy := -B.Height div 2;
   SetWorldTransform(hDc, M);

   a := PI/6;
   fillChar(M, sizeOf(M), 0);
   M.eM11 := Cos(a);
   M.eM12 := Sin(a);
   M.eM21 := -Sin(a);
   M.eM22 := Cos(a);
   M.eDx := 0;
   M.eDy := 0;
   ModifyWorldTransform(hDc, M, MWT_RIGHTMULTIPLY);

   M.eM11 := 1;
   M.eM12 := 0;
   M.eM21 := 0;
   M.eM22 := 1;
   M.eDx := B.Width div 2;
   M.eDy := B.Height div 2;
   ModifyWorldTransform(hDc, M, MWT_RIGHTMULTIPLY);

   image1.Canvas.Draw(0, 0, b);
// или BitBlt(hDc, 0, 0, image1.Width, image1.Height, B.Canvas.Handle, 0, 0, SRCCOPY);
end;
при его использовании повернутое изображение вылазит за рамки картинки...
2)
Код:
Поворот изображения на N градусов 

Поворот проще всего осуществляется в полярных кординатах, а у нас доступны только Декартовы. Перевод осуществляется по формулам:
x=LCos(@) L=Sqrt(x**2+y**2)
y=LSin(@) @=arctg(y/x)

Для поворота достаточно добавить к a угол, на который осуществляется поворот. И новые координаты будут выглядеть так:
x'=LCos(@+t)
y'=LSin(@+t)

В принципе это все. Давайте теперь напишем функцию, которая будет переводить координаты из старых в новые.

procedure NewCoord(Var X, Y : Integer; Alpha : Double);
Var
A, L: Double;
Begin
// Вычисляем размер плеча
L:= Sqrt(X*X+Y*Y);
// Вычисляем угол поворота, но если X = 0, то на него делить нельзя, поэтому запишем угол равный PI/2
IF X = 0 THEN
IF Y < 0 THEN
A:= -PI/2
ELSE
A:= PI/2
ELSE
A:= ArcTan(Y/X);
// Скорректируем значение угла (если X < 0, то угол должен лежать в диапазоне от PI/2 до 3PI/2)
IF X < 0 THEN
A:= A+PI;
// Вычисляем новые координаты
X:= Round(L*(Cos(A+Alpha)));
Y:= Round(L*(Sin(A+Alpha)));
End;

Единственный тонкий момент - это вычисление угла. Функция ArcTan возвращает значение в диапазоне -PI/2 до PI/2. Мы должны сами корректировать это значение в зависимости от аргументов.

Теперь, когда есть функция, напишем саму процедуру поворота.
Нам понадобятся 2 объекта TImage, поле для ввода угла поворота и кнопочка, по которой будет осуществляться поворот.
Загрузим в первый объект TImage картинку в формате bmp. А в обработчике события кнопки будем писать саму процедуру.

Var
N : Double;
I, J: Integer;
XMax, YMax: Integer;
Max : Integer;
X, Y: Integer;
Xm, Ym, Xx, Yx: Integer;
L, A: Double;
begin
//Для начала преобразуем наш угол поворота в радианы
N:= -StrToFloat(Edit1.Text)*PI/180;
// Узнаем максимальные размеры изображения
XMax:= Image1.Width-1;
YMax:= Image1.Height-1;
// Получим координаты середины изображения (именно вокруг него мы и будем вращать)
X2:= XMax DIV 2;
Y2:= YMax DIV 2;
//Размеры будущего изображения
Xm:= 0; Xx:= 0; Ym:= 0; Yx:= 0;
//Определяем размер получаемого изображения
//левый верхний угол
X:= -X2; Y:= -Y2;
NewCoord(X, Y, -N);
X:= X+X2; Y:= Y+Y2;
IF X < Xm THEN
Xm:= X;
IF X > Xx THEN
Xx:= X;
IF Y < Ym THEN
Ym:= Y;
IF Y > Yx THEN
Yx:= Y;
//правый верхний угол
X:= X2; Y:= -Y2;
NewCoord(X, Y, -N);
X:= X+X2; Y:= Y+Y2;
IF X < Xm THEN
Xm:= X;
IF X > Xx THEN
Xx:= X;
IF Y < Ym THEN
Ym:= Y;
IF Y > Yx THEN
Yx:= Y;
//правый нижний угол
X:= X2; Y:= Y2;
NewCoord(X, Y, -N);
X:= X+X2; Y:= Y+Y2;
IF X < Xm THEN
Xm:= X;
IF X > Xx THEN
Xx:= X;
IF Y < Ym THEN
Ym:= Y;
IF Y > Yx THEN
Yx:= Y;
//левый нижний угол
X:= -X2; Y:= Y2;
NewCoord(X, Y, -N);
X:= X+X2; Y:= Y+Y2;
IF X < Xm THEN
Xm:= X;
IF X > Xx THEN
Xx:= X;
IF Y < Ym THEN
Ym:= Y;
IF Y > Yx THEN
Yx:= Y;
//Теперь мы знаем размеры изображения, которое получится
Image2.Width:= Xx-Xm;
Image2.Height:= Yx-Ym;
//Идем по координатам полученной картинки и вычисляем для них координаты исходного изображения
FOR I:= Xm TO Xx DO 
FOR J:= Ym TO Yx DO 
Begin
//Получаем координаты точки изображения относительно его центра
X:= I-X2;
Y:= J-Y2;
//Преобразовываем
NewCoord(X, Y, N);
//Переходим к абсолютным координатам
X:= X+X2; Y:= Y+Y2;
//Если координаты точки не попадают в исходное изображение, то рисуем простую белую точку
IF (X > Image1.Width-1) OR (Y > Image1.Height-1) OR (X < 0) OR (Y < 0) THEN
Image2.Canvas.Pixels[I-Xm, J-Ym]:= clWhite
ELSE // иначе переносим точку с изображения оригинала
Image2.Canvas.Pixels[I-Xm, J-Ym]:= Image1.Canvas.Pixels[X, Y];
End;
//Все поворот завершен
End;
в нем отрисовывается только та часть что входит в первую картинку...

можете скинуть рабочий код?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 21.06.2009, 19:53   #2
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Чтобы не выходило за границы, нужно масштабировать:
Код:
procedure TForm14.Button2Click(Sender: TObject);
var M:TXFORM;
    a:Double;
    HDC:THandle;
    b:TBitMap;
    M1, M2, k : double;
begin
   B := TBitMap.Create;
   try
      B.LoadFromFile('c:\logo.bmp');

      hDc := image1.Canvas.Handle;
      SetGraphicsMode(hDc, GM_ADVANCED);

      // translate
      fillChar(M, sizeOf(M), 0);
      M.eM11 := 1;
      M.eM12 := 0;
      M.eM21 := 0;
      M.eM22 := 1;
      M.eDx := -B.Width div 2;
      M.eDy := -B.Height div 2;
      SetWorldTransform(hDc, M);

      // scale
      fillChar(M, sizeOf(M), 0);
      M1 := Min(Image1.Width, Image1.Height);
      M2 := sqrt(sqr(b.Width) + sqr(b.Height));
      k := M1/M2;
      M.eM11 := k;
      M.eM12 := 0;
      M.eM21 := 0;
      M.eM22 := k;
      M.eDx := 0;
      M.eDy := 0;
      ModifyWorldTransform(hDc, M, MWT_RIGHTMULTIPLY);

      // rotate
      a := PI/6;
      fillChar(M, sizeOf(M), 0);
      M.eM11 := Cos(a);
      M.eM12 := Sin(a);
      M.eM21 := -Sin(a);
      M.eM22 := Cos(a);
      M.eDx := 0;
      M.eDy := 0;
      ModifyWorldTransform(hDc, M, MWT_RIGHTMULTIPLY);

      // translate
      M.eM11 := 1;
      M.eM12 := 0;
      M.eM21 := 0;
      M.eM22 := 1;
      M.eDx := Image1.Width div 2;
      M.eDy := Image1.Height div 2;
      ModifyWorldTransform(hDc, M, MWT_RIGHTMULTIPLY);

      image1.Canvas.Draw(0, 0, b);
   finally
      b.free;
   end;
end;
alexBlack вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поворот за мышью??? Kostia Gamedev - cоздание игр: Unity, OpenGL, DirectX 34 29.06.2009 15:02
поворот на плоскости gluik Общие вопросы C/C++ 2 10.04.2009 09:26
Вращение (поворот на заданный угол) векторного изображения Македонский Мультимедиа в Delphi 6 26.02.2009 21:19
Поворот изображения на заданный угол. taller07 Мультимедиа в Delphi 4 28.11.2008 14:01
Чтение изображения из базы данных, Вместо изображения - "System.Byte[]" ruelCrow Общие вопросы .NET 3 10.07.2008 23:29