I am writing a 2d game engine out of SDL using the ada binding and found what seems to be useful code for image rotation (similar to rotozoom). The code itself, although well formatted, is completely uncommented. I, as I previously stated, am not well versed in the C language and therefore do not completely comprehend the necessity, if existent, of the bit-wise manipulation.
If someone could explain the reasoning behind this and answer the questions preceding the following snippets, in particular, it would be greatly appreciated.
Bit-shifting instead of typecasting?
Code:
newx = rotx >> 16;
newy = roty >> 16;
What pointers, where?!
Code:
*(Uint16 *) dp = *(Uint16 *) sp;
I am assuming that bpp retains its assigned value after this IF statement, is this correct?
Code:
if((bpp = Surface->format->BytesPerPixel) == 3) {
....
Code for the whole function...
Code:
#include "SDL_Bilinear.h"
SDL_Surface *SDL_Rotate(SDL_Surface *Surface, double angle) {
double dcos = cos(angle);
double dsin = sin(angle);
int iWidth = (int) ceil(ABS(Surface->h * dsin) + ABS(Surface->w * dcos));
int iHeight = (int) ceil(ABS(Surface->h * dcos) + ABS(Surface->w * dsin));
int centre_x = Surface->w << 15;
int centre_y = Surface->h << 15;
int dx = iWidth >> 1;
int dy = iHeight >> 1;
int rotx, roty, newx, newy, x, y;
int ncos = (int) (dcos * 65536.0f);
int nsin = (int) (dsin * 65536.0f);
int srotx = (int) (-dx * ncos + dy * nsin) + centre_x;
int sroty = (int) (-dx * nsin - dy * ncos) + centre_y;
Uint8 *sp, *dp, bpp;
Uint16 destinationGap;
SDL_Surface *destination;
if((bpp = Surface->format->BytesPerPixel) == 3) {
return NULL;
}
if((destination = SDL_CreateRGBSurface(Surface->flags, iWidth, iHeight,
Surface->format->BitsPerPixel,
Surface->format->Rmask,
Surface->format->Gmask,
Surface->format->Bmask,
Surface->format->Amask)) == NULL) {
return NULL;
}
if(SDL_MUSTLOCK(Surface)) {
if(SDL_LockSurface(Surface) < 0) {
return NULL;
}
}
if(SDL_MUSTLOCK(destination)) {
if(SDL_LockSurface(destination) < 0) {
return NULL;
}
}
dp = (Uint8 *) destination->pixels;
destinationGap = destination->pitch - destination->w * bpp;
for(y = 0; y < iHeight; y++) {
rotx = srotx = srotx - nsin;
roty = sroty = sroty + ncos;
for(x = 0; x < iWidth; x++) {
newx = rotx >> 16;
newy = roty >> 16;
if(newx >= 0 && newx < Surface->w && newy >= 0 && newy < Surface->h) {
sp = (Uint8 *) Surface->pixels
+ (((int) newy) * Surface->pitch)
+ (((int) newx) * bpp);
switch(bpp) {
case 1:
*dp = *sp;
break;
case 2:
*(Uint16 *) dp = *(Uint16 *) sp;
break;
case 4:
*(Uint32 *) dp = *(Uint32 *) sp;
break;
default:
break;
}
}
rotx += ncos;
roty += nsin;
dp += bpp;
}
dp += destinationGap;
}
if(SDL_MUSTLOCK(Surface)) {
SDL_UnlockSurface(Surface);
}
if(SDL_MUSTLOCK(destination)) {
SDL_UnlockSurface(destination);
}
return destination;
}
Thanks in advance (for scrolling at least)!