Mercurial > repos > blastem
annotate png.c @ 1538:b581663c42ec nuklear_ui
Don't try to use GLES specific stuff unless we're actualy on a GLES platform
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 25 Mar 2018 10:47:48 -0700 |
parents | b505083dcd87 |
children | 0ec89dadb36d |
rev | line source |
---|---|
1532
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
1 #include <stdint.h> |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
2 #include <stdlib.h> |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
3 #include <stdio.h> |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
4 #include "zlib/zlib.h" |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
5 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
6 static const char png_magic[] = {0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n'}; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
7 static const char ihdr[] = {'I', 'H', 'D', 'R'}; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
8 static const char plte[] = {'P', 'L', 'T', 'E'}; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
9 static const char idat[] = {'I', 'D', 'A', 'T'}; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
10 static const char iend[] = {'I', 'E', 'N', 'D'}; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
11 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
12 enum { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
13 COLOR_TRUE = 2, |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
14 COLOR_INDEXED |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
15 }; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
16 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
17 static void write_chunk(FILE *f, const char*id, uint8_t *buffer, uint32_t size) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
18 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
19 uint8_t tmp[4] = {size >> 24, size >> 16, size >> 8, size}; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
20 uint8_t warn = 0; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
21 warn = warn || (sizeof(tmp) != fwrite(tmp, 1, sizeof(tmp), f)); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
22 warn = warn || (4 != fwrite(id, 1, 4, f)); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
23 if (size) { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
24 warn = warn || (size != fwrite(buffer, 1, size, f)); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
25 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
26 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
27 uint32_t crc = crc32(0, NULL, 0); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
28 crc = crc32(crc, id, 4); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
29 if (size) { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
30 crc = crc32(crc, buffer, size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
31 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
32 tmp[0] = crc >> 24; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
33 tmp[1] = crc >> 16; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
34 tmp[2] = crc >> 8; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
35 tmp[3] = crc; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
36 warn = warn || (sizeof(tmp) != fwrite(tmp, 1, sizeof(tmp), f)); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
37 if (warn) { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
38 fprintf(stderr, "Failure during write of %c%c%c%c chunk\n", id[0], id[1], id[2], id[3]); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
39 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
40 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
41 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
42 static void write_header(FILE *f, uint32_t width, uint32_t height, uint8_t color_type) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
43 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
44 uint8_t chunk[13] = { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
45 width >> 24, width >> 16, width >> 8, width, |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
46 height >> 24, height >> 16, height >> 8, height, |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
47 8, color_type, 0, 0, 0 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
48 }; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
49 if (sizeof(png_magic) != fwrite(png_magic, 1, sizeof(png_magic), f)) { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
50 fputs("Error writing PNG magic\n", stderr); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
51 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
52 write_chunk(f, ihdr, chunk, sizeof(chunk)); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
53 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
54 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
55 void save_png24(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
56 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
57 uint32_t idat_size = (1 + width*3) * height; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
58 uint8_t *idat_buffer = malloc(idat_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
59 uint32_t *pixel = buffer; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
60 uint8_t *cur = idat_buffer; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
61 for (uint32_t y = 0; y < height; y++) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
62 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
63 //save filter type |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
64 *(cur++) = 0; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
65 uint32_t *start = pixel; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
66 for (uint32_t x = 0; x < width; x++, pixel++) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
67 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
68 uint32_t value = *pixel; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
69 *(cur++) = value >> 16; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
70 *(cur++) = value >> 8; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
71 *(cur++) = value; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
72 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
73 pixel = start + pitch / sizeof(uint32_t); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
74 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
75 write_header(f, width, height, COLOR_TRUE); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
76 uLongf compress_buffer_size = idat_size + 5 * (idat_size/16383 + 1) + 3; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
77 uint8_t *compressed = malloc(compress_buffer_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
78 compress(compressed, &compress_buffer_size, idat_buffer, idat_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
79 free(idat_buffer); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
80 write_chunk(f, idat, compressed, compress_buffer_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
81 write_chunk(f, iend, NULL, 0); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
82 free(compressed); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
83 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
84 |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
85 void save_png(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
86 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
87 uint32_t palette[256]; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
88 uint8_t pal_buffer[256*3]; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
89 uint32_t num_pal = 0; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
90 uint32_t index_size = (1 + width) * height; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
91 uint8_t *index_buffer = malloc(index_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
92 uint8_t *cur = index_buffer; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
93 uint32_t *pixel = buffer; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
94 for (uint32_t y = 0; y < height; y++) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
95 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
96 //save filter type |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
97 *(cur++) = 0; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
98 uint32_t *start = pixel; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
99 for (uint32_t x = 0; x < width; x++, pixel++, cur++) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
100 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
101 uint32_t value = (*pixel) & 0xFFFFFF; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
102 uint32_t i; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
103 for (i = 0; i < num_pal; i++) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
104 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
105 if (palette[i] == value) { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
106 break; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
107 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
108 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
109 if (i == num_pal) { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
110 if (num_pal == 256) { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
111 free(index_buffer); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
112 save_png24(f, buffer, width, height, pitch); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
113 return; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
114 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
115 palette[i] = value; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
116 num_pal++; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
117 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
118 *cur = i; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
119 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
120 pixel = start + pitch / sizeof(uint32_t); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
121 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
122 write_header(f, width, height, COLOR_INDEXED); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
123 cur = pal_buffer; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
124 for (uint32_t i = 0; i < num_pal; i++) |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
125 { |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
126 *(cur++) = palette[i] >> 16; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
127 *(cur++) = palette[i] >> 8; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
128 *(cur++) = palette[i]; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
129 } |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
130 write_chunk(f, plte, pal_buffer, num_pal * 3); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
131 uLongf compress_buffer_size = index_size + 5 * (index_size/16383 + 1) + 3; |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
132 uint8_t *compressed = malloc(compress_buffer_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
133 compress(compressed, &compress_buffer_size, index_buffer, index_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
134 free(index_buffer); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
135 write_chunk(f, idat, compressed, compress_buffer_size); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
136 write_chunk(f, iend, NULL, 0); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
137 free(compressed); |
b505083dcd87
Added png screenshot support
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
138 } |