Kamppailen arkkiviholliseni, pyöritysalgoritmin, kanssa jälleen kerran. Tällä kertaa apunani on soodan mainio 2d pisteen (ja kuvion) kääntö asteittain -koodivinkki. Koen kuitenkin outouksia omassa C++-versiossani.
Pyöritän sinistä, 30x30-laatikkoa ympäri ja koen jatkuvaa pikselikatoa. Kun kulma siirtyy n. 30 asteen kohdalle, pikseleitä katoaa laatikon keskeltä. Tämä tarkoittaa, ettei tiettyjä koordinaatteja täytetä sinisellä värillä ollenkaan.
Kuuluuko tämä asiaan (epätarkka matriisi?) vai olenko tehnyt jotain väärin? Koodini perusidea on sama kuin soodalla, mutta ohjelma pyörii jatkuvassa loopissa, joka kasvattaa kulmaa joka kierroksella yhdellä. Ohjelma ei myöskään muokkaa jatkuvasti uusia arvoja pisteille vaan ohjelman alussa luodaan koordinaatit, joihin ei kajota kuin hetkellisesti (pyöritetyt pisteet lasketaan alkuperäisistä pisteistä, ei valmiiksi käännetyistä).
Kun kuviota käännetään, useamman pisteen uudet koordinaatit saattavat pyöristyä samoihin kokonaislukuihin. Siksi oikeaa kuvan kääntöä ei voi järkevästi tehdä vain siirtämällä jokaista pikseliä uuteen kohtaan, vaan käytetään jossain määrin hienostuneempia algoritmeja.
Näet tilanteen ehkä paremmin, jos teet laatikon, jossa kaikki pikselit ovat omalla värillään ja lähekkäiset mahdollisimman eri väreillä.
Ahaa, eli minun kannattaa siirtyä suoraan hienostuneempiin algoritmeihin? Mistä näitä löytyy?
Tämähän on vain tavallista geometriaa. Tässä on itse kehitetty ratkaisu: Laske kulmien uudet sijainnit. Käy läpi kaikki uudelle alueelle kuuluvat pikselit. Jos haluat vain pyöritetyn kuvion, voit suoraan värittää pikselit. Jos on tarkoitus kääntää kunnollista kuvaa, tee joka pikselille vastakkainen pyöritys ja katso, mihin kohti alkuperäistä kuvaa se osuu. Jos otat suoraan lähimmän pikselin alkuperäisestä kuvasta, saat nopean mutta aika ruman lopputuloksen. (Tee kuitenkin ensin niin.) Siistimpi tulee, kun otat oikeat osuudet lähimmistä pikseleistä.
(Edit. Grez päätyi alla samaan tulokseen. Siinäpä tuli se lähimpien pikselien laskeminenkin.)
(Edit. Hidas, Metabolix näköjään selitti jo saman asian)
Itse tekisin yksinkertaisesti toisin päin, eli hakisin kutakin piirrettävää pikseliä kohden vastaavan pikselin alkuperäisestä kuvasta.
Jos haluaisi vielä hienomman (ja CPU-aikaa riittää), niin voisi tehdä huomioida myös viereiset pikselit. Eli jos piirrettävää pikseliä vastaavat koordinaatit alkuperäisessä kuvassa olisi 20.81 ja 31.22 niin otettaisiin pikseliä 20,31 0.19*0.78 osaa, pikseliä 21,31 0.81*0.78 osaa, pikseliä 20,32 0.19*0.22 osaa ja pikseliä 21,32 0.81*0.22 osaa.
Tarkemmin kyse on siis tästä:
http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
Grezin ja Metabolixin mainitsema blilineaarinen interpolaatio on vain yksi mahdollinen tekniikka hienostuneempaan kuvan vääntelyyn.
Jos CPU-aika huolestuttaa, niin tässä tapauksessa ongelma on helppo ratkaista: älä kuluta CPU:ta vaan GPU:ta. Näytönohjain pyörittää isompiakin kuvia oikein mukavan näköisesti reaaliajassa.
Aihe on jo aika vanha, joten et voi enää vastata siihen.