Difference between revisions of "Vertically invert a surface in SDL"
Jump to navigation
Jump to search
Line 44: | Line 44: | ||
} | } | ||
− | return 1; | + | return 0; |
+ | } | ||
+ | </nowiki> | ||
+ | |||
+ | |||
+ | Here's another one that does one fewer <code>memcpy</code> per two rows, but then must do a large <code>memmove</code> near the end. This one I believe would be less computationally intensive. And, of course, I haven't tested this code in SDL yet. | ||
+ | |||
+ | <nowiki> | ||
+ | #define SDL_LOCKIFMUST(s) (SDL_MUSTLOCK(s) ? SDL_LockSurface(s) : 0) | ||
+ | #define SDL_UNLOCKIFMUST(s) { if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); } | ||
+ | |||
+ | int invert_surface_vertical(SDL_Surface *surface) | ||
+ | { | ||
+ | Uint8 *t; | ||
+ | register Uint8 *a, *b; | ||
+ | Uint8 *last; | ||
+ | register Uint16 pitch; | ||
+ | |||
+ | if( SDL_LOCKIFMUST(surface) < 0 ) | ||
+ | return -2; | ||
+ | |||
+ | /* do nothing unless at least two lines */ | ||
+ | if(surface->h < 2) { | ||
+ | SDL_UNLOCKIFMUST(surface); | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | /* get a place to store a line */ | ||
+ | pitch = surface->pitch; | ||
+ | t = (Uint8*)malloc(pitch); | ||
+ | |||
+ | if(t == NULL) { | ||
+ | SDL_UNLOCKIFMUST(surface); | ||
+ | return -2; | ||
+ | } | ||
+ | |||
+ | /* get first line; it's about to be trampled */ | ||
+ | memcpy(t,surface->pixels,pitch); | ||
+ | |||
+ | /* now, shuffle the rest so it's almost correct */ | ||
+ | a = (Uint8*)surface->pixels; | ||
+ | last = a + pitch * (surface->h - 1); | ||
+ | b = last; | ||
+ | |||
+ | while(a < b) { | ||
+ | memcpy(a,b,pitch); | ||
+ | a += pitch; | ||
+ | memcpy(b,a,pitch); | ||
+ | b -= pitch; | ||
+ | } | ||
+ | |||
+ | /* in this shuffled state, the bottom slice is too far down */ | ||
+ | memmove( b, b+pitch, last-b ); | ||
+ | |||
+ | /* now we can put back that first row--in the last place */ | ||
+ | memcpy(last,t,pitch); | ||
+ | |||
+ | /* everything is in the right place; close up. */ | ||
+ | free(t); | ||
+ | SDL_UNLOCKIFMUST(surface); | ||
+ | |||
+ | return 0; | ||
} | } | ||
</nowiki> | </nowiki> |
Revision as of 03:56, 1 June 2005
This code flips an SDL_Surface
upside-down by using a buffer the size of one line of the image to swap the first and last successively until the middle is reached.
int invert_surface_vertical(SDL_Surface *surface) { /* buffer big enough for one line of this image */ Uint8 *line; Uint8 *a, *b; Uint16 pitch; if( SDL_MUSTLOCK(surface) ) { if( SDL_LockSurface(surface) < 0 ) { return -2; } } pitch = surface->pitch * sizeof(Uint8); line = (Uint8*)malloc(pitch); if( line == NULL ) return -1; /* let us begin swapping the first and last lines of an ever-narrowing area of the image */ a = (Uint8*)surface->pixels; b = a + pitch * (surface->h - 1); while( a < b ) { /* memcpy(dest, src, len) */ memcpy(line, b, pitch); memcpy(b, a, pitch); memcpy(a, line, pitch); a += pitch; b -= pitch; } free(line); if( SDL_MUSTLOCK(surface) ) { SDL_UnlockSurface(surface); } return 0; }
Here's another one that does one fewer memcpy
per two rows, but then must do a large memmove
near the end. This one I believe would be less computationally intensive. And, of course, I haven't tested this code in SDL yet.
#define SDL_LOCKIFMUST(s) (SDL_MUSTLOCK(s) ? SDL_LockSurface(s) : 0) #define SDL_UNLOCKIFMUST(s) { if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); } int invert_surface_vertical(SDL_Surface *surface) { Uint8 *t; register Uint8 *a, *b; Uint8 *last; register Uint16 pitch; if( SDL_LOCKIFMUST(surface) < 0 ) return -2; /* do nothing unless at least two lines */ if(surface->h < 2) { SDL_UNLOCKIFMUST(surface); return 0; } /* get a place to store a line */ pitch = surface->pitch; t = (Uint8*)malloc(pitch); if(t == NULL) { SDL_UNLOCKIFMUST(surface); return -2; } /* get first line; it's about to be trampled */ memcpy(t,surface->pixels,pitch); /* now, shuffle the rest so it's almost correct */ a = (Uint8*)surface->pixels; last = a + pitch * (surface->h - 1); b = last; while(a < b) { memcpy(a,b,pitch); a += pitch; memcpy(b,a,pitch); b -= pitch; } /* in this shuffled state, the bottom slice is too far down */ memmove( b, b+pitch, last-b ); /* now we can put back that first row--in the last place */ memcpy(last,t,pitch); /* everything is in the right place; close up. */ free(t); SDL_UNLOCKIFMUST(surface); return 0; }