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}