Permalänk
Medlem

pensel med opacity i ritprogram?

Hur ska man göra för att implementera en ritpensel med genomskinlighet? I API:et jag kör med (Symbian C++, UIQ3) så kan man rita linjer med alpha-värden, men linjerna blir avrundade, och om man då ritar två linjer som har en gemensam punkt så överlappar dom på ett mycket fult sätt just på den punkten, ungefär såhär: ===()===, istället för ======.

Även om man skulle råda bot på det så finns det fortfarande ett till problem, om man skulle rita till exempel en ögla så skulle det synas att dom överlappat, så funkar det inte i till exempel The Gimp och Photoshop. Hur göra?

Permalänk

Så fungerar det i Gimp. Vad de gör för att minimera effekten är att de inte låter ett penseldrag överlappa sig själv. Om du ritar ett kors med två penseldrag i Gimp så kommer korsningen synas.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Korkskruv
Så fungerar det i Gimp. Vad de gör för att minimera effekten är att de inte låter ett penseldrag överlappa sig själv. Om du ritar ett kors med två penseldrag i Gimp så kommer korsningen synas.

Jo jag vet, jag kanske uttryckte mig lite konstigt, men det är alltså just den effekten jag vill efterlikna, men jag kommer inte på hur man ska koda det hela.

EDIT: http://www.thinlincusergroup.se/applikationsdatabas/images/tu...
skuggan på trädet illustrerar mitt problem väldigt bra, i mitt program blir det precis på det sättet (eftersom man blittar massa cirklar, och många av dom överlappar varandra), men jag vill alltså ha det som i the gimp och photoshop.

Permalänk

Som jag skrev tidigare så måste du hålla samman ett penseldrag. Du skulle till exempel kunna ha ett temporärt lager som du ritar i. Det räcker kanske med att var pixel representeras av en bit.

Under tiden som då målar så markerar du relavanta bitar till 1. För att rita ut det temporära lagret så målar du var pixel som är markerad med 1 med den markerade penselns egenskaper. Bitar markerade med 0 ritar du med underliggande lagers värden. När penseldraget är avslutat så överför du det temporära lagret till den riktiga ritytan samtidigt som du nollställer det temporära.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Korkskruv
Som jag skrev tidigare så måste du hålla samman ett penseldrag. Du skulle till exempel kunna ha ett temporärt lager som du ritar i. Det räcker kanske med att var pixel representeras av en bit.

Under tiden som då målar så markerar du relavanta bitar till 1. För att rita ut det temporära lagret så målar du var pixel som är markerad med 1 med den markerade penselns egenskaper. Bitar markerade med 0 ritar du med underliggande lagers värden. När penseldraget är avslutat så överför du det temporära lagret till den riktiga ritytan samtidigt som du nollställer det temporära.

Jo jag tänkte på nåt liknande med, men det kan jag bara komma på hur man genomför med en penstorlek på 1 pixel.. Hur markerar man resterande pixlar i en radie som är lika med penstorleken? Bresenhams cirkelalgoritm?

Permalänk

Hur ritar du cirklar nu? Går det inte att utnyttja den funktionen?

Om du måste implementera en egen funktion så kan du förslagsvis börja med fasta strukturer. Exempel på en nästan rund pensel

bool pensel[4][4] = {{0,1,1,0}, {1,1,1,1}, {1,1,1,1}, {0,1,1,0}};

Här är annars kärnan i en cirkelfunktion som jag implementerade en gång i tiden.

d1 = d1 + x + x + 1; d2 = d1 + y + y + 1; if (abs(d1) < abs(d2)) x++; else { x++; y++; d1 = d2; }

Om jag inte minns fel så började jag rita cirkeln från botten i fjärde kvadranten med y=-r och x=0 samt d1=d2=0. Sen är det bra att iterera sig upp mot första kvadranten.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Korkskruv
Hur ritar du cirklar nu? Går det inte att utnyttja den funktionen?

Om du måste implementera en egen funktion så kan du förslagsvis börja med fasta strukturer. Exempel på en nästan rund pensel

bool pensel[4][4] = {{0,1,1,0}, {1,1,1,1}, {1,1,1,1}, {0,1,1,0}};

Här är annars kärnan i en cirkelfunktion som jag implementerade en gång i tiden.

d1 = d1 + x + x + 1; d2 = d1 + y + y + 1; if (abs(d1) < abs(d2)) x++; else { x++; y++; d1 = d2; }

Om jag inte minns fel så började jag rita cirkeln från botten i fjärde kvadranten med y=-r och x=0 samt d1=d2=0. Sen är det bra att iterera sig upp mot första kvadranten.

Tack så mycket för utförliga svar!
Men scheiße, för den snabba pixelsättar-funktionen klarar inte av att sätta alfavärden, 0x00bbggrr står det i dokumentationen, hur kalkylerar man då ut det nya värdet genom att ta den underliggande pixeln o lägga på det nya, men helt skippa alfakanalen? Alla andra pixelsättarmetoder är nog uteslutna tyvärr, då de är sjukt sega (hade en floodfill-funktion med den ett tag, kunde ta 10 sek att fylla en 320x240 bild...)

Permalänk
Medlem

Det du vill göra är att räkna ut ett RGB-värde givet 2 RGB värden samt opacitet.
I en tråd... http://sweclockers.com/forum/showthread.php?s=&threadid=64848...
Diskuteras en snabb implementation av detta, dock är den implementationen för RGB-565
Men principen är densamme.

Lycka till

Visa signatur

weeeee

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av mounte
Det du vill göra är att räkna ut ett RGB-värde givet 2 RGB värden samt opacitet.
I en tråd... http://sweclockers.com/forum/showthread.php?s=&threadid=64848...
Diskuteras en snabb implementation av detta, dock är den implementationen för RGB-565
Men principen är densamme.

Lycka till

Ah, äntligen fick jag det att funka, men det verkar lite knasigt.. Blandar man exempelvis 0x80ff0000 med sig själv (röd med 128 i opacity) så får man någon slags lila (kan tyvärr inte se exakt), här är min kod:

TInt redA = (c1 & 0xff0000) >> 16; TInt greenA = (c1 & 0x00ff00) >> 8; TInt blueA = (c1 & 0xff); TInt redB = (c2 & 0xff0000) >> 16; TInt greenB = (c2 & 0x00ff00) >> 8; TInt blueB = (c2 & 0xff); TInt alpha = currColor.Alpha(); TInt red = (alpha * redB + (255-alpha)*redA) >> 8; TInt green = (alpha * greenB + (255-alpha)*greenA) >> 8; TInt blue = (alpha * blueB + (255-alpha)*blueA) >> 8; TUint32 newColor = (blue << 16) | (green << 8) | (red);

blue green red är rätt för övrigt. Alpha() returnerar ett värde mellan 0 och 255.

EDIT: Hmm, det måste visst vara red green blue, men då blir det fel på annat håll, jag får nog byta plats på röd och blå innan istället.