GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_image_reader_colorspace_convert.c Lines: 111 111 100.0 %
Date: 2026-03-06 19:21:09 Branches: 45 45 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Image Reader Management (Image Reader)                              */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_system.h"
29
#include "gx_image_reader.h"
30
31
#define GX_FS_SCALE             10
32
#define GX_DITHER_SPECKLE_LIMIT 400
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _gx_image_reader_one_row_dither                     PORTABLE C      */
39
/*                                                           6.1          */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    Kenneth Maxwell, Microsoft Corporation                              */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    This helper function does dithering for one row of the pixelmap.    */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    image_reader                          Image reader control block    */
51
/*    error_ptr                             Memory for error information  */
52
/*                                                                        */
53
/*  OUTPUT                                                                */
54
/*                                                                        */
55
/*    None                                                                */
56
/*                                                                        */
57
/*  CALLS                                                                 */
58
/*                                                                        */
59
/*    [gx_image_reader_pixel_read]          Read a pixel from input buffer*/
60
/*    [gx_image_reader_pixel_write]         Write a pixel out with        */
61
/*                                            specified color format      */
62
/*                                                                        */
63
/*  CALLED BY                                                             */
64
/*                                                                        */
65
/*    _gx_image_reader_colorspace_convert                                 */
66
/*                                                                        */
67
/**************************************************************************/
68
#if defined(GX_SOFTWARE_DECODER_SUPPORT)
69
32388
static VOID _gx_image_reader_one_row_dither(GX_IMAGE_READER *image_reader, INT *error_ptr)
70
{
71
UINT     width;
72
UINT     err_width;
73
UINT     col;
74
GX_PIXEL want_pixel;
75
GX_PIXEL written_pixel;
76
INT      red_err;
77
INT      green_err;
78
INT      blue_err;
79
INT     *next_err;
80
INT     *cur_err;
81
82
32388
    width = image_reader -> gx_image_reader_image_width;
83
32388
    err_width = width + 2;
84
85
32388
    cur_err = error_ptr;
86
32388
    next_err = error_ptr + err_width * 3;
87
32388
    memset(next_err, 0, sizeof(INT) * err_width * 3);
88
89
7907426
    for (col = 0; col < width; col++)
90
    {
91
7875038
        image_reader -> gx_image_reader_pixel_read(image_reader, (INT)col, &want_pixel);
92
93
7875038
        red_err = (cur_err[col + 1] >> GX_FS_SCALE);
94
7875038
        green_err = (cur_err[err_width + col + 1] >> GX_FS_SCALE);
95
7875038
        blue_err = (cur_err[err_width * 2 + col + 1] >> GX_FS_SCALE);
96
97
7875038
        if (want_pixel.gx_pixel_red + red_err > 255)
98
        {
99
1075846
            want_pixel.gx_pixel_red = 255;
100
        }
101
6799192
        else if (want_pixel.gx_pixel_red + red_err < 0)
102
        {
103
127656
            want_pixel.gx_pixel_red = 0;
104
        }
105
        else
106
        {
107
6671536
            want_pixel.gx_pixel_red = (GX_UBYTE)(want_pixel.gx_pixel_red + red_err);
108
        }
109
110
7875038
        if (want_pixel.gx_pixel_green + green_err > 255)
111
        {
112
685176
            want_pixel.gx_pixel_green = 255;
113
        }
114
7189862
        else if (want_pixel.gx_pixel_green + green_err < 0)
115
        {
116
141350
            want_pixel.gx_pixel_green = 0;
117
        }
118
        else
119
        {
120
7048512
            want_pixel.gx_pixel_green = (GX_UBYTE)(want_pixel.gx_pixel_green + green_err);
121
        }
122
123
7875038
        if (want_pixel.gx_pixel_blue + blue_err > 255)
124
        {
125
758129
            want_pixel.gx_pixel_blue = 255;
126
        }
127
7116909
        else if (want_pixel.gx_pixel_blue + blue_err < 0)
128
        {
129
479439
            want_pixel.gx_pixel_blue = 0;
130
        }
131
        else
132
        {
133
6637470
            want_pixel.gx_pixel_blue = (GX_UBYTE)(want_pixel.gx_pixel_blue + blue_err);
134
        }
135
136
7875038
        written_pixel = want_pixel;
137
138
7875038
        image_reader -> gx_image_reader_pixel_write(image_reader, &written_pixel);
139
140
        /* Calculate color space convert error. */
141
7875038
        red_err = ((want_pixel.gx_pixel_red - written_pixel.gx_pixel_red) << GX_FS_SCALE);
142
7875038
        green_err = ((want_pixel.gx_pixel_green - written_pixel.gx_pixel_green) << GX_FS_SCALE);
143
7875038
        blue_err = ((want_pixel.gx_pixel_blue - written_pixel.gx_pixel_blue) << GX_FS_SCALE);
144
145
        /* Red error.  */
146
7875038
        if (GX_ABS(red_err) > GX_DITHER_SPECKLE_LIMIT)
147
        {
148
4409010
            cur_err[col + 2]  += ((red_err * 7) >> 4);
149
4409010
            next_err[col]     += ((red_err * 3) >> 4);
150
4409010
            next_err[col + 1] += ((red_err * 5) >> 4);
151
4409010
            next_err[col + 2] += ((red_err) >> 4);
152
        }
153
        else
154
        {
155
3466028
            cur_err[col + 2]  = 0;
156
3466028
            next_err[col]     = 0;
157
3466028
            next_err[col + 1] = 0;
158
3466028
            next_err[col + 2] = 0;
159
        }
160
161
        /* Green error. */
162
7875038
        if (GX_ABS(green_err) > GX_DITHER_SPECKLE_LIMIT)
163
        {
164
4199296
            cur_err[err_width + col + 2]  += ((green_err * 7) >> 4);
165
4199296
            next_err[err_width + col]     += ((green_err * 3) >> 4);
166
4199296
            next_err[err_width + col + 1] += ((green_err * 5) >> 4);
167
4199296
            next_err[err_width + col + 2] += ((green_err) >> 4);
168
        }
169
        else
170
        {
171
3675742
            cur_err[err_width + col + 2]  = 0;
172
3675742
            next_err[err_width + col]     = 0;
173
3675742
            next_err[err_width + col + 1] = 0;
174
3675742
            next_err[err_width + col + 2] = 0;
175
        }
176
177
        /* Blue error.  */
178
7875038
        if (GX_ABS(blue_err) > GX_DITHER_SPECKLE_LIMIT)
179
        {
180
4335150
            cur_err[err_width * 2 + col + 2] += ((blue_err * 7) >> 4);
181
4335150
            next_err[err_width * 2 + col] += ((blue_err * 3) >> 4);
182
4335150
            next_err[err_width * 2 + col + 1] += ((blue_err * 5) >> 4);
183
4335150
            next_err[err_width * 2 + col + 2] += ((blue_err) >> 4);
184
        }
185
        else
186
        {
187
3539888
            cur_err[err_width * 2 + col + 2]  = 0;
188
3539888
            next_err[err_width * 2 + col]     = 0;
189
3539888
            next_err[err_width * 2 + col + 1] = 0;
190
3539888
            next_err[err_width * 2 + col + 2] = 0;
191
        }
192
    }
193
194
32388
    memcpy((void *)cur_err, (void *)next_err, err_width * 3 * sizeof(INT)); /* Use case of memcpy is verified. */
195
32388
}
196
#endif
197
198
/**************************************************************************/
199
/*                                                                        */
200
/*  FUNCTION                                               RELEASE        */
201
/*                                                                        */
202
/*    _gx_image_reader_one_row_convert                    PORTABLE C      */
203
/*                                                           6.1          */
204
/*  AUTHOR                                                                */
205
/*                                                                        */
206
/*    Kenneth Maxwell, Microsoft Corporation                              */
207
/*                                                                        */
208
/*  DESCRIPTION                                                           */
209
/*                                                                        */
210
/*    This helper function converts pixel data to specified color format  */
211
/*    for one row of the pixelmap.                                        */
212
/*                                                                        */
213
/*  INPUT                                                                 */
214
/*                                                                        */
215
/*    image_reader                          Image reader control block    */
216
/*    width                                 Pointer to pixelmap width     */
217
/*                                                                        */
218
/*  OUTPUT                                                                */
219
/*                                                                        */
220
/*    None                                                                */
221
/*                                                                        */
222
/*  CALLS                                                                 */
223
/*                                                                        */
224
/*    [gx_image_reader_pixel_read]          Read a pixel from input buffer*/
225
/*    [gx_image_reader_pixel_write]         Write a pixel out with        */
226
/*                                            specified color format      */
227
/*                                                                        */
228
/*  CALLED BY                                                             */
229
/*                                                                        */
230
/*    _gx_image_reader_colorspace_convert                                 */
231
/*                                                                        */
232
/**************************************************************************/
233
#if defined(GX_SOFTWARE_DECODER_SUPPORT)
234
42576
static VOID _gx_image_reader_one_row_convert(GX_IMAGE_READER *image_reader, INT *width)
235
{
236
INT      xval;
237
GX_PIXEL pixel;
238
239
8563734
    for (xval = 0; xval < (*width); xval++)
240
    {
241
8521158
        image_reader -> gx_image_reader_pixel_read(image_reader, xval, &pixel);
242
8521158
        image_reader -> gx_image_reader_pixel_write(image_reader, &pixel);
243
    }
244
42576
}
245
#endif
246
247
/**************************************************************************/
248
/*                                                                        */
249
/*  FUNCTION                                               RELEASE        */
250
/*                                                                        */
251
/*    _gx_image_reader_one_row_rotated_convert            PORTABLE C      */
252
/*                                                           6.1.3        */
253
/*  AUTHOR                                                                */
254
/*                                                                        */
255
/*    Kenneth Maxwell, Microsoft Corporation                              */
256
/*                                                                        */
257
/*  DESCRIPTION                                                           */
258
/*                                                                        */
259
/*    This helper function converts pixel data to specified color format  */
260
/*    for one row of the pixelmap with rotation.                          */
261
/*                                                                        */
262
/*  INPUT                                                                 */
263
/*                                                                        */
264
/*    image_reader                          Image reader control block    */
265
/*    width                                 Pointer to pixelmap width     */
266
/*                                                                        */
267
/*  OUTPUT                                                                */
268
/*                                                                        */
269
/*    None                                                                */
270
/*                                                                        */
271
/*  CALLS                                                                 */
272
/*                                                                        */
273
/*    [gx_image_reader_pixel_read]          Read a pixel from input buffer*/
274
/*    [gx_image_reader_pixel_write]         Write a pixel out with        */
275
/*                                            specified color format      */
276
/*                                                                        */
277
/*  CALLED BY                                                             */
278
/*                                                                        */
279
/*    _gx_image_reader_colorspace_convert                                 */
280
/*                                                                        */
281
/**************************************************************************/
282
#if defined(GX_SOFTWARE_DECODER_SUPPORT)
283
28833
static VOID _gx_image_reader_one_row_rotated_convert(GX_IMAGE_READER *image_reader, INT *width)
284
{
285
INT      xval;
286
GX_PIXEL pixel;
287
288
28833
    image_reader -> gx_image_reader_putdata = image_reader -> gx_image_reader_putdatarow;
289
28833
    image_reader -> gx_image_reader_putauxdata = image_reader -> gx_image_reader_putauxdatarow;
290
291
5415504
    for (xval = 0; xval < (*width); xval++)
292
    {
293
5386671
        image_reader -> gx_image_reader_pixel_read(image_reader, xval, &pixel);
294
5386671
        image_reader -> gx_image_reader_pixel_write(image_reader, &pixel);
295
    }
296
297
28833
    image_reader -> gx_image_reader_putdatarow += image_reader -> gx_image_reader_putdatarow_stride;
298
28833
    image_reader -> gx_image_reader_putauxdatarow += image_reader -> gx_image_reader_putauxdatarow_stride;
299
28833
}
300
#endif
301
302
/**************************************************************************/
303
/*                                                                        */
304
/*  FUNCTION                                               RELEASE        */
305
/*                                                                        */
306
/*    _gx_image_reader_colorspace_convert                 PORTABLE C      */
307
/*                                                           6.1          */
308
/*  AUTHOR                                                                */
309
/*                                                                        */
310
/*    Kenneth Maxwell, Microsoft Corporation                              */
311
/*                                                                        */
312
/*  DESCRIPTION                                                           */
313
/*                                                                        */
314
/*    This function converts a pixelmap to the specified color format     */
315
/*    with or without dithering process.                                  */
316
/*                                                                        */
317
/*  INPUT                                                                 */
318
/*                                                                        */
319
/*    image_reader                          Image reader control block    */
320
/*    outmap                                Output pixelmap               */
321
/*                                                                        */
322
/*  OUTPUT                                                                */
323
/*                                                                        */
324
/*    None                                                                */
325
/*                                                                        */
326
/*  CALLS                                                                 */
327
/*                                                                        */
328
/*    _gx_image_reader_one_row_dither      Process dithering for one row  */
329
/*    _gx_image_reader_one_row_convert     Process direct convert for one */
330
/*                                           row                          */
331
/*                                                                        */
332
/*  CALLED BY                                                             */
333
/*                                                                        */
334
/*    GUIX Internal Code                                                  */
335
/*                                                                        */
336
/**************************************************************************/
337
#if defined(GX_SOFTWARE_DECODER_SUPPORT)
338
765
UINT _gx_image_reader_colorspace_convert(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap)
339
{
340
INT  yval;
341
765
INT *param = GX_NULL;
342
INT  width;
343
INT  height;
344
VOID (*row_convert)(GX_IMAGE_READER *, INT *);
345
346
765
    width = outmap -> gx_pixelmap_width;
347
765
    height = outmap -> gx_pixelmap_height;
348
349
765
    if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_DITHER)
