• 12
• 12
• 9
• 10
• 13

# 2D Image Rotation around origin

This topic is 3867 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, Sorry if this is in the wrong forum, it seemed the most appropriate. I have a problem with my rotation which im stumped with. Im trying to rotate the image around its centre. The image rotates but the drawing area when rotated by so much cuts off the image :(. This can be seen in the image at the below link, when progressing to 90degree rotation the image is now not drawn :/. Any help would be greatly appreciated.
float radians = (2*3.1416*angle)/360;

int x1 = (int)(-m_imageheight * sine);
int y1 = (int)(m_imageheight * cosine);
int x2 = (int)(m_imagewidth * cosine - m_imageheight * sine);
int y2 = (int)(m_imageheight * cosine + m_imagewidth * sine);
int x3 = (int)(m_imagewidth * cosine);
int y3 = (int)(m_imagewidth * sine);

int minx = min(0,min(x1, min(x2,x3)));
int miny = min(0,min(y1, min(y2,y3)));
int maxx = max(x1, max(x2,x3));
int maxy = max(y1, max(y2,y3));

int w = maxx - minx;
int h = maxy - miny;

int xyoffet = (x + y * windowWidth);

int x10 = m_imagewidth/2;
int y10 = m_imageheight/2;

for( int y_ = (miny-y10); y_ <= (maxy-y10); y_++ )
{
for( int x_ = (minx-x10); x_ <= (maxx-x10); x_++ )
{
int sourcex = x_*cosine + y_*sine;
int sourcey = y_*cosine - x_*sine;

if( (sourcex + x10) >= 0 && (sourcex + x10) < m_imagewidth && (sourcey + y10) >= 0 && (sourcey + y10) < m_imageheight )
topleftimage[ (x_ + x10) + ((y_ + y10) * windowWidth) +xyoffet ] = imagepointer[ (sourcex+x10) + m_imagewidth * (sourcey+y10) ];
}
}



##### Share on other sites
The image is probably rotating fine, but it looks like you're not expanding or rotating the actual drawing surface for the image. Are you doing this in DirectX?

##### Share on other sites
Its straight from source image data to screen data, not directx. I have seen a few methods similar and when trying them I also get the same problem.

##### Share on other sites
If I'm right then your routine iterates the drawing area on a per pixel basis, computes where the pixel originates in the source image, and transfers that pixel. This is, in fact, the correct way of doing such things.

However, the extent of the drawing area is definitely given by the ranges of the both loops y_ and x_. Presumbly you want to iterate over the _whole_ drawing area.

EDIT: You're doing much "mysterious" calculations that look like optimizations to me. Perhaps you should go back to the roots by calculating the original pixel address in 1 step inside the loops e.g. by a combined affine transformation and look what happens if changing things. This would give you the flexibility of scaling and translation and non-center rotations all at once. Later then, with that understanding, start to optimize if necessary.

##### Share on other sites
The drawing area within the loops appears to be correct on debuggin though which is whats annoying me.

EDIT: The method is described here

##### Share on other sites

I went back to basics and tried rotating around the top left 0,0 and the problem similar is in here also.
It is fine until 90 degrees in which the edges start to move in similar to the previous problem.

	float radians = (2*3.1416*angle)/360;	float cosine = (float)cos(radians);	float sine = (float)sin(radians);	int x1 = (-m_imageheight * sine);	int y1 = (m_imageheight * cosine);	int x2 = ((m_imagewidth * cosine) - (m_imageheight * sine));	int y2 = ((m_imageheight * cosine) + (m_imagewidth * sine));	int x3 = (m_imagewidth * cosine);	int y3 = (m_imagewidth * sine);	int minx = min(0,min(x1, min(x2,x3)));	int miny = min(0,min(y1, min(y2,y3)));	int maxx = max(x1, max(x2,x3));	int maxy = max(y1, max(y2,y3));	int w = maxx - minx;	int h = maxy - miny;	int xyoffet = (x + y * windowWidth);	for( int y_ = miny; y_ < maxy; y_++ )	{		for( int x_ = minx; x_ < maxx; x_++ )		{			int sourcex = x_*cosine + y_*sine;			int sourcey = y_*cosine - x_*sine;			if( sourcex >= 0 && sourcex < m_imagewidth && sourcey >= 0 && sourcey < m_imageheight )				topleftimage[x_+(y_*windowWidth)+xyoffet] = imagepointer[sourcex+(m_imagewidth*sourcey)];		}	}

##### Share on other sites
Here's some SDL code I came up with a while back for an Asteroids clone I am/was working on:
void RotBlitSurface(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect, int angle){        double cosT, sinT;        double radangle = angle * (3.141592654 / 180.0);        cosT = cos(radangle);        sinT = sin(radangle);        // fix alignment on cardinal directions        if(angle == 0)   { cosT = 1; sinT = 0; }        if(angle == 90)  { cosT = 0; sinT = 1; }        if(angle == 180) { cosT = -1; sinT = 0; }        if(angle == 270) { cosT = 0; sinT = -1; }        // center of rotation        int x1p = srcrect->w/2 + srcrect->x;        int y1p = srcrect->h/2 + srcrect->y;        // blit position        int x1 = dstrect->x + dstrect->w/2;        int y1 = dstrect->y + dstrect->h/2;        // destination area (clipped to dst surface)        int min_x = max(dstrect->x, (Sint16)0);         // cast to shut up gcc/STL        int max_x = min(min_x+dstrect->w, dst->w);        int min_y = max(dstrect->y, (Sint16)0);        int max_y = min(min_y+dstrect->h, dst->h);        Uint32* s = (Uint32*)src->pixels;        Uint32* d = (Uint32*)dst->pixels;        Uint32 color;        double xp, yp;        for(int y = min_y; y < max_y; y++)        {                xp = (min_x-x1)*cosT + (y-y1)*sinT + x1p;                yp = (y-y1)*cosT - (min_x-x1)*sinT + y1p;                for(int x = min_x; x < max_x; x++)                {                        if(xp >= srcrect->x &&                           yp >= srcrect->y &&                           xp < srcrect->x+srcrect->w &&                           yp < srcrect->y+srcrect->h)                        {                                color = s[(int)xp+(int)yp*src->w];                                if(color != src->format->colorkey) d[x+y*dst->w] = color;                        }                        xp += cosT;                        yp -= sinT;                }        }}

I'm pretty sure I simply glued together two rotation algorithms I found, but I can't remember which ones.

Off-topic, but does anyone know why my code is double-spaced? It looks fine on my system, but gdnet seems to mangle it somehow.

Oops, forgot usage. Make sure dstrect is large enough to contain your rotated sprite, otherwise it will clip to dstrect as in your screenshots.

EDIT: Fixed code spacing.

[Edited by - GenPFault on August 19, 2007 10:17:23 AM]

##### Share on other sites
Quote:
 Original post by GenPFault[...]Off-topic, but does anyone know why my code is double-spaced? It looks fine on my system, but gdnet seems to mangle it somehow.[...]
It's probably related to line endings. I'd guess you are on a mac, which has line endings in the opposite order as windows (one is CR LF the other LF CR) and the way GDNet copes with "broken"(since it's made for windows probably) line endings ends up expanding mac line endings to two HTML line endings.

##### Share on other sites
Quote:
Original post by Extrarius
Quote:
 Original post by GenPFault[...]Off-topic, but does anyone know why my code is double-spaced? It looks fine on my system, but gdnet seems to mangle it somehow.[...]
It's probably related to line endings. I'd guess you are on a mac, which has line endings in the opposite order as windows (one is CR LF the other LF CR) and the way GDNet copes with "broken"(since it's made for windows probably) line endings ends up expanding mac line endings to two HTML line endings.

Linux, actually. Copy-pasted out of gedit, so it's probably just LF's. Weird. Thanks for the heads-up though.

##### Share on other sites
thanks, I sorted this now with centre origin. It was the drawing area, I devised a method which changed the loop sizes so they expand and decrease with the size.

Now to think how to do pixel collisions between the rotated and scaled sprites :/, but thats another problem.