GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/pngimages.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 99 304 32.6%
Functions: 4 9 44.4%
Branches: 35 164 21.3%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/graphics/pngimages.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33 #if defined(GATE_EXTLIB_LIBPNG)
34 # define GATE_GRAPHICS_PNG_USE_LIBPNG 1
35 #else
36 # if defined(GATE_SYS_WIN)
37 # define GATE_GRAPHICS_PNG_USE_OLE_IPICTURE 1
38 # else
39 # define GATE_GRAPHICS_PNG_NO_IMPL 1
40 # endif
41 #endif
42
43
44 #if defined(GATE_GRAPHICS_PNG_USE_LIBPNG)
45
46 #if !defined(GATE_SYS_WINCE) || defined(GATE_COMPILER_MSVC)
47 # define GATE_GRAPHICS_PNG_SETJMP 1
48 #endif
49 #include "png.h"
50
51
52
53 typedef struct gate_png_param_class
54 {
55 gate_stream_t* stream;
56 gate_result_t result;
57 } gate_png_param_t;
58
59 9 static void gate_png_stream_read_data(png_structp png, png_bytep data, png_size_t length)
60 {
61 9 gate_png_param_t* user_param = (gate_png_param_t*)png_get_io_ptr(png);
62 gate_size_t bytesreturned;
63 gate_result_t result;
64
65 9 result = gate_stream_read_block(user_param->stream, (char*)data, length, &bytesreturned);
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (GATE_FAILED(result))
67 {
68 user_param->result = result;
69 }
70 else
71 {
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (bytesreturned != length)
73 {
74 user_param->result = GATE_RESULT_ENDOFSTREAM;
75 }
76 }
77 9 }
78
79 9 static void gate_png_stream_write_data(png_structp png, png_bytep data, png_size_t length)
80 {
81 9 gate_png_param_t* user_param = (gate_png_param_t*)png_get_io_ptr(png);
82 gate_size_t byteswritten;
83 gate_result_t result;
84
85 9 result = gate_stream_write_block(user_param->stream, (char const*)data, length, &byteswritten);
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (GATE_FAILED(result))
87 {
88 user_param->result = result;
89 }
90 else
91 {
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (byteswritten != length)
93 {
94 user_param->result = GATE_RESULT_ENDOFSTREAM;
95 }
96 }
97 9 }
98
99 static void gate_png_stream_flush(png_structp png)
100 {
101 gate_png_param_t* user_param = (gate_png_param_t*)png_get_io_ptr(png);
102 gate_stream_flush(user_param->stream);
103
104 }
105
106 static void gate_png_error_handler(png_structp png, png_const_charp msg)
107 {
108 void* error_ptr = png_get_error_ptr(png);
109 GATE_UNUSED_ARG(msg);
110 if (error_ptr == NULL)
111 {
112 GATE_DEBUG_BREAKPOINT;
113 }
114 else
115 {
116 #if defined(GATE_GRAPHICS_PNG_SETJMP)
117 jmp_buf* jmpbuffer = (jmp_buf*)(error_ptr);
118 longjmp(*jmpbuffer, 1);
119 #endif
120 }
121 }
122
123 static void gate_png_warning_handler(png_structp png, png_const_charp msg)
124 {
125 (void)png;
126 (void)msg;
127 }
128
129
130 1 gate_result_t gate_pngimage_load(gate_stream_t* srcstream, gate_rasterimage_t* image, gate_enumint_t flags)
131 {
132 gate_result_t ret;
133 gate_rasterimage_t raster;
134 png_byte buffer[4096 * 3];
135 1 png_byte* ptrbuffer = &buffer[0];
136 1 png_structp png = NULL;
137 1 png_infop png_info = NULL;
138 1 png_infop png_info_end = NULL;
139
140 do
141 {
142 gate_png_param_t user_param;
143 #if defined(GATE_GRAPHICS_PNG_SETJMP)
144 jmp_buf jmpbuffer;
145 #endif
146 unsigned char png_interlace_type;
147 unsigned char png_color_type;
148 unsigned char png_bit_depth;
149
150 gate_size_t linebytes;
151 gate_color_t* ptrpixels;
152 gate_uint32_t x, y;
153 png_bytep ptrbytes;
154
155 1 user_param.stream = srcstream;
156 1 user_param.result = GATE_RESULT_OK;
157
158 1 gate_rasterimage_create(&raster, GATE_IMAGE_PIXELFORMAT_DEFAULT, 0, 0, NULL);
159
160
161 1 png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (png == NULL)
163 {
164 ret = GATE_RESULT_OUTOFMEMORY;
165 break;
166 }
167
168 1 png_info = png_create_info_struct(png);
169 1 png_info_end = png_create_info_struct(png);
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (png_info == NULL)
171 {
172 ret = GATE_RESULT_OUTOFMEMORY;
173 break;
174 }
175
176 #if defined(GATE_GRAPHICS_PNG_SETJMP)
177
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (setjmp(jmpbuffer) != 0)
178 {
179 ret = GATE_RESULT_CRITICALERROR;
180 break;
181 }
182 1 png_set_error_fn(png, &jmpbuffer, &gate_png_error_handler, &gate_png_warning_handler);
183 #endif
184
185 1 png_set_read_fn(png, (png_voidp)&user_param, &gate_png_stream_read_data);
186 1 png_read_info(png, png_info);
187
188
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (NULL == gate_rasterimage_create(&raster, GATE_IMAGE_PIXELFORMAT_DEFAULT,
189 png_get_image_width(png, png_info),
190 png_get_image_height(png, png_info), NULL))
191 {
192 ret = GATE_RESULT_OUTOFMEMORY;
193 break;
194 }
195
196 1 png_interlace_type = png_get_interlace_type(png, png_info);
197 1 png_color_type = png_get_color_type(png, png_info);
198
199
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (png_interlace_type == PNG_INTERLACE_ADAM7)
201 {
202 /* skip smaller preview images */
203 int png_number_of_passes;
204 int ndx;
205
206 linebytes = png_get_rowbytes(png, png_info);
207 if (linebytes > sizeof(buffer))
208 {
209 ptrbuffer = gate_mem_alloc(linebytes);
210 if (ptrbuffer == NULL)
211 {
212 ret = GATE_RESULT_OUTOFMEMORY;
213 break;
214 }
215 }
216
217 png_number_of_passes = png_set_interlace_handling(png);
218 for (ndx = 1; ndx != png_number_of_passes; ++ndx)
219 {
220 for (y = 0; y != raster.height; ++y)
221 {
222 ptrbytes = (png_bytep)ptrbuffer;
223 png_read_row(png, ptrbuffer, NULL);
224 }
225 }
226
227 if (ptrbuffer != &buffer[0])
228 {
229 gate_mem_dealloc(ptrbuffer);
230 ptrbuffer = &buffer[0];
231 }
232 }
233
234 1 ret = GATE_RESULT_OK;
235
236 1 png_bit_depth = png_get_bit_depth(png, png_info);
237
1/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 switch (png_color_type)
238 {
239 case PNG_COLOR_TYPE_PALETTE:
240 { // we have a palette
241 png_colorp png_palette;
242 int png_palette_size;
243
244 if (png_bit_depth < 8)
245 {
246 png_set_packing(png);
247 }
248 if (png_bit_depth > 8)
249 {
250 ret = GATE_RESULT_NOTSUPPORTED;
251 break;
252 }
253
254 linebytes = raster.width;
255 if (linebytes > sizeof(buffer))
256 {
257 ptrbuffer = gate_mem_alloc(linebytes);
258 if (ptrbuffer == NULL)
259 {
260 ret = GATE_RESULT_OUTOFMEMORY;
261 break;
262 }
263 }
264 ptrpixels = (gate_color_t*)gate_rasterimage_get_line_ptr(&raster, 0);
265 png_get_PLTE(png, png_info, &png_palette, &png_palette_size);
266 for (y = 0; y < raster.height; ++y)
267 {
268 ptrbytes = (png_bytep)ptrbuffer;
269 png_read_row(png, ptrbuffer, NULL);
270 for (x = 0; x < raster.width; ++x)
271 {
272 if (*ptrbytes < png_palette_size)
273 {
274 ptrpixels->r = (gate_uint8_t)(png_palette[*ptrbytes].red);
275 ptrpixels->g = (gate_uint8_t)(png_palette[*ptrbytes].green);
276 ptrpixels->b = (gate_uint8_t)(png_palette[*ptrbytes].blue);
277 }
278 else
279 {
280 ptrpixels->r = 255;
281 ptrpixels->g = 255;
282 ptrpixels->b = 255;
283 }
284 ptrpixels->a = 255;
285 ++ptrpixels;
286 ++ptrbytes;
287 }
288 }
289 png_read_end(png, png_info_end);
290 break;
291 }
292 case PNG_COLOR_TYPE_RGB:
293 {
294 png_set_strip_16(png);
295 linebytes = png_get_rowbytes(png, png_info);
296 if (linebytes > sizeof(buffer))
297 {
298 ptrbuffer = gate_mem_alloc(linebytes);
299 if (ptrbuffer == NULL)
300 {
301 ret = GATE_RESULT_OUTOFMEMORY;
302 break;
303 }
304 }
305 ptrpixels = (gate_color_t*)gate_rasterimage_get_line_ptr(&raster, 0);
306 for (y = 0; y < raster.height; ++y)
307 {
308 ptrbytes = (png_bytep)ptrbuffer;
309 png_read_row(png, ptrbuffer, NULL);
310 for (x = 0; x < raster.width; ++x)
311 {
312 ptrpixels->r = (gate_uint8_t) * (ptrbytes++);
313 ptrpixels->g = (gate_uint8_t) * (ptrbytes++);
314 ptrpixels->b = (gate_uint8_t) * (ptrbytes++);
315 ptrpixels->a = 255;
316 ++ptrpixels;
317 }
318 }
319 png_read_end(png, png_info_end);
320 break;
321 }
322
323 1 case PNG_COLOR_TYPE_RGB_ALPHA:
324 {
325 1 png_set_strip_16(png);
326 1 linebytes = png_get_rowbytes(png, png_info);
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (linebytes > sizeof(buffer))
328 {
329 ptrbuffer = gate_mem_alloc(linebytes);
330 if (ptrbuffer == NULL)
331 {
332 ret = GATE_RESULT_OUTOFMEMORY;
333 break;
334 }
335 }
336 1 ptrpixels = (gate_color_t*)gate_rasterimage_get_line_ptr(&raster, 0);
337
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
33 for (y = 0; y < raster.height; ++y)
338 {
339 32 ptrbytes = (png_bytep)ptrbuffer;
340 32 png_read_row(png, ptrbuffer, NULL);
341
2/2
✓ Branch 0 taken 2048 times.
✓ Branch 1 taken 32 times.
2080 for (x = 0; x < raster.width; ++x)
342 {
343 2048 ptrpixels->r = (gate_uint8_t) * (ptrbytes++);
344 2048 ptrpixels->g = (gate_uint8_t) * (ptrbytes++);
345 2048 ptrpixels->b = (gate_uint8_t) * (ptrbytes++);
346 2048 ptrpixels->a = (gate_uint8_t) * (ptrbytes++);
347 2048 ++ptrpixels;
348 }
349 }
350 1 png_read_end(png, png_info_end);
351 1 break;
352 }
353 case PNG_COLOR_TYPE_GRAY:
354 {
355 if (png_bit_depth > 8)
356 {
357 linebytes = png_get_rowbytes(png, png_info);
358 if (linebytes > sizeof(buffer))
359 {
360 ptrbuffer = gate_mem_alloc(linebytes);
361 if (ptrbuffer == NULL)
362 {
363 ret = GATE_RESULT_OUTOFMEMORY;
364 break;
365 }
366 }
367 ptrpixels = (gate_color_t*)gate_rasterimage_get_line_ptr(&raster, 0);
368 for (y = 0; y < raster.height; ++y)
369 {
370 ptrbytes = (png_bytep)ptrbuffer;
371 png_read_row(png, ptrbuffer, NULL);
372 for (x = 0; x < raster.width; ++x)
373 {
374 ptrpixels->r = (gate_uint8_t)*ptrbytes;
375 ptrpixels->g = (gate_uint8_t)*ptrbytes;
376 ptrpixels->b = (gate_uint8_t)*ptrbytes;
377 ptrpixels->a = 255;
378 ++ptrpixels;
379 ptrbytes += 2;
380 }
381 }
382 }
383 else
384 {
385 if (png_bit_depth < 8)
386 {
387 png_set_expand(png);
388 }
389
390 linebytes = png_get_rowbytes(png, png_info);
391 if (linebytes > sizeof(buffer))
392 {
393 ptrbuffer = gate_mem_alloc(linebytes);
394 if (ptrbuffer == NULL)
395 {
396 ret = GATE_RESULT_OUTOFMEMORY;
397 break;
398 }
399 }
400 ptrpixels = (gate_color_t*)gate_rasterimage_get_line_ptr(&raster, 0);
401 for (y = 0; y < raster.height; ++y)
402 {
403 ptrbytes = (png_bytep)ptrbuffer;
404 png_read_row(png, ptrbuffer, NULL);
405 for (x = 0; x < raster.width; ++x)
406 {
407 ptrpixels->r = (gate_uint8_t) * (ptrbytes);
408 ptrpixels->g = (gate_uint8_t) * (ptrbytes);
409 ptrpixels->b = (gate_uint8_t) * (ptrbytes);
410 ptrpixels->a = (gate_uint8_t) * (ptrbytes);
411 ++ptrpixels;
412 ++ptrbytes;
413 }
414 }
415 }
416 png_read_end(png, png_info_end);
417 break;
418 }
419 default:
420 {
421 ret = GATE_RESULT_NOTSUPPORTED;
422 break;
423 }
424
425 } // switch(info->color_type)
426
427
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
428 {
429 1 gate_mem_copy(image, &raster, sizeof(raster));
430 1 gate_mem_clear(&raster, sizeof(raster));
431 }
432
433 } while (0);
434
435
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (png != NULL)
436 {
437 1 png_destroy_read_struct(&png, &png_info, &png_info_end);
438 }
439
440
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if ((ptrbuffer != &buffer[0]) && (ptrbuffer != NULL))
441 {
442 gate_mem_dealloc(ptrbuffer);
443 }
444
445 1 gate_rasterimage_release(&raster);
446
447 1 return ret;
448 }
449
450 static gate_bool_t gate_png_equals_color(png_color const* pngcolor, gate_color_t const* gatecolor)
451 {
452 return (pngcolor->red == gatecolor->r)
453 && (pngcolor->green == gatecolor->g)
454 && (pngcolor->blue == gatecolor->b)
455 ;
456 }
457
458 static void copy_rgba(gate_uint8_t* dst, gate_uint8_t const* src, gate_size_t pixel_count)
459 {
460 gate_mem_copy(dst, src, pixel_count * 4);
461 }
462
463 1 gate_result_t gate_pngimage_save(gate_rasterimage_t const* image, gate_stream_t* deststream, gate_enumint_t flags)
464 {
465 1 gate_result_t ret = GATE_RESULT_OK;
466 1 png_structp png = NULL;
467 1 png_infop png_info = NULL;
468 png_byte buffer[4096];
469 1 gate_uint8_t* ptr_buffer = NULL;
470
471 do
472 {
473 gate_png_param_t user_param;
474 #if defined(GATE_GRAPHICS_PNG_SETJMP)
475 jmp_buf jmpbuffer;
476 #endif
477
478 png_color png_palette[256];
479 gate_uint8_t const* ptr_line;
480 gate_size_t buffer_required_len;
481 int p;
482 1 int png_palette_size = 0;
483 1 png_const_colorp ptrpalette = NULL;
484 gate_uint32_t imagesize;
485
486 unsigned x, y;
487 1 void(*line_writer)(gate_uint8_t*, gate_uint8_t const*, gate_size_t) = NULL;
488
489
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if ((image->width == 0) || (image->height == 0) || (image->data == NULL))
490 {
491 ret = GATE_RESULT_INVALIDDATA;
492 break;
493 }
494
495
1/11
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
1 switch (image->pixel_format)
496 {
497 case GATE_IMAGE_PIXELFORMAT_RGBA:
498 case GATE_IMAGE_PIXELFORMAT_RGB32: line_writer = &copy_rgba; break;
499 case GATE_IMAGE_PIXELFORMAT_BGRA:
500 case GATE_IMAGE_PIXELFORMAT_BGR32: line_writer = &gate_color_convert_rgba_from_bgra_32; break;
501
502 1 case GATE_IMAGE_PIXELFORMAT_RGB24: line_writer = &gate_color_convert_rgba_from_rgb_24; break;
503 case GATE_IMAGE_PIXELFORMAT_BGR24: line_writer = &gate_color_convert_rgba_from_bgr_24; break;
504
505 case GATE_IMAGE_PIXELFORMAT_RGB555: line_writer = &gate_color_convert_rgba_from_rgb_15; break;
506 case GATE_IMAGE_PIXELFORMAT_RGB565: line_writer = &gate_color_convert_rgba_from_rgb_16; break;
507 case GATE_IMAGE_PIXELFORMAT_ARGB4: line_writer = &gate_color_convert_rgba_from_argb_16; break;
508 case GATE_IMAGE_PIXELFORMAT_YUV2: line_writer = &gate_color_convert_rgba_from_yuv2_16; break;
509
510 case GATE_IMAGE_PIXELFORMAT_PAL8: line_writer = &gate_color_convert_rgba_from_pal_8; break;
511 case GATE_IMAGE_PIXELFORMAT_GRAY8: line_writer = &gate_color_convert_rgba_from_gray_8; break;
512 default:
513 break;
514 }
515
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (line_writer == NULL)
517 {
518 ret = GATE_RESULT_NOTSUPPORTED;
519 break;
520 }
521
522 1 buffer_required_len = (gate_size_t)image->width * 4u;
523
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_required_len <= sizeof(buffer))
524 {
525 1 ptr_buffer = &buffer[0];
526 }
527 else
528 {
529 ptr_buffer = gate_mem_alloc(buffer_required_len);
530 if (ptr_buffer == NULL)
531 {
532 ret = GATE_RESULT_OUTOFMEMORY;
533 break;
534 }
535 }
536
537 1 imagesize = image->width * image->height;
538 1 user_param.stream = deststream;
539 1 user_param.result = GATE_RESULT_OK;
540 1 png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (png == NULL)
542 {
543 ret = GATE_RESULT_FAILED;
544 break;
545 }
546 1 png_info = png_create_info_struct(png);
547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (png_info == NULL)
548 {
549 ret = GATE_RESULT_INVALIDHEADER;
550 break;
551 }
552
553 #if defined(GATE_GRAPHICS_PNG_SETJMP)
554
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (setjmp(jmpbuffer) != 0)
555 {
556 ret = GATE_RESULT_FAILED;
557 break;
558 }
559 1 png_set_error_fn(png, &jmpbuffer, &gate_png_error_handler, &gate_png_warning_handler);
560 #endif
561
562 1 png_set_write_fn(png, &user_param, &gate_png_stream_write_data, &gate_png_stream_flush);
563
564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FLAG_ENABLED(flags, GATE_IMAGE_FLAG_PALETTE))
565 {
566 gate_color_t const* ptrpixels = (gate_color_t const*)gate_rasterimage_get_line_ptr(image, 0);
567 ptrpalette = &png_palette[0];
568 for (y = 0; (y != image->height) && (ptrpalette != NULL); ++y)
569 {
570 ptr_line = (gate_uint8_t const*)gate_rasterimage_get_line_ptr(image, y);
571 line_writer(ptr_buffer, ptr_line, image->width);
572 ptrpixels = (gate_color_t const*)ptr_buffer;
573 for (x = 0; x != image->width; ++x)
574 {
575 gate_bool_t found = false;
576 for (p = 0; p != png_palette_size; ++p)
577 {
578 if (gate_png_equals_color(&png_palette[p], &ptrpixels[x]))
579 {
580 found = true;
581 break;
582 }
583 }
584 if (!found)
585 {
586 png_palette[png_palette_size].red = ptrpixels[x].r;
587 png_palette[png_palette_size].green = ptrpixels[x].g;
588 png_palette[png_palette_size].blue = ptrpixels[x].b;
589 ++png_palette_size;
590 if (png_palette_size >= 256)
591 {
592 ptrpalette = NULL;
593 break;
594 }
595 }
596 }
597 }
598 }
599
600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptrpalette != NULL)
601 {
602 /* write an indexed palette image */
603
604 png_set_IHDR(png, png_info, image->width, image->height, 8, PNG_COLOR_TYPE_PALETTE,
605 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
606
607 png_set_PLTE(png, png_info, ptrpalette, png_palette_size);
608 png_write_info(png, png_info);
609
610 for (y = 0; y != image->height; ++y)
611 {
612 ptr_line = (gate_uint8_t const*)gate_rasterimage_get_line_ptr(image, 0);
613 line_writer(ptr_buffer, ptr_line, image->width);
614 for (x = 0; x != image->width; ++x)
615 {
616 for (p = 0; p != png_palette_size; ++p)
617 {
618 if (gate_png_equals_color(&png_palette[p], (gate_color_t const*)&ptr_buffer[x * 4]))
619 {
620 ptr_buffer[x] = (png_byte)p;
621 break;
622 }
623 }
624 }
625 png_write_row(png, ptr_buffer);
626 }
627 }
628 else
629 {
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (line_writer == NULL)
631 {
632 ret = GATE_RESULT_NOTSUPPORTED;
633 }
634 else
635 {
636 1 png_set_IHDR(png, png_info, image->width, image->height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
637 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
638 1 png_write_info(png, png_info);
639
640
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
33 for (y = 0; y != image->height; ++y)
641 {
642 32 ptr_line = (gate_uint8_t const*)gate_rasterimage_get_line_ptr(image, y);
643 32 line_writer(ptr_buffer, ptr_line, image->width);
644
645 32 png_write_row(png, (png_bytep)ptr_buffer);
646 }
647 }
648 }
649 1 png_write_end(png, png_info);
650
651 } while (0);
652
653
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (ptr_buffer && (ptr_buffer != &buffer[0]))
654 {
655 gate_mem_dealloc(ptr_buffer);
656 }
657
658
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (png != NULL)
659 {
660 1 png_destroy_write_struct(&png, &png_info);
661 }
662
663 1 return ret;
664 }
665
666 #endif /* GATE_GRAPHICS_PNG_USE_LIBPNG */
667
668
669
670 #if defined(GATE_GRAPHICS_PNG_USE_OLE_IPICTURE)
671
672 #include "gate/graphics/platform/win32_olepicture.h"
673
674 gate_result_t gate_pngimage_load(gate_stream_t* srcstream, gate_rasterimage_t* image, gate_enumint_t flags)
675 {
676 return gate_win32_load_ole_picture_file(srcstream, image);
677 }
678
679 gate_result_t gate_pngimage_save(gate_rasterimage_t const* image, gate_stream_t* deststream, gate_enumint_t flags)
680 {
681 (void)image;
682 (void)deststream;
683 (void)flags;
684 return GATE_RESULT_NOTIMPLEMENTED;
685 }
686
687 #endif /* GATE_GRAPHICS_PNG_USE_OLE_IPICTURE */
688
689
690
691 #if defined(GATE_GRAPHICS_PNG_NO_IMPL)
692
693 gate_result_t gate_pngimage_load(gate_stream_t* srcstream, gate_rasterimage_t* image, gate_enumint_t flags)
694 {
695 (void)srcstream;
696 (void)image;
697 (void)flags;
698 return GATE_RESULT_NOTIMPLEMENTED;
699 }
700
701 gate_result_t gate_pngimage_save(gate_rasterimage_t const* image, gate_stream_t* deststream, gate_enumint_t flags)
702 {
703 (void)image;
704 (void)deststream;
705 (void)flags;
706 return GATE_RESULT_NOTIMPLEMENTED;
707 }
708
709
710 #endif /* GATE_GRAPHICS_PNG_NO_IMPL */
711
712