Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Paletti ei toimi?

kayttaja-3842 [19.08.2009 22:23:27]

#

Tervehdys, elikkäs minulla tuli pieni ongelma palettien kanssa.

Eli minulla on paletti joka muodostaa värit pohjalta 000000-FF0000-FFFF00-FFFFFF, elikkäs ns. tuli paletti.

Nytten tuli ongelma paletin käytössä pikseli pehmennyksessä

Haen ensiksi taulukkoon pikselien väriarvot seuraavasti:

- Itse oman pikselin väri
- Ylhäällä olevan pikselin väri
- Alapuolella olevan pikselin väri
- Vasemmalla olevan pikselin väri
- Oikealla olevan pikselin väri


Tämän jälkeen käyn silmukassa kaikki arvot läpi ja lisään ne yhteen, jonka jälkeen jaan ne 5, eli siis haen pikselin keskiarvon. Tämän jälkeen lasken rgb värien yhteisen keskiarvon, mutta nytten tulee ongelma.

Jos haen nytten newColorin arvon mukaan paletista värin, saan tulokseksi värillisen lumisateen enkä hienoa tuli pehmennystä.

Uint32 paletti[] {0, 12345 ....}


//....

         cm[0].color = draw.getPixel(window.getWindow(), x, y);

        if( y > 0 )
         cm[1].color = draw.getPixel(window.getWindow(), x, y-1);

        if( y < WIN_HEIGHT-1 )
         cm[2].color = draw.getPixel(window.getWindow(), x, y+1);

        if( x > 0 )
         cm[3].color = draw.getPixel(window.getWindow(), x-1, y);

        if( x < WIN_WIDTH-1 )
         cm[4].color = draw.getPixel(window.getWindow(), x+1, y);

     for( int c = 0; c < 5; c++ ){
       rgb[0] += (cm[c].color >> 16) & 255;
       rgb[1] += (cm[c].color >> 8) & 255;
       rgb[2] += (cm[c].color) & 255;
     }

     rgb[0] = rgb[0] / 5;
     rgb[1] = rgb[1] / 5;
     rgb[2] = rgb[2] / 5;

     newColor = (rgb[0]+rgb[1]+rgb[2]) / 3;


       draw.putPixel(window.getWindow(), x, y, paletti[newColor]);

...toivottavasti saatte nyt edes jotai tolkkua kysymyksestäni. Tämä on vain jotenkin todella vaikee selittää, mutta kysykää ihmeessä lisää tietoa jos tarvitaan. :)


Kiitos.

Metabolix [19.08.2009 22:42:43]

#

Kaksi virhettä näkyy jo tuosta. Et näytä nollaavan rgb:tä ollenkaan, joten lasket vain lisää ja lisää yhteen. Lisäksi laitat uuden pikselin paikalleen kierroksen lopussa, joten seuraavan pikselin kohdalla keskiarvon laskuun käytetään tätä uutta arvoa eikä pikselin alkuperäistä arvoa. Muuta koodia en kommentoi, toivottavasti itse tiedät, mitä paletissa on ja millä perusteella tuosta kaavasta pitäisi saada alkuunkaan järkevä kuva aikaan.

kayttaja-2499 [19.08.2009 22:45:37]

#

Metabolixin huomaamien asioiden lisäksi.

newColor = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];

ps. Tutustu bittioperaatioihin.

edit. Tai sitten ei, riippuen siitä mitä paletti-taulukko sisältää.

kayttaja-3842 [19.08.2009 22:55:42]

#

Metabolix kirjoitti:

Kaksi virhettä näkyy jo tuosta. Et näytä nollaavan rgb:tä ollenkaan, joten lasket vain lisää ja lisää yhteen. Lisäksi laitat uuden pikselin paikalleen kierroksen lopussa, joten seuraavan pikselin kohdalla keskiarvon laskuun käytetään tätä uutta arvoa eikä pikselin alkuperäistä arvoa. Muuta koodia en kommentoi, toivottavasti itse tiedät, mitä paletissa on ja millä perusteella tuosta kaavasta pitäisi saada alkuunkaan järkevä kuva aikaan.

