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

Вниз

Вывести графику на Canvas с Anti-Aliasing ом   Найти похожие ветки 

 
DVM ©   (2008-01-22 23:05) [40]

function MixerColors(FromColor, ToColor: TColor; Rate: Single): TColor;
var
 ra, rb: byte;
begin
 RA := round(Rate * 255);
 RB := 255 - RA;
 result := (((Lo(FromColor) * RA + Lo(ToColor) * RB) shr 8) or
           (((Lo(FromColor shr 8) * RA + Lo(ToColor shr 8) * RB) shr 8) shl 8) or
           (((Lo(FromColor shr 16) * RA + Lo(ToColor shr 16) * RB) shr 8) shl 16));
end;

//------------------------------------------------------------------------------

procedure SetPixel(X : Integer; Y : Integer; Alpha : Double; ACanvas: TCanvas);
VAR
 T: byte;
begin
 ACanvas.Pixels[x,y] := MixerColors(ACanvas.Pen.Color, ACanvas.Pixels[x,y], Alpha);
end;

procedure DrawWuCircle(cx : Integer; cy : Integer; R : Integer; ACanvas: TCanvas);
var
   X : Integer;
   Y : Integer;
   T : Double;
   D : Double;
   J : Integer;
   KX : Integer;
   KY : Integer;
   LastX : Integer;
begin
   x := R;
   LastX := R;
   y := 0;
   T := 0;
   J:=0;
   while J<=3 do
   begin
       KX := J mod 2*2-1;
       KY := J div 2 mod 2*2-1;
       SetPixel(KX*x+cx, KY*y+cy, 1, ACanvas);
       SetPixel(KX*y+cx, KY*x+cy, 1, ACanvas);
       Inc(J);
   end;
   while x>y do
   begin
       y := y+1;
       D := Ceil(Sqrt(R*R-y*y))-Sqrt(R*R-y*y);
       if D<T then
       begin
           x := x-1;
       end;
       if x<y then
       begin
           Break;
       end;
       if (x=y) and (LastX=x) then
       begin
           Break;
       end;
       J:=0;
       while J<=3 do
       begin
           KX := J mod 2*2-1;
           KY := J div 2 mod 2*2-1;
           SetPixel(KX*x+cx, KY*y+cy, 1-D, ACanvas);
           SetPixel(KX*y+cx, KY*x+cy, 1-D, ACanvas);
           if x-1>=y then
           begin
               SetPixel(KX*(x-1)+cx, KY*y+cy, D, ACanvas);
               SetPixel(KX*y+cx, KY*(x-1)+cy, D, ACanvas);
           end;
           Inc(J);
       end;
       T := D;
       LastX := X;
   end;  
end;


 
DVM ©   (2008-01-22 23:06) [41]

А вот то же самое (черновой вариант) со сканлайнами


procedure DrawCircle1(DC: HDC; CX, CY, R: Integer; Color: TColor);
type
RGBTripleArray = array[0..0] of TRGBTriple;
var
oldpt, pt: tpoint;

bmi: BITMAPINFO;
PBits: pointer;
MemDC: HDC;
MemBmp: HBITMAP;

w,h: integer;
X : Integer;
Y : Integer;
T : Double;
D : Double;
J : Integer;
KX : Integer;
KY : Integer;
LastX : Integer;
res: integer;

rgn: HRGN;

function MixerColors(FromColor, ToColor: TColor; Rate: Single): TColor;
var
  ra, rb: byte;
begin
  RA := round(Rate * 255);
  RB := 255 - RA;
  result := (((Lo(FromColor) * RA + Lo(ToColor) * RB) shr 8) or
            (((Lo(FromColor shr 8) * RA + Lo(ToColor shr 8) * RB) shr 8) shl 8) or
            (((Lo(FromColor shr 16) * RA + Lo(ToColor shr 16) * RB) shr 8) shl 16));
end;

function BytesPerScanline(PixelsPerScanline, BitsPerPixel, Alignment: Longint): Longint;
begin
 Dec(Alignment);
 Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and not Alignment;
 Result := Result div 8;
end;

function GetScanLine(bmi: BITMAPINFO; Bits: pointer; Row: Integer): Pointer;
var
  nRow: integer;
