Lephisto/utils/mkspr/main.c
2013-06-23 16:21:16 +02:00

228 lines
5.8 KiB
C

#include <stdlib.h>
#include <malloc.h>
#include <png.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
# define RMASK 0xff000000
# define BMASK 0x00ff0000
# define GMASK 0x0000ff00
# define AMASK 0x000000ff
#else
# define RMASK 0x000000ff
# define BMASK 0x0000ff00
# define GMASK 0x00ff0000
# define AMASK 0xff0000
#endif
#define RGBAMASK RMASK, GMASK, BMASK, AMASK
/* Logging macros. */
#define LOG(str, args...)(fprintf(stdout, str"\n", ## args))
#define WARN(str, args...)(fprintf(stderr, "Warning: "str"\n", ## args))
#define ERR(str, args...) { fprintf(stderr, "ERROR %s:%d: "str"\n", \
__FILE__, __LINE__, ## args); return EXIT_FAILURE; }
#define WS 6
#define HS 6
static int save_png(SDL_Surface* surface, const char* file);
static int write_png(const char* file_name, png_bytep* rows, int w, int h, int colourtype, int bitdepth);
int main(int argc, char* argv[]) {
int i, ws, hs;
unsigned int sflags, salpha;
char file[8];
SDL_Surface* final, *tmp, **load;
SDL_Rect r;
/* Init variables. */
r.w = r.h = 0;
if(argc == 2) {
ws = hs = atoi(argv[1]);
}
else if(argc == 3) {
ws = atoi(argv[1]);
hs = atoi(argv[2]);
} else {
ws = WS;
hs = HS;
}
load = NULL;
tmp = NULL;
final = NULL;
/* Init SDL. */
if(SDL_Init(SDL_INIT_VIDEO)) ERR("Initializing SDL: %s", SDL_GetError());
/* Create the window. */
tmp = SDL_SetVideoMode(320, 240, 0, SDL_NOFRAME);
if(tmp == NULL) ERR("Initializing video surface: %s", SDL_GetError());
/* Open RAM for the images. */
load = malloc(sizeof(SDL_Surface*)*(ws*hs));
if(load == NULL) ERR("Out of RAM");
/* Load all the images to RAM. */
for(i = 0; i < (ws*hs); i++) {
/* Filenames will be in the sequence of: 000.png, 001.png, ..., 045.png, etc. */
sprintf(file, "%d%d%d.png", i/100, (i%100)/10, i%10);
/* Load the image properly. */
tmp = IMG_Load(file);
if(tmp == NULL) ERR("Problem loading file '%s': %s", file, IMG_GetError());
sflags = tmp->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY);
salpha = tmp->format->alpha;
if(sflags & SDL_SRCALPHA)
SDL_SetAlpha(tmp, 0, SDL_ALPHA_OPAQUE);
if(sflags & SDL_SRCCOLORKEY)
SDL_SetColorKey(tmp, 0, tmp->format->colorkey);
load[i] = tmp;
/* Check if size has changed. */
if(r.w == 0 && r.h == 0) {
r.w = load[i]->w;
r.h = load[i]->h;
}
else if((r.w != load[i]->w) || (r.h != load[i]->h))
ERR("File '%s' is not of the same dimensions as the files before!", file);
/* Create the suface if it hasn't been created already. */
if(!final) {
final = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, ws*r.w, hs*r.h,
load[i]->format->BitsPerPixel, RGBAMASK);
if(!final) ERR("Problem creating RGB Surface: %s", SDL_GetError());
tmp = final;
}
/* New position. */
r.y = r.h * (i/ws);
r.x = r.w * (i%ws);
if(SDL_BlitSurface(load[i], NULL, final, &r))
ERR("Problem blitting surface '%s' to final surface: %s", file, SDL_GetError());
SDL_FreeSurface(load[i]);
}
/* Draw the result and cleanup. */
save_png(final, "sprite.png");
SDL_FreeSurface(final);
free(load);
SDL_Quit();
return EXIT_SUCCESS;
}
static int save_png(SDL_Surface* surface, const char* file) {
static unsigned char** ss_rows;
static int ss_size;
static int ss_w, ss_h;
SDL_Surface* ss_surface;
SDL_Rect ss_rect;
int r, i;
int alpha = 0;
int pixel_bits = 32;
unsigned surf_flags;
unsigned surf_alpha;
ss_rows = 0;
ss_size = 0;
ss_surface = 0;
ss_w = surface->w;
ss_h = surface->h;
if(surface->format->Amask) {
alpha = 1;
pixel_bits = 32;
} else {
pixel_bits = 24;
}
ss_surface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, ss_w, ss_h, pixel_bits, RGBAMASK);
if(ss_surface == 0) {
return -1;
}
surf_flags = surface->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY);
surf_alpha = surface->format->alpha;
if(surf_flags & SDL_SRCALPHA)
SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE);
if(surf_flags & SDL_SRCCOLORKEY)
SDL_SetColorKey(surface, 0, surface->format->colorkey);
ss_rect.x = 0;
ss_rect.y = 0;
ss_rect.w = ss_w;
ss_rect.h = ss_h;
SDL_BlitSurface(surface, &ss_rect, ss_surface, 0);
if(ss_size == 0) {
ss_size = ss_h;
ss_rows = (unsigned char**)malloc(sizeof(unsigned char*) * ss_size);
if(ss_rows == 0) {
return -1;
}
}
if(surf_flags & SDL_SRCALPHA)
SDL_SetAlpha(surface, SDL_SRCALPHA, (Uint8)surf_alpha);
if(surf_flags & SDL_SRCCOLORKEY)
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, surface->format->colorkey);
for(i = 0; i < ss_h; i++) {
ss_rows[i] = ((unsigned char*)ss_surface->pixels) + i * ss_surface->pitch;
}
if(alpha) {
r = write_png(file, ss_rows, surface->w, surface->h, PNG_COLOR_TYPE_RGB_ALPHA, 8);
} else {
r = write_png(file, ss_rows, surface->w, surface->h, PNG_COLOR_TYPE_RGB, 8);
}
free(ss_rows);
SDL_FreeSurface(ss_surface);
ss_surface = NULL;
return r;
}
static int write_png(const char* file_name, png_bytep* rows, int w, int h, int colourtype, int bitdepth) {
png_structp png_ptr;
png_infop info_ptr;
FILE* fp = NULL;
char* doing = "Open for writing";
if(!(fp = fopen(file_name, "wb"))) goto fail;
doing = "Create png info struct";
if(!(info_ptr = png_create_info_struct(png_ptr))) goto fail;
if(setjmp(png_jmpbuf(png_ptr))) goto fail;
doing = "Init IO";
png_init_io(png_ptr, fp);
png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colourtype, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
doing = "Write info";
png_write_end(png_ptr, info_ptr);
doing = "Write image";
png_write_image(png_ptr, rows);
doing = "Write end";
png_write_end(png_ptr, NULL);
doing = "Closing file";
if(0 != fclose(fp)) goto fail;
return 0;
fail:
WARN("write_png: Could not %s", doing);
return -1;
}