Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.11.29;
Скачать: CL | DM;

Вниз

Вывести графику на 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 вся ветка

Текущий архив: 2009.11.29;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.013 c
4-1223712939
@!!ex
2008-10-11 12:15
2009.11.29
Получение данных с ИК порта.


15-1254378020
RWolf
2009-10-01 10:20
2009.11.29
Инструменты для ведения лога обращений к памяти


15-1254078510
DillerXX
2009-09-27 23:08
2009.11.29
подскажите как сделать avi из картинки + mp3


8-1173516347
hypnotize
2007-03-10 11:45
2009.11.29
Вывести графику на Canvas с Anti-Aliasing ом


4-1223538073
Дмитрий Белькевич
2008-10-09 11:41
2009.11.29
Асинхронный ввод двух бит через ком порт