### Rotating SDL_Surfaces

Since SDL doesn't have it's own function for rotating images and I'm tired of storing multiple angles of the same sprite in a file, I created my own function for doing so:

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145`` ``````//XY Class class XY { public: XY(){} XY(float x, float y); float X; float Y; float Magnitude(); void Display(); XY operator+( XY other ); XY operator-( XY other ); XY operator+=( XY other ); XY operator-=( XY other ); XY operator*( float scalar ); XY operator/( float scalar ); XY operator*=( float scalar ); XY operator/=( float scalar ); XY operator-(); bool operator==( XY other ); }; XY::XY(float x,float y) { X = x; Y = y; } float XY::Magnitude() { return sqrt( pow(X,2) + pow(Y,2) ); } void XY::Display() { cout<<'('<pixels; Pixels[ x + Surface->w*y ] = Pixel; } Uint32 Get_Pixel( SDL_Surface* Surface, int x, int y ) { Uint32* Pixels = (Uint32*)Surface->pixels; return Pixels[ x + Surface->w*y ]; } SDL_Surface* Spin( SDL_Surface* Surface, float degrees, SDL_Surface* Buffer) { //Surface must be a square and Buffer has to be wider and longer if ( Buffer == NULL or Buffer->w < Surface->w or Buffer->h < Surface->h or Surface->w != Surface->h ) exit(0xBAD); int Width = Surface->w, Height = Surface->h; SDL_Surface* Return = Buffer; for ( int x = 0; x < Return->w; x++ ) for ( int y = 0; y < Return->h; y++ ) Set_Pixel( Return, x, y, SDL_MapRGB( Return->format, 0, 255, 255 ) ); for ( int x = 0, x2 = 0; x < Width; x++ ) for ( int y = 0, y2 = 0; y < Height; y++ ) { x2 = Rotate( degrees, XY(x,y), XY( Width/2, Height/2 ) ).X; y2 = Rotate( degrees, XY(x,y), XY( Width/2, Height/2 ) ).Y; if ( x2 + Return->w*y2 < 0 ) continue; Set_Pixel( Return, x2, y2, Get_Pixel( Surface, x, y ) ); } return Return; }``````

The problem is while Spin does spin the surface correctly, some pixels are rotated to the same new position so gaps appear in the returned surface. I need a way of filling in the gaps so the returned image looks better. A link to a program I made that uses this function is below so you can see the problem that I'm talking about.

http://www.mediafire.com/?cvk78bawxp9gdyw

Anyone have any ideas on what I could do?

Edit:
I currently use SDL 1.2. Could my problem be fixed if I used 2.0? For example, does SDL 2.0 have a built in function for rotating surfaces?
Last edited on
The SDL_gfx library has surface rotation/zoom in it.

Having a library of surfaces that are pre-rotated is preferred -- always offload as much processing as possible to somewhere other than your main event loop.

In terms of your code, you are thinking about it backwards. Scan rasters across the final surface, and sample the source image pixels, interpolating colors as appropriate.

 ``1234567`` ``````for (yf in dest->h) for (xf in dest->w) { xs, ys = Rotate( -degrees, XY( xf, yf ), XY( ... ) ); Set_Pixel( dest, xf, yf, Get_Pixel( source, xs, ys ) ); }``````

The above code just grabs the most convenient pixel, meaning that the resulting image will have obvious artifacts in it.

If you wish to actually sample the source image instead of just getting the closest pixel, make sure that xs and ys are float and then get the four closest pixel colors. Weight them by how close they are to the point, then combine them using a simple linear average. (Remember to handle each color component separately.)

Hope this helps.
Thanks for the help. I modified my Spin function a little using your advice ( I didn't follow your advice exactly for sake of simplicity since the surface I'm rotating is all one color ), but I'm going to check out SDL_gfx for future programs instead of using my function.
Personally I wouldn't spend too much time looking into SDL_gfx and try to switch over to opengl to do scaling/rotating etc. It will perform much faster and I'm sure it will help in the future.

(I am guessing you have thought of this already as well).
Topic archived. No new replies allowed.