-
Здратвуйте Мастера! Не знает ли кто-нибудь из присутвующих как выводить на Канву графику (с Трансперентом) со сглаживанием (Анти-Алиасингом)? То есть нету ли какого либо аналога процедуры Canvas.Draw(x,y,graphic); только, со сглаживанием)
-
Аналога нет, и уточни что тебе надо рисовать? Картинку или примитивы?
-
Разве картинку возможно выводить с антиальясингом? По сабжу ничего не скажу, погугли, для С++ имеется библиотека с такими штуками.
-
Может нужна 32-х битная картинка? Тогда смотри AlphaBlend или пиши свою процедуру!
-
Выводить нужно Bitmap с Transperent:=true; (невидимая часть фиолетовым цветом закрашена) , но после вывода очень заметны грани, нельзя ли их сгладить как нить? Дело в том что я сам не понимаю принцип работы Анти Алиасинга, я нашел в инете один примерчик, но он жуууутко тормозит. А как отрисовать картинку с AlphaBlend'ом?
-
Тебе поможет GDI+. Здесь порт на delphi {******************************************************************} { GDI+ API } { } { home page : http://www.progdigy.com } { email : hgourvest@progdigy.com } { } { date : 15-02-2002 } { } { The contents of this file are used with permission, subject to } { the Mozilla Public License Version 1.1 (the "License"); you may } { not use this file except in compliance with the License. You may } { obtain a copy of the License at } { http://www.mozilla.org/MPL/MPL-1.1.html } { } { Software distributed under the License is distributed on an } { "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or } { implied. See the License for the specific language governing } { rights and limitations under the License. } { } { *****************************************************************}
-
Есть eще GDI функции BitBlt,MaskBlt,StretchBlt.
-
Если тебе нужен Анти-Алиасинг тогда используй GDI+
SetCompositingMode Method у TGPGraphic
CompositingModeSourceOver Specifies that when a color is rendered, it is blended with the background color. The blend is determined by the alpha component of the color being rendered.
CompositingModeSourceCopy Specifies that when a color is rendered, it overwrites the background color. This mode cannot be used along with TextRenderingHintClearTypeGridFit.
Graphics::SetInterpolationMode Method у TGPGraphic
Constants
InterpolationModeInvalid Used internally
InterpolationModeDefault Specifies the default interpolation mode.
InterpolationModeLowQuality Specifies a low-quality mode.
InterpolationModeHighQuality Specifies a high-quality mode.
InterpolationModeBilinear Specifies bilinear interpolation. No prefiltering is done. This mode is not suitable for shrinking an image below 50 percent of its original size.
InterpolationModeBicubic Specifies bicubic interpolation. No prefiltering is done. This mode is not suitable for shrinking an image below 25 percent of its original size.
InterpolationModeNearestNeighbor Specifies nearest-neighbor interpolation.
InterpolationModeHighQualityBilinear Specifies high-quality, bilinear interpolation. Prefiltering is performed to ensure high-quality shrinking.
InterpolationModeHighQualityBicubic Specifies high-quality, bicubic interpolation. Prefiltering is performed to ensure high-quality shrinking. This mode produces the highest quality transformed images.
Вот и все.
-
Анти-Алиас здесь Graphics::SetSmoothingMode Method
The SmoothingMode enumeration specifies the type of smoothing (antialiasing) that is applied to lines and curves. This enumeration is used by the GetSmoothingMode and SetSmoothingMode methods of the Graphics class.
Syntax
typedef enum { SmoothingModeInvalid = QualityModeInvalid, SmoothingModeDefault = QualityModeDefault, SmoothingModeHighSpeed = QualityModeLow, SmoothingModeHighQuality = QualityModeHigh, SmoothingModeNone, SmoothingModeAntiAlias8x4, SmoothingModeAntiAlias = SmoothingModeAntiAlias8x4, SmoothingModeAntiAlias8x8 } SmoothingMode;
Constants
SmoothingModeInvalid Reserved.
SmoothingModeDefault Specifies that smoothing is not applied.
SmoothingModeHighSpeed Specifies that smoothing is not applied.
SmoothingModeHighQuality Specifies that smoothing is applied using an 8 X 4 box filter.
SmoothingModeNone Specifies that smoothing is not applied.
SmoothingModeAntiAlias8x4 Specifies that smoothing is applied using an 8 X 4 box filter.
SmoothingModeAntiAlias Specifies that smoothing is applied using an 8 X 4 box filter.
SmoothingModeAntiAlias8x8 Specifies that smoothing is applied using an 8 X 8 box filter.
-
Ы, как много информации, буду изучать)
-
Ы, как много информации, буду изучать) спасибо
-
Ы, как много информации, буду изучать) спасибо
-
Ы... а может ненадо... GDI рулит!
-
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;
Работает неплохо для небольших изображений :)
-
> Ы... а может ненадо... GDI рулит!
Ы, а Анти-Алиасинг где?
-
-
в посте выше алиасинг:)
-
> [15] antonn © (12.03.07 00:22)
Судя по скриншоту там ресамплинг по квадрату 3х3. Я как-то пытался написать алгоритм алиасинга для элипса без ресамплинга, чисто из геометрических соображений :) По моему это должно быть более эффективно, но увы, так ничего и не получилось.
-
угу, 3*3, можно и больше присобачить, если догадаться как:)
-
> угу, 3*3, можно и больше присобачить, если догадаться как: > )
Может все таки GDI+?
-
> Может все таки GDI+? </> может, автор ведь не уточнил, для каких задач ему нужно (ему вообще, имхо, альфаблендинг нужен:)), иногда можно обойтись и GDI...
-
>Я как-то пытался написать алгоритм алиасинга для элипса без ресамплинга, чисто из геометрических соображений :)
Который алгоритм Wu уже давно реализован.
-
> Который алгоритм Wu уже давно реализован. Спасибо, нашел, буду думать как его переделать для толщины линии >1
-
-
> 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. Нет ли каких идей?
-
имхо только set/getpixels для канвы... вот поэтому я предпочитаю все рисовать на буферном битмапе, битмап он более "физический", чем указатель-hdc, по нему можно циклом на асме пройтись и добраться до пикселей даже быстрее сканлайна.
-
> вот поэтому я предпочитаю все рисовать на буферном битмапе, > битмап он более "физический", чем указатель-hdc, по нему > можно циклом на асме пройтись и добраться до пикселей даже > быстрее сканлайна.
Сканлайном я лишь метод обозначил. На асме или нет, но при больших размерах этот метод медленнее, чем то же самое, но через SetPixel.
-
> [24] DVM © (22.01.08 15:19) > При маленьких размерах эллипса это быстрее, чем SetPixel, > но при больших даже медленнее.
Напрасно ты так думаешь. Размер тут не причем.
-
> Напрасно ты так думаешь.
Я не думаю, я попробовал. Блиттинг с канвы и обратно при большом размере картинки занимает больше времени, чем отрисовка всех точек эллипса. через SetPixel.
Пример: окружность радиус 100 через SetPixel - 16800 микросекунд через Scanline - 3400 микросекнд
Пример: окружность радиус 500 через SetPixel - 35000 микросекунд через Scanline - 20000 микросекнд
Пример: окружность радиус 700 через SetPixel - 32000 микросекунд через Scanline - 29000 микросекнд
Для роадиуса 1000 сканлайн уже отстает
-
Функции GDI уже давно во всю используют аппаратное ускорение. Проблема с DC даже не в том, что он менее «физический», просто объект, для работы с которым DC является идентификатаром, находится в виделпамяти (при наличии доступной оной). Но при расчете эллипса вывод это дело 10-е, важнее математика. У меня есть алгоритм идеально сглаженного заполненного эллипса. У меня есть алгоритм получения (что проще) идеальной окружности с произвольной толшиной линии. Но я нигде не видел алгоритма получения идельного матиматически сглаженного эллипса с произвольной толщиной линии. Все виденые мной способы получения такого сглаживания не математическим путем основывались на 2-х алгоритмах: Так называемый AA (рисование при большем разрешении и потом билинейная фильрация к исходному разрешению), и рисование сглаженными отрезками. Я раньше пользовался первым методом. Фотошоп по все видимости тоже пользуется им, но с некоторой оптимизацией, участки, сглаживание которых не нужно, не попадают под фильтрацию. Как я понял, в GDI+ и agg используется второй. Здесь сравнительный скриншот разных моих изысков в этй области и фотошопа: http://homm86.narod.ru/files/myellipse-new.pngPS. БОЛЬШОЕ спасибо DM, в котором по видимому есть автосейв сообщений, без него это сообщение стало бы намного короче.
-
> Но при расчете эллипса вывод это дело 10-е, важнее математика. >
Математика для меня не проблема, здесь я хоть могу крутить - вертеть - придумывать. А вот сделать быстрее вывод похоже невозможно.
Алгоритмы то все у меня есть, кроме пожалуй сглаженного эллипса с произвольной толщиной линии и заливкой. Но впринципе в книгах описан - сделать можно будет.
-
> [30] DVM © (22.01.08 22:28) > Но впринципе в книгах описан - сделать можно будет.
Проверь, математические ли там алгоритмы, а не то, что я описал?
-
-
> [32] DVM © (22.01.08 22:35) > да стандартный метод Wu, основанный на вычислении площади > трапеции. > > вот результат кстати > > http://dvmuratov.narod.ru/aa.png
До такого, как я уже сказал, я и сам дошел :) Ты кажется говорил об алгоритме с произвольной толщиной линии.
-
> Ты кажется говорил об алгоритме с произвольной толщиной > линии.
Я же наоборот говорил, что кроме него все есть.
-
> homm ©
Слушай, а может рисовать вложенные эллипсы, а между ними пространство залить?
-
Хотя не, не вложатся они нормально один в другой. Чем больше сплющен эллипс, тем более различаться по толщине будет граница.
-
> [35] DVM © (22.01.08 22:44) > Слушай, а может рисовать вложенные эллипсы, а между ними > пространство залить?
Наивный :)
> [36] DVM © (22.01.08 22:50)
Угу.
-
> [28] DVM © (22.01.08 22:18) > Я не думаю, я попробовал.
Ну вот я попробовал: procedure TForm1.Button2Click(Sender: PObj);
var
BMP: PBitmap;
I, T, J, K: Integer;
DC: HDC;
C: PCanvas;
begin
T := GetTickCount;
DC := GetDC(0);
for i := 0 to 49 do begin
BMP := NewDIBBitmap(1280, 1024, pf32bit);
BitBlt(BMP.Canvas.Handle, 0, 0, 1280, 1024, DC, 0, 0, SRCCOPY);
FillMemory(BMP.DIBBits, 1280*1024*4, $80);
BMP.Draw(DC, 0, 0);
BMP.Free;
end;
ReleaseDC(0, DC);
InvalidateRect(0, nil, false);
ShowMessage(int2str(gettickCount-T));
T := GetTickCount;
DC := GetDC(0);
C := NewCanvas(DC);
for i := 0 to 0 do begin
for j := 0 to 1024-1 do
for k := 0 to 1280-1 do begin
C.Pixels[K,J] := $80808080;
end;
end;
ReleaseDC(0, DC);
C.Free;
InvalidateRect(0, nil, false);
ShowMessage(int2str(gettickCount-T));
end; Вариант1: 547 мс Вариант2: 842 мс А теперь обрати внимание, что первый вариант выполняется в цикле 50 раз, а второй только 1 :) Разница примерно в 80 раз. Уж не знаю, как ты так мерил.
-
> homm ©
Ты не забывай, что алгоритм Wu не перебирает все пикселы прямоугольника, в который вписан в эллипс. Берется сравнительно небольшое число точек. Твой пример не подходит совсем.
-
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;
-
А вот то же самое (черновой вариант) со сканлайнами
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;
-
При большом кол-ве отрисовок, особенно с наложениями, буферный битмап будет просто необходим - чтобы не мерцало. Но если так уж хочется ПРЯМО на экран - можно использовать 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.
-
> Sapersky (23.01.08 13:50) [42]
> DrawWuCircleDDraw(fd, 400, 300, R, 0);
А что внутри?
> DrawCircle1 вообще не работает, GetScanLine возвращает nil.
У меня работает, но там код сырой, где то ошибка(и).
-
> При большом кол-ве отрисовок, особенно с наложениями, буферный > битмап будет просто необходим - чтобы не мерцало.
Хотелось бы чтобы в функцию передавалось именно DC, как и в WinApi, но тогда буферный битмап придется создавать внутри функции, что мне не очень нравится.
-
А что внутри?
Там далеко не всё внутри, инициализация/финализация DDraw, например, снаружи. И полностью код трудно привести, используется много разных модулей. Если надо - позже выложу пример. И, конечно, передаётся в функцию совсем не DC, так что внешнего сходства с GDI (если оно имеет значение) нет. Поэтому, возможно, проще всё-таки буферный битмап на всю форму (скорость сопоставимая).
-
-
> Sapersky (23.01.08 16:55) [46]
Спасибо посмотрел. Добавил ту свою функцию со сканлайном, что выше. При маленьких размерах окружностей результаты таковы:
На основе FastDIB - 633 На основе DD - 1480 Моя функция со сканлайном - 1237
При рисовании на холсте 1280*1024:
На основе FastDIB - 3967 На основе DD - 3877 Моя функция со сканлайном - 9600
Т.е. DD не дает особого преимущества.
-
Вариант через SetPixel 10625 и 33023 соответственно.
-
Результаты буферных функций - с копированием буфера на экран или без? И если оно делается, то как - по моему методу, с заранее созданным буфером на всю форму (картинка с экрана в него не копируется), или как в [41], с созданием битмапа "на лету" и копированием туда-обратно?
Так, ради интереса. У меня получилось - с учётом копирования быстрее DD, без копирования - "неDD". Оно и понятно, функция одна и та же, отличается метод (и вообще наличие) передачи данных из/в видеопамять. Т.е. DD быстрее для единичной отрисовки - драйвер, видимо, передаёт туда-обратно относительно небольшие блоки данных, не весь экран, хотя даётся команда на блокировку всей "первички". Но если рисовать нужно много, лучше использовать буферный метод - поднакопить данные в системной памяти и потом "одним движением" сбросить в видео.
-
> Sapersky (23.01.08 18:37) [49]
В [47] и [48] копирование картинки с экрана в ваших функциях не производилось, а в моей производилось. Если в вашу фунцию с FastDIB добавить создание экземпляра TFastDIB на лету и копирование в него картинки с экрана, а потом вывод обратно на экран, то скорость будет примерно такая же как и в моей функции. Так и там и там используется одна и таже BitBlt и главные тормоза в ней. Пикселей перебирается не так уж много в алгоритме, поэтому сам алгоритм на скорость влияет мало, как и поиск строки в битмапе и точки в строке и вычисление ее цвета.
> У меня получилось - с учётом копирования быстрее DD, без > копирования - "неDD".
ну собственно у меня так же.
Но вариант с DD мне все равно не подходит. Если только для удовлетворения любопытства.
|