If the image (png btw) is just a plain old array, and I could modify it like an array, then I could do it myself (that is, if I know how to access the image like an array).
so here's my pseudo algorithm
surface newtile
newtile width = 32 //same width as a normal tile
newtile height = 32 // "" height"" "" "" "" "" "
copy the tile data to new tile with a for loop
rotate new tile with a for loop
merge tilesheet and newtile with for loop
I know how to rotate things with a for loop, I already made an algorithm for that.
Now, I guess my question is, can a surface be accessed like an array? or how can I modify, access certain pixels?
[SOLVED][SDL] Rotating a specific area of a surface
Moderator: Coders of Rage
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: [SDL] Rotating a specific area of a surface
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
-
- Respected Programmer
- Posts: 387
- Joined: Fri Dec 19, 2008 3:33 pm
- Location: Dallas
- Contact:
Re: [SDL] Rotating a specific area of a surface
Now yer thinkin.
Absolutely you can. Just like a regular array, you can offset by width and height. The only difference in an image is that you have to offset by the bytes per pixel as well. So when you map the tilesheet from memory, you can read in pixel by pixel with whatever looping structure you've got. If you've got a 24 bit image (RGB8), then thats 3 bytes per pixel (3 chars per pixel). If the format is BGR8, then simply interpret the pixel order in reverse. Same goes for a 32 bit image (RGBA8), then thats 4 bytes per pixel (4 chars per pixel).
OR...you can forego that and just setup a struct for common pixel types
struct RGBA8_PIX
{
char r, g, b, a;
};
struct BGRA8_PIX
{
char b, g, r, a;
};
then read in RGBA8_PIX or BGRA_8 pix. Whatever works for ya.
Absolutely you can. Just like a regular array, you can offset by width and height. The only difference in an image is that you have to offset by the bytes per pixel as well. So when you map the tilesheet from memory, you can read in pixel by pixel with whatever looping structure you've got. If you've got a 24 bit image (RGB8), then thats 3 bytes per pixel (3 chars per pixel). If the format is BGR8, then simply interpret the pixel order in reverse. Same goes for a 32 bit image (RGBA8), then thats 4 bytes per pixel (4 chars per pixel).
OR...you can forego that and just setup a struct for common pixel types
struct RGBA8_PIX
{
char r, g, b, a;
};
struct BGRA8_PIX
{
char b, g, r, a;
};
then read in RGBA8_PIX or BGRA_8 pix. Whatever works for ya.
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: [SDL] Rotating a specific area of a surface
What if I am unsure of the type? and if the type varies? if there a way to retrieve this information?
So, I would define those structs, and use something like
?
Would using the surface as an array return the type I want? :S
So, I would define those structs, and use something like
Code: Select all
RGBA8_PIX pixels[32][32];
for (int i=clip.y; i < clip.y + 32; i++)
{
for (int j = clip.x; j < clip.x + 32; j++)
{
pixel[j][(clip.y + 32 -1)-i] = surface[i][j];
}
}
for (int i=clip.y; i < clip.y + 32; i++)
{
for (int j = clip.x; j < clip.x + 32; j++)
{
surface[i][j] = pixel[i][j];
}
}
Would using the surface as an array return the type I want? :S
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
-
- Respected Programmer
- Posts: 387
- Joined: Fri Dec 19, 2008 3:33 pm
- Location: Dallas
- Contact:
Re: [SDL] Rotating a specific area of a surface
The API (whichever you're using...SDL, LibPNG or what have you) should be able to retrieve all that information for you. Either way, if you load an image you MUST know those things.
If the memory lock maps to a void* or char* then you can just cast it to a BGRA8_PIX type or what have you and you'd be reading pixel by pixel as opposed to byte by byte.
If the memory lock maps to a void* or char* then you can just cast it to a BGRA8_PIX type or what have you and you'd be reading pixel by pixel as opposed to byte by byte.
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: [SDL] Rotating a specific area of a surface
I am using SDl, but I also have LibPNG setup... I think using LibPNG should be easier right?
and I would do something like this right?
and I would do something like this right?
Code: Select all
RGBA8_PIX pixels[32][32];
SDL_Surface* surface;
surface = load_image("somepng.png");
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 32; j++)
{
pixels[i][j] = surface[i][j];
}
}
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
-
- Respected Programmer
- Posts: 387
- Joined: Fri Dec 19, 2008 3:33 pm
- Location: Dallas
- Contact:
Re: [SDL] Rotating a specific area of a surface
You might define something like so:
Code: Select all
struct RGBA8_PIX
{
char r, g, b, a; // 32 bpp in RGBA (DirectX style) ordering
};
struct RGB8_PIX
{
char r, g, b; // 24 bpp in RGB (DirectX style) ordering
};
template <class T>
static void swap_pix(T& l, T& r)
{
T tmp = l;
l = r;
t = tmp;
}
// Might check this looping structure, it's off the top of my head but should be fine //
// buf is an array of "whatever", be it chars, be it RGBA8_PIX, be it RGB8_PIX...etc etc //
template <class T>
static void rotate_90_ccw(T* buf, const int imgWidth, const int imgHeight)
{
for(int i = 0; i < imgWidth; ++i)
{
for(int j = 0; j < imgHeight; ++j)
{
int dest = i * imgWidth + j;
int src = ((imgHeight - i - 1) * imgWidth) + (imgWidth - j - 1);
swap_pix(buf[dest], buf[src]);
}
}
}
static void some_image_loading_thing( ... someParameters... )
{
// some image loading code goes here //
int bpp = Some_API_GetBitsPerPixel(ProbablyAnImageParameter); // BITS per pixel
int Bpp = bpp / 8; // BYTES per pixel
// The API probably gives you vodi* or char* when obtaining pixels //
// DO NOT....take this as an image loader design pattern....this is terrible and only serves to show you the interface //
if(Bpp == 3)
RGB8_PIX* pix = (RGB8_PIX*)Some_API_GetPixels(); // This is a MAPPING....meaning its an alias to memory for a texture THAT HAS ALREADY BEEN ALLOCATED
// thusly, you do not need to allocate "pix". If the function returns a COPY...you WILL need to allocate "pix"
else if(Bpp == 4)
RGBA8_PIX* pix = (RGBA8_PIX*)Some_API_GetPixels();
else
return;
int imgWidth = Some_API_GetImageWidth();
int imgHeight = Some_API_GetImageHeight();
rotate_90_ccw(pix, imgWidth, imgHeight);
}
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: [SDL] Rotating a specific area of a surface
D: ok, this is a bit advanced for me... but I think I am getting it lol. I'll try to implement and record my fail here.qpHalcy0n wrote:You might define something like so:
Code: Select all
struct RGBA8_PIX { char r, g, b, a; // 32 bpp in RGBA (DirectX style) ordering }; struct RGB8_PIX { char r, g, b; // 24 bpp in RGB (DirectX style) ordering }; template <class T> static void swap_pix(T& l, T& r) { T tmp = l; l = r; t = tmp; } // Might check this looping structure, it's off the top of my head but should be fine // // buf is an array of "whatever", be it chars, be it RGBA8_PIX, be it RGB8_PIX...etc etc // template <class T> static void rotate_90_ccw(T* buf, const int imgWidth, const int imgHeight) { for(int i = 0; i < imgWidth; ++i) { for(int j = 0; j < imgHeight; ++j) { int dest = i * imgWidth + j; int src = ((imgHeight - i - 1) * imgWidth) + (imgWidth - j - 1); swap_pix(buf[dest], buf[src]); } } } static void some_image_loading_thing( ... someParameters... ) { // some image loading code goes here // int bpp = Some_API_GetBitsPerPixel(ProbablyAnImageParameter); // BITS per pixel int Bpp = bpp / 8; // BYTES per pixel // The API probably gives you vodi* or char* when obtaining pixels // // DO NOT....take this as an image loader design pattern....this is terrible and only serves to show you the interface // if(Bpp == 3) RGB8_PIX* pix = (RGB8_PIX*)Some_API_GetPixels(); // This is a MAPPING....meaning its an alias to memory for a texture THAT HAS ALREADY BEEN ALLOCATED // thusly, you do not need to allocate "pix". If the function returns a COPY...you WILL need to allocate "pix" else if(Bpp == 4) RGBA8_PIX* pix = (RGBA8_PIX*)Some_API_GetPixels(); else return; int imgWidth = Some_API_GetImageWidth(); int imgHeight = Some_API_GetImageHeight(); rotate_90_ccw(pix, imgWidth, imgHeight); }
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
- xiphirx
- Chaos Rift Junior
- Posts: 324
- Joined: Mon Mar 22, 2010 3:15 pm
- Current Project: ******** (Unkown for the time being)
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C++
- Contact:
Re: [SDL] Rotating a specific area of a surface
*update*
Reporting in...
I have successfully gotten vertical flip and horizontal flip to work, and rotating by 90 degree increments shouldn't be hard at all. I just noticed that I overlooked one of lazyfoo's tutorials that deals with pixel manipulation. I copied his function over, and tweaked it so it rotates the individual tiles, and not the whole surface :3 I am very satisfied. Thank you qpHalcy0n and lazyfoo.
EDIT: FINISHED FUNCTIONS
Reporting in...
I have successfully gotten vertical flip and horizontal flip to work, and rotating by 90 degree increments shouldn't be hard at all. I just noticed that I overlooked one of lazyfoo's tutorials that deals with pixel manipulation. I copied his function over, and tweaked it so it rotates the individual tiles, and not the whole surface :3 I am very satisfied. Thank you qpHalcy0n and lazyfoo.
EDIT: FINISHED FUNCTIONS
Code: Select all
//Credit: LazyFoo (base function), qpHalcy0n (help), Xiphirx (tweaking)
void flip_surface( SDL_Surface *surface, int flags, int TILE_DIM)
{
int FLIP_VERTICAL = 1;
int FLIP_HORIZONTAL = 2;
SDL_Surface *flipped = NULL;
if (SDL_MUSTLOCK(surface))
{
SDL_LockSurface(surface);
}
if( surface->flags & SDL_SRCCOLORKEY )
{
flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, 0 );
}
else
{
flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask );
}
if( flags & FLIP_VERTICAL )
{
for (int i=0; i<flipped->h/TILE_DIM; i++)
{
//Go through columns
for( int x = 0, rx = flipped->w-1; x < flipped->w; x++, rx-- )
{
//Go through rows
for( int y = i*TILE_DIM, ry = i*TILE_DIM+TILE_DIM-1; y < i*TILE_DIM+TILE_DIM; y++, ry-- )
{
//Get pixel
Uint32 pixel = get_pixel32( surface, x, y );
put_pixel32( flipped, x, ry, pixel );
}
}
}
}
if( flags & FLIP_HORIZONTAL )
{
for (int i=0; i<flipped->w/TILE_DIM; i++)
{
//Go through columns
for( int x = i*TILE_DIM, rx = i*TILE_DIM+TILE_DIM-1; x < i*TILE_DIM+TILE_DIM; x++, rx-- )
{
//Go through rows
for( int y = 0, ry = flipped->h-1; y < flipped->h; y++, ry-- )
{
//Get pixel
Uint32 pixel = get_pixel32( surface, x, y );
put_pixel32( flipped, rx, y, pixel );
}
}
}
}
if( SDL_MUSTLOCK( surface ) )
{
SDL_UnlockSurface( surface );
}
if( surface->flags & SDL_SRCCOLORKEY )
{
SDL_SetColorKey( flipped, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );
}
SDL_Rect clip;
clip.x = clip.y = 0;
clip.h = flipped->h;
clip.w = flipped->w;
SDL_BlitSurface(flipped, &clip, surface, &clip);
SDL_FreeSurface(flipped);
}
void rotate_surface( SDL_Surface *surface, int flags, SDL_Rect* clip)
{
int DEG90 = 1;
int DEGn90 = 2;
SDL_Surface *rotated = NULL;
if (SDL_MUSTLOCK(surface))
{
SDL_LockSurface(surface);
}
if( surface->flags & SDL_SRCCOLORKEY )
{
rotated = SDL_CreateRGBSurface( SDL_SWSURFACE, clip->w, clip->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, 0 );
}
else
{
rotated = SDL_CreateRGBSurface( SDL_SWSURFACE, clip->w, clip->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask );
}
if( flags & DEG90 )
{
for (int y=0; y < rotated->h; y++)
{
for (int x=0; x < rotated->w; x++)
{
Uint32 pixel = get_pixel32(surface, clip->x+x, clip->y+y);
put_pixel32(rotated, rotated->h-y-1, x, pixel);
}
}
}
if( flags & DEGn90 )
{
for (int y=0; y < rotated->h; y++)
{
for (int x=0; x < rotated->w; x++)
{
Uint32 pixel = get_pixel32(surface, clip->x+x, clip->y+y);
put_pixel32(rotated, y,rotated->h-x-1, pixel);
}
}
}
if( SDL_MUSTLOCK( surface ) )
{
SDL_UnlockSurface( surface );
}
if( surface->flags & SDL_SRCCOLORKEY )
{
SDL_SetColorKey( rotated, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );
}
SDL_Rect offset, blergh;
offset.x = clip->x;
offset.y = clip->y;
offset.w = surface->w;
offset.h = surface->h;
blergh.x = blergh.y = 0;
blergh.w = clip->w;
blergh.h = clip->h;
SDL_BlitSurface(rotated, &blergh, surface, &offset);
SDL_FreeSurface(rotated);
}
StarCraft II Zerg Strategy, open to all levels of players!
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of
Looking for paid work :< Contact me if you are interested in creating a website, need a web design, or anything else you think I'm capable of