Tuo rgb nollaus löytyy koodistani jota en tosin tuohon laittanut näkyviin, olisi ilmeisemmin pitänyt laittaa koko silmukka eikä vain tiettyä kohtaa. piskelin paikalleen laittamin löytyy kyllä oikeasta kohdasta sillä x ja y for silmukoiden siällä.

Anteeksi paljon kun en laittanut koko koodia, tuli ilmeisesti hieman väärin käsityksiä. :)

Tässä koko koodi.

 //Tämä on palettini joka vastaa paletti[0] = musta, paletti[255] valkoinen

Uint32 paletti[] = {0, 327680, 720896, 1048576, 1376256, 1769472, 2097152, 2424832, 2818048, 3145728, 3473408, 3801088, 4194304, 4521984, 4849664, 5242880, 5570560, 5898240, 6291456, 6619136, 6946816, 7340032, 7667712, 7995392, 8388608, 8716288, 9043968, 9371648, 9764864, 10092544, 10420224, 10813440, 11141120, 11468800, 11862016, 12189696, 12517376, 12910592, 13238272, 13565952, 13959168, 14286848, 14614528, 14942208, 15335424, 15663104, 15990784, 16384000, 16711680, 16712192, 16712704, 16713216, 16713984, 16714496, 16715008, 16715520, 16716032, 16716544, 16717312, 16717824, 16718336, 16718848, 16719360, 16719872, 16720384, 16721152, 16721664, 16722176, 16722688, 16723200, 16723712, 16724224, 16724992, 16725504, 16726016, 16726528, 16727040, 16727552, 16728320, 16728832, 16729344, 16729856, 16730368, 16730880, 16731392, 16732160, 16732672, 16733184, 16733696, 16734208, 16734720, 16735488, 16736000, 16736512, 16737024, 16737536, 16738048, 16738560, 16739328, 16739840, 16740352, 16740864, 16741376, 16741888, 16742656, 16743168, 16743680, 16744192, 16744704, 16745216, 16745728, 16746496, 16747008, 16747520, 16748032, 16748544, 16749056, 16749568, 16750336, 16750848, 16751360, 16751872, 16752384, 16752896, 16753664, 16754176, 16754688, 16755200, 16755456, 16755712, 16755968, 16756224, 16756480, 16756736, 16757248, 16757504, 16757760, 16758016, 16758272, 16758528, 16758784, 16759040, 16759296, 16759552, 16759808, 16760064, 16760320, 16760832, 16761088, 16761344, 16761600, 16761856, 16762112, 16762368, 16762624, 16762880, 16763136, 16763392, 16763648, 16763904, 16764416, 16764672, 16764928, 16765184, 16765440, 16765696, 16765952, 16766208, 16766464, 16766720, 16766976, 16767232, 16767488, 16767744, 16768256, 16768512, 16768768, 16769024, 16769280, 16769536, 16769792, 16770048, 16770304, 16770560, 16770816, 16771072, 16771328, 16771840, 16772096, 16772352, 16772608, 16772864, 16773120, 16773376, 16773632, 16773888, 16774144, 16774400, 16774656, 16774912, 16775424, 16775680, 16775936, 16776192, 16776448, 16776704, 16776960, 16776965, 16776970, 16776976, 16776981, 16776986, 16776991, 16776996, 16777002, 16777007, 16777012, 16777017, 16777022, 16777028, 16777033, 16777038, 16777043, 16777048, 16777054, 16777059, 16777064, 16777069, 16777074, 16777080, 16777085, 16777090, 16777095, 16777101, 16777106, 16777111, 16777116, 16777121, 16777127, 16777132, 16777137, 16777142, 16777147, 16777153, 16777158, 16777163, 16777168, 16777173, 16777179, 16777184, 16777189, 16777194, 16777199, 16777205, 16777210, 16777215, 0};
int newColor = 0;
int rgb[3];
 ...

     for( int x = 0; x < WIN_WIDTH; x++ ){
      for( int y = 0; y < WIN_HEIGHT; y++ ){

       newColor = 0;
      rgb[0] = 0;
      rgb[1] = 0;
      rgb[2] = 0;

          cm[0].color = draw.getPixel(window.getWindow(), x, y);

         if( y > 0 )
          cm[1].color = draw.getPixel(window.getWindow(), x, y-1);

         if( y < WIN_HEIGHT-1 )
          cm[2].color = draw.getPixel(window.getWindow(), x, y+1);

         if( x > 0 )
          cm[3].color = draw.getPixel(window.getWindow(), x-1, y);

         if( x < WIN_WIDTH-1 )
          cm[4].color = draw.getPixel(window.getWindow(), x+1, y);

      for( int c = 0; c < 5; c++ ){
        rgb[0] += (cm[c].color >> 16) & 255;
        rgb[1] += (cm[c].color >> 8) & 255;
        rgb[2] += (cm[c].color) & 255;
      }

      rgb[0] = rgb[0] / 5;
      rgb[1] = rgb[1] / 5;
      rgb[2] = rgb[2] / 5;

      newColor = (rgb[0]+rgb[1]+rgb[2]) / 3;


        draw.putPixel(window.getWindow(), x, y, paletti[newColor]);


      }
     }

