Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C: SDL getPixel alpha

Sivun loppuun

kayttaja-3842 [03.12.2008 20:31:59]

#

Terve vaan kaikille...

Elikkäs miten on mahdollsita ottaa SDL:än avulla ruudusta pikseli ja sen mukana sen sisältämä alphan value.

Eli siis löysin googlesta pari koodi pätkää, mutta mikään ei "tukenut" alpha kanavan arvon ottoa. Eli kaikki hakivat vain arvot RGB ja tarvitisisin RGBA.


Miten tuota saisi fixailtua niin, että se hakisi myös alpha kanavan arvon???

Uint32 _fastcall getpixel(SDL_Surface *surface, int x, int y)
{
    int bpp = surface->format->BytesPerPixel;
    // p on osoitin pikseliin, jonka haluamme kopioida
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        return *p;

    case 2:
        return *(Uint16 *)p;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;

    case 4:
        return *(Uint32 *)p;

    default:
        return 0;       // ei pitäisi tapahtua.
    }
}

Metabolix [03.12.2008 20:40:09]

#

Kyllähän tuo alfan hakee, paitsi että sellaista ei ole kuin 32-bittisillä pinnoilla. Näyttöpinnalla sitä ei ole koskaan, eihän siitä näy läpi. Mistä yrität hakea alfaa ja miten koodit mielestäsi eivät toimi? Lataa esimerkiksi läpinäkyviä kohtia sisältävä PNG-kuva SDL_image-kirjastolla, niin voit helposti todeta, että funktiot toimivat.

kayttaja-3842 [03.12.2008 20:57:11]

#

Noh itselläni ei ainakaan toimi?

Eli luon eka pinnan, sitten piirrän siihen kuvasta haetun pikselin ja pikselin jonka arvon asetan suoraan...

  tempImg = SDL_CreateRGBSurface(SDL_SWSURFACE, imgs[0]->w, imgs[0]->h, 32, r_mask, g_mask, b_mask, a_mask);

//Tämä toimii
putPixel(tempImg, 10, 10, 0xffffffff);

//Tämä ei toimi!
putPixel(tempImg, 11, 11, getpixel(img, 32, 32));

...minusta tuo vika on vaan se, että getpixel ei syystä tai toisesta syötä alphaa ja pikseli on siten läpinäkyvä?

Metabolix [03.12.2008 21:03:56]

#

Mikä on tämän img-pinnan formaatti? Tuo getpixel-funktio palauttaa tietenkin arvon, joka toimii oikein vain samanlaisella pinnalla. Muilla pinnoilla se on jotain aivan muuta. Näkeehän sen tuosta koodistakin, että esimerkiksi 24-bittisestä pinnasta otetaan vain nuo kolme tavua ja neljäs on nolla.

kayttaja-3842 [03.12.2008 21:13:04]

#

Eli siis img on SDL_Surface * ja img sisältää ladataun .bmp kuvan. Sitä olenkin tässä jo pähkällytkin, eli periaatteessa jos sen neljäs pinnan arvoksi laitetaan 255 ja se lisättäisiin tuohon, niin voisiko se sitten näkyä?

Metabolix [03.12.2008 21:21:18]

#

Kyllä, jos kyseessä on 24-bittinen BMP.

kayttaja-3842 [03.12.2008 21:25:16]

#

En tiedä onko tuo alla oleva määrittely oikein, mutta tuon tehdessäni kuva tuli kyllä esille, mutta värit ovat vääristyneet.. :/

if(SDL_BYTEORDER == SDL_BIG_ENDIAN){
    p[0] = 255;
    return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}else{
    p[3] = 255;
    return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
}

Sainkin sen itse toimiaan alla olevalla koodilla

if(SDL_BYTEORDER == SDL_BIG_ENDIAN){
    p[0] = 255;
    return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}else{
    p[3] = 255;
    return p[0] << 16 | p[1] << 8 | p[2]  | p[3] << 24;
}

Metabolix [03.12.2008 21:34:04]

#

Ei, ei missään tapauksessa. Mietihän nyt järkevästi, mitä oikein teet, kun sijoitat taulukkoon ylimääräisen arvon ja muutat indeksointia. Muutat alkuperäisen kuvan dataa ja otat siitä väriarvot eri kohdasta, kuin oikeasti pitäisi.

Lisää se arvo vakiona lausekkeeseen. BIG_ENDIAN-tapauksesta ei ehkä kannata alkuun välittää, koska x86 on LE-kone. Ennen kaikkea kuitenkin dataa ja indeksointia ei pidä mennä muuttamaan!

kayttaja-3842 [04.12.2008 15:48:05]

#

...siis mitenkä?

Tarkoitatko näin?

return p[0] | p[1] << 8 | p[2] << 16 | 0xff << 24

Metabolix [04.12.2008 15:58:16]

#

Esimerkiksi noin.

Indeksointi tietenkin riippuu siitä, missä järjestyksessä komponentit (RGB) ovat pinnalla, mutta jos ne siis tulevat sieltä oikein, indeksien muuttaminen vaihtaa ne väärään järjestykseen. Järjestys taas riippuu pinnasta, esim. BMP:t ovat yleensä BGR-dataa ja PNG:t RGB-dataa. Siksi tuo funktio voikin toimia joskus väärin. Oikea tapa olisi käyttää pinnan pikseliformaatin arvoja Rmask, Rshift jne.

kayttaja-3842 [04.12.2008 17:13:58]

#

Kyllä, värit toimivat oikein, mutta maskaaminen SetColorKeyllä ei tahdo nytten onnistua. Johtuneepi luultavasti data muunnoksesta?

Metabolix [04.12.2008 17:29:19]

#

Pikselikohtainen alfa-arvo ja color key ovat toisensa poissulkevia. Voit tuon putpixel-getpixel-kopiointisi yhteydessä tarkistaa väriarvon ja ottaa siitä sen juuri vaivalla lisäämäsi alfa-arvon pois, niin siitä tulee läpinäkyvä. Miksi muutat pinnan RGBA:ksi, jos et edes halua käyttää sitä A:ta?

kayttaja-3842 [04.12.2008 17:37:06]

#

Koska jostain syytä ilman tuota A:ta en saa kuvaa näkyviin. :)

...mutta sain sen nytten kuitenkin toimimaan. Kiitos paljon! :D


Sivun alkuun

Vastaus

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

Tietoa sivustosta