GCC Code Coverage Report


Directory: src/gate/
File: src/gate/graphics/images.c
Date: 2025-09-14 13:10:38
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