GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/images.c
Date: 2025-09-22 22:57:09
Exec Total Coverage
Lines: 251 675 37.2%
Functions: 28 54 51.9%
Branches: 67 259 25.9%

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