350
    {
351
        /* This function is called to convert decoded png/jpeg data to guix format pixelmap,
352
           max png/jpeg width and heigt is limited to 14 bits, so overflow cannot occur. */
353
159
        param = (INT *)_gx_system_memory_allocator(sizeof(INT) * (UINT)(width + 2) * 6);
354
355
159
        if (!param)
356
        {
357
3
            return GX_SYSTEM_MEMORY_ERROR;
358
        }
359
360
156
        memset((VOID *)param, 0, (sizeof(INT) * (UINT)(width + 2) * 3));
361
156
        row_convert = _gx_image_reader_one_row_dither;
362
    }
363
    else
364
    {
365
606
        param = &width;
366
367
606
        if (image_reader -> gx_image_reader_mode & (GX_IMAGE_READER_MODE_ROTATE_CW | GX_IMAGE_READER_MODE_ROTATE_CCW))
368
        {
369
177
            row_convert = _gx_image_reader_one_row_rotated_convert;
370
        }
371
        else
372
        {
373
429
            row_convert = _gx_image_reader_one_row_convert;
374
        }
375
    }
376
377
762
    image_reader -> gx_image_reader_size_testing = GX_FALSE;
378
379
    /* Run color space convert.  */
380
104559
    for (yval = 0; yval < height; yval++)
