GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/images.c
Date: 2026-06-21 00:38:37
Exec Total Coverage
Lines: 525 681 77.1%
Functions: 45 54 83.3%
Branches: 161 263 61.2%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, 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/images.h"
30 #include "gate/memalloc.h"
31 #include "gate/results.h"
32
33 53 static gate_image_databuffer_t* gate_image_databuffer_create(gate_uint32_t bits_per_pixel, gate_uint32_t width, gate_uint32_t height)
34 {
35 53 gate_image_databuffer_t* ret = NULL;
36
37 do
38 {
39 53 unsigned bits_per_line = (unsigned)(width * bits_per_pixel);
40 53 unsigned bytes_per_line = bits_per_line / 8;
41 53 unsigned diff = bits_per_line % 8;
42 53 unsigned padding = 0;
43 gate_uint32_t data_size;
44
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (diff != 0)
45 {
46 ++bytes_per_line;
47 }
48 53 diff = bytes_per_line % 4;
49
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52 times.
53 if (diff != 0)
50 {
51 1 padding = (4 - diff);
52 1 bytes_per_line += padding;
53 }
54
55 53 data_size = (gate_uint32_t)bytes_per_line * height;
56
57 53 ret = (gate_image_databuffer_t*)gate_mem_alloc(sizeof(gate_image_databuffer_t) + data_size);
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (NULL == ret)
59 {
60 break;
61 }
62 53 gate_mem_clear(ret, sizeof(gate_image_databuffer_t) + data_size);
63 53 gate_atomic_int_init(&ret->ref_counter, 1);
64 53 ret->bits_per_pixel = bits_per_pixel;
65 53 ret->bytes_per_line = bytes_per_line;
66 53 ret->padding_per_line = padding;
67 53 ret->width = width;
68 53 ret->height = height;
69 } while (0);
70
71 53 return ret;
72 }
73
74 5 static gate_int32_t gate_image_databuffer_retain(gate_image_databuffer_t* buffer)
75 {
76 5 gate_int32_t ret = 0;
77
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (buffer)
78 {
79 5 ret = gate_atomic_int_inc(&buffer->ref_counter);
80 }
81 5 return ret;
82 }
83
84 58 static void gate_image_databuffer_release(gate_image_databuffer_t* buffer)
85 {
86
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 if (buffer)
87 {
88
2/2
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 5 times.
58 if (0 == gate_atomic_int_dec(&buffer->ref_counter))
89 {
90 53 gate_mem_dealloc(buffer);
91 }
92 }
93 58 }
94
95
96 339940 static gate_uint8_t* rgba_bgra_get_ptr(gate_uint8_t* data, unsigned width, unsigned height, unsigned line_pad, unsigned x, unsigned y)
97 {
98 339940 const unsigned linelen = width * 4 + line_pad;
99 GATE_UNUSED_ARG(height);
100 339940 return data + (gate_size_t)(y * linelen + x * 4u);
101 }
102 337842 static void rgba_write_pixel(gate_uint8_t* data, gate_color_t const* col)
103 {
104 337842 *((gate_color_t*)data) = *col;
105 337842 }
106 407243 static void rgba_read_pixel(gate_uint8_t const* data, gate_color_t* col)
107 {
108 407243 *col = *((gate_color_t*)data);
109 407243 }
110
111 8192 static void bgra_write_pixel(gate_uint8_t* data, gate_color_t const* col)
112 {
113 8192 data[0] = col->b;
114 8192 data[1] = col->g;
115 8192 data[2] = col->r;
116 8192 data[3] = col->a;
117 8192 }
118 static void bgra_read_pixel(gate_uint8_t const* data, gate_color_t* col)
119 {
120 col->b = data[0];
121 col->g = data[1];
122 col->r = data[2];
123 col->a = data[3];
124 }
125
126 918 static gate_uint8_t* rgb_bgr_get_ptr(gate_uint8_t* data, unsigned width, unsigned height, unsigned line_pad, unsigned x, unsigned y)
127 {
128 918 const unsigned linelen = width * 3 + line_pad;
129 GATE_UNUSED_ARG(height);
130 918 return data + (gate_size_t)y * linelen + (gate_size_t)x * 3u;
131 }
132 14966 static void rgb_write_pixel(gate_uint8_t* data, gate_color_t const* col)
133 {
134 14966 data[0] = col->r;
135 14966 data[1] = col->g;
136 14966 data[2] = col->b;
137 14966 }
138 630 static void rgb_read_pixel(gate_uint8_t const* data, gate_color_t* col)
139 {
140 630 col->r = data[0];
141 630 col->g = data[1];
142 630 col->b = data[2];
143 630 }
144 4096 static void bgr_write_pixel(gate_uint8_t* data, gate_color_t const* col)
145 {
146 4096 data[0] = col->b;
147 4096 data[1] = col->g;
148 4096 data[2] = col->r;
149 4096 }
150 static void bgr_read_pixel(gate_uint8_t const* data, gate_color_t* col)
151 {
152 col->b = data[0];
153 col->g = data[1];
154 col->r = data[2];
155 }
156
157 256 static gate_uint8_t* col16_get_ptr(gate_uint8_t* data, unsigned width, unsigned height, unsigned line_pad, unsigned x, unsigned y)
158 {
159 256 const unsigned linelen = width * 2 + line_pad;
160 GATE_UNUSED_ARG(height);
161 256 return data + (gate_size_t)y * linelen + (gate_size_t)x * 2u;
162 }
163 4096 static void rgb555_write_pixel(gate_uint8_t* data, gate_color_t const* col)
164 {
165 8192 unsigned num = ((unsigned)(col->r >> 3)) << 10
166 4096 | ((unsigned)(col->g >> 3)) << 5
167 4096 | ((unsigned)(col->b >> 3));
168 4096 data[0] = (gate_uint8_t)(num & 0xff);
169 4096 data[1] = (gate_uint8_t)(num >> 8);
170 4096 }
171 static void rgb555_read_pixel(gate_uint8_t const* data, gate_color_t* col)
172 {
173 static unsigned short const red_mask = 0x7C00;
174 static unsigned short const green_mask = 0x3E0;
175 static unsigned short const blue_mask = 0x1F;
176
177 unsigned short pixel = (unsigned)data[0] | (((unsigned)data[1]) << 8);
178
179 unsigned short r = (pixel & red_mask) >> 10;
180 unsigned short g = (pixel & green_mask) >> 5;
181 unsigned short b = (pixel & blue_mask);
182
183 col->r = (gate_uint8_t)((r << 3) | (r >> 2));
184 col->g = (gate_uint8_t)((g << 3) | (g >> 2));
185 col->b = (gate_uint8_t)((b << 3) | (b >> 2));
186 col->a = 255;
187 }
188 4096 static void rgb565_write_pixel(gate_uint8_t* data, gate_color_t const* col)
189 {
190 8192 unsigned num = ((unsigned)(col->r >> 3)) << 11
191 4096 | ((unsigned)(col->g >> 2)) << 5
192 4096 | ((unsigned)(col->b >> 3));
193 4096 data[0] = (gate_uint8_t)(num & 0xff);
194 4096 data[1] = (gate_uint8_t)(num >> 8);
195 4096 }
196 static void rgb565_read_pixel(gate_uint8_t const* data, gate_color_t* col)
197 {
198 static unsigned short const red_mask = 0xF800;
199 static unsigned short const green_mask = 0x7E0;
200 static unsigned short const blue_mask = 0x1F;
201
202 unsigned short pixel = (unsigned)data[0] | (((unsigned)data[1]) << 8);
203
204 unsigned short r = (pixel & red_mask) >> 11;
205 unsigned short g = (pixel & green_mask) >> 5;
206 unsigned short b = (pixel & blue_mask);
207
208 col->r = (gate_uint8_t)((r << 3) | (r >> 2));
209 col->g = (gate_uint8_t)((g << 2) | (g >> 4));
210 col->b = (gate_uint8_t)((b << 3) | (b >> 2));
211 col->a = 255;
212 }
213 4096 static void argb4_write_pixel(gate_uint8_t* data, gate_color_t const* col)
214 {
215 8192 unsigned pixel = ((unsigned)(col->a & 0xF0)) << 8
216 4096 | ((unsigned)(col->r & 0xF0)) << 4
217 4096 | ((unsigned)(col->g & 0xF0))
218 4096 | ((unsigned)(col->b & 0xF0)) >> 4;
219 4096 data[0] = (gate_uint8_t)(pixel & 0xff);
220 4096 data[1] = (gate_uint8_t)(pixel >> 8);
221 4096 }
222 static void argb4_read_pixel(gate_uint8_t const* data, gate_color_t* col)
223 {
224 static unsigned short const alpha_mask = 0xF000;
225 static unsigned short const red_mask = 0x0F00;
226 static unsigned short const green_mask = 0x00F0;
227 static unsigned short const blue_mask = 0x000F;
228
229 unsigned short pixel = (unsigned)data[0] | (((unsigned)data[1]) << 8);
230 unsigned short a = (pixel & alpha_mask) >> 8;
231 unsigned short r = (pixel & red_mask) >> 4;
232 unsigned short g = (pixel & green_mask);
233 unsigned short b = (pixel & blue_mask) << 4;
234 col->r = (gate_uint8_t)(r | (r >> 4));
235 col->g = (gate_uint8_t)(g | (g >> 4));
236 col->b = (gate_uint8_t)(b | (b >> 4));
237 col->a = (gate_uint8_t)(a | (a >> 4));
238 }
239 4096 static void yuv2_write_pixel(gate_uint8_t* data, gate_color_t const* col)
240 {
241 4096 data[0] = col->b;
242 4096 data[1] = col->g;
243 4096 data[2] = col->r;
244 4096 }
245 static void yuv2_read_pixel(gate_uint8_t const* data, gate_color_t* col)
246 {
247 col->b = data[0];
248 col->g = data[1];
249 col->r = data[2];
250 }
251 7828 static gate_uint8_t* col8_get_ptr(gate_uint8_t* data, unsigned width, unsigned height, unsigned line_pad, unsigned x, unsigned y)
252 {
253 7828 const unsigned linelen = width + line_pad;
254 GATE_UNUSED_ARG(height);
255 7828 return data + (gate_size_t)y * linelen + (gate_size_t)x;
256 }
257 4096 static void pal8_write_pixel(gate_uint8_t* data, gate_color_t const* col)
258 {
259 4096 const gate_color_rgb_t rgb = { col->r, col->g, col->b };
260 4096 *data = gate_color_palette_rgb8_index_from_color(rgb);
261 /*
262 unsigned r = (((unsigned)col->r) + 25) / 51;
263 unsigned g = (((unsigned)col->g) + 25) / 51;
264 unsigned b = (((unsigned)col->b) + 25) / 51;
265 data[0] = (gate_uint8_t)(16 + (r * 36 + g * 6 + b));
266 */
267 4096 }
268 static void pal8_read_pixel(gate_uint8_t const* data, gate_color_t* col)
269 {
270 gate_color_rgb_t col_rgb;
271 gate_color_palette_rgb8_from_index(*data, &col_rgb);
272 col->r = col_rgb.r;
273 col->g = col_rgb.g;
274 col->b = col_rgb.b;
275 col->a = 255;
276 /*
277 unsigned index = ((unsigned)*data);
278 if (index >= 16)
279 {
280 index -= 16;
281 col->r = (gate_uint8_t)((index / 36) * 51);
282 col->g = (gate_uint8_t)(((index % 36) / 6) * 51);
283 col->b = (gate_uint8_t)(((index % 36) % 6) * 51);
284 col->a = 255u;
285 }
286 */
287 }
288 11687 static void gray_write_pixel(gate_uint8_t* data, gate_color_t const* col)
289 {
290 11687 data[0] = (gate_uint8_t)(((unsigned)col->b + (unsigned)col->g + (unsigned)col->r) / 3);
291 11687 }
292 135 static void gray_read_pixel(gate_uint8_t const* data, gate_color_t* col)
293 {
294 135 col->r = col->g = col->b = data[0];
295 135 }
296
297
298 99 gate_rasterimage_t* gate_rasterimage_create(gate_rasterimage_t* image, gate_enumint_t pixel_format,
299 unsigned width, unsigned height,
300 gate_color_t const* copypixels)
301 {
302 99 gate_rasterimage_t* ret = NULL;
303
304 do
305 {
306 99 gate_rasterimage_get_ptr_t get_ptr = NULL;
307 99 gate_rasterimage_write_pixel_t write_pixel = NULL;
308 99 gate_rasterimage_read_pixel_t read_pixel = NULL;
309 99 unsigned bits_per_pixel = 0;
310 99 unsigned bytes_per_line = 0;
311 99 gate_bool_t direct_copy = false;
312
313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (image == NULL)
314 {
315 break;
316 }
317
318
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
99 if ((width == 0) || (height == 0))
319 {
320 46 gate_mem_clear(image, sizeof(gate_rasterimage_t));
321 46 ret = image;
322 46 break;
323 }
324
11/12
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
53 switch (pixel_format)
325 {
326 17 case GATE_IMAGE_PIXELFORMAT_DEFAULT:
327 {
328 17 pixel_format = GATE_IMAGE_PIXELFORMAT_RGB32;
329 /* fall-through desired! */
330 }
331 33 case GATE_IMAGE_PIXELFORMAT_RGB32:
332 case GATE_IMAGE_PIXELFORMAT_RGBA:
333 {
334 33 get_ptr = &rgba_bgra_get_ptr;
335 33 read_pixel = &rgba_read_pixel;
336 33 write_pixel = &rgba_write_pixel;
337 33 bits_per_pixel = 32;
338 33 direct_copy = true;
339 33 break;
340 }
341 2 case GATE_IMAGE_PIXELFORMAT_BGR32:
342 case GATE_IMAGE_PIXELFORMAT_BGRA:
343 {
344 2 get_ptr = &rgba_bgra_get_ptr;
345 2 read_pixel = &bgra_read_pixel;
346 2 write_pixel = &bgra_write_pixel;
347 2 bits_per_pixel = 32;
348 2 direct_copy = true;
349 2 break;
350 }
351
352 6 case GATE_IMAGE_PIXELFORMAT_RGB24:
353 {
354 6 get_ptr = &rgb_bgr_get_ptr;
355 6 read_pixel = &rgb_read_pixel;
356 6 write_pixel = &rgb_write_pixel;
357 6 bits_per_pixel = 24;
358 6 direct_copy = true;
359 6 break;
360 }
361 1 case GATE_IMAGE_PIXELFORMAT_BGR24:
362 {
363 1 get_ptr = &rgb_bgr_get_ptr;
364 1 read_pixel = &bgr_read_pixel;
365 1 write_pixel = &bgr_write_pixel;
366 1 bits_per_pixel = 24;
367 1 direct_copy = true;
368 1 break;
369 }
370
371 1 case GATE_IMAGE_PIXELFORMAT_RGB555:
372 {
373 1 get_ptr = &col16_get_ptr;
374 1 read_pixel = &rgb555_read_pixel;
375 1 write_pixel = &rgb555_write_pixel;
376 1 bits_per_pixel = 16;
377 1 direct_copy = true;
378 1 break;
379 }
380 1 case GATE_IMAGE_PIXELFORMAT_RGB565:
381 {
382 1 get_ptr = &col16_get_ptr;
383 1 read_pixel = &rgb565_read_pixel;
384 1 write_pixel = &rgb565_write_pixel;
385 1 bits_per_pixel = 16;
386 1 direct_copy = true;
387 1 break;
388 }
389 1 case GATE_IMAGE_PIXELFORMAT_ARGB4:
390 {
391 1 get_ptr = &col16_get_ptr;
392 1 read_pixel = &argb4_read_pixel;
393 1 write_pixel = &argb4_write_pixel;
394 1 bits_per_pixel = 16;
395 1 direct_copy = true;
396 1 break;
397 }
398 1 case GATE_IMAGE_PIXELFORMAT_YUV2:
399 {
400 1 get_ptr = &col16_get_ptr;
401 1 read_pixel = &yuv2_read_pixel;
402 1 write_pixel = &yuv2_write_pixel;
403 1 bits_per_pixel = 16;
404 1 direct_copy = true;
405 1 break;
406 }
407
408 4 case GATE_IMAGE_PIXELFORMAT_PAL8:
409 {
410 4 get_ptr = &col8_get_ptr;
411 4 read_pixel = &pal8_read_pixel;
412 4 write_pixel = &pal8_write_pixel;
413 4 bits_per_pixel = 8;
414 4 direct_copy = true;
415 4 break;
416 }
417 3 case GATE_IMAGE_PIXELFORMAT_GRAY8:
418 {
419 3 get_ptr = &col8_get_ptr;
420 3 read_pixel = &gray_read_pixel;
421 3 write_pixel = &gray_write_pixel;
422 3 bits_per_pixel = 8;
423 3 direct_copy = true;
424 3 break;
425 }
426
427 default:
428 return NULL;
429 }
430
431 53 image->databuffer = gate_image_databuffer_create(bits_per_pixel, width, height);
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (image->databuffer == NULL)
433 {
434 break;
435 }
436
437 53 image->width = width;
438 53 image->height = height;
439 53 image->bits_per_pixel = (gate_uint16_t)(image->databuffer->bits_per_pixel);
440 53 image->line_padding = (gate_uint16_t)(image->databuffer->padding_per_line);
441 53 bytes_per_line = image->databuffer->bytes_per_line;
442 53 image->pixel_format = (gate_uint16_t)pixel_format;
443 53 image->pixel_length = (gate_uint16_t)((image->databuffer->bits_per_pixel + 7) / 8);
444 53 image->get_ptr = get_ptr;
445 53 image->read_pixel = read_pixel;
446 53 image->write_pixel = write_pixel;
447 53 image->data = &image->databuffer->data[0];
448
449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 if (copypixels)
450 {
451 if (direct_copy)
452 {
453 gate_mem_copy(image->data, copypixels, (gate_size_t)bytes_per_line * height);
454 }
455 else
456 {
457 unsigned y;
458 for (y = 0; y < height; ++y)
459 {
460 unsigned x;
461 for (x = 0; x < width; ++x)
462 {
463 gate_uint8_t* ptr_data = image->get_ptr(image->data, image->width, image->height, image->line_padding, x, y);
464 image->write_pixel(ptr_data, copypixels);
465 ++copypixels;
466 }
467 }
468 }
469 }
470 53 ret = image;
471 } while (0);
472 99 return ret;
473 }
474
475
476 84 void gate_rasterimage_release(gate_rasterimage_t* image)
477 {
478
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 26 times.
84 if (image->databuffer)
479 {
480 58 gate_image_databuffer_release(image->databuffer);
481 }
482 84 gate_mem_clear(image, sizeof(gate_rasterimage_t));
483 84 }
484
485 4 gate_rasterimage_t* gate_rasterimage_duplicate(gate_rasterimage_t* dest_image, gate_rasterimage_t const* src_image)
486 {
487 4 gate_mem_copy(dest_image, src_image, sizeof(gate_rasterimage_t));
488 4 gate_image_databuffer_retain(dest_image->databuffer);
489 4 return dest_image;
490 }
491 gate_rasterimage_t* gate_rasterimage_copy(gate_rasterimage_t* dest_image, gate_rasterimage_t const* src_image)
492 {
493 gate_rasterimage_t* ret = gate_rasterimage_create(dest_image, src_image->pixel_format, src_image->width, src_image->height, NULL);
494 if (ret)
495 {
496 gate_size_t const line_length = (src_image->bits_per_pixel * src_image->width + 7) / 8;
497 unsigned y;
498 for (y = 0; y != src_image->height; ++y)
499 {
500 gate_uint8_t const* ptr_src = src_image->get_ptr(src_image->data, src_image->width, src_image->height, src_image->line_padding, 0, y);
501 gate_uint8_t* ptr_dest = dest_image->get_ptr(dest_image->data, dest_image->width, dest_image->height, src_image->line_padding, 0, y);
502 gate_mem_copy(ptr_dest, ptr_src, line_length);
503 }
504 }
505 return ret;
506 }
507
508 12 gate_rasterimage_t* gate_rasterimage_convert(gate_rasterimage_t* dest_image, gate_enumint_t pixel_format, gate_rasterimage_t const* src_image)
509 {
510 12 gate_rasterimage_t* ret = NULL;
511
512 12 ret = gate_rasterimage_create(dest_image, pixel_format, src_image->width, src_image->height, NULL);
513
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (ret != NULL)
514 {
515 12 unsigned const src_pixel_len = src_image->pixel_length;
516 12 unsigned const dest_pixel_len = dest_image->pixel_length;
517 unsigned y;
518
519
2/2
✓ Branch 0 taken 768 times.
✓ Branch 1 taken 12 times.
780 for (y = 0; y != src_image->height; ++y)
520 {
521 unsigned x;
522 768 gate_uint8_t* ptr_src = src_image->get_ptr(src_image->data, src_image->width, src_image->height, src_image->line_padding, 0, y);
523 768 gate_uint8_t* ptr_dest = dest_image->get_ptr(dest_image->data, dest_image->width, dest_image->height, dest_image->line_padding, 0, y);
524
525
2/2
✓ Branch 0 taken 49152 times.
✓ Branch 1 taken 768 times.
49920 for (x = 0; x != src_image->width; ++x)
526 {
527 gate_color_t col;
528 49152 src_image->read_pixel(ptr_src, &col);
529 49152 dest_image->write_pixel(ptr_dest, &col);
530 49152 ptr_src += src_pixel_len;
531 49152 ptr_dest += dest_pixel_len;
532 }
533 }
534 }
535 12 return ret;
536 }
537
538 1 gate_result_t gate_rasterimage_subset(gate_rasterimage_t* dest_image, gate_rasterimage_t const* src_image, unsigned x, unsigned y, unsigned width, unsigned height)
539 {
540 unsigned ny;
541
542
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!dest_image || !src_image)
543 {
544 return GATE_RESULT_INVALIDARG;
545 }
546
547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (x >= src_image->width) return GATE_RESULT_INVALIDARG;
548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (y >= src_image->height) return GATE_RESULT_INVALIDARG;
549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((x + width) > src_image->width) width = src_image->width - (x + width);
550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((y + height) > src_image->height) height = src_image->height - (x + height);
551
552
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if ((x == 0) && (width == src_image->width))
553 {
554 /* try a line-based slice */
555 gate_mem_copy(dest_image, src_image, sizeof(gate_rasterimage_t));
556 dest_image->width = width;
557 dest_image->height = height;
558 if (dest_image->databuffer)
559 {
560 gate_image_databuffer_retain(dest_image->databuffer);
561 }
562 dest_image->data = (gate_uint8_t*)gate_rasterimage_get_line_ptr(src_image, y);
563 return GATE_RESULT_OK;
564 }
565
566
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (src_image->bits_per_pixel >= 8)
567 {
568 gate_uint8_t const* end_line;
569 gate_uint8_t const* next_line;
570 /* try to build a padded subset image */
571 1 gate_mem_copy(dest_image, src_image, sizeof(gate_rasterimage_t));
572 1 dest_image->width = width;
573 1 dest_image->height = height;
574
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (dest_image->databuffer)
575 {
576 1 gate_image_databuffer_retain(dest_image->databuffer);
577 }
578 1 end_line = (gate_uint8_t const*)gate_rasterimage_get_pixel_ptr(src_image, x + width - 1, 0);
579 1 next_line = (gate_uint8_t const*)gate_rasterimage_get_pixel_ptr(src_image, x, 1);
580 1 dest_image->data = (gate_uint8_t*)gate_rasterimage_get_pixel_ptr(src_image, x, y);
581 1 dest_image->line_padding = (gate_uint16_t)((unsigned)(next_line - end_line)) - src_image->pixel_length;
582 1 return GATE_RESULT_OK;
583 }
584
585 /* create a new image with a copy of the subset */
586 if (NULL == gate_rasterimage_create(dest_image, src_image->pixel_format, width, height, NULL))
587 {
588 return GATE_RESULT_OUTOFMEMORY;
589 }
590 for (ny = y; ny < height; ++ny)
591 {
592 void const* ptr_src = gate_rasterimage_get_pixel_ptr(src_image, x, ny);
593 void* ptr_dst = gate_rasterimage_get_pixel_ptr(dest_image, 0, ny - y);
594 unsigned len = (((unsigned)src_image->bits_per_pixel * width + 7) / 8);
595 gate_mem_copy(ptr_dst, ptr_src, len);
596 }
597 return GATE_RESULT_OK;
598 }
599
600
601
602 2347 void* gate_rasterimage_get_line_ptr(gate_rasterimage_t const* image, unsigned y)
603 {
604 2347 gate_size_t line_width = (gate_size_t)(image->bits_per_pixel / 8) * (gate_size_t)image->width;
605 2347 gate_uint8_t* ptr = NULL;
606
1/2
✓ Branch 0 taken 2347 times.
✗ Branch 1 not taken.
2347 if (y < image->height)
607 {
608 2347 ptr = image->data + (line_width + image->line_padding) * y;
609 }
610 2347 return (void*)ptr;
611 }
612
613 1 gate_enumint_t gate_rasterimage_format(gate_rasterimage_t const* image)
614 {
615
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (image != NULL)
616 {
617 1 return image->pixel_format;
618 }
619 else
620 {
621 return GATE_IMAGE_PIXELFORMAT_UNKNOWN;
622 }
623 }
624
625 163 unsigned int gate_rasterimage_width(gate_rasterimage_t const* image)
626 {
627 163 unsigned int ret = 0;
628
1/2
✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
163 if (image != NULL)
629 {
630 163 ret = image->width;
631 }
632 163 return ret;
633 }
634
635 163 unsigned int gate_rasterimage_height(gate_rasterimage_t const* image)
636 {
637 163 unsigned int ret = 0;
638
1/2
✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
163 if (image != NULL)
639 {
640 163 ret = image->height;
641 }
642 163 return ret;
643 }
644
645 4 void* gate_rasterimage_get_pixel_ptr(gate_rasterimage_t const* image, unsigned x, unsigned y)
646 {
647
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (image && image->get_ptr)
648 {
649 4 return image->get_ptr(image->data, image->width, image->height, image->line_padding, x, y);
650 }
651 return NULL;
652 }
653
654 292948 gate_result_t gate_rasterimage_get_pixel(gate_rasterimage_t const* image, unsigned x, unsigned y, gate_color_t* out_pixel)
655 {
656 gate_uint8_t* ptr_pixel;
657
5/10
✓ Branch 0 taken 292948 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 292948 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 292948 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 292948 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 292948 times.
292948 if (!image || !image->read_pixel || !out_pixel || (x > image->width) || (y > image->height))
658 {
659 return GATE_RESULT_INVALIDARG;
660 }
661 292948 ptr_pixel = image->get_ptr(image->data, image->width, image->height, image->line_padding, x, y);
662 292948 image->read_pixel(ptr_pixel, out_pixel);
663 292948 return GATE_RESULT_OK;
664 }
665
666 42907 gate_result_t gate_rasterimage_set_pixel(gate_rasterimage_t* image, unsigned x, unsigned y, gate_color_t const* pixel)
667 {
668 gate_uint8_t* ptr_pixel;
669
5/10
✓ Branch 0 taken 42907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42907 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42907 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 42907 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 42907 times.
42907 if (!image || !image->write_pixel || !pixel || (x > image->width) || (y > image->height))
670 {
671 return GATE_RESULT_INVALIDARG;
672 }
673 42907 ptr_pixel = image->get_ptr(image->data, image->width, image->height, image->line_padding, x, y);
674 42907 image->write_pixel(ptr_pixel, pixel);
675 42907 return GATE_RESULT_OK;
676 }
677
678 1 gate_result_t gate_rasterimage_paste_image(gate_rasterimage_t* dst_image, gate_rasterimage_t const* src_image,
679 int dst_x, int dst_y,
680 int src_x, int src_y,
681 int width, int height,
682 gate_bool_t transparent)
683 {
684 1 gate_result_t ret = GATE_RESULT_OK;
685
686 do
687 {
688 1 int dst_width = (int)dst_image->width;
689 1 int dst_height = (int)dst_image->height;
690 1 int src_width = (int)src_image->width;
691 1 int src_height = (int)src_image->height;
692 1 int x_offset = 0;
693 1 int y_offset = 0;
694 1 int x_len = 0;
695 1 int y_len = 0;
696 int x, y;
697 unsigned src_pixel_length;
698 unsigned dst_pixel_length;
699 gate_bool_t equal_format;
700
701 /* source x/y outside of real source image*/
702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_x >= src_width) break;
703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_y >= src_height) break;
704
705
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (width > 0) width = src_width; else width += src_width;
706
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (height > 0) height = src_height; else height += src_height;
707
708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_x < 0)
709 {
710 width += src_x;
711 src_x = 0;
712 }
713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_y < 0)
714 {
715 height += src_y;
716 src_y = 0;
717 }
718
719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_x + width < 0) break;
720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_y + height < 0) break;
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_x + width > src_width) width = src_width - src_x;
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src_y + height > src_height) height = src_height - src_y;
723
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_x > dst_width) break;
725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_y > dst_height) break;
726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_x + width < 0) break;
727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_y + height < 0) break;
728
729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_x < 0)
730 {
731 x_offset = -dst_x;
732 width += dst_x;
733 dst_x = 0;
734 }
735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_y < 0)
736 {
737 y_offset = -dst_y;
738 height += dst_y;
739 dst_y = 0;
740 }
741
742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_x + width > dst_width) width = dst_width - dst_x;
743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst_y + height > dst_height) height = dst_height - dst_y;
744
745 1 x_len = (int)width;
746 1 y_len = (int)height;
747
748 1 src_pixel_length = src_image->pixel_length;
749 1 dst_pixel_length = dst_image->pixel_length;
750
751 1 equal_format = (src_pixel_length == dst_pixel_length)
752
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 && (src_image->pixel_format == dst_image->pixel_format);
753
754
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != y_len; ++y)
755 {
756 256 gate_uint8_t* src_data = src_image->get_ptr(src_image->data,
757 64 src_image->width, src_image->height, src_image->line_padding, x_offset + src_x, y + src_y + y_offset);
758 192 gate_uint8_t* dst_data = dst_image->get_ptr(dst_image->data,
759 64 dst_image->width, dst_image->height, dst_image->line_padding, dst_x, y + dst_y);
760
761
2/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 64 times.
64 if (equal_format && !transparent)
762 {
763 /* optimized mem-copy */
764 gate_mem_copy(dst_data, src_data, (gate_size_t)x_len * src_pixel_length);
765 }
766 else
767 {
768 /* transform pixel by pixel */
769
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x != x_len; ++x)
770 {
771 gate_color_t col;
772 4096 src_image->read_pixel(src_data, &col);
773 4096 dst_image->write_pixel(dst_data, &col);
774 4096 src_data += src_pixel_length;
775 4096 dst_data += dst_pixel_length;
776 }
777 }
778 }
779
780 } while (0);
781
782 1 return ret;
783 }
784
785
786 6 gate_bool_t gate_rasterimage_is_empty(gate_rasterimage_t const* image)
787 {
788
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
6 return (image->width == 0) || (image->height == 0) || (image->data == NULL);
789 }
790
791
792 1 gate_result_t gate_rasterimage_to_grayscale(gate_rasterimage_t* image)
793 {
794 1 gate_result_t ret = GATE_RESULT_OK;
795 1 unsigned const width = image->width;
796 1 unsigned const height = image->height;
797 1 unsigned const pixellength = image->pixel_length;
798 unsigned y;
799
800
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != height; ++y)
801 {
802 unsigned x;
803 64 gate_uint8_t* ptrpixel = image->get_ptr(image->data, width, height, image->line_padding, 0, y);
804
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = image->width; x != 0; --x)
805 {
806 gate_color_t col;
807 gate_uint8_t gray;
808 4096 image->read_pixel(ptrpixel, &col);
809 4096 gray = gate_color_to_grayscale(&col);
810 4096 col.r = gray;
811 4096 col.g = gray;
812 4096 col.b = gray;
813 4096 image->write_pixel(ptrpixel, &col);
814 4096 ptrpixel += pixellength;
815 }
816 }
817 1 return ret;
818 }
819
820 15940 static void update_pixel(gate_rasterimage_t* image, gate_uint8_t* ptrpixel, int value)
821 {
822 gate_color_t col;
823 int oldvalue;
824 int newvalue;
825
826 15940 image->read_pixel(ptrpixel, &col);
827 15940 oldvalue = ((int)col.r + (int)col.g + (int)col.b) / 3;
828 15940 newvalue = (int)oldvalue + value;
829
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 15835 times.
15940 if (newvalue < 0) newvalue = 0;
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15940 times.
15940 if (newvalue > 255) newvalue = 0;
831 15940 col.r = (gate_uint8_t)newvalue;
832 15940 col.g = (gate_uint8_t)newvalue;
833 15940 col.b = (gate_uint8_t)newvalue;
834 15940 image->write_pixel(ptrpixel, &col);
835 15940 }
836
837 1 gate_result_t gate_rasterimage_to_monochrome(gate_rasterimage_t* image)
838 {
839 1 gate_result_t ret = GATE_RESULT_OK;
840 gate_size_t pixelcount;
841 gate_uint8_t* ptrpixel /*= image->get_ptr(image->data, image->width, image->height, image->line_padding, 0, 0)*/;
842 1 gate_uint64_t pixelsum = 0;
843 gate_uint8_t avgpixel;
844 unsigned x, y;
845 1 unsigned const pixel_length = image->pixel_length;
846 gate_color_t col;
847
848
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != image->height; ++y)
849 {
850 64 ptrpixel = image->get_ptr(image->data, image->width, image->height, image->line_padding, 0, y);
851
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x != image->width; ++x)
852 {
853 4096 image->read_pixel(ptrpixel, &col);
854 4096 pixelsum += ((gate_uint16_t)col.r + (gate_uint16_t)col.g + (gate_uint16_t)col.b) / 3;
855 4096 ptrpixel += pixel_length;
856 }
857 }
858
859 1 pixelcount = (gate_size_t)image->width * (gate_size_t)image->height;
860 1 avgpixel = (gate_uint8_t)(pixelsum / (gate_uint64_t)pixelcount);
861
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (avgpixel < 64) avgpixel = 64;
862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (avgpixel > 192) avgpixel = 192;
863 1 ptrpixel = image->get_ptr(image->data, image->width, image->height, image->line_padding, 0, 0);
864
865 1 update_pixel(image, ptrpixel, 0); /* make first pixel gray-scale */
866
867
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != image->height; ++y)
868 {
869 gate_uint8_t* ptrpixel1 /*= image->get_ptr(image->data, image->width, image->height, image->line_padding, 1, 0)*/;
870 gate_uint8_t* ptrpixel2 /*= image->get_ptr(image->data, image->width, image->height, image->line_padding, image->width - 1, 0)*/;
871 gate_uint8_t* ptrpixel3 /*= image->get_ptr(image->data, image->width, image->height, image->line_padding, 1, 0)*/;
872 gate_uint8_t* ptrpixel4 /*= image->get_ptr(image->data, image->width, image->height, image->line_padding, 1, 1)*/;
873
874 64 ptrpixel = image->get_ptr(image->data, image->width, image->height, image->line_padding, 0, y);
875 64 ptrpixel1 = ptrpixel + pixel_length;
876 64 ptrpixel3 = image->get_ptr(image->data, image->width, image->height, image->line_padding, 0, y + 1);
877 64 ptrpixel2 = ptrpixel3 - pixel_length;
878 64 ptrpixel4 = ptrpixel3 + pixel_length;
879
880
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x != image->width; ++x)
881 {
882 gate_uint8_t curpixel;
883 gate_uint8_t newpixel;
884 int qerror;
885
886 4096 image->read_pixel(ptrpixel, &col);
887 4096 curpixel = col.r; /* all color-values are already equal*/
888
2/2
✓ Branch 0 taken 3850 times.
✓ Branch 1 taken 246 times.
4096 if (curpixel < avgpixel)
889 {
890 3850 newpixel = 0;
891 }
892 else
893 {
894 246 newpixel = 255;
895 }
896 4096 col.r = col.g = col.b = newpixel;
897 4096 image->write_pixel(ptrpixel, &col);
898 4096 qerror = curpixel - newpixel;
899
900
901
4/4
✓ Branch 0 taken 4032 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 3969 times.
✓ Branch 3 taken 63 times.
4096 if ((y != image->height - 1) && (x != image->width - 1))
902 {
903 3969 update_pixel(image, ptrpixel1, qerror * 7 / 16);
904 }
905
906
2/2
✓ Branch 0 taken 4032 times.
✓ Branch 1 taken 64 times.
4096 if (y != image->height - 1)
907 {
908 4032 update_pixel(image, ptrpixel2, qerror * 3 / 16);
909 4032 update_pixel(image, ptrpixel3, qerror * 5 / 16);
910
4/4
✓ Branch 0 taken 3968 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 3906 times.
✓ Branch 3 taken 62 times.
4032 if ((y != image->height - 2) && (x != image->width - 1))
911 {
912 3906 update_pixel(image, ptrpixel4, qerror * 1 / 16);
913 }
914 }
915
916 4096 ptrpixel += pixel_length;
917 4096 ptrpixel1 += pixel_length;
918 4096 ptrpixel2 += pixel_length;
919 4096 ptrpixel3 += pixel_length;
920 4096 ptrpixel4 += pixel_length;
921 }
922 }
923 1 return ret;
924 }
925
926 static void gate_rasterimage_clear_pal8(gate_rasterimage_t* dest, gate_color_t const* clear_color)
927 {
928 gate_size_t line_len = (gate_size_t)dest->pixel_length * (gate_size_t)dest->width + dest->line_padding;
929 gate_size_t buffer_len = line_len * (gate_size_t)dest->height;
930 gate_uint8_t pix;
931 pal8_write_pixel(&pix, clear_color);
932 gate_mem_fill(dest->data, (char)pix, buffer_len);
933 }
934 2 static void gate_rasterimage_clear_gray8(gate_rasterimage_t* dest, gate_color_t const* clear_color)
935 {
936 2 gate_size_t line_len = (gate_size_t)dest->pixel_length * (gate_size_t)dest->width + dest->line_padding;
937 2 gate_size_t buffer_len = line_len * (gate_size_t)dest->height;
938 gate_uint8_t pix;
939 2 gray_write_pixel(&pix, clear_color);
940 2 gate_mem_fill(dest->data, (char)pix, buffer_len);
941 2 }
942
943 15 gate_result_t gate_rasterimage_clear(gate_rasterimage_t* dest, gate_color_t const* clear_color)
944 {
945 15 unsigned const width = dest->width;
946 15 unsigned const height = dest->height;
947 15 unsigned const pixel_length = dest->pixel_length;
948 gate_color_t col;
949
950
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (clear_color)
951 {
952 15 col = *clear_color;
953 }
954 else
955 {
956 gate_mem_clear(&col, sizeof(gate_color_t));
957 }
958
959
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
15 switch (dest->pixel_format)
960 {
961 case GATE_IMAGE_PIXELFORMAT_PAL8:
962 {
963 gate_rasterimage_clear_pal8(dest, &col);
964 break;
965 }
966 2 case GATE_IMAGE_PIXELFORMAT_GRAY8:
967 {
968 2 gate_rasterimage_clear_gray8(dest, &col);
969 2 break;
970 }
971 13 default:
972 {
973 unsigned y;
974 /* generic implementation */
975
2/2
✓ Branch 0 taken 1226 times.
✓ Branch 1 taken 13 times.
1239 for (y = 0; y != height; ++y)
976 {
977 unsigned x;
978 1226 gate_uint8_t* ptr = dest->get_ptr(dest->data, width, height, dest->line_padding, 0, y);
979
2/2
✓ Branch 0 taken 253668 times.
✓ Branch 1 taken 1226 times.
254894 for (x = 0; x != width; ++x)
980 {
981 253668 dest->write_pixel(ptr, &col);
982 253668 ptr += pixel_length;
983 }
984 }
985 13 break;
986 }
987 }
988 15 return GATE_RESULT_OK;
989 }
990
991
992 1 gate_result_t gate_rasterimage_rotate_left(gate_rasterimage_t* dst, gate_rasterimage_t const* src)
993 {
994 unsigned y;
995 1 unsigned const dst_width = src->height;
996 1 unsigned const dst_height = src->width;
997 1 unsigned src_line_length = src->width * sizeof(gate_color_t) + src->line_padding;
998 1 unsigned dst_pixel_length = src->pixel_length;
999
1000
1001
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_rasterimage_create(dst, src->pixel_format, dst_width, dst_height, NULL))
1002 {
1003 return GATE_RESULT_OUTOFMEMORY;
1004 }
1005
1006
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != dst_height; ++y)
1007 {
1008 unsigned x;
1009 64 gate_uint8_t const* ptr_src = src->get_ptr(src->data, src->width, src->height, src->line_padding, src->width - 1 - y, 0);
1010 64 gate_uint8_t* ptr_dst = dst->get_ptr(dst->data, dst_width, dst_height, dst->line_padding, 0, y);
1011
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x != dst_width; ++x)
1012 {
1013 gate_color_t col;
1014 4096 src->read_pixel(ptr_src, &col);
1015 4096 dst->write_pixel(ptr_dst, &col);
1016 4096 ptr_dst += dst_pixel_length;
1017 4096 ptr_src += src_line_length;
1018 }
1019 }
1020 1 return GATE_RESULT_OK;
1021 }
1022
1023 1 gate_result_t gate_rasterimage_rotate_right(gate_rasterimage_t* dst, gate_rasterimage_t const* src)
1024 {
1025 unsigned y;
1026 1 unsigned const width = src->height;
1027 1 unsigned const height = src->width;
1028 1 unsigned const pixel_len = src->pixel_length;
1029 1 unsigned const line_length = ((src->width * (unsigned)src->bits_per_pixel + 7) / 8) + src->line_padding;
1030 gate_color_t col;
1031
1032
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_rasterimage_create(dst, src->pixel_format, width, height, NULL))
1033 {
1034 return GATE_RESULT_OUTOFMEMORY;
1035 }
1036
1037
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != height; ++y)
1038 {
1039 unsigned x;
1040 64 gate_uint8_t const* ptr_src = src->get_ptr(src->data, src->width, src->height, src->line_padding, y, src->height - 1);
1041 64 gate_uint8_t* ptr_dst = dst->get_ptr(dst->data, dst->width, dst->height, dst->line_padding, 0, y);
1042
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x != dst->width; ++x)
1043 {
1044 4096 src->read_pixel(ptr_src, &col);
1045 4096 dst->write_pixel(ptr_dst, &col);
1046 4096 ptr_dst += pixel_len;
1047 4096 ptr_src -= line_length;
1048 }
1049 }
1050 1 return GATE_RESULT_OK;
1051 }
1052
1053 1 gate_result_t gate_rasterimage_roll_over(gate_rasterimage_t* dst, gate_rasterimage_t const* src)
1054 {
1055 1 unsigned const width = src->width;
1056 1 unsigned const height = src->height;
1057 1 unsigned const pixel_len = src->pixel_length;
1058 unsigned y;
1059
1060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dst == src)
1061 {
1062 const unsigned half_width = width / 2;
1063 for (y = 0; y != height; ++y)
1064 {
1065 unsigned x;
1066 gate_uint8_t* ptr_src = src->get_ptr(src->data, width, height, src->line_padding, width - 1, height - 1 - y);
1067 gate_uint8_t* ptr_dst = dst->get_ptr(dst->data, width, height, dst->line_padding, 0, y);
1068 for (x = 0; x != half_width; ++x)
1069 {
1070 gate_color_t col1;
1071 gate_color_t col2;
1072 src->read_pixel(ptr_src, &col1);
1073 dst->read_pixel(ptr_dst, &col2);
1074
1075 src->write_pixel(ptr_src, &col2);
1076 dst->write_pixel(ptr_dst, &col1);
1077 ptr_src -= pixel_len;
1078 ptr_dst += pixel_len;
1079 }
1080 }
1081 }
1082 else
1083 {
1084
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_rasterimage_create(dst, src->pixel_format, width, height, NULL))
1085 {
1086 return GATE_RESULT_OUTOFMEMORY;
1087 }
1088
1089
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != height; ++y)
1090 {
1091 unsigned x;
1092 64 gate_uint8_t const* ptr_src = src->get_ptr(src->data, width, height, src->line_padding, width - 1, height - 1 - y);
1093 64 gate_uint8_t* ptr_dst = dst->get_ptr(dst->data, width, height, dst->line_padding, 0, y);
1094
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x != width; ++x)
1095 {
1096 gate_color_t col;
1097 4096 src->read_pixel(ptr_src, &col);
1098 4096 dst->write_pixel(ptr_dst, &col);
1099 4096 ptr_src -= pixel_len;
1100 4096 ptr_dst += pixel_len;
1101 }
1102 }
1103 }
1104 1 return GATE_RESULT_OK;
1105 }
1106
1107 1 gate_result_t gate_rasterimage_flip_x(gate_rasterimage_t* dst, gate_rasterimage_t const* src)
1108 {
1109 unsigned x, y;
1110 gate_uint8_t* ptr_left;
1111 gate_uint8_t* ptr_right;
1112 1 unsigned const pixel_len = src->pixel_length;
1113 gate_color_t col_a;
1114
1115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src == dst)
1116 {
1117 unsigned const len = dst->width / 2;
1118 for (y = 0; y != dst->height; ++y)
1119 {
1120 ptr_left = dst->get_ptr(dst->data, dst->width, dst->height, dst->line_padding, 0, y);
1121 ptr_right = dst->get_ptr(dst->data, dst->width, dst->height, dst->line_padding, dst->width - 1, y);
1122 for (x = 0; x != len; ++x)
1123 {
1124 gate_color_t col_b;
1125 dst->read_pixel(ptr_left, &col_a);
1126 dst->read_pixel(ptr_right, &col_b);
1127 dst->write_pixel(ptr_left, &col_b);
1128 dst->write_pixel(ptr_right, &col_a);
1129 ptr_left += pixel_len;
1130 ptr_right -= pixel_len;
1131 }
1132 }
1133 }
1134 else
1135 {
1136
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_rasterimage_create(dst, src->pixel_format, src->width, src->height, NULL))
1137 {
1138 return GATE_RESULT_OUTOFMEMORY;
1139 }
1140
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != src->height; ++y)
1141 {
1142 64 ptr_left = src->get_ptr(src->data, src->width, src->height, src->line_padding, src->width - 1, y);
1143 64 ptr_right = dst->get_ptr(dst->data, dst->width, dst->height, dst->line_padding, 0, y);
1144
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x != src->width; ++x)
1145 {
1146 4096 src->read_pixel(ptr_left, &col_a);
1147 4096 dst->write_pixel(ptr_right, &col_a);
1148 4096 ptr_left -= pixel_len;
1149 4096 ptr_right += pixel_len;
1150 }
1151 }
1152 }
1153 1 return GATE_RESULT_OK;
1154 }
1155
1156 1 gate_result_t gate_rasterimage_flip_y(gate_rasterimage_t* dst, gate_rasterimage_t const* src)
1157 {
1158 unsigned y;
1159 gate_uint8_t* ptr_top;
1160 gate_uint8_t* ptr_bottom;
1161 unsigned length;
1162
1163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src == dst)
1164 {
1165 unsigned const count = dst->height / 2;
1166 length = dst->pixel_length;
1167
1168 for (y = 0; y != count; ++y)
1169 {
1170 unsigned x;
1171 ptr_top = dst->get_ptr(dst->data, dst->width, dst->height, dst->line_padding, 0, y);
1172 ptr_bottom = dst->get_ptr(dst->data, dst->width, dst->height, dst->line_padding, 0, dst->height - 1 - y);
1173
1174 for (x = 0; x != dst->width; ++x)
1175 {
1176 gate_color_t col_a;
1177 gate_color_t col_b;
1178 dst->read_pixel(ptr_top, &col_a);
1179 dst->read_pixel(ptr_bottom, &col_b);
1180 dst->write_pixel(ptr_bottom, &col_a);
1181 dst->write_pixel(ptr_top, &col_b);
1182 ptr_top += length;
1183 ptr_bottom += length;
1184 }
1185 }
1186 }
1187 else
1188 {
1189
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_rasterimage_create(dst, src->pixel_format, src->width, src->height, NULL))
1190 {
1191 return GATE_RESULT_OUTOFMEMORY;
1192 }
1193
1194 1 length = src->pixel_length * src->width;
1195
1196
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y != src->height; ++y)
1197 {
1198 64 ptr_bottom = src->get_ptr(src->data, src->width, src->height, src->line_padding, 0, src->height - 1 - y);
1199 64 ptr_top = dst->get_ptr(dst->data, dst->width, dst->height, dst->line_padding, 0, y);
1200 64 gate_mem_copy(ptr_top, ptr_bottom, length);
1201 }
1202 }
1203 1 return GATE_RESULT_OK;
1204 }
1205
1206 1 gate_result_t gate_rasterimage_resample(gate_rasterimage_t* dest, gate_rasterimage_t const* src)
1207 {
1208 unsigned x, y;
1209 float dx, dy;
1210
1211 1 dx = (float)src->width / (float)dest->width;
1212 1 dy = (float)src->height / (float)dest->height;
1213
1214
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1 times.
65 for (y = 0; y < dest->height; ++y)
1215 {
1216 64 gate_uint8_t* ptr_out = dest->get_ptr(dest->data, dest->width, dest->height, dest->line_padding, 0, y);
1217 64 unsigned const miny = (unsigned)((float)y * dy);
1218 64 unsigned maxy = (unsigned)((float)(y + 1) * dy);
1219
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 63 times.
64 if (maxy >= src->height)
1220 {
1221 1 maxy = src->height - 1;
1222 }
1223
1224
2/2
✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 64 times.
4160 for (x = 0; x < dest->width; ++x)
1225 {
1226 4096 float r = 0.0f, g = 0.0f, b = 0.0f, count = 0.0f;
1227 gate_color_t col;
1228 unsigned sy;
1229 4096 unsigned const minx = (unsigned)((float)x * dx);
1230 4096 unsigned maxx = (unsigned)((float)(x + 1) * dy);
1231
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4032 times.
4096 if (maxx >= src->width)
1232 {
1233 64 maxx = src->width - 1;
1234 }
1235
1236
2/2
✓ Branch 0 taken 8128 times.
✓ Branch 1 taken 4096 times.
12224 for (sy = miny; sy <= maxy; ++sy)
1237 {
1238 unsigned sx;
1239 8128 gate_uint8_t const* ptr_in = src->get_ptr(src->data, src->width, src->height, src->line_padding, minx, sy);
1240
2/2
✓ Branch 0 taken 16129 times.
✓ Branch 1 taken 8128 times.
24257 for (sx = minx; sx <= maxx; ++sx)
1241 {
1242 16129 src->read_pixel(ptr_in, &col);
1243 16129 r += (float)col.r;
1244 16129 g += (float)col.g;
1245 16129 b += (float)col.b;
1246 16129 count += 1.0f;
1247 16129 ptr_in += src->pixel_length;
1248 }
1249 }
1250 4096 col.r = (gate_uint8_t)(unsigned)(r / count + 0.5f);
1251 4096 col.g = (gate_uint8_t)(unsigned)(g / count + 0.5f);
1252 4096 col.b = (gate_uint8_t)(unsigned)(b / count + 0.5f);
1253 4096 col.a = 255;
1254 4096 dest->write_pixel(ptr_out, &col);
1255 4096 ptr_out += dest->pixel_length;
1256 }
1257 }
1258 1 return GATE_RESULT_OK;
1259 }
1260