use SDL_RWops to read png textures

This commit is contained in:
Andrei "Akari" Alexeyev 2017-03-12 23:07:21 +02:00
parent a787f88cff
commit 4b132656a5
4 changed files with 36 additions and 25 deletions

View file

@ -52,36 +52,30 @@ Texture* prefix_get_tex(const char *name, const char *prefix) {
return tex;
}
static SDL_Surface* load_png(const char *filename) {
static SDL_Surface* load_png_p(const char *filename, SDL_RWops *rwops) {
#define PNGFAIL(msg) { warnx("load_png(): couldn't load '%s': %s", filename, msg); return NULL; }
FILE *fp = fopen(filename, "rb");
if(!fp) {
PNGFAIL("fopen() failed")
if(!rwops) {
PNGFAIL(SDL_GetError())
}
png_structp png_ptr;
if(!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) {
fclose(fp);
PNGFAIL("png_create_read_struct() failed")
}
png_infop info_ptr;
if(!(info_ptr = png_create_info_struct(png_ptr))) {
fclose(fp);
png_destroy_read_struct(&png_ptr, NULL, NULL);
PNGFAIL("png_create_info_struct() failed")
}
png_infop end_info;
if(!(end_info = png_create_info_struct(png_ptr))) {
fclose(fp);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
PNGFAIL("png_create_info_struct() failed")
}
png_init_io(png_ptr, fp);
png_init_rwops(png_ptr, rwops);
png_read_info(png_ptr, info_ptr);
int colortype = png_get_color_type(png_ptr,info_ptr);
@ -95,19 +89,19 @@ static SDL_Surface* load_png(const char *filename) {
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
png_read_update_info(png_ptr, info_ptr);
int width = png_get_image_width(png_ptr, info_ptr);
int height = png_get_image_height(png_ptr, info_ptr);
int depth = png_get_bit_depth(png_ptr, info_ptr);
png_bytep row_pointers[height];
Uint32 *pixels = malloc(sizeof(Uint32)*width*height);
for(int i = 0; i < height; i++)
row_pointers[i] = (png_bytep)(pixels+i*width);
png_read_image(png_ptr, row_pointers);
png_read_end(png_ptr, end_info);
@ -129,17 +123,22 @@ static SDL_Surface* load_png(const char *filename) {
SDL_Surface *res = SDL_CreateRGBSurfaceFrom(pixels, width, height, depth*4, 0, rmask, gmask, bmask, amask);
if(!res) {
fclose(fp);
PNGFAIL(SDL_GetError())
}
fclose(fp);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
return res;
#undef PNGFAIL
}
static SDL_Surface* load_png(const char *filename) {
SDL_RWops *rwops = SDL_RWFromFile(filename, "r");
SDL_Surface *surf = load_png_p(filename, rwops);
SDL_RWclose(rwops);
return surf;
}
void load_sdl_surf(SDL_Surface *surface, Texture *texture) {
glGenTextures(1, &texture->gltex);
glBindTexture(GL_TEXTURE_2D, texture->gltex);

View file

@ -351,6 +351,25 @@ Hashtable* parse_keyvalue_file(const char *filename, size_t tablesize) {
return ht;
}
static void png_rwops_write_data(png_structp png_ptr, png_bytep data, png_size_t length) {
SDL_RWops *out = png_get_io_ptr(png_ptr);
SDL_RWwrite(out, data, length, 1);
}
static void png_rwops_flush_data(png_structp png_ptr) {
// no flush operation in SDL_RWops
}
static void png_rwops_read_data(png_structp png_ptr, png_bytep data, png_size_t length) {
SDL_RWops *out = png_get_io_ptr(png_ptr);
SDL_RWread(out, data, length, 1);
}
void png_init_rwops(png_structp png, SDL_RWops *rwops) {
png_set_write_fn(png, rwops, png_rwops_write_data, png_rwops_flush_data);
png_set_read_fn(png, rwops, png_rwops_read_data);
}
//
// misc utils
//

View file

@ -6,6 +6,7 @@
#include <string.h>
#include <stdio.h>
#include <zlib.h> // compiling under mingw may fail without this...
#include <png.h>
#include <SDL.h>
#include "hashtable.h"
@ -96,6 +97,7 @@ bool parse_keyvalue_stream_cb(SDL_RWops *strm, KVCallback callback, void *data);
bool parse_keyvalue_file_cb(const char *filename, KVCallback callback, void *data);
Hashtable* parse_keyvalue_stream(SDL_RWops *strm, size_t tablesize);
Hashtable* parse_keyvalue_file(const char *filename, size_t tablesize);
void png_init_rwops(png_structp png, SDL_RWops *rwops);
//
// misc utils

View file

@ -221,15 +221,6 @@ void video_setmode(int w, int h, bool fs, bool resizable) {
_video_setmode(w, h, flags, false);
}
static void png_rwops_write_data(png_structp png_ptr, png_bytep data, png_size_t length) {
SDL_RWops *out = png_get_io_ptr(png_ptr);
SDL_RWwrite(out, data, length, 1);
}
static void png_rwops_flush_data(png_structp png_ptr) {
// no flush operation in SDL_RWops
}
void video_take_screenshot(void) {
SDL_RWops *out;
char *data;
@ -282,7 +273,7 @@ void video_take_screenshot(void) {
memcpy(row_pointers[y], data + rw*3*(h-1-y), w*3);
}
png_set_write_fn(png_ptr, out, png_rwops_write_data, png_rwops_flush_data);
png_init_rwops(png_ptr, out);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);