Metabolix [19.08.2009 23:10:29]

#

Ensimmäisen huomioni osoitit tosiaan vääräksi, mutta sen sijaan cm taitaa myös jäädä nollaamatta, joten lopputulos on yhä sama. Tämä on luultavasti koodin varsinainen ongelma.

Jälkimmäistä huomiotani et sen sijaan ymmärtänyt oikein. Nyt ylikirjoitat kuvaa samalla, kun muunnat sitä, joten käytät myöhempien pikselien laskemiseen arvoja, jotka olet juuri äsken laskenut. Esimerkki:

Kuva:  Uusi F:  Uusi G:
abcd    abcd     abcd
efgh => eFgh  => eFGh
ijkl    ijkl     ijkl

Tässä uusi F lasketaan pisteistä befgj mutta uusi G pisteistä cFkgh, huomaa jälkimmäisessä iso F eikä pikku f. Laskuun käytetäänkin siis jo muutettua F:n arvoa eikä alkuperäistä f:ää. Lopputuloksesta tulee sumea.

Tässä on vielä kaupan päälle ohjelmallinen paletti:

#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))

Uint32 tuli(int i) {
	// parametrina i välillä 0 - 0xff (255)
	// muuttele näitä (0 - 0x200):
	const int g0 = 0xc0, b0 = 0x180;
	// skaalataan i sopivalle välille (yo. arvoilla 0 - 0x27f):
	i = (MAX(b0, g0) + 0xff) * i / 0xff;
	int r = MIN(MAX(0, i), 0xff);
	int g = MIN(MAX(0, i - g0), 0xff);
	int b = MIN(MAX(0, i - b0), 0xff);
	return (r<<16) + (g<<8) + (b<<0);
}

kayttaja-3842 [19.08.2009 23:18:52]

#

Ahaa, eli siis minun pitäisi käydä ekaksi koko ruutu läpi ja tallentaa pikselien uudet arvot esim. taulukkoon, jonka jälkeen piirrän uuden kuvan taulukon uusien väriarvojen mukaan?

Metabolix [21.08.2009 12:36:56]

#

Testasin algoritmiasi. Kirjoitin koko koodin hieman eri tavalla, mutta en käytännössä muuttanut kuin pari kohtaa: cm-muuttuja nollataan joka kierroksella, ja palettina käytetään antamaani funktiota. Koodi toimi jokseenkin odotetusti eli muutti kuvan käyttämään annettua palettia. Kuva sinänsä säilyi täysin tunnistettavana. Jälkimmäistä korjausta (väliaikaista taulukkoa) ei välttämättä tarvita, voit kokeilla sen kanssa ja ilman. Vaikuttaa jonkin verran kuvan kirkkauteen ja rajojen tarkkuuteen.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta