Anti-aliasing para LineTo
Olá!
Alguem tem alguma função que traceja um LineTo em um canvas com Anti-aliasing (sem rebarba)?
Obrigado!
Alguem tem alguma função que traceja um LineTo em um canvas com Anti-aliasing (sem rebarba)?
Obrigado!
Nildo
Curtidas 0
Respostas
Cebikyn
10/05/2004
[b:57810accca]Depois[/b:57810accca] do LineTo e qualquer outro método que vc for usar, vc pode usar esta função (que irá colocar anti-aliasing em tudo que já estiver no Image):
Em que Percent é quanto de anti-aliasing vc quer.
procedure Antialiasing(Image: TImage; Percent: Integer); type TRGBTripleArray = array[0..32767] of TRGBTriple; PRGBTripleArray = ^TRGBTripleArray; var SL, SL2: PRGBTripleArray; l, m, p: Integer; R, G, B: TColor; R1, R2, G1, G2, B1, B2: Byte; begin with Image.Canvas do begin Brush.Style := bsClear; Pixels[1, 1] := Pixels[1, 1]; for l := 0 to Image.Height - 1 do begin SL := Image.Picture.Bitmap.ScanLine[l]; for p := 1 to Image.Width - 1 do begin R1 := SL[p].rgbtRed; G1 := SL[p].rgbtGreen; B1 := SL[p].rgbtBlue; // Left if (p < 1) then m := Image.Width else m := p - 1; R2 := SL[m].rgbtRed; G2 := SL[m].rgbtGreen; B2 := SL[m].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL[m].rgbtRed := R; SL[m].rgbtGreen := G; SL[m].rgbtBlue := B; end; //Right if (p > Image.Width - 2) then m := 0 else m := p + 1; R2 := SL[m].rgbtRed; G2 := SL[m].rgbtGreen; B2 := SL[m].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL[m].rgbtRed := R; SL[m].rgbtGreen := G; SL[m].rgbtBlue := B; end; if (l < 1) then m := Image.Height - 1 else m := l - 1; //Over SL2 := Image.Picture.Bitmap.ScanLine[m]; R2 := SL2[p].rgbtRed; G2 := SL2[p].rgbtGreen; B2 := SL2[p].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL2[p].rgbtRed := R; SL2[p].rgbtGreen := G; SL2[p].rgbtBlue := B; end; if (l > Image.Height - 2) then m := 0 else m := l + 1; //Under SL2 := Image.Picture.Bitmap.ScanLine[m]; R2 := SL2[p].rgbtRed; G2 := SL2[p].rgbtGreen; B2 := SL2[p].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL2[p].rgbtRed := R; SL2[p].rgbtGreen := G; SL2[p].rgbtBlue := B; end; end; end; end; end;
Em que Percent é quanto de anti-aliasing vc quer.
GOSTEI 0
Nildo
10/05/2004
Obrigado Cebikyn, mas...
Do canvas inteiro somente esta linha pode ficar anti-aliasinged. É um grafico que eu estou fazendo em um canvas, de velocidade atingida, e só somente estas linhas devem ficar com anti-aliasign. Será que nao tem como?
Do canvas inteiro somente esta linha pode ficar anti-aliasinged. É um grafico que eu estou fazendo em um canvas, de velocidade atingida, e só somente estas linhas devem ficar com anti-aliasign. Será que nao tem como?
GOSTEI 0
Cebikyn
10/05/2004
Se for viável:
Faz a(s) linha(s) -> antialiazing -> faz o resto do gráfico
Se não for:
Desenha a linha pixel a pixel (usando um for-to-do c/ a equação da reta que pode ser obtida facilmente a partir dos pontos que seriam passados pro LineTo), combinando os pixels ao redor do pixel principal com o fundo (vai demorar bem mais, mas vai funcionar).
Faz a(s) linha(s) -> antialiazing -> faz o resto do gráfico
Se não for:
Desenha a linha pixel a pixel (usando um for-to-do c/ a equação da reta que pode ser obtida facilmente a partir dos pontos que seriam passados pro LineTo), combinando os pixels ao redor do pixel principal com o fundo (vai demorar bem mais, mas vai funcionar).
GOSTEI 0
Nildo
10/05/2004
Bom vou fazer esta função e posto aqui quando acabar.
[quote:10f0733ed3=´C:>´]combinando os pixels ao redor do pixel principal com o fundo[/quote:10f0733ed3]
Qual seria o algoritmo para fazer esta combinação, com 50¬ de agregação? Digo... se o Fundo eh Branco, e a linha eh Preta, este pixel deveria ficar Cinza (50¬ branca e 50¬ preta). Qual seria o algoritmo para isso?
[quote:10f0733ed3=´C:>´]combinando os pixels ao redor do pixel principal com o fundo[/quote:10f0733ed3]
Qual seria o algoritmo para fazer esta combinação, com 50¬ de agregação? Digo... se o Fundo eh Branco, e a linha eh Preta, este pixel deveria ficar Cinza (50¬ branca e 50¬ preta). Qual seria o algoritmo para isso?
GOSTEI 0
Marcelo Saviski
10/05/2004
De uma olhada nisso aqui, http://www.swissdelphicenter.ch/en/showcode.php?id=1812
achei esse site num dos tópicos do cebikyn
achei esse site num dos tópicos do cebikyn
GOSTEI 0
Fórum Vini
10/05/2004
Ae nildo, foi mal pela demora...
Eu procurei lah em casa mas ainda naum achei.. mas pelo que vi ela naum vai resolver o seu problema, pois funciona da mesma forma que a do cebikyn..
No algoritmo que eu tenho, a imagem eh ampliada três vezes(com StretchDraw mesmo..) e depois ele tirava a média das cores de cada pixel...(isso eh o que eu lembro, mas faz mais coisas tbm..)
T+,
Vinicius;
Eu procurei lah em casa mas ainda naum achei.. mas pelo que vi ela naum vai resolver o seu problema, pois funciona da mesma forma que a do cebikyn..
Qual seria o algoritmo para fazer esta combinação, com 50¬ de agregação? Digo... se o Fundo eh Branco, e a linha eh Preta, este pixel deveria ficar Cinza (50¬ branca e 50¬ preta). Qual seria o algoritmo para isso?
No algoritmo que eu tenho, a imagem eh ampliada três vezes(com StretchDraw mesmo..) e depois ele tirava a média das cores de cada pixel...(isso eh o que eu lembro, mas faz mais coisas tbm..)
T+,
Vinicius;
GOSTEI 0
Nildo
10/05/2004
Firmeza Vini nao se preocupa não! Isso é só implementação, não necessidade aqui!
Mesmo assim obrigado mesmo!
Mesmo assim obrigado mesmo!
GOSTEI 0
Nildo
10/05/2004
[quote:1df62fe198=´Marcelo Saviski´]De uma olhada nisso aqui, http://www.swissdelphicenter.ch/en/showcode.php?id=1812
achei esse site num dos tópicos do cebikyn[/quote:1df62fe198]
Valew marcelo, parece que é exatamente o que eu quero!
Mas parece que nao funcionou...
Eu chamo da seguinte maneira:
WuLine( Image1.Picture.Bitmap, Point( 10, 10 ), Point( 100, 100 ), clRed );
Só que ele apaga todo meu bitmap...
achei esse site num dos tópicos do cebikyn[/quote:1df62fe198]
Valew marcelo, parece que é exatamente o que eu quero!
Mas parece que nao funcionou...
Eu chamo da seguinte maneira:
WuLine( Image1.Picture.Bitmap, Point( 10, 10 ), Point( 100, 100 ), clRed );
Só que ele apaga todo meu bitmap...
GOSTEI 0
Nildo
10/05/2004
Alias, nao apaga nao. Se eu traco qualquer reta na diagonal ele nao funciona
GOSTEI 0
Marcelo Saviski
10/05/2004
bom,vamos por partes
Garante que você seta um tamanho para o bitmap antes?
[color=green:bdd3b12767]Image.Picture.Bitmap.Width := X;
Image.Picture.Bitmap.Heught := Y;[/color:bdd3b12767]
Garante que você seta um tamanho para o bitmap antes?
[color=green:bdd3b12767]Image.Picture.Bitmap.Width := X;
Image.Picture.Bitmap.Heught := Y;[/color:bdd3b12767]
GOSTEI 0
Marcelo Saviski
10/05/2004
Alias, nao apaga nao. Se eu traco qualquer reta na diagonal ele nao funciona
Deve ter a ver com essa parte:
deltax := abs(x2 - x1); deltay := abs(y2 - y1); if (deltax = 0) or (deltay = 0) then begin // straight lines ABitmap.Canvas.Pen.Color := AColor; ABitmap.Canvas.MoveTo(x1, y1); ABitmap.Canvas.LineTo(x2, y2); exit; end;
Talvez o seu pen.Style esteja em algo diferente....
GOSTEI 0
Nildo
10/05/2004
[quote:ecaa483da1=´Marcelo Saviski´]Garante que você seta um tamanho para o bitmap antes?
[color=green:ecaa483da1]Image.Picture.Bitmap.Width := X;
Image.Picture.Bitmap.Heught := Y;[/color:ecaa483da1][/quote:ecaa483da1]
Eu já carrego um bitmap dentro dele. Isso já auto-atribue estas propriedades
[color=green:ecaa483da1]Image.Picture.Bitmap.Width := X;
Image.Picture.Bitmap.Heught := Y;[/color:ecaa483da1][/quote:ecaa483da1]
Eu já carrego um bitmap dentro dele. Isso já auto-atribue estas propriedades
GOSTEI 0
Beppe
10/05/2004
Uma pergunta boba?
Tem certeza de que é um bitmap, não um jpeg?
Tem certeza de que é um bitmap, não um jpeg?
GOSTEI 0
Nildo
10/05/2004
Quando a imagem sumia, era um JPG :oops: Mas o fato de nao traçar era realmente um BMP. Mas eu achei uma função que faz isso, e então eu adaptei pro meu componente que herda de um TQrImage.
procedure TQrGrafico.LineTo2(x, y: Single);
function CrossFadeColor(FromColor, ToColor: TColor; Rate: Single): TColor;
var
r, g, b: byte;
begin
r := Round(GetRValue(FromColor) * Rate + GetRValue(ToColor) * (1 - Rate));
g := Round(GetGValue(FromColor) * Rate + GetGValue(ToColor) * (1 - Rate));
b := Round(GetBValue(FromColor) * Rate + GetBValue(ToColor) * (1 - Rate));
Result := RGB(r, g, b);
end;
procedure hpixel(x: single; y: integer);
var
FadeRate: single;
begin
FadeRate := x - trunc(x);
with canvas do
begin
pixels[trunc(x), y] := CrossFadeColor(Canvas.Pen.Color, Pixels[Trunc(x), y], 1 - FadeRate);
pixels[trunc(x) + 1, y] := CrossFadeColor(Canvas.Pen.Color, Pixels[Trunc(x) + 1, y],
FadeRate);
end;
end;
procedure vpixel(x: integer; y: single);
var
FadeRate: single;
begin
FadeRate := y - trunc(y);
with canvas do
begin
pixels[x, trunc(y)] := CrossFadeColor(Canvas.Pen.Color, Pixels[x, Trunc(y)], 1 - FadeRate);
pixels[x, trunc(y) + 1] := CrossFadeColor(Canvas.Pen.Color, Pixels[x, Trunc(y) + 1],
FadeRate);
end;
end;
var
i: integer;
ly, lx, currentx, currenty, deltax, deltay, l, skipl: single;
x1,x2,y1,y2: Single;
begin
x1 := canvas.PenPos.X;
x2 := X;
y1 := canvas.PenPos.Y;
y2 := Y;
if (x1 <> x2) or (y1 <> y2) then
begin
currentx := x1;
currenty := y1;
lx := abs(x2 - x1);
ly := abs(y2 - y1);
if lx > ly then
begin
l := trunc(lx);
deltay := (y2 - y1) / l;
if x1 > x2 then
begin
deltax := -1;
skipl := (currentx - trunc(currentx));
end
else
begin
deltax := 1;
skipl := 1 - (currentx - trunc(currentx));
end;
end
else
begin
l := trunc(ly);
deltax := (x2 - x1) / l;
if y1 > y2 then
begin
deltay := -1;
skipl := (currenty - trunc(currenty));
end
else
begin
deltay := 1;
skipl := 1 - (currenty - trunc(currenty));
end;
end;
currentx := currentx + deltax * skipl;
currenty := currenty + deltay * skipl; {}
for i := 1 to trunc(l) do
begin
if lx > ly then
vpixel(trunc(currentx), currenty)
else
hpixel(currentx, trunc(currenty));
currentx := currentx + deltax;
currenty := currenty + deltay;
end;
end;
end;
GOSTEI 0
Beppe
10/05/2004
Como está de velocidade? Não se se ficou lento pra ti, mas pode ser bem melhor...eu tb tinha escrito uma função q calculava pontos de reta, usando doubles(ao menos, use Double´s, são mais rápidos q Single´s). Achei uma implementação q portei para Delphi, sem comparação, bem melhor...Mas nem é necessário tanto, a função LineDDA da GDI faz isto, e tão eficiente quato a q portei. É só passar um callback pra ela, chamada para cada ponto da reta. Mas veja se não vai complicar sua implementação, pois vc vai ter q remover o código q esta inline na função de calcula, pode ser meio chato...só faça isso se quiser mais eficiência...
GOSTEI 0
Nildo
10/05/2004
Valew Beppe, mas processamento não é problema aqui. As máquinas que usam o sistema normalmente são máquinas foderosas. E eu também não posso te afirmar a velocidade, pois aqui no trampo estou com um P4 2.8ghz e 512 de ram. Então o processo é imediato, isso que eu traço mais de 5 mil retas com esta função e o resultado é imediato
GOSTEI 0
Beppe
10/05/2004
Valew Beppe, mas processamento não é problema aqui. As máquinas que usam o sistema normalmente são máquinas foderosas. E eu também não posso te afirmar a velocidade, pois aqui no trampo estou com um P4 2.8ghz e 512 de ram. Então o processo é imediato, isso que eu traço mais de 5 mil retas com esta função e o resultado é imediato
hehe, cuidado pra naum se acostumar com esses PCzinhos aí...
GOSTEI 0
Nildo
10/05/2004
hehe, cuidado pra naum se acostumar com esses PCzinhos aí...
Hehe O pior é que eu dá mó raiva porque o P3 850 lá de casa ja ta mó lerdo. E olha que nem é, mas eu jah me acostumei com esses daqui, esse foi o problema :cry:
GOSTEI 0
Marcelo Saviski
10/05/2004
(ao menos, use Double´s, são mais rápidos q Single´s)
Doubles são mais rápidos? mais eles não são maiores? ou não tem nada a ver?
GOSTEI 0
Nildo
10/05/2004
Quando se usa linhas duplas, o afastamento em pixels de uma rebarba até uma distancia X é menor do que o afastamento de uma linha dupla. O processamento mesmo é gerar as cores Alpha para colocar nas rebarbas. Eu não consigo me expressar muito bem, mas é mais ou menos assim que funciona
GOSTEI 0
Beppe
10/05/2004
[quote:7993b16e02=´Marcelo Saviski´]
Doubles são mais rápidos? mais eles não são maiores? ou não tem nada a ver?[/quote:7993b16e02]
Senhor, sim, sim, sim!(by GVT)
Single: 4 bytes
Double: 8 bytes
Extended: 10 bytes
O Double é o mais rápido(na verdade, menos lento) dos três, segundo meus testes. Extended é o maior e um pouco mais lento que Double, embora seja do formato nativo da máquina. Por formato nativo, digo o tamanho de um registrador de ponto flutuante, ST(r). Eu poderia até explicar pq Single é mais lento ainda(conversão para Double, opera sobre, e converte de volta), mas nada sobre Extended. Eu nunca precisei usar pf em assembly, por isto não sei certo, mas vou checar isto.
(ao menos, use Double´s, são mais rápidos q Single´s)
Doubles são mais rápidos? mais eles não são maiores? ou não tem nada a ver?[/quote:7993b16e02]
Senhor, sim, sim, sim!(by GVT)
Single: 4 bytes
Double: 8 bytes
Extended: 10 bytes
O Double é o mais rápido(na verdade, menos lento) dos três, segundo meus testes. Extended é o maior e um pouco mais lento que Double, embora seja do formato nativo da máquina. Por formato nativo, digo o tamanho de um registrador de ponto flutuante, ST(r). Eu poderia até explicar pq Single é mais lento ainda(conversão para Double, opera sobre, e converte de volta), mas nada sobre Extended. Eu nunca precisei usar pf em assembly, por isto não sei certo, mas vou checar isto.
GOSTEI 0
Marcelo Saviski
10/05/2004
Eu sempre usei Singles porque achava que eles eram mais ´ligth´, interessante isso :)
GOSTEI 0