![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как, не испортив изображения, повернуть прямоугольник в TImage [D6, Win95/98, Win2k, WinXP]
LicProd © (2004-10-08 17:18:00)Спасибо всем, что "помогли" мне разобраться с вопросом о Хэндле Тулбара! Я его сам уже решил, очень даже красиво!
Так вот теперь очередной вопрос! :)
Как можно качественно повернуть изображение?
Если я поворачиваю его попиксельно или полинейно, то получаются небольшие просветы! Я не говорю про красочные рисунки!
К примеру как качественно повернуть изображение TImage в котором нарисован простой чёрный ПРЯМОУГОЛЬНИК
З.Ы.: Есть одна компанента такая Graphics32 помоему так называется, но она никак не хочет союзничать с моей программой!
Defunct (2004-10-09 15:27:00) [1]LicProd
Ты когда-нибудь работал с LCD монитором? Тут тоже самое, хочешь качественного поворота, увеличь изображение раз в 10, поверни со сглаживанием, а потом уменьши.
Чава (2004-10-09 14:57:00) [2]Белые точки на повернутом битмапе [D7, WinXP]
dimon_prorammer (07.04.04 12:54)
Почему если вертеть битмап по формулам:
x1=x0+(x-x0)cos(a)-(y-y0)sin(a)
y1=y0+(x-x0)sin(a)+(y-0)cos(a),
где a-угол, x1,y1-новые координаты, то в результате на картинке
будут белые точки? Как от них избавится?
--------------------------------------------------------------------------------
MBo © (07.04.04 13:28) [1]
Нужно делать обратный маппинг, т.е. каждой точке нового битмапа ставить в соответствие точку старого.
--------------------------------------------------------------------------------
miek © (07.04.04 18:16) [2]
Или (что проще, но очень некрасиво) каждую точку выводить два раза - туда, куда надо и в соседнюю позицию справа.
--------------------------------------------------------------------------------
MBo © (07.04.04 18:18) [3]
это ничем не проще (за исключением отслеживания границ)
--------------------------------------------------------------------------------
bolegator © (21.04.04 13:11) [4]
Простой поворот хорош только для картинок, начиная
с разрешения 500 dpi и выше. В остальных случаях
поворот будет искажать картинку. Выхода два:
1) использовать поворот с интерполяцией (линейной или нелинейной),
2) использовать антиалиасинг-поворот.
Первый способ хорош для цветных изображений и плох для черно-белых. Второй способ хорош для черно-белых.
Ну и MBo конечно прав. Хотя я думаю, что точки от этого не пропадут, но скорость поворота увеличится.
--------------------------------------------------------------------------------
Думкин © (21.04.04 13:42) [5]
> bolegator © (21.04.04 13:11) [4]
> Ну и MBo конечно прав. Хотя я думаю, что точки от этого не пропадут, но скорость поворота увеличится.
Они как раз пропадут.
LicProd (2004-10-09 10:39:00) [3]> Mihey_temporary ©
Спасибо большое за отпадную программу, но опять такисути проблемы она не решает!
Попробуй повернуть изображение на 3 градусас помощью своей программы и ты сам увидишь, что появляются нежеланные эффекты с которыми я так упорно борюсь.
Mihey_temporary (2004-10-08 21:37:00) [4]Вращение с anti-aliasing:
http://www.efg2.com/Lab/Library/Delphi/Graphics/JackSudarevRotateBitmap.txt
Fenik (2004-10-08 19:38:00) [5]> LicProd (08.10.04 18:56) [14]
Тогда только крайние пиксели смазывать.
LicProd (2004-10-08 18:56:00) [6]О! Уже какой-то есть результат с твоей функцией, но, опять таки! изображение то размывчатое получается! А не должно! Как-будто на него плюнули :)
Fenik (2004-10-08 18:44:00) [7]А попробуй просто вызвать RotateBitmap, а затем AntiAlias.
Может результат будет удовлетворительный? :)
Fenik (2004-10-08 18:43:00) [8]Вот пример сглаживания всего изображения:
procedure AntiAlias(Bitmap: TBitmap);
var x, y: Integer;
p0, p1, p2: pByteArray;
begin
for y := 1 to Bitmap.Height - 2 do begin
p1 := Bitmap.ScanLine[y];
p0 := Bitmap.ScanLine[y - 1];
p2 := Bitmap.ScanLine[y + 1];
for x := 0 to Bitmap.Width - 2 do begin
p1[x*3] := (p0[x*3] +p2[x*3] +p1[(x-1)*3] +p1[(x+1)*3]) div 4;
p1[x*3+1] := (p0[x*3+1]+p2[x*3+1]+p1[(x-1)*3+1]+p1[(x+1)*3+1]) div 4;
p1[x*3+2] := (p0[x*3+2]+p2[x*3+2]+p1[(x-1)*3+2]+p1[(x+1)*3+2]) div 4;
end;
end;
end;
Т.е. находится среднеарифметическое по каждому компоненту цвета для соседей пиксела. Найденное значение присваивается этому пикселу.
LicProd (2004-10-08 18:35:00) [9]К сожалению я их сглаживать не умею... к сожалению
Fenik (2004-10-08 18:33:00) [10]Может просто сглаживать крайние пиксели?
LicProd (2004-10-08 18:28:00) [11]> Fenik
Нет, извини, твоя процедура орегинальна, но она не решает мою проблему, к сожалению, но всё-равно спасибо!
Как бы быть точным?! Вот к примеру В ACDSee при повороте изображения оно сглаживается! но кроме альясинга там есть ещё что-то, т.к. сглаживается не векторное изображение, как собственно говоря и в моём случае.
Fenik (2004-10-08 18:28:00) [12]> LicProd (08.10.04 18:22) [7]
> И... т.е. она без искожения поворачивает?
По крайней мере без просветов :)
LicProd (2004-10-08 18:22:00) [13]> Fenik
И... т.е. она без искожения поворачивает?
Странно, работает так же как и моя, только твоя пошустрее будет
Fenik (2004-10-08 18:22:00) [14]По поводу оптимизации. Например yp*ASin и yp*ACos можно вычислять только для новой строки, а не для каждого пиксела.
Fenik (2004-10-08 18:18:00) [15]Моя старенькая процедура:
http://delphibase.endimus.ru/?action=viewfunc&topic=mediaimg&id=10186
Можно ещё немного оптимизировать.
LicProd (2004-10-08 18:14:00) [16]Запросто!
------
RTBMPR:TBitmap;
RTAngle:integer;
-----
Function TurnAngle(const tk,tn:TPoint; const Angle:integer):TPoint;
const Pi180 = pi/180;
var f:real;
begin
f := pi180*Angle;
with tk do begin
result.x := round((x - tn.x)*Cos(f)-(y - tn.y)*Sin(f) + tn.x);
result.y := round((x - tn.x)*Sin(f)+(y - tn.y)*Cos(f) + tn.y);
end;
end;
procedure PaintPixel( const p:TPOint; const color:TColor );
begin
изображение.Canvas.Pixels[p.x+50,p.y+50] := color;
end;
procedure ОКНО.FormCreate(Sender: TObject);
begin
RTbmpR:=TBitmap.Create;
end;
procedure ОКНО.PovorotChange(Sender: TObject);
var
scanx,scany:integer;
dest,scanp:TPoint;
begin
Dest := point(RTBMPR.Width div 2, RTBMPR.Height div 2 );
Canvas.Brush.Color:=clwhite;
изображение.Canvas.Rectangle(-1,-1,изображение.Width+1,изображение.Height+1);
scanpos:=Povorot.Position;
//inc(Angle);
for scanx := 1 to RTBMPR.width-1 do
for scany := 1 to RTBMPR.Height-1 do
begin
scanp := TurnAngle(point(scanx,scany),dest,scanpos);
PaintPixel(scanp,RTBMPR.Canvas.Pixels[scanx,scany]);
end;
Application.ProcessMessages;
sleep(10);
end;
не смотри такими большими глазами! просот уже я привык к этой функции, но если есть предложения, я только рад... но это не главное! Главное это вопрос ...
MBo (2004-10-08 17:58:00) [17]покажи, как ты поворачиваешь
LicProd (2004-10-08 17:51:00) [18]Это значит мне надо накладывать одно изображение на предыдущее???
Я не понимаю!
MBo (2004-10-08 17:30:00) [19]Для каждой точки нового рисунка рассчитывай соотв. координаты в старом