GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/images.c
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 526 673 78.2%
Functions: 45 54 83.3%
Branches: 160 259 61.8%

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