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:
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:
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.