Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.16;
Скачать: CL | DM;

Вниз

Повернуть изображение в TImage на 90 градусов   Найти похожие ветки 

 
AlexV ©   (2004-02-19 11:25) [0]

Всем привет.

Вопрос прост: Как можно повернуть изображение в TImage на 90 градусов ?
Есть ли какие-то станд.средства или ф-я WinAPI ?
Или придется только вручную попиксельно переносить в другую канву ?

Заранее благодарен, AlexV.


 
alless ©   (2004-02-19 12:24) [1]

не мое:)

Сделайте наложение пиксель-на-пиксель из исходного изображение на целевой (используя свойство Canvas.Pixels). Для каждого пикселя осуществите преобразование полярных координат, добавьте компенсирующий угол к полярной координате, затем спозиционируйте это обратно на координаты прямоугольника, и разместите пиксель с новыми координатами на целевом изображении. Также вы можете добавлять какой-либо псевдослучайный пиксель через определенное их количество, если хотите задать какую-то точность вашей операции.

Для преобразования X- и Y-координат объявлены следующие переменные:

X,Y    = старые координаты пикселя
X1,Y1  = новые координаты пикселя
T      = угол вращения (в радианах)

R, A   - промежуточные величины, представляющие собой полярные координаты

R = Sqrt(Sqr(X) + Sqr(Y));

A = Arctan(Y/X);

X1 = R * Cos(A+T);

Y1 = R * Sin(A+T);
Я отдаю себе отчет, что это не оптимальное решение, поэтому, если вы найдете еще какое-либо решение, дайте мне знать. В действительности мой метод работает, но делает это очень медленно.

Создайте наложение пиксель-на-пиксель исходного изображение на целевое (используя свойство Canvas.Pixels).
...это хорошее начало, но я думаю другой способ будет немного лучшим. Создайте наложение пиксель-на-пиксель целевого изображения на исходное так, чтобы нам было нужно вычислять откуда брать нужные пиксели, а не думать над тем, куда их нужно поместить.

Для начала вот мой вариант формулы вращения:

x, y = координаты в целевом изображении
t = угол
u, v = координаты в исходном изображении

x = u * cos(t) - v * sin(t)
y = v * cos(t) + u * sin(t)
Теперь, если я захочу решить эти уравнения и вычислить u и v (привести их к правой части уравнения), то формулы будут выглядеть следующим образом (без гарантии, по этой причине я и включил исходные уравнения!):
     x * cos(t) + y
u = --------------------
   sqr(cos(t)) + sin(t)

v =   y * cos(t) - x
   --------------------
   sqr(cos(t)) + sin(t)
Так, подразумевая, что вы уже знаете угол вращения, можно вычислить константы cos(t) и 1/sqr(cos(t))+sin(t) непосредственно перед самим циклом; это может выглядеть примерно так (приблизительный код):

--------------------------------------------------------------------------------
   ct := cos(t);
ccst := 1/sqr(cos(t))+sin(t);
for x := 0 to width do

for y := 0 to height do
dest.pixels[x,y] := source.pixels[Round((x * ct + y) * ccst),
Round((y * ct - x) * ccst)];

Если вы хотите ускорить этот процесс, и при этом волнуетесь за накопление ошибки округления, то вам следует обратить внимание на используемую нами технологию: мы перемещаем за один раз один пиксель, дистанция между пикселями равна u, v содержит константу, определяющую колонку с перемещаемым пикселем. Я использую расчитанные выше переменные как рычаг с коротким плечом (с вычисленной длиной и точкой приложения). Просто поместите в (x,y) = (1,0) и (x,y) = (0,1) и уравнение, приведенное выше:

--------------------------------------------------------------------------------
   duCol := ct * ccst;
dvCol := -ccst;

duRow := ccst;
dvRow := ct * ccst;

uStart := 0;
vStart := 0;

for x := 0 to width do

begin
u := uStart;
v := vStart;
for y := 0 to height do
begin
dest.pixels[x,y] := source.pixels[Round(u), Round(v)];
u := u + rowdu;
v := v + rowdv;
end;
uStart := uStart + duCol;
vStart := vStart + dvCol;
end;

Приведенный выше код можно использовать "как есть", и я не даю никаких гарантий отностительно его использования!

Если вы в душе испытатель, и хотите попробовать вращение вокруг произвольной точки, попробуйте поиграться со значенияим u и v:

Xp, Yp (X-sub-p, Y-sub-p) точка оси вращения, другие константы определены выше
x = Xp + (u - Xp) * cos(t) - (y - Yp) * sin(t)
y = Yp + (y - Yp) * cos(t) - (x - Xp) * sin(t)
Оригинальные уравнения:
 x = u * cos(t) - v * sin(t)
 y = v * cos(t) + u * sin(t)
верны, но когда я решаю их для u и v, я получаю это:
     x * cos(t) + y * sin(t)
 u = -----------------------
    sqr(cos(t)) + sqr(sin(t))

     y * cos(t) - x * sin(t)
 v = ------------------------
     sqr(cos(t)) + sqr(sin(t))
[


 
ALEIIIKA ©   (2004-02-19 12:51) [2]

Полный алес!!!
Вопрос был как повернуть на 90 градусов, а не туда сюда потом обратно.
из всего выше сказанного можно выжать одно:
X,Y : старые координаты пикселя;
X1,Y1 :  новые координаты пикселя;
Alpha :  угол поворота изображения;

uses
 Math;
var
 SinA, CosA : Extended;
begin
 SinCos(Alpha,SinA, CosA);
 X1 = X * CosA + Y * SinA;
 Y1 = X * SinA + Y * CosA;
end;

причем самый быстрый вариант
отсюда можно написать для поворота на 90:

uses
 Math;
var
 SinA, CosA : Extended;
begin
 SinA := 1;
 CosA := 0;
 X1 = X * CosA + Y * SinA;
 Y1 = X * SinA + Y * CosA;
//-------------------------
 X1 = Y;
 Y1 = X;
//-------------------------
end;


 
AlexV ©   (2004-02-19 13:20) [3]

Спасибо.
Попробую


 
KilkennyCat ©   (2004-02-19 18:17) [4]

если не ошибаюсь, самое простое решение - использовать DrawStrecth или как она там...
при задании конечного ректа повернутыми координатами получиться исходный вариант. а попиксельно быстро не будет, лучше тогда скайнлайн использовать.


 
MBo ©   (2004-02-19 18:38) [5]

>KilkennyCat
StretchDraw на 90 не повернет - только зеркально может.
PlgBlt умеет, но только на NT-системах.

Быстрая работа с пикселами - см. в Статьях "Поставить точку..."


 
KilkennyCat ©   (2004-02-21 11:33) [6]

> MBo

да, верно... что-то я тормознул, как обычно.



Страницы: 1 вся ветка

Текущий архив: 2004.05.16;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.024 c
14-1083132708
Тимохов
2004-04-28 10:11
2004.05.16
Режим пользователя и режим ядра.


14-1082787568
gn
2004-04-24 10:19
2004.05.16
Новая технология защиты кредитных карт с распознаванием голоса


1-1082870526
Schummi
2004-04-25 09:22
2004.05.16
Быстрое заполнение AdvStringGrid


1-1083207568
Артем К.
2004-04-29 06:59
2004.05.16
Как создать ярлык программы на рабочем столе?


4-1080544622
Akvilon
2004-03-29 11:17
2004.05.16
окно выбора папки