mgba/src/util/png-io.c

77 lines
2.0 KiB
C
Raw Normal View History

2014-07-25 12:44:20 +00:00
#include "util/png-io.h"
#include "vfs.h"
static void _pngWrite(png_structp png, png_bytep buffer, png_size_t size) {
struct VFile* vf = png_get_io_ptr(png);
size_t written = vf->write(vf, buffer, size);
if (written != size) {
png_error(png, "Could not write PNG");
}
}
png_structp PNGWriteOpen(struct VFile* source) {
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (!png) {
return 0;
}
if (setjmp(png_jmpbuf(png))) {
png_destroy_write_struct(&png, 0);
return 0;
}
png_set_write_fn(png, source, _pngWrite, 0);
return png;
}
png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height) {
png_infop info = png_create_info_struct(png);
if (!info) {
return 0;
}
png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png, info);
return info;
}
bool PNGWritePixels(png_structp png, unsigned width, unsigned height, unsigned stride, void* pixels) {
png_bytep row = malloc(sizeof(png_bytep) * width * 3);
if (!row) {
return false;
}
png_bytep pixelData = pixels;
if (setjmp(png_jmpbuf(png))) {
free(row);
return false;
}
unsigned i;
for (i = 0; i < height; ++i) {
unsigned x;
for (x = 0; x < width; ++x) {
row[x * 3] = pixelData[stride * i * 4 + x * 4];
row[x * 3 + 1] = pixelData[stride * i * 4 + x * 4 + 1];
row[x * 3 + 2] = pixelData[stride * i * 4 + x * 4 + 2];
}
png_write_row(png, row);
}
free(row);
return true;
}
bool PNGWriteCustomChunk(png_structp png, const char* name, size_t size, void* data) {
char realName[5];
strncpy(realName, name, 4);
realName[0] = tolower(realName[0]);
realName[1] = tolower(realName[1]);
realName[4] = '\0';
if (setjmp(png_jmpbuf(png))) {
return false;
}
png_write_chunk(png, (png_const_bytep) realName, data, size);
return true;
}
void PNGWriteClose(png_structp png, png_infop info) {
png_write_end(png, info);
png_destroy_write_struct(&png, &info);
}