Hyppää sisältöön

Kuvan käsittely pikselitasolla

Image-luokan kuvia voidaan muokata ja ottaa kuvasta palanen ja siirtää se toiseen kohtaan. Kuvien yksittäisiä pikseleitä on myös mahdollista manipuloida.

Kuvan yksittäisten pikselien muokkaaminen

Image-oliota voidaan myös käsitellä kaksiulotteisena värimatriisina. Esimerkiksi:

Image kuva = LoadImage("norsu.png");
kuva[36, 50] = Color.Red;
kuva[36, 70] = Color.Red;

asettaisi nämä kaksi pikseliä punaiseksi. Huomaa, että koordinaatit menevät järjestyksessä [y, x] vasemmasta yläkulmasta katsottuna.

Harmaasävykuva

Kuvasta voidaan tehdä harmaasävykuva esimerkiksi seuraavasti:

public override void Begin()
{
    Image kuva = LoadImage("lammas");
    Harmaasavy(kuva);
    GameObject lammas = new GameObject(kuva);
    Add(lammas);
    ...
}

public static void Harmaasavy(Image kuva)
{
    for (int iy = 0; iy < kuva.Height; iy++)
        for (int ix = 0; ix < kuva.Width; ix++)
        {
            Color c = kuva[iy, ix];
            byte b = (byte)((c.RedComponent +
                             c.GreenComponent +
                             c.BlueComponent) / 3);
            kuva[iy, ix] = new Color(b, b, b);
        }
}

Kuvan kloonaaminen

Joskus kuvasta voi tarvita useita erilaisia versioita. Siksi edellä olisi voitu tehdä myös

public override void Begin()
{
    Image kuva = LoadImage("lammas");
    Image harmaaKuva = kuva.Clone();
    Harmaasavy(harmaaKuva);
    GameObject lammas = new GameObject(kuva);
    Add(lammas);
    GameObject harmaaLammas = new GameObject(harmaaKuva);
    Add(harmaaLammas);
    ...
}

Kuvan käsittely Color-taulukossa

Harmaasävykuvan esimerkki toimii pienille kuville. Suora kuvan käsittely Imagessa voi olla hidasta ja siksi suurempia kuvan käsittelyjä varten kuva kannattaa ottaa Color-taulukkoon, jossa sitä käsitellään.

Esimerkkinä vaikka harmaasävykuvan tekeminen tehokkaammin:

public static void HarmaasavyTaulukolla(Image kuva)
{
    Color[,] bmp = kuva.GetData();
    int ny = kuva.Height;
    int nx = kuva.Width;
    for (int iy = 0; iy < ny; iy++)
        for (int ix = 0; ix < nx; ix++)
        {
            Color c = bmp[iy, ix];
            byte b = (byte)((c.RedComponent +
                             c.GreenComponent +
                             c.BlueComponent) / 3);
            bmp[iy, ix] = new Color(b, b, b);
        }
    kuva.SetData(bmp);
}

Kuvan käsittely uint-taulukossa

Joskus on vielä tehokkaampaa käsitellä kuvaa kokonaislukutaulukossa. Tällöin voidaan kuvan värielementit pakata yhteen positiiviseen kokonaislukutaulukkoon niin, että

  • värin alpha-arvo (läpinäkyvyyden osuus, 255=ei läpinäkyvä) vie yhden tavun
  • värin punaisen osuus (r, red) vie yhden tavun (arvo 0-255)
  • värin vihreän osuus (g, green) vie yhden tavun (arvo 0-255)
  • värin sinisen osuus (b, blue) vie yhden tavun (arvo 0-255)

Seuraavalla aliohjelmalla kuva voidaan muuttaa täysin punaiseksi "unohtamalla" kuvasta muut värit:

public static void Punaiseksi(Image kuva)
{
    uint[,] bmp = kuva.GetDataUInt();
    int ny = kuva.Height;
    int nx = kuva.Width;
    for (int iy = 0; iy < ny; iy++)
        for (int ix = 0; ix < nx; ix++)
        {
            uint c = bmp[iy, ix];
            byte r = Color.GetRed(c);
            byte g = 0;
            byte b = 0;
            bmp[iy, ix] = Color.PackRGB(r, g, b);
        }
    kuva.SetData(bmp);
}

Taulukko voidaan ottaa myös uint[][]-muodossa, mikä on vielä hieman tehokkaampaa käsittelyn kannalta C#-kielessä.

Kuvan palan siirtäminen toiseen kohtaan

Käyttäen edellistä ideaa, voidaan kuvasta ottaa esimerkiksi palanen ja siirtää se saman tai toisen kuvan johonkin kohtaan, esimerkiksi:

uint[,] pala = kuva.GetDataUInt(200, 100,100,50);
kuva.SetData(pala,200,150);

Tätä ideaa käyttäen voitaisiin esimerkiksi animaatio piirtää yhteen ainoaan kuvaan niin, että siinä olisi vaikka 100 pikselin leveydeltä aina kutakin hahmon asentoa. Sitten kuva voitaisiin pilkkoa useaksi pienemmäksi kuvaksi:

Image kuva = LoadImage(kuvannimi);
int n = 5;
int korkeus = 200;
int leveys = 100;
Image[] kuvat = new Image[n];

for (int i = 0; i < n; i++)
{
    kuvat[i] = new Image(leveys, korkeus, Color.Black);
    uint[,] pala = kuva.GetDataUInt(i * leveys, 0, leveys, korkeus);
    kuvat[i].SetData(pala);
}

Nyt kuvat-taulukossa olisi 5 kuvaa eri tilanteissa käytettäväksi.