all repos — mgba @ bbe52bf632b75e0ea3e7d3a3027fe985ad5ebc29

mGBA Game Boy Advance Emulator

src/util/png-io.c (view raw)

 1#include "util/png-io.h"
 2
 3#include "vfs.h"
 4
 5static void _pngWrite(png_structp png, png_bytep buffer, png_size_t size) {
 6	struct VFile* vf = png_get_io_ptr(png);
 7	size_t written = vf->write(vf, buffer, size);
 8	if (written != size) {
 9		png_error(png, "Could not write PNG");
10	}
11}
12
13png_structp PNGWriteOpen(struct VFile* source) {
14	png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
15	if (!png) {
16		return 0;
17	}
18	if (setjmp(png_jmpbuf(png))) {
19		png_destroy_write_struct(&png, 0);
20		return 0;
21	}
22	png_set_write_fn(png, source, _pngWrite, 0);
23	return png;
24}
25
26png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height) {
27	png_infop info = png_create_info_struct(png);
28	if (!info) {
29		return 0;
30	}
31	png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
32	png_write_info(png, info);
33	return info;
34}
35
36bool PNGWritePixels(png_structp png, unsigned width, unsigned height, unsigned stride, void* pixels) {
37	png_bytep row = malloc(sizeof(png_bytep) * width * 3);
38	if (!row) {
39		return false;
40	}
41	png_bytep pixelData = pixels;
42	if (setjmp(png_jmpbuf(png))) {
43		free(row);
44		return false;
45	}
46	unsigned i;
47	for (i = 0; i < height; ++i) {
48		unsigned x;
49		for (x = 0; x < width; ++x) {
50			row[x * 3] = pixelData[stride * i * 4 + x * 4];
51			row[x * 3 + 1] = pixelData[stride * i * 4 + x * 4 + 1];
52			row[x * 3 + 2] = pixelData[stride * i * 4 + x * 4 + 2];
53		}
54		png_write_row(png, row);
55	}
56	free(row);
57	return true;
58}
59
60bool PNGWriteCustomChunk(png_structp png, const char* name, size_t size, void* data) {
61	char realName[5];
62	strncpy(realName, name, 4);
63	realName[0] = tolower(realName[0]);
64	realName[1] = tolower(realName[1]);
65	realName[4] = '\0';
66	if (setjmp(png_jmpbuf(png))) {
67		return false;
68	}
69	png_write_chunk(png, (png_const_bytep) realName, data, size);
70	return true;
71}
72
73void PNGWriteClose(png_structp png, png_infop info) {
74	png_write_end(png, info);
75	png_destroy_write_struct(&png, &info);
76}