![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вывести графику на Canvas с Anti-Aliasing'ом [D7, WinXP]
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]Ы, как много информации, буду изучать) спасибо