381
    {
382
103797
        row_convert(image_reader, param);
383
384
103797
        image_reader -> gx_image_reader_getdata += image_reader -> gx_image_reader_input_stride;
385
103797
        image_reader -> gx_image_reader_getauxdata += width;
386
387
103797
        switch (image_reader -> gx_image_reader_color_format)
388
        {
389
4176
        case GX_COLOR_FORMAT_4BIT_GRAY:
390
4176
            if (image_reader -> gx_image_reader_putdata_mask != 0xf0)
391
            {
392
2670
                image_reader -> gx_image_reader_putdata++;
393
2670
                image_reader -> gx_image_reader_putdata_mask = 0xf0;
394
            }
395
396
4176
            if (image_reader -> gx_image_reader_putauxdata)
397
            {
398
1618
                if (image_reader -> gx_image_reader_putauxdata_mask != 0x80)
399
                {
400
1602
                    image_reader -> gx_image_reader_putauxdata++;
401
1602
                    image_reader -> gx_image_reader_putauxdata_mask = 0x80;
402
                }
403
            }
404
4176
            break;
405
406
4640
        case GX_COLOR_FORMAT_MONOCHROME:
407
4640
            if (image_reader -> gx_image_reader_putdata_mask != 0x80)
408
            {
409
4576
                image_reader -> gx_image_reader_putdata++;
410
4576
                image_reader -> gx_image_reader_putdata_mask = 0x80;
411
            }
412
4640
            break;
413
        }
414
    }
415
416
762
    if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_DITHER)
417
    {
418
156
        _gx_system_memory_free((VOID *)param);
419
    }
420
421
762
    return GX_SUCCESS;
422
}
423
#endif
424