Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Вниз

Повернуть изображение в 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 вся ветка

Форум: "Media";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.035 c
1-1083572538
magician
2004-05-03 12:22
2004.05.16
Как просмотреть содержимое DLL.


14-1082530451
SergLight
2004-04-21 10:54
2004.05.16
Что выбрать Indy или ICS (Internet Component Suite)?


3-1082112658
Dimbas
2004-04-16 14:50
2004.05.16
Проблема открытия базы с CD


4-1079608010
andri
2004-03-18 14:06
2004.05.16
Как запустить файл от имени другого пользователя (NT)


3-1082308600
linx
2004-04-18 21:16
2004.05.16
Не получается настроить права в InterBase.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский