GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_image_reader_colorspace_convert.c Lines: 111 111 100.0 %
Date: 2024-12-05 08:52:37 Branches: 45 45 100.0 %

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