Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вывести графику на Canvas с Anti-Aliasing'ом [D7, WinXP]


Страницы:   1 2 3

hypnotize ©   (2007-03-10 11:45:00) 

Здратвуйте Мастера! Не знает ли кто-нибудь из присутвующих как выводить на Канву графику (с Трансперентом) со сглаживанием (Анти-Алиасингом)? То есть нету ли какого либо аналога процедуры Canvas.Draw(x,y,graphic);только, со сглаживанием)


DVM   (2008-01-22 22:28:00) [21]


> Но при расчете эллипса вывод это дело 10-е, важнее математика.
>  

Математика для меня не проблема, здесь я хоть могу крутить - вертеть - придумывать. А вот сделать быстрее вывод похоже невозможно.

Алгоритмы то все у меня есть, кроме пожалуй сглаженного эллипса с произвольной толщиной линии и заливкой. Но впринципе в книгах описан - сделать можно будет.


homm   (2008-01-22 22:21:00) [22]

Функции GDI уже давно во всю используют аппаратное ускорение. Проблема с DC даже не в том, что он менее «физический», просто объект, для работы с которым DC является идентификатаром, находится в виделпамяти (при наличии доступной оной).

Но при расчете эллипса вывод это дело 10-е, важнее математика. У меня есть алгоритм идеально сглаженного заполненного эллипса. У меня есть алгоритм получения (что проще) идеальной окружности с произвольной толшиной линии. Но я нигде не видел алгоритма получения идельного матиматически сглаженного эллипса с произвольной толщиной линии. Все виденые мной способы получения такого сглаживания не математическим путем основывались на 2-х алгоритмах: Так называемый AA (рисование при большем разрешении и потом билинейная фильрация к исходному разрешению), и рисование сглаженными отрезками. Я раньше пользовался первым методом. Фотошоп по все видимости тоже пользуется им, но с некоторой оптимизацией, участки, сглаживание которых не нужно, не попадают под фильтрацию. Как я понял, в GDI+ и agg используется второй.

Здесь сравнительный скриншот разных моих изысков в этй области и фотошопа:
http://homm86.narod.ru/files/myellipse-new.png

PS. БОЛЬШОЕ спасибо DM, в котором по видимому есть автосейв сообщений, без него это сообщение стало бы намного короче.


DVM   (2008-01-22 22:18:00) [23]


> Напрасно ты так думаешь.

Я не думаю, я попробовал. Блиттинг с канвы и обратно при большом размере картинки занимает больше времени, чем отрисовка всех точек эллипса. через SetPixel.

Пример: окружность радиус 100
через SetPixel - 16800 микросекунд
через Scanline - 3400 микросекнд

Пример: окружность радиус 500
через SetPixel - 35000 микросекунд
через Scanline - 20000 микросекнд

Пример: окружность радиус 700
через SetPixel - 32000 микросекунд
через Scanline - 29000 микросекнд

Для роадиуса 1000 сканлайн уже отстает


homm   (2008-01-22 21:55:00) [24]

> [24] DVM ©   (22.01.08 15:19)
> При маленьких размерах эллипса это быстрее, чем SetPixel,
> но при больших даже медленнее.

Напрасно ты так думаешь. Размер тут не причем.


DVM   (2008-01-22 21:05:00) [25]


> вот поэтому я предпочитаю все рисовать на буферном битмапе,
>  битмап он более "физический", чем указатель-hdc, по нему
> можно циклом на асме пройтись и добраться до пикселей даже
> быстрее сканлайна.

Сканлайном я лишь метод обозначил. На асме или нет, но при больших размерах этот метод медленнее, чем то же самое, но через SetPixel.


antonn (work)   (2008-01-22 19:30:00) [26]

имхо только set/getpixels для канвы...
вот поэтому я предпочитаю все рисовать на буферном битмапе, битмап он более "физический", чем указатель-hdc, по нему можно циклом на асме пройтись и добраться до пикселей даже быстрее сканлайна.


DVM   (2008-01-22 15:19:00) [27]


> homm ©   (12.03.07 08:47) [17]
> > [15] antonn ©   (12.03.07 00:22)
>
> Судя по скриншоту там ресамплинг по квадрату 3х3. Я как-
> то пытался написать алгоритм алиасинга для элипса без ресамплинга,
>  чисто из геометрических соображений :) По моему это должно
> быть более эффективно, но увы, так ничего и не получилось.
>

По поводу антиалиазинга хотел посоветоваться, раз уж пост всплыл. Каков бы не был алгоритм рисования того же эллипса с антиалиазингом есть проблема вот какого рода.

