diff --git a/utils.cpp b/utils.cpp index 6b8cee8..cda11b7 100644 --- a/utils.cpp +++ b/utils.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,7 @@ static int cmpstringp(const void *p1, const void *p2) const char *p1_s = *(const char**)p1; const char *p2_s = *(const char**)p2; - /* Put directories first */ + /* Put directories first and handle some special cases */ if (*p1_s == '[' && *p2_s != '[') return -1; if (*p1_s != '[' && *p2_s == '[') @@ -107,6 +108,9 @@ const char **get_file_list(const char *base_dir, const char *exts[]) char *p; size_t len = strlen(de->d_name) + 4; + /* We don't need the current dir */ + if (strcmp(de->d_name, ".") == 0) + continue; p = (char*)malloc( len ); snprintf(p, len, "[%s]", de->d_name); file_list[cur++] = p; @@ -134,3 +138,103 @@ const char **get_file_list(const char *base_dir, const char *exts[]) return file_list; } + + +/* PNG writing */ +struct png_write_user_struct +{ + size_t sz; + void *data; +}; + +static void user_write_fn(png_structp png_ptr, png_bytep bytes, png_size_t sz) +{ + struct png_write_user_struct *out = (struct png_write_user_struct *)png_ptr->io_ptr; + + out->data = xrealloc(out->data, out->sz + sz); + memcpy((uint8_t*)out->data + out->sz, bytes, sz); + out->sz += sz; +} + + +static int png_colortype_from_surface(SDL_Surface *surface) +{ + int colortype = PNG_COLOR_MASK_COLOR; /* grayscale not supported */ + + if (surface->format->palette) + colortype |= PNG_COLOR_MASK_PALETTE; + else if (surface->format->Amask) + colortype |= PNG_COLOR_MASK_ALPHA; + + return colortype; +} + + +static void png_user_warn(png_structp ctx, png_const_charp str) +{ + fprintf(stderr, "libpng: warning: %s\n", str); +} + + +static void png_user_error(png_structp ctx, png_const_charp str) +{ + fprintf(stderr, "libpng: error: %s\n", str); +} + + +/* This is taken from http://encelo.netsons.org/programming/sdl (GPLed) */ +void *sdl_surface_to_png(SDL_Surface *surf, size_t *out_sz) +{ + png_structp png_ptr; + png_infop info_ptr; + int i, colortype; + png_bytep *row_pointers; + struct png_write_user_struct out; + + out.sz = 0; + out.data = NULL; + + /* Initializing png structures and callbacks */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, png_user_error, png_user_warn); + if (png_ptr == NULL) { + printf("png_create_write_struct error!\n"); + return NULL; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + printf("png_create_info_struct error!\n"); + exit(-1); + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + exit(-1); + } + + png_set_write_fn(png_ptr, (void *)&out, user_write_fn, NULL); + + colortype = png_colortype_from_surface(surf); + png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + /* Writing the image */ + png_write_info(png_ptr, info_ptr); + png_set_packing(png_ptr); + + row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surf->h); + for (i = 0; i < surf->h; i++) + row_pointers[i] = (png_bytep)(Uint8 *)surf->pixels + i*surf->pitch; + png_write_image(png_ptr, row_pointers); + png_write_end(png_ptr, info_ptr); + + /* Cleaning out... */ + free(row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + + *out_sz = out.sz; + + return out.data; +} diff --git a/utils.hh b/utils.hh index 48f719a..6ab5210 100644 --- a/utils.hh +++ b/utils.hh @@ -5,6 +5,7 @@ #include #include +#include #include #define BUG_ON(cond) @@ -57,4 +58,6 @@ TTF_Font *read_and_alloc_font(const char *path, int pt_size); const char **get_file_list(const char *base_dir, const char *exts[]); +void *sdl_surface_to_png(SDL_Surface *src, size_t *out_sz); + #endif /* __UTILS_H__ */