Koska joku aiheesta keskustelussa kysyi enkä jaksanut selvittää, onko jossakin SDL:n lisäkirjastossa valmiiksi tällaista, päätin tehdä oman version. Funktio siis viistottaa kuvaa vaakasuunnassa eli siten, että korkeus säilyy samana. Vastaava funktio olisi jokseenkin yhtä helppo tehdä myös pystysuunnassa. Reunanpehmennyksen lisääminen vaatisi hieman ylimääräistä aritmetiikkaa, mutta sekään ei olisi suuri lisäys.
Funktion parametriksi annetaan alkuperäinen kuva ja vasemman alakulman uusi x-koordinaatti. Oletusarvoisesti siis vasemman yläkulman katsotaan pysyvän paikallaan. Funktion palauttama pinta tulee lopuksi vapauttaa (kuten kaikki muutkin SDL-pinnat näyttöpintaa lukuun ottamatta).
Funktio itse
#include <SDL.h> SDL_Surface *MySDL_Viistota(SDL_Surface *k, int vas_ala_x) { SDL_Surface *ret; char *pix; int leveys, i; // Tarkistuksia if (!k || (SDL_MUSTLOCK(k) && !SDL_LockSurface(k))) { return 0; } // Luodaan uusi pinta ; leveys pitää laskea (lisätään siirron itseisarvo) leveys = k->w + ((vas_ala_x < 0) ? -vas_ala_x : vas_ala_x); ret = SDL_CreateRGBSurface(k->flags, leveys, k->h, k->format->BitsPerPixel, k->format->Rmask, k->format->Gmask, k->format->Bmask, k->format->Amask); // Onnistuiko, vai pitääkö lopettaa? if (!ret || (SDL_MUSTLOCK(ret) && !SDL_LockSurface(ret))) { if (ret) { SDL_FreeSurface(ret); } if (SDL_MUSTLOCK(k)) { SDL_UnlockSurface(k); } return 0; } // Jos siirtymä olisi nolla, kopioidaan suoraan if (vas_ala_x == 0) { memcpy(ret->pixels, k->pixels, (k->h - 1) * k->pitch + (k->w * k->format->BytesPerPixel)); goto lopetus_ja_palautus; } if (vas_ala_x < 0) { // Negatiivisella siirretään piirtokohtaa hieman, ettei mene ulkopuolelle pix = (char*)ret->pixels - (vas_ala_x * ret->format->BytesPerPixel); } else { // Oikea siirtokohta kelpaa positiivisilla pix = ret->pixels; } // Rivi kerrallaan for (i = 0; i < k->h; ++i) { memcpy( /* kohde-Y = i */ pix + (i * ret->pitch) /* kohde-X ... */ + (((i * vas_ala_x) + (vas_ala_x / 2)) / (ret->h - 1)) * ret->format->BytesPerPixel, /* lähde = 0,i */ (char*)k->pixels + (i * k->pitch), /* Rivin koko */ k->format->BytesPerPixel * k->w); } lopetus_ja_palautus: if (SDL_MUSTLOCK(ret)) { SDL_UnlockSurface(ret); } if (SDL_MUSTLOCK(k)) { SDL_UnlockSurface(k); } return ret; }
Käyttöesimerkki
// Alustus SDL_Surface *ruutu = SDL_SetVideoMode(...); SDL_Surface *kuva = SDL_LoadBMP("kuva.bmp"); SDL_Surface *viistokuva; // Kivan viistotuksen laskenta (ajan mukaan) // viistous = [-4000, 3999] int viistous = (SDL_GetTicks() % 8000) - 4000; // viistous = [0, 4000] if (viistous < 0) { viistous = -viistous; } // viistous = [-kuva->w, kuva->w] viistous = (viistous * (2 * kuva->w) / 4000) - kuva->w; // Viistotus, piirto ja vapautus viistokuva = MySDL_Viistota(kuva, viistous); SDL_BlitSurface(viistokuva, 0, ruutu, 0); SDL_FreeSurface(viistokuva); // Loppuvapautus SDL_FreeSurface(kuva);
Aihe on jo aika vanha, joten et voi enää vastata siihen.