Допустим нам надо сделать функцию, аналогичную функции GDI но с анталиазингом: Ellipse(DC, x1, y1, x2, y2). Как бы мы не рисовали точки, нам один фиг не пройти либо Set/GetPixel, что довольно медленно, либо надо созавать временный битмап, копировать на него точки, пробегать сканлайном по нему менять цвета точке в соответствии с алгоритмом рисования и далее битмап выводить обратно на DC. При маленьких размерах эллипса это быстрее, чем SetPixel, но при больших даже медленнее.
Вот если бы как то можно было бы добраться до отдельных пикселей DC напрямую. Как вообще работают стандартные функции рисования Windows. Они явно не пользуются для изменения цвета точки функциями SetPixel.
Нет ли каких идей?


ZEF   (2008-01-22 00:25:00) [28]

Без GDI+ можно. Смотри http://sourceforge.net/projects/graphics32


homm   (2007-03-12 23:51:00) [29]

> Который алгоритм Wu уже давно реализован.
Спасибо, нашел, буду думать как его переделать для толщины линии >1


Vovan #3   (2007-03-12 23:03:00) [30]

> Я как-то пытался написать алгоритм алиасинга для элипса без ресамплинга, чисто из геометрических соображений :)

Который алгоритм Wu уже давно реализован.


antonn   (2007-03-12 21:35:00) [31]


> Может все таки GDI+?
</>
может, автор ведь не уточнил, для каких задач ему нужно (ему вообще, имхо, альфаблендинг нужен:)), иногда можно обойтись и GDI...


oxffff   (2007-03-12 10:20:00) [32]


> угу, 3*3, можно и больше присобачить, если догадаться как:
> )


Может все таки GDI+?


antonn   (2007-03-12 09:02:00) [33]

угу, 3*3, можно и больше присобачить, если догадаться как:)


homm   (2007-03-12 08:47:00) [34]

> [15] antonn ©   (12.03.07 00:22)

Судя по скриншоту там ресамплинг по квадрату 3х3. Я как-то пытался написать алгоритм алиасинга для элипса без ресамплинга, чисто из геометрических соображений :) По моему это должно быть более эффективно, но увы, так ничего и не получилось.


antonn   (2007-03-12 00:48:00) [35]

в посте выше алиасинг:)


antonn   (2007-03-12 00:22:00) [36]

Через GDI можно и антиалиасинг, и альфаблендинг.
архивчик (471Кб, сорри, там просто картинка на форме:)) - http://antonn.ru/index.php?download=5b27b304_1173648104.rar&id=e08a9dc9592d84ccbcf9b87cb4f6b0f0
скринчик (16Кб) - http://antonn.ru/index.php?download=e8970bc8_1173648034.PNG&id=c4df3b8638bca0989914c5220e90c72a


oxffff   (2007-03-11 23:55:00) [37]


> Ы... а может ненадо... GDI рулит!


Ы, а Анти-Алиасинг где?


Степан   (2007-03-11 22:16:00) [38]


function DrawAlphaBitmap(const Canvas: TCanvas; var ColorBitmap,
 MaskBitmap: TBitmap; X, Y: Integer): Boolean;

type
 TArray = array [0..0] of Integer;

 function GetGradientColor(Color1, Color2: TColor; BlockCount, BlockIndex:
   Integer): TColor;
 var
   DifR, DifB, DifG: Integer;
   SR, SG, SB: Integer;
 begin
   SR := Color1 and $FF;
   DifR := (Color2 and $FF) - SR;
   SG := (Color1 shr 8) and $FF;
   DifG := ((Color2 shr 8) and $FF) - SG;
   SB := (Color1 shr 16) and $FF;
   DifB:=((Color2 shr 16) and $FF) - SB;
   Result := RGB((BlockIndex * DifR) div (BlockCount - 1) + SR,
     (BlockIndex * DifG) div (BlockCount - 1) + SG,
     (BlockIndex * DifB) div (BlockCount - 1) + SB);
 end;

 function GetBitsColor(var Bits: Pointer; Width, Height: Integer;
 X, Y: Cardinal): Integer;
 begin
   Result := 0;
   try
     Result := TArray(Bits^)[Integer(X) + Integer(Y) * Width];
   except
   end;
 end;

 procedure SetBitsColor(var Bits: Pointer; Width, Height: Integer;
   X, Y: Cardinal; Color: Integer);
 begin
   try
     TArray(Bits^)[Integer(X) + Integer(Y) * Width] := Color;
   except
   end;
 end;

 function GetMaxIntensity(Color: TColor): Byte;
 var
   SR, SG, SB: Byte;
 begin
   SR := Color and $FF;
   SG := (Color shr 8) and $FF;
   SB := (Color shr 16) and $FF;
   if SR > SG then
     Result := SR
   else
     Result := SG;
   if SB > Result then
     Result := SB;
 end;

