rita tjocka, anti-aliaserade linjer?
Jag har ingen kunskap på området men efter att ha kollat upp Wu's algoritm på Wikipedia så har jag ett förslag.
Ta en titt på pseudokoden i artikeln:
// main loop
for x from xpxl1 + 1 to xpxl2 - 1 do
plot(x, ipart(intery), rfpart(intery))
plot(x, ipart(intery) + 1, fpart(intery))
intery = intery + gradient
repeat
Mitt förslag är följande ändringar, antag att det finns en variabel w för bredden på linjen:
// main loop
for x from xpxl1 + 1 to xpxl2 - 1 do
plot(x, ipart(intery), rfpart(intery))
for foo from 1 to (w - 1) do
plot(x, ipart(intery) + w, 1)
repeat
plot(x, ipart(intery) + w, fpart(intery)) //**ändrad
intery = intery + gradient
repeat
Notera den nya loopen i mitten och ändringen i en av de existerande raderna.
Du har ju redan implementerat algoritmen så det lär inte vara några större problem för dig att införa mina föreslagna ändringar. Själv är jag nyfiken på om de ens funkar. Har inte tänkt över det så värst mycket så det är möjligt att jag fått ett hjärnsläpp.
Får vara fräck och fråga vad det ska användas till?
EDIT: klantade mig igår kväll, glömde ändra koden i foo-loopen, den är fixad nu.
Ursprungligen inskrivet av Didonk
*snip*
Får vara fräck och fråga vad det ska användas till?
Ska testa det där imorrn, verkar intressant.. är för trött nu dock..
Det är till ett ritprogram jag håller på att utveckla till Symbian UIQ3-mobiler, bland annat SE M600 och SE P1i. Än så länge har jag en penna med olika storlek, och även genomskinlighet på den. Sudd, fyllverktyg (bucket fill), linjer, bezier-linjer, cirklar (ellipser), rektanglar, färgväljare, zoom, blur (buggig dock, blurrar bara horisontellt..) och undo/redo..
Bild på GUI:t: http://www.esato.com/board/ui/VFFmjy1c7nf2QhhP016A.jpg
alla verktyg finns inte som knappar, och GUI:t är väldigt ointuitivt och inte så värst förklarande. De fyra slidersarna är penstorlek, Röd, Grön, Blå och Alfa.
En bild jag fixat ihop: http://tux.servegame.org/~webbdesing/tux_hkpaint.png
Skulle du inte kunna göra en polygon eller path (polygon där en edge kan vara en bezierkurva) av linjen istället? Då kan du ju använda din kod för tunna linjer för att rita konturerna med AA, men rita innanmätet av linjen genom att fylla polygonen.
Alla män är dödliga. Sokrates var dödlig. Alltså är alla män Sokrates.
Ursprungligen inskrivet av selotodo
Skulle du inte kunna göra en polygon eller path (polygon där en edge kan vara en bezierkurva) av linjen istället? Då kan du ju använda din kod för tunna linjer för att rita konturerna med AA, men rita innanmätet av linjen genom att fylla polygonen.
Fylla den med bucket fill med andra ord? Det skulle nog gå, men då skulle det väl bli lite såhär pga AA-linjerna?: http://tux.servegame.org/~webbdesing/litefail.png
Då måste jag ändå hitta dom två röda linjerna som jag illustrerade på förra bilden också, som jag inte vet exakt hur man gör...
Skulle man inte kunna ta linjen som är 1px och endast göra den tjockare. Det vill säga att man flyttar de genomskinliga pixlarna ovanför den verkliga linjen uppåt och och sen fyller i mellanrummet med svart.
Man kan även rendera linjen i högre upplösning för att sedan skala ner den innan man ritar ut den.
Korkskruv: Det är precis så mitt kodexempel är tänkt att fungera.
ErkHK: Har du fått det att fungera än?
Edit: Klantade mig i min första post, glömde ändra koden i loopen, den är fixad nu.
Ursprungligen inskrivet av Didonk
Korkskruv: Det är precis så mitt kodexempel är tänkt att fungera.
ErkHK: Har du fått det att fungera än?
Edit: Klantade mig i min första post, glömde ändra koden i loopen, den är fixad nu.
hmm.. Nae inte direkt: http://tux.servegame.org/~webbdesing/fail.png
Den rätta linjen demonstrerar hur jag vill att det ska se ut, jag lade till den i the gimp. Här är koden jag använder (det är säkert fel nånstans):
void Pen::DrawWuLine( CFbsBitmap & screen, int X0, int Y0, int X1, int Y1, TRgb clrLine, TInt penSize)
{
/* Make sure the line runs top to bottom */
if (Y0 > Y1)
{
int Temp = Y0; Y0 = Y1; Y1 = Temp;
Temp = X0; X0 = X1; X1 = Temp;
}
/* Draw the initial pixel, which is always exactly intersected by
the line and so needs no weighting */
DrawPixel(screen, X0, Y0, clrLine );
int XDir, DeltaX = X1 - X0;
if( DeltaX >= 0 )
{
XDir = 1;
}
else
{
XDir = -1;
DeltaX = 0 - DeltaX; /* make DeltaX positive */
}
/* Special-case horizontal, vertical, and diagonal lines, which
require no weighting because they go right through the center of
every pixel */
int DeltaY = Y1 - Y0;
if (DeltaY == 0)
{
/* Horizontal line */
while (DeltaX-- != 0)
{
X0 += XDir;
DrawPixel(screen, X0, Y0, clrLine );
for(int w = 1; w < penSize - 1; w++)
DrawPixel(screen, X0, Y0+w, clrLine);
}
return;
}
if (DeltaX == 0)
{
/* Vertical line */
do
{
Y0++;
DrawPixel(screen, X0, Y0, clrLine );
for(int w = 1; w < penSize - 1; w++)
DrawPixel(screen, X0, Y0+w, clrLine);
} while (--DeltaY != 0);
return;
}
if (DeltaX == DeltaY)
{
/* Diagonal line */
do
{
X0 += XDir;
Y0++;
DrawPixel(screen, X0, Y0, clrLine );
for(int w = 1; w < penSize - 1; w++)
DrawPixel(screen, X0, Y0+w, clrLine);
} while (--DeltaY != 0);
return;
}
unsigned short ErrorAdj;
unsigned short ErrorAccTemp, Weighting;
/* Line is not horizontal, diagonal, or vertical */
unsigned short ErrorAcc = 0; /* initialize the line error accumulator to 0 */
TInt rl = (clrLine.Value() & 0xff0000) >> 16;
TInt gl = (clrLine.Value() & 0x00ff00) >> 8;
TInt bl = (clrLine.Value() & 0xff);
double grayl = rl * 0.299 + gl * 0.587 + bl * 0.114;
/* Is this an X-major or Y-major line? */
if (DeltaY > DeltaX)
{
/* Y-major line; calculate 16-bit fixed-point fractional part of a
pixel that X advances each time Y advances 1 pixel, truncating the
result so that we won't overrun the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY;
/* Draw all pixels other than the first and last */
while (--DeltaY) {
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
ErrorAcc += ErrorAdj; /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the X coord */
X0 += XDir;
}
Y0++; /* Y-major, so always advance Y */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> 8;
ASSERT( Weighting < 256 );
ASSERT( ( Weighting ^ 255 ) < 256 );
//get the color
screen.LockHeap();
TUint32 * tmp = screen.DataAddress();
TUint32 clrBackground = tmp[X0+Y0*240];
screen.UnlockHeap();
TInt rb = (clrBackground & 0xff0000) >> 16;
TInt gb = (clrBackground & 0x00ff00) >> 8;
TInt bb = (clrBackground & 0xff);
double grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
double rr = ( rb > rl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:
(Weighting ^ 255)) ) / 255.0 * ( rb - rl ) + rl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:(Weighting ^ 255)) )
/ 255.0 * ( rl - rb ) + rb ) ) );
double gr = ( gb > gl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:
(Weighting ^ 255)) ) / 255.0 * ( gb - gl ) + gl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:(Weighting ^ 255)) )
/ 255.0 * ( gl - gb ) + gb ) ) );
double br = ( bb > bl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:
(Weighting ^ 255)) ) / 255.0 * ( bb - bl ) + bl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:(Weighting ^ 255)) )
/ 255.0 * ( bl - bb ) + bb ) ) );
DrawPixel(screen, X0, Y0, TRgb(rr,gr,br));
for(int w = 1;w < penSize-1; w++)
{
DrawPixel(screen, X0, Y0+w, clrLine);
}
//get the color
screen.LockHeap();
tmp = screen.DataAddress();
clrBackground = tmp[X0+XDir+(Y0+penSize)*240];
screen.UnlockHeap();
rb = (clrBackground & 0xff0000) >> 16;
gb = (clrBackground & 0x00ff00) >> 8;
bb = (clrBackground & 0xff);
grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
rr = ( rb > rl ? (/* ( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):
Weighting) ) / 255.0 * ( rb - rl ) + rl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):Weighting) )
/ 255.0 * ( rl - rb ) + rb ) ) );
gr = ( gb > gl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):
Weighting) ) / 255.0 * ( gb - gl ) + gl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):Weighting) )
/ 255.0 * ( gl - gb ) + gb ) ) );
br = ( bb > bl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):
Weighting) ) / 255.0 * ( bb - bl ) + bl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):Weighting) )
/ 255.0 * ( bl - bb ) + bb ) ) );
DrawPixel(screen, X0 + XDir, Y0+penSize, TRgb(rr,gr,br));
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
DrawPixel(screen, X1, Y1, clrLine);
return;
}
//else if(deltax > deltay)
/* It's an X-major line; calculate 16-bit fixed-point fractional part of a
pixel that Y advances each time X advances 1 pixel, truncating the
result to avoid overrunning the endpoint along the X axis */
ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX;
/* Draw all pixels other than the first and last */
while (--DeltaX) {
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */
ErrorAcc += ErrorAdj; /* calculate error for next pixel */
if (ErrorAcc <= ErrorAccTemp) {
/* The error accumulator turned over, so advance the Y coord */
Y0++;
}
X0 += XDir; /* X-major, so always advance X */
/* The IntensityBits most significant bits of ErrorAcc give us the
intensity weighting for this pixel, and the complement of the
weighting for the paired pixel */
Weighting = ErrorAcc >> 8;
ASSERT( Weighting < 256 );
ASSERT( ( Weighting ^ 255 ) < 256 );
//get the color
screen.LockHeap();
TUint32 * tmp = screen.DataAddress();
TUint32 clrBackground = tmp[X0+Y0*240];
screen.UnlockHeap();
TInt rb = (clrBackground & 0xff0000) >> 16;
TInt gb = (clrBackground & 0x00ff00) >> 8;
TInt bb = (clrBackground & 0xff);
double grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
double rr = ( rb > rl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:
(Weighting ^ 255)) ) / 255.0 * ( rb - rl ) + rl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:(Weighting ^ 255)) )
/ 255.0 * ( rl - rb ) + rb ) ) );
double gr = ( gb > gl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:
(Weighting ^ 255)) ) / 255.0 * ( gb - gl ) + gl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:(Weighting ^ 255)) )
/ 255.0 * ( gl - gb ) + gb ) ) );
double br = ( bb > bl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:
(Weighting ^ 255)) ) / 255.0 * ( bb - bl ) + bl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?Weighting:(Weighting ^ 255)) )
/ 255.0 * ( bl - bb ) + bb ) ) );
DrawPixel(screen, X0, Y0, TRgb(rr, gr, br));
for(int w = 1;w < penSize-1; w++)
{
DrawPixel(screen, X0, Y0+w, clrLine);
}
screen.LockHeap();
tmp = screen.DataAddress();
//clrBackground = tmp[X0+(Y0+1)*240];
clrBackground = tmp[(X0)+(Y0+penSize)*240];
screen.UnlockHeap();
rb = (clrBackground & 0xff0000) >> 16;
gb = (clrBackground & 0x00ff00) >> 8;
bb = (clrBackground & 0xff);
grayb = rb * 0.299 + gb * 0.587 + bb * 0.114;
rr = ( rb > rl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):
Weighting) ) / 255.0 * ( rb - rl ) + rl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):Weighting) )
/ 255.0 * ( rl - rb ) + rb ) ) );
gr = ( gb > gl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):
Weighting) ) / 255.0 * ( gb - gl ) + gl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):Weighting) )
/ 255.0 * ( gl - gb ) + gb ) ) );
br = ( bb > bl ? ( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):
Weighting) ) / 255.0 * ( bb - bl ) + bl ) ) :
( /*( TInt )*/( ( ( double )( grayl<grayb?(Weighting ^ 255):Weighting) )
/ 255.0 * ( bl - bb ) + bb ) ) );
//DrawPixel(screen, X0, Y0 + 1, TRgb(rr, gr, br));
DrawPixel(screen, X0, Y0 + (penSize), TRgb(rr, gr, br));
for(int w = 1;w < penSize-1; w++)
{
DrawPixel(screen, X0, Y0+w, TRgb(0,0,0));
}
}
/* Draw the final pixel, which is always exactly intersected by the line
and so needs no weighting */
DrawPixel(screen, X1, Y1, clrLine);
}
EDIT: originalkoden jag stulit det ifrån: http://www.suchit-tiwari.org/download/aawu.c
- Idag Iphones marknadsandel faller i USA 12
- Igår Airtec Pro Type1 – batteridrivet alternativ till tryckluft på burk 47
- Igår Nu stiger hårddiskpriserna med uppemot 10 procent 15
- Igår Analytiker: Apple har överskattat intresset för Vision Pro 50
- 24 / 4 AMD, Nvidia och Intel – vad är det för skillnad mellan grafikkortstillverkarna? 27
- Elbilar - Tråden för intresserade23178
- Iphones marknadsandel faller i USA13
- Nintendo-innehåll tas bort från Garrys Mod20
- Epic games nere?2
- Herman Miller X Logitech G Embody Gaming Chair, recension?117
- Konsumentverket granskar tio nätbutiker som lurat kunder14
- Telenors router och netgear sammankopplade4
- Wordle på svenska - ordlig.se7856
- Posta din hastighet!2444
- Amazons Fallout-serie regisseras av Jonathan Nolan (Inte den Nolan, men hans brorsa)333
- Säljes i3-8100
- Köpes Luftkylning och Fläktar
- Köpes Nvidia Quadro P400,600 eller 620
- Säljes Dell Latitude 7530 15,6”
- Köpes Önskar köpa 6700xt eller 3070
- Säljes Asus Geforce RTX 2070 8GB Strix Gaming OC
- Köpes Köper bärbara datorer, trasiga, utan skärm etc.
- Säljes Lenovo Thinkcentre M73
- Säljes Lenovo Legion Slim 5 14” OLED
- Säljes Asus VG248 24"
- Iphones marknadsandel faller i USA13
- Konsumentverket granskar tio nätbutiker som lurat kunder14
- Airtec Pro Type1 – batteridrivet alternativ till tryckluft på burk47
- Nintendo-innehåll tas bort från Garrys Mod20
- Nu stiger hårddiskpriserna med uppemot 10 procent15
- Quiz: Vad kan du om Inet?68
- Analytiker: Apple har överskattat intresset för Vision Pro50
- Microsoft rullar ut Startmenyreklam till alla59
- EU röstar igenom ”rätten att reparera”53
- Viaplay sätter ner foten mot delade konton55