begin
  result := nil;
  if (Row < 0) or (Row >= bmi.bmiHeader.biHeight) then exit;
  if bmi.bmiHeader.biHeight > 0 then
    nRow := bmi.bmiHeader.biHeight - Row - 1
  else
    nRow := Row;
  Integer(Result) := Integer(Bits) + nRow * BytesPerScanline(bmi.bmiHeader.biWidth, bmi.bmiHeader.biBitCount, 32);
end;

procedure SetPixel(bmi: BITMAPINFO; Bits: pointer; X : Integer; Y : Integer;  Alpha : Double; Color: TColor);
var
  Line: ^RGBTripleArray;
  BkColor: TColor;
  NewColor: TColor;
begin
  Line := GetScanLine(bmi, Bits, Y);
  if not assigned(line) then exit;
  if (x<0) or (x>=bmi.bmiHeader.biWidth) then exit;
  BkColor := RGB(Line[x].rgbtRed, Line[x].rgbtGreen, Line[x].rgbtBlue);
  NewColor := MixerColors(COLOR, BkColor, alpha);
  Line[x].rgbtRed   := GetRValue(NewColor);
  Line[x].rgbtGreen := GetgValue(NewColor);
  Line[x].rgbtBlue  := GetbValue(NewColor);
end;

begin
  if (r <= 0)  then exit;

  W := 2 * r;
  H := 2 * r;

  ZeroMemory(@bmi, sizeof(bmi));

  bmi.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
  bmi.bmiHeader.biCompression := BI_RGB;
  bmi.bmiHeader.biBitCount := 24;
  bmi.bmiHeader.biPlanes := 1;
  bmi.bmiHeader.biWidth := w;
  bmi.bmiHeader.biHeight := h;
  bmi.bmiHeader.biSizeImage := bmi.bmiHeader.biWidth * bmi.bmiHeader.biHeight * 3;
  bmi.bmiHeader.biClrUsed :=0;
  bmi.bmiHeader.biClrImportant:=0;

  MemBmp := CreateDIBSection(DC, bmi, DIB_RGB_COLORS, pBits, 0, 0);
  MemDC := CreateCompatibleDC(DC);
  SelectObject(MemDC, MemBmp);

  BitBlt(MemDC, 0, 0, w, h, DC, 0, 0, SRCCOPY);
   x := R;
   LastX := R;
   y := 0;
   T := 0;
   J:=0;
   while J<=3 do
   begin
       KX := J mod 2*2-1;
       KY := J div 2 mod 2*2-1;
       SetPixel(BMI, PBits, KX*x+cx, KY*y+cy, 1, color);
       SetPixel(BMI, PBits,KX*y+cx, KY*x+cy, 1, color);
       Inc(J);
   end;
   while x>y do
   begin
       y := y+1;
       D := Ceil(Sqrt(R*R-y*y))-Sqrt(R*R-y*y);
       if D<T then
       begin
           x := x-1;
       end;
       if x<y then
       begin
           Break;
       end;
       if (x=y) and (LastX=x) then
       begin
           Break;
       end;
       J:=0;
       while J<=3 do
       begin
           KX := J mod 2*2-1;
           KY := J div 2 mod 2*2-1;
           SetPixel(BMI, PBits, KX * x + cx, KY * y + cy, 1-D, color);
           SetPixel(BMI, PBits, KX * y + cx, KY * x + cy, 1-D, color);
           if x-1>=y then
           begin
               SetPixel(BMI, PBits,KX*(x-1)+cx, KY*y+cy, D, color);
               SetPixel(BMI, PBits,KX*y+cx, KY*(x-1)+cy, D, color);
           end;
           Inc(J);
       end;
       T := D;
       LastX := X;
   end;
  BitBlt(DC, 0, 0, W, H, MemDC, 0, 0, SRCCOPY);
  DeleteObject(MemBmp);
  DeleteObject(MemDC);
end;



 
Sapersky   (2008-01-23 13:50) [42]

При большом кол-ве отрисовок, особенно с наложениями, буферный битмап будет просто необходим - чтобы не мерцало.
Но если так уж хочется ПРЯМО на экран - можно использовать DirectDraw с выводом на "первичку". Прямее некуда - без учёта перекрытия окон и строго в пиксельном формате рабочего стола.
Сейчас сравнил:
DrawWuCircle(400, 300, R, Canvas);
// R300 - 18 ms, R30 - 2 ms
DrawWuCircleDDraw(fd, 400, 300, R, 0);
// R300 - 1 ms, R30 - 0.15 ms
DrawCircle1 вообще не работает, GetScanLine возвращает nil.


 
DVM ©   (2008-01-23 13:56) [43]