var
 ColorBits: Pointer;
 MaskBits: Pointer;
 DestBitmap: HBITMAP;
 DestDC: HDC;
 DestBits: Pointer;
 BitmapInfo: TBitmapInfo;
 Color1, Color2, MaskColor: Integer;
 CX, CY: Integer;
begin
 Result := False;
 if (MaskBitmap.Width < ColorBitmap.Width) or (MaskBitmap.Width <
 ColorBitmap.Width) then
   Exit;
 GetMem(ColorBits, ColorBitmap.Width * ColorBitmap.Height *
   GetDeviceCaps(ColorBitmap.Canvas.Handle, BITSPIXEL) div 8);
 BitmapInfo.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
 BitmapInfo.bmiHeader.biWidth := ColorBitmap.Width;
 BitmapInfo.bmiHeader.biHeight := - ColorBitmap.Height;
 BitmapInfo.bmiHeader.biPlanes := 1;
 BitmapInfo.bmiHeader.biBitCount := GetDeviceCaps(ColorBitmap.Canvas.Handle,
   BITSPIXEL);
 BitmapInfo.bmiHeader.biCompression := BI_RGB;
 if GetDIBits(ColorBitmap.Canvas.Handle, ColorBitmap.Handle, 0,
 ColorBitmap.Height, ColorBits, BitmapInfo, DIB_RGB_COLORS) = 0 then
   Exit;
 GetMem(MaskBits, MaskBitmap.Width * MaskBitmap.Height *
   GetDeviceCaps(MaskBitmap.Canvas.Handle, BITSPIXEL) div 8);
 BitmapInfo.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
 BitmapInfo.bmiHeader.biWidth := MaskBitmap.Width;
 BitmapInfo.bmiHeader.biHeight := - MaskBitmap.Height;
 BitmapInfo.bmiHeader.biPlanes := 1;
 BitmapInfo.bmiHeader.biBitCount := GetDeviceCaps(MaskBitmap.Canvas.Handle,
   BITSPIXEL);
 BitmapInfo.bmiHeader.biCompression := BI_RGB;
 if GetDIBits(MaskBitmap.Canvas.Handle, MaskBitmap.Handle, 0,
   MaskBitmap.Height, MaskBits, BitmapInfo, DIB_RGB_COLORS) = 0 then
   Exit;
 BitmapInfo.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
 BitmapInfo.bmiHeader.biWidth := ColorBitmap.Width;
 BitmapInfo.bmiHeader.biHeight := - ColorBitmap.Height;
 BitmapInfo.bmiHeader.biPlanes := 1;
 BitmapInfo.bmiHeader.biBitCount := 32;
 BitmapInfo.bmiHeader.biCompression := BI_RGB;
 DestBitmap := CreateDIBSection(DIB_PAL_COLORS, BitmapInfo, DIB_RGB_COLORS,
   DestBits, 0, 0);
 DestDC := CreateCompatibleDC(Canvas.Handle);
 SelectObject(DestDC, DestBitmap);
 BitBlt(DestDC, 0, 0, ColorBitmap.Width, ColorBitmap.Height, Canvas.Handle, X,
   Y, SRCCOPY);

 for CY := 0 to ColorBitmap.Height - 1 do
   for CX := 0 to ColorBitmap.Width - 1 do begin
     Color1 := GetBitsColor(DestBits, ColorBitmap.Width, ColorBitmap.Height,
       CX, CY);
     Color2 := GetBitsColor(ColorBits, ColorBitmap.Width, ColorBitmap.Height,
       CX, CY);
     MaskColor := GetBitsColor(MaskBits, MaskBitmap.Width, MaskBitmap.Height,
       CX, CY);
     Color1 := GetGradientColor(Color1, Color2, 256, GetMaxIntensity(MaskColor));
     SetBitsColor(DestBits, ColorBitmap.Width, ColorBitmap.Height, CX, CY,
       Color1);
   end;
 BitBlt(Canvas.Handle, X, Y, ColorBitmap.Width, ColorBitmap.Height, DestDC, 0,
   0, SRCCOPY);

 DeleteObject(DestBitmap);
 DeleteObject(DestDC);
 Dispose(ColorBits);
 Dispose(MaskBits);
 Result := True;
end;


Работает неплохо для небольших изображений :)


Степан   (2007-03-11 22:11:00) [39]

Ы... а может ненадо... GDI рулит!


hypnotize   (2007-03-10 13:43:00) [40]

Ы, как много информации, буду изучать) спасибо


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо