comparison png.c @ 2685:da2e06c42d16

Add a compile-time flag to use RGB565 instead of ABGR/ARGB
author Michael Pavone <pavone@retrodev.com>
date Sun, 30 Mar 2025 00:06:53 -0700
parents 0111c8344477
children
comparison
equal deleted inserted replaced
2684:c649bcc18487 2685:da2e06c42d16
58 fputs("Error writing PNG magic\n", stderr); 58 fputs("Error writing PNG magic\n", stderr);
59 } 59 }
60 write_chunk(f, ihdr, chunk, sizeof(chunk)); 60 write_chunk(f, ihdr, chunk, sizeof(chunk));
61 } 61 }
62 62
63 void save_png24_frame(FILE *f, uint32_t *buffer, apng_state *apng, uint32_t width, uint32_t height, uint32_t pitch) 63 void save_png24_frame(FILE *f, pixel_t *buffer, apng_state *apng, uint32_t width, uint32_t height, uint32_t pitch)
64 { 64 {
65 uint32_t idat_size = (1 + width*3) * height; 65 uint32_t idat_size = (1 + width*3) * height;
66 uint8_t *idat_buffer = malloc(idat_size); 66 uint8_t *idat_buffer = malloc(idat_size);
67 uint32_t *pixel = buffer; 67 pixel_t *pixel = buffer;
68 uint8_t *cur = idat_buffer; 68 uint8_t *cur = idat_buffer;
69 for (uint32_t y = 0; y < height; y++) 69 for (uint32_t y = 0; y < height; y++)
70 { 70 {
71 //save filter type 71 //save filter type
72 *(cur++) = 0; 72 *(cur++) = 0;
73 uint32_t *start = pixel; 73 pixel_t *start = pixel;
74 for (uint32_t x = 0; x < width; x++, pixel++) 74 for (uint32_t x = 0; x < width; x++, pixel++)
75 { 75 {
76 uint32_t value = *pixel; 76 pixel_t value = *pixel;
77 #ifdef USE_RGB565
78 *(cur++) = (value >> 8 & 0xF8) | (value >> (8+5));
79 *(cur++) = (value >> 3 & 0xFC) | (value >> (3+5) & 0x3);
80 *(cur++) = value << 3 | (value >> (5-3) & 0x3);
81 #else
82 #ifdef USE_GLES
83 *(cur++) = value;
84 *(cur++) = value >> 8;
85 *(cur++) = value >> 16;
86 #else
77 *(cur++) = value >> 16; 87 *(cur++) = value >> 16;
78 *(cur++) = value >> 8; 88 *(cur++) = value >> 8;
79 *(cur++) = value; 89 *(cur++) = value;
90 #endif
91 #endif
80 } 92 }
81 pixel = start + pitch / sizeof(uint32_t); 93 pixel = start + pitch / sizeof(pixel_t);
82 } 94 }
83 95
84 uLongf compress_buffer_size = idat_size + 5 * (idat_size/16383 + 1) + 3; 96 uLongf compress_buffer_size = idat_size + 5 * (idat_size/16383 + 1) + 3;
85 uint32_t offset = 0; 97 uint32_t offset = 0;
86 if (apng) { 98 if (apng) {
145 fwrite(bytes, 1, sizeof(bytes), f); 157 fwrite(bytes, 1, sizeof(bytes), f);
146 fclose(f); 158 fclose(f);
147 free(apng); 159 free(apng);
148 } 160 }
149 161
150 void save_png24(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch) 162 void save_png24(FILE *f, pixel_t *buffer, uint32_t width, uint32_t height, uint32_t pitch)
151 { 163 {
152 write_header(f, width, height, COLOR_TRUE); 164 write_header(f, width, height, COLOR_TRUE);
153 save_png24_frame(f, buffer, NULL, width, height, pitch); 165 save_png24_frame(f, buffer, NULL, width, height, pitch);
154 write_chunk(f, iend, NULL, 0); 166 write_chunk(f, iend, NULL, 0);
155 } 167 }
156 168
157 void save_png(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch) 169 void save_png(FILE *f, pixel_t *buffer, uint32_t width, uint32_t height, uint32_t pitch)
158 { 170 {
159 uint32_t palette[256]; 171 pixel_t palette[256];
160 uint8_t pal_buffer[256*3]; 172 uint8_t pal_buffer[256*3];
161 uint32_t num_pal = 0; 173 uint32_t num_pal = 0;
162 uint32_t index_size = (1 + width) * height; 174 uint32_t index_size = (1 + width) * height;
163 uint8_t *index_buffer = malloc(index_size); 175 uint8_t *index_buffer = malloc(index_size);
164 uint8_t *cur = index_buffer; 176 uint8_t *cur = index_buffer;
165 uint32_t *pixel = buffer; 177 pixel_t *pixel = buffer;
166 for (uint32_t y = 0; y < height; y++) 178 for (uint32_t y = 0; y < height; y++)
167 { 179 {
168 //save filter type 180 //save filter type
169 *(cur++) = 0; 181 *(cur++) = 0;
170 uint32_t *start = pixel; 182 pixel_t *start = pixel;
171 for (uint32_t x = 0; x < width; x++, pixel++, cur++) 183 for (uint32_t x = 0; x < width; x++, pixel++, cur++)
172 { 184 {
173 uint32_t value = (*pixel) & 0xFFFFFF; 185 uint32_t value = (*pixel) & 0xFFFFFF;
174 uint32_t i; 186 uint32_t i;
175 for (i = 0; i < num_pal; i++) 187 for (i = 0; i < num_pal; i++)
187 palette[i] = value; 199 palette[i] = value;
188 num_pal++; 200 num_pal++;
189 } 201 }
190 *cur = i; 202 *cur = i;
191 } 203 }
192 pixel = start + pitch / sizeof(uint32_t); 204 pixel = start + pitch / sizeof(pixel_t);
193 } 205 }
194 write_header(f, width, height, COLOR_INDEXED); 206 write_header(f, width, height, COLOR_INDEXED);
195 cur = pal_buffer; 207 cur = pal_buffer;
196 for (uint32_t i = 0; i < num_pal; i++) 208 for (uint32_t i = 0; i < num_pal; i++)
197 { 209 {
210 #ifdef USE_RGB565
211 *(cur++) = (palette[i] >> 8 & 0xF8) | (palette[i] >> (8+5));
212 *(cur++) = (palette[i] >> 3 & 0xFC) | (palette[i] >> (3+5) & 0x3);
213 *(cur++) = palette[i] << 3 | (palette[i] >> (5-3) & 0x3);
214 #else
215 #ifdef USE_GLES
216 *(cur++) = palette[i];
217 *(cur++) = palette[i] >> 8;
218 *(cur++) = palette[i] >> 16;
219 #else
198 *(cur++) = palette[i] >> 16; 220 *(cur++) = palette[i] >> 16;
199 *(cur++) = palette[i] >> 8; 221 *(cur++) = palette[i] >> 8;
200 *(cur++) = palette[i]; 222 *(cur++) = palette[i];
223 #endif
224 #endif
201 } 225 }
202 write_chunk(f, plte, pal_buffer, num_pal * 3); 226 write_chunk(f, plte, pal_buffer, num_pal * 3);
203 uLongf compress_buffer_size = index_size + 5 * (index_size/16383 + 1) + 3; 227 uLongf compress_buffer_size = index_size + 5 * (index_size/16383 + 1) + 3;
204 uint8_t *compressed = malloc(compress_buffer_size); 228 uint8_t *compressed = malloc(compress_buffer_size);
205 compress(compressed, &compress_buffer_size, index_buffer, index_size); 229 compress(compressed, &compress_buffer_size, index_buffer, index_size);