> Sapersky   (23.01.08 13:50) [42]


> DrawWuCircleDDraw(fd, 400, 300, R, 0);

А что внутри?


> DrawCircle1 вообще не работает, GetScanLine возвращает nil.

У меня работает, но там код сырой, где то ошибка(и).


 
DVM ©   (2008-01-23 14:05) [44]


> При большом кол-ве отрисовок, особенно с наложениями, буферный
> битмап будет просто необходим - чтобы не мерцало.

Хотелось бы чтобы в функцию передавалось именно DC, как и в WinApi, но тогда буферный битмап придется создавать внутри функции, что мне не очень нравится.


 
Sapersky   (2008-01-23 15:09) [45]

А что внутри?

Там далеко не всё внутри, инициализация/финализация DDraw, например, снаружи. И полностью код трудно привести, используется много разных модулей. Если надо - позже выложу пример.
И, конечно, передаётся в функцию совсем не DC, так что внешнего сходства с GDI (если оно имеет значение) нет. Поэтому, возможно, проще всё-таки буферный битмап на всю форму (скорость сопоставимая).


 
Sapersky   (2008-01-23 16:55) [46]

http://sapersky.narod.ru/files/DrawEllipse.rar
Глубина цвета рабочего стола должна быть 32 bpp.


 
DVM ©   (2008-01-23 17:19) [47]


> Sapersky   (23.01.08 16:55) [46]

Спасибо посмотрел. Добавил ту свою функцию со сканлайном, что выше.
При маленьких размерах окружностей результаты таковы:

На основе FastDIB  - 633
На основе DD  - 1480
Моя функция со сканлайном   - 1237

При рисовании на холсте 1280*1024:

На основе FastDIB  - 3967
На основе DD  - 3877
Моя функция со сканлайном   - 9600

Т.е. DD не дает особого преимущества.


 
DVM ©   (2008-01-23 17:23) [48]

Вариант через SetPixel 10625 и 33023 соответственно.


 
Sapersky   (2008-01-23 18:37) [49]

Результаты буферных функций - с копированием буфера на экран или без? И если оно делается, то как - по моему методу, с заранее созданным буфером на всю форму (картинка с экрана в него не копируется), или как в [41], с созданием битмапа "на лету" и копированием туда-обратно?

Так, ради интереса. У меня получилось - с учётом копирования быстрее DD, без копирования - "неDD". Оно и понятно, функция одна и та же, отличается метод (и вообще наличие) передачи данных из/в видеопамять.
Т.е. DD быстрее для единичной отрисовки - драйвер, видимо, передаёт туда-обратно относительно небольшие блоки данных, не весь экран, хотя даётся команда на блокировку всей "первички". Но если рисовать нужно много, лучше использовать буферный метод - поднакопить данные в системной памяти и потом "одним движением" сбросить в видео.


 
DVM ©   (2008-01-24 11:22) [50]


> Sapersky   (23.01.08 18:37) [49]

В [47] и [48] копирование картинки с экрана в ваших функциях не производилось, а в моей производилось. Если в вашу фунцию с FastDIB добавить создание экземпляра TFastDIB на лету и копирование в него картинки с экрана, а потом вывод обратно на экран, то скорость будет примерно такая же как и в моей функции. Так и там и там используется одна и таже BitBlt и главные тормоза в ней. Пикселей перебирается не так уж много в алгоритме, поэтому сам алгоритм на скорость влияет мало, как и поиск строки в битмапе и точки в строке и вычисление ее цвета.


> У меня получилось - с учётом копирования быстрее DD, без
> копирования - "неDD".

ну собственно у меня так же.

Но вариант с DD мне все равно не подходит. Если только для удовлетворения любопытства.



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

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

Наверх




Память: 0.56 MB
Время: 0.006 c
15-1254576288
vrem
2009-10-03 17:24
2009.11.29
Windows: странные задержки


15-1254375904
VladOfMonster
2009-10-01 09:45
2009.11.29
Где найти значки для панели инструментов


1-1210408735
fender2008
2008-05-10 12:38
2009.11.29
C++ DLL


2-1255592105
zorik
2009-10-15 11:35
2009.11.29
xml edit


15-1254136426
картман
2009-09-28 15:13
2009.11.29
Паттерн наблюдатель





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский