[SDL] Rotating an image.

Started by
1 comment, last by nyrhinen 17 years, 7 months ago
My question today is, "How to rotate an image with SDL?". I've tried SDL_Gfx's rotozoom, but I'd like to make my own function for that. So I started to study math, and I have accomplished a code like this:

#include <math.h>
#include <SDL/SDL.h>
	#define PI 3.14159
	#define SWIDTH 640
	#define SHEIGHT 400
void Putpixel(SDL_Surface *screen, int x, int y, int r, int g, int b) {
	unsigned char *pixel;
	pixel = screen->pixels;
	pixel = pixel + y * SWIDTH * 4;
	pixel = pixel + x * 4;
	*pixel = b; pixel++;
	*pixel = g; pixel++;
	*pixel = r;
}
int sgn (long a) {
	if (a > 0) return +1;
		else if (a < 0) return -1;
			else return 0;
}
void Line(SDL_Surface *screen, int a, int b, int c, int d, int col) {
	long u,s,v,d1x,d1y,d2x,d2y,m,n;
	int  i;
	u   = c-a;
	v   = d-b;
	d1x = sgn(u);
	d1y = sgn(v);
	d2x = sgn(u);
	d2y = 0;
	m   = abs(u);
	n   = abs(v);
	if (m <= n) {
		d2x = 0;
		d2y = sgn(v);
		m   = abs(v);
		n   = abs(u);
	}
	s = (int)(m / 2);
	for (i = 0; i < round(m); i++) {
		Putpixel(screen, a, b, 255, 255, 255);
		s = s + n;
		if (s >= m) {
			s = s - m;
			a = a + d1x;
			b = b + d1y;
		} else {
			a = a + d2x;
			b = b + d2y;
		}
	}
}
int main(int argc, char *argv[])
{
	SDL_Init(SDL_INIT_VIDEO);
	SDL_WM_SetCaption("Rotating", NULL);
	SDL_Surface *screen = SDL_SetVideoMode(640, 400, 32, SDL_SWSURFACE);
	SDL_Event event;
	int angle = 0, i;
	while (1) {
		SDL_FillRect(screen, NULL, 0);
		SDL_PollEvent(&event);
		if (event.type == SDL_QUIT) break;
			else if (event.type == SDL_KEYDOWN)
				if (event.key.keysym.sym == SDLK_ESCAPE) break;
		Line(screen, 320, 200, -sin(angle*PI/180)*100+320, cos(angle*PI/180)*100+200, 255);
		Line(screen, 320, 200, -sin((angle+90)*PI/180)*100+320, cos((angle+90)*PI/180)*100+200, 255);
		if (angle > 360) angle = 0;
		angle = angle + 1;
		SDL_Delay(1);
		SDL_Flip(screen);
	}
	SDL_FreeSurface(screen);
	SDL_Quit();
	return 0;
}

No comments, sorry. :-) But the code above rotates a corner (two lines), and my goal with that code was to rotate a full square, and then texturise it with lines. Yes, I know, it sounds stupid, but it was the first thing that came to my mind. So any ideas to rotate a texturised image? Or to improve my code above? Thanks already! -nyrhinen
The important thing is to never stop questioning. - Albert Einstein
Advertisement
The main problem with that method is that unless your vertices are screen-aligned, filling it in with lines won't necessarily fill the box - you'll get missing and duplicated pixels.

Anyway, the idea is to create the new quad by rotating the vertices of the original, then rasterise it using the original as the sample source (texture): Once the quad has been transformed, determine which pixels lie within the new bounds (a couple of linear inequalities will take care of this). For each of these, transform the coordinates back (inverse rotate) to find out which part of the original quad it came from and determine the pixel colour from there.
A pixel-rotate will use a point-sampler, which rounds the result (of the reverse rotation) to the nearest pixel before reading in the colour. This looks pretty rough. A much prettier sampling technique is the bilinear filter, which takes the weighted average of the nearest two pixels in each dimension and averages the result. This will only work with continuous colour scales (so no palettes), will produce colours that don't appear in the original and, if done many times, will blur the image noticeably.

As you can see, this involves a fair bit of work, but it's rewarding when your implementation works. I'm sure other posters can suggest some optimisations for/details on/alternatives to the technique.

Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by TheAdmiral
The main problem with that method is that unless your vertices are screen-aligned, filling it in with lines won't necessarily fill the box - you'll get missing and duplicated pixels.

I was aware of that when I started doing this, but I just wanted a basic rotater, not anything fancy.
But about that bilinear-techique, any examples or something?

-nyrhinen

[Edited by - nyrhinen on September 7, 2006 3:06:30 AM]
The important thing is to never stop questioning. - Albert Einstein

This topic is closed to new replies.

Advertisement