• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

saitoha / libsixel / 29651119742

18 Jul 2026 02:41PM UTC coverage: 85.03% (-0.3%) from 85.292%
29651119742

push

github

saitoha
fix: clip size fill for transparent offset bands

79318 of 144774 branches covered (54.79%)

4 of 6 new or added lines in 1 file covered. (66.67%)

3156 existing lines in 22 files now uncovered.

141353 of 166238 relevant lines covered (85.03%)

6269019.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.37
/tests/processing/decoder/0008_decoder_pixels_output_formats.c
1
/*
2
 * SPDX-License-Identifier: MIT
3
 *
4
 * Verify that sixel_decode_pixels() returns the requested packed byte order
5
 * and marks fully opaque output so callers can use RGBX/XRGB fast paths.
6
 */
7

8
#if defined(HAVE_CONFIG_H)
9
#include "config.h"
10
#endif
11

12
#include <stdio.h>
13
#include <stdlib.h>
14
#include <string.h>
15

16
#include <sixel.h>
17

18
typedef struct decoder_pixels_format_case {
19
    int pixelformat;
20
    char const *name;
21
    unsigned char expected[4];
22
} decoder_pixels_format_case_t;
23

24
static unsigned char const g_output_formats_payload[] =
25
    "\033Pq\"1;1;2;1#1;2;100;0;0#1@@\033\\";
26

27
static unsigned char const g_output_formats_alpha_payload[] =
28
    "\033Pq\"1;1;2;1#1;2;100;0;0#1@\033\\";
29

30
static unsigned char const g_output_formats_transparent_neighbor_payload[] =
31
    "\033Pq\"1;1;2;1#0;2;80;0;0#1;2;100;0;0#1?@\033\\";
32

33
static decoder_pixels_format_case_t const g_output_format_cases[] = {
34
    { SIXEL_PIXELFORMAT_XRGB8888, "XRGB8888", { 0xffU, 0xffU, 0x00U, 0x00U } },
35
    { SIXEL_PIXELFORMAT_RGBX8888, "RGBX8888", { 0xffU, 0x00U, 0x00U, 0xffU } },
36
    { SIXEL_PIXELFORMAT_XBGR8888, "XBGR8888", { 0xffU, 0x00U, 0x00U, 0xffU } },
37
    { SIXEL_PIXELFORMAT_BGRX8888, "BGRX8888", { 0x00U, 0x00U, 0xffU, 0xffU } }
38
};
39

40
static char const *const g_output_format_dequantize_cases[] = {
41
    "k_undither",
42
    "lso_undither:Vlight",
43
    "lso_undither:Vfs",
44
    "selective_blur:threshold=24",
45
    "s:T24"
46
};
47

48
static int
49
decoder_pixels_check_dequantize(char const *dequantize,
80✔
50
                                sixel_allocator_t *allocator)
51
{
52
    SIXELSTATUS status;
35✔
53
    sixel_decoder_t *decoder;
35✔
54
    sixel_decode_options_t options;
35✔
55
    sixel_decode_result_t result;
35✔
56
    int ok;
35✔
57

58
    decoder = NULL;
80✔
59
    ok = 0;
80✔
60
    memset(&options, 0, sizeof(options));
80✔
61
    memset(&result, 0, sizeof(result));
80✔
62

63
    status = sixel_decoder_new(&decoder, allocator);
80✔
64
    if (SIXEL_FAILED(status)) {
80!
UNCOV
65
        goto end;
×
66
    }
67
    status = sixel_decoder_setopt(decoder,
85✔
68
                                  SIXEL_OPTFLAG_DEQUANTIZE,
69
                                  dequantize);
5✔
70
    if (SIXEL_FAILED(status)) {
80!
UNCOV
71
        fprintf(stderr, "%s setopt failed: %04x\n", dequantize, status);
×
UNCOV
72
        goto end;
×
73
    }
74

75
    options.preferred_pixelformat = SIXEL_PIXELFORMAT_BGRX8888;
80✔
76
    status = sixel_decoder_decode_pixels(
80✔
77
        decoder,
5✔
78
        g_output_formats_payload,
79
        sizeof(g_output_formats_payload) - 1U,
80
        &options,
81
        &result);
82
    if (SIXEL_FAILED(status)) {
80!
UNCOV
83
        fprintf(stderr, "%s decode_pixels failed: %04x\n",
×
84
                dequantize,
85
                status);
UNCOV
86
        goto end;
×
87
    }
88
    if (result.width != 2 || result.height != 1 || result.stride != 8) {
80!
UNCOV
89
        fprintf(stderr, "%s dimensions are %dx%d stride %d\n",
×
90
                dequantize,
91
                result.width,
92
                result.height,
93
                result.stride);
UNCOV
94
        goto end;
×
95
    }
96
    if (result.pixelformat != SIXEL_PIXELFORMAT_BGRX8888) {
80!
UNCOV
97
        fprintf(stderr, "%s returned pixelformat %d\n",
×
98
                dequantize,
99
                result.pixelformat);
UNCOV
100
        goto end;
×
101
    }
102
    if (result.pixels == NULL ||
80!
103
            result.pixels[0] != 0x00U ||
80!
104
            result.pixels[1] != 0x00U ||
80!
105
            result.pixels[2] != 0xffU ||
80!
106
            result.pixels[3] != 0xffU) {
80!
UNCOV
107
        fprintf(stderr, "%s first pixel is not BGRX red\n", dequantize);
×
UNCOV
108
        goto end;
×
109
    }
110
    if ((result.flags & SIXEL_DECODE_PIXELS_RESULT_ALPHA_OPAQUE) == 0U) {
80!
UNCOV
111
        fprintf(stderr, "%s did not report opaque alpha\n", dequantize);
×
UNCOV
112
        goto end;
×
113
    }
114

115
    ok = 1;
45✔
116

117
end:
75✔
118
    if (allocator != NULL && result.pixels != NULL) {
80!
119
        sixel_allocator_free(allocator, result.pixels);
80✔
120
    }
5✔
121
    if (decoder != NULL) {
80!
122
        sixel_decoder_unref(decoder);
80✔
123
    }
5✔
124
    return ok;
80✔
125
}
126

127
static int
128
decoder_pixels_check_dequantize_alpha(char const *dequantize,
80✔
129
                                      sixel_allocator_t *allocator)
130
{
131
    SIXELSTATUS status;
35✔
132
    sixel_decoder_t *decoder;
35✔
133
    sixel_decode_options_t options;
35✔
134
    sixel_decode_result_t result;
35✔
135
    int ok;
35✔
136

137
    decoder = NULL;
80✔
138
    ok = 0;
80✔
139
    memset(&options, 0, sizeof(options));
80✔
140
    memset(&result, 0, sizeof(result));
80✔
141

142
    status = sixel_decoder_new(&decoder, allocator);
80✔
143
    if (SIXEL_FAILED(status)) {
80!
UNCOV
144
        goto end;
×
145
    }
146
    status = sixel_decoder_setopt(decoder,
85✔
147
                                  SIXEL_OPTFLAG_DEQUANTIZE,
148
                                  dequantize);
5✔
149
    if (SIXEL_FAILED(status)) {
80!
UNCOV
150
        fprintf(stderr, "%s alpha setopt failed: %04x\n",
×
151
                dequantize,
152
                status);
UNCOV
153
        goto end;
×
154
    }
155

156
    options.preferred_pixelformat = SIXEL_PIXELFORMAT_RGBA8888;
80✔
157
    status = sixel_decoder_decode_pixels(
80✔
158
        decoder,
5✔
159
        g_output_formats_alpha_payload,
160
        sizeof(g_output_formats_alpha_payload) - 1U,
161
        &options,
162
        &result);
163
    if (SIXEL_FAILED(status)) {
80!
UNCOV
164
        fprintf(stderr, "%s alpha decode_pixels failed: %04x\n",
×
165
                dequantize,
166
                status);
UNCOV
167
        goto end;
×
168
    }
169
    if (result.width != 2 || result.height != 1 || result.stride != 8) {
80!
UNCOV
170
        fprintf(stderr, "%s alpha dimensions are %dx%d stride %d\n",
×
171
                dequantize,
172
                result.width,
173
                result.height,
174
                result.stride);
UNCOV
175
        goto end;
×
176
    }
177
    if ((result.flags & SIXEL_DECODE_PIXELS_RESULT_ALPHA_OPAQUE) != 0U) {
80!
UNCOV
178
        fprintf(stderr,
×
179
                "%s alpha decode incorrectly reported opaque"
180
                " flags=%08x a0=%u a1=%u\n",
181
                dequantize,
182
                result.flags,
183
                result.pixels == NULL ? 0U : (unsigned int)result.pixels[3],
×
UNCOV
184
                result.pixels == NULL ? 0U : (unsigned int)result.pixels[7]);
×
UNCOV
185
        goto end;
×
186
    }
187
    if (result.pixels == NULL ||
80!
188
            result.pixels[3] != 0xffU ||
80!
189
            result.pixels[7] != 0x00U) {
80!
190
        fprintf(stderr, "%s alpha decode did not preserve alpha mask\n",
×
191
                dequantize);
UNCOV
192
        goto end;
×
193
    }
194

195
    ok = 1;
45✔
196

197
end:
75✔
198
    if (allocator != NULL && result.pixels != NULL) {
80!
199
        sixel_allocator_free(allocator, result.pixels);
80✔
200
    }
5✔
201
    if (decoder != NULL) {
80!
202
        sixel_decoder_unref(decoder);
80✔
203
    }
5✔
204
    return ok;
80✔
205
}
206

207
static int
208
decoder_pixels_check_dequantize_transparent_neighbor(
80✔
209
    char const *dequantize,
210
    sixel_allocator_t *allocator)
211
{
212
    SIXELSTATUS status;
35✔
213
    sixel_decoder_t *decoder;
35✔
214
    sixel_decode_options_t options;
35✔
215
    sixel_decode_result_t result;
35✔
216
    int ok;
35✔
217

218
    decoder = NULL;
80✔
219
    ok = 0;
80✔
220
    memset(&options, 0, sizeof(options));
80✔
221
    memset(&result, 0, sizeof(result));
80✔
222

223
    status = sixel_decoder_new(&decoder, allocator);
80✔
224
    if (SIXEL_FAILED(status)) {
80!
UNCOV
225
        goto end;
×
226
    }
227
    status = sixel_decoder_setopt(decoder,
85✔
228
                                  SIXEL_OPTFLAG_DEQUANTIZE,
229
                                  dequantize);
5✔
230
    if (SIXEL_FAILED(status)) {
80!
UNCOV
231
        fprintf(stderr, "%s neighbor setopt failed: %04x\n",
×
232
                dequantize,
233
                status);
UNCOV
234
        goto end;
×
235
    }
236

237
    options.preferred_pixelformat = SIXEL_PIXELFORMAT_RGBA8888;
80✔
238
    status = sixel_decoder_decode_pixels(
80✔
239
        decoder,
5✔
240
        g_output_formats_transparent_neighbor_payload,
241
        sizeof(g_output_formats_transparent_neighbor_payload) - 1U,
242
        &options,
243
        &result);
244
    if (SIXEL_FAILED(status)) {
80!
UNCOV
245
        fprintf(stderr, "%s neighbor decode_pixels failed: %04x\n",
×
246
                dequantize,
247
                status);
UNCOV
248
        goto end;
×
249
    }
250
    if (result.width != 2 || result.height != 1 || result.stride != 8) {
80!
UNCOV
251
        fprintf(stderr, "%s neighbor dimensions are %dx%d stride %d\n",
×
252
                dequantize,
253
                result.width,
254
                result.height,
255
                result.stride);
UNCOV
256
        goto end;
×
257
    }
258
    if (result.pixels == NULL ||
80!
259
            result.pixels[0] != 0x00U ||
80!
260
            result.pixels[1] != 0x00U ||
80!
261
            result.pixels[2] != 0x00U ||
80!
262
            result.pixels[3] != 0x00U ||
80!
263
            result.pixels[4] != 0xffU ||
80!
264
            result.pixels[5] != 0x00U ||
80!
265
            result.pixels[6] != 0x00U ||
80!
266
            result.pixels[7] != 0xffU) {
80!
UNCOV
267
        fprintf(stderr,
×
268
                "%s transparent neighbor influenced dequantize"
269
                " rgba=%u,%u,%u,%u %u,%u,%u,%u\n",
270
                dequantize,
271
                result.pixels == NULL ? 0U :
×
272
                    (unsigned int)result.pixels[0],
×
273
                result.pixels == NULL ? 0U :
×
274
                    (unsigned int)result.pixels[1],
×
275
                result.pixels == NULL ? 0U :
×
276
                    (unsigned int)result.pixels[2],
×
277
                result.pixels == NULL ? 0U :
×
278
                    (unsigned int)result.pixels[3],
×
279
                result.pixels == NULL ? 0U :
×
280
                    (unsigned int)result.pixels[4],
×
281
                result.pixels == NULL ? 0U :
×
282
                    (unsigned int)result.pixels[5],
×
283
                result.pixels == NULL ? 0U :
×
284
                    (unsigned int)result.pixels[6],
×
285
                result.pixels == NULL ? 0U :
×
UNCOV
286
                    (unsigned int)result.pixels[7]);
×
UNCOV
287
        goto end;
×
288
    }
289

290
    ok = 1;
45✔
291

292
end:
75✔
293
    if (allocator != NULL && result.pixels != NULL) {
80!
294
        sixel_allocator_free(allocator, result.pixels);
80✔
295
    }
5✔
296
    if (decoder != NULL) {
80!
297
        sixel_decoder_unref(decoder);
80✔
298
    }
5✔
299
    return ok;
80✔
300
}
301

302
int
303
test_decoder_0008_decoder_pixels_output_formats(int argc, char **argv)
16✔
304
{
305
    SIXELSTATUS status;
7✔
306
    sixel_allocator_t *allocator;
7✔
307
    sixel_decode_options_t options;
7✔
308
    sixel_decode_result_t result;
7✔
309
    size_t i;
7✔
310
    size_t cases;
7✔
311
    size_t dequantize_cases;
7✔
312
    int ok;
7✔
313

314
    (void)argc;
8✔
315
    (void)argv;
8✔
316

317
    allocator = NULL;
16✔
318
    i = 0U;
16✔
319
    cases = sizeof(g_output_format_cases) / sizeof(g_output_format_cases[0]);
16✔
320
    dequantize_cases = sizeof(g_output_format_dequantize_cases) /
16✔
321
        sizeof(g_output_format_dequantize_cases[0]);
322
    ok = 0;
16✔
323
    memset(&options, 0, sizeof(options));
16✔
324
    memset(&result, 0, sizeof(result));
16✔
325

326
    status = sixel_allocator_new(&allocator, NULL, NULL, NULL, NULL);
16✔
327
    if (SIXEL_FAILED(status)) {
16!
UNCOV
328
        goto end;
×
329
    }
330

331
    for (i = 0U; i < cases; ++i) {
80✔
332
        options.flags = 0U;
64✔
333
        options.preferred_pixelformat = g_output_format_cases[i].pixelformat;
64✔
334
        options.bgcolor[0] = 0U;
64✔
335
        options.bgcolor[1] = 0U;
64✔
336
        options.bgcolor[2] = 0U;
64✔
337
        memset(&result, 0, sizeof(result));
64✔
338

339
        status = sixel_decode_pixels(
64✔
340
            g_output_formats_payload,
341
            sizeof(g_output_formats_payload) - 1U,
342
            &options,
343
            &result,
344
            allocator);
4✔
345
        if (SIXEL_FAILED(status)) {
64!
UNCOV
346
            fprintf(stderr, "%s decode failed: %04x\n",
×
347
                    g_output_format_cases[i].name,
×
348
                    status);
UNCOV
349
            goto end;
×
350
        }
351
        if (result.width != 2 || result.height != 1 || result.stride != 8) {
64!
UNCOV
352
            fprintf(stderr, "%s dimensions are %dx%d stride %d\n",
×
UNCOV
353
                    g_output_format_cases[i].name,
×
354
                    result.width,
355
                    result.height,
356
                    result.stride);
UNCOV
357
            goto end;
×
358
        }
359
        if (result.pixelformat != g_output_format_cases[i].pixelformat) {
64!
UNCOV
360
            fprintf(stderr, "%s returned pixelformat %d\n",
×
361
                    g_output_format_cases[i].name,
×
362
                    result.pixelformat);
UNCOV
363
            goto end;
×
364
        }
365
        if (result.pixels == NULL ||
64!
366
                memcmp(result.pixels,
68✔
367
                       g_output_format_cases[i].expected,
64!
368
                       4U) != 0) {
4✔
369
            fprintf(stderr, "%s first pixel is not in requested byte order\n",
×
UNCOV
370
                    g_output_format_cases[i].name);
×
UNCOV
371
            goto end;
×
372
        }
373
        if ((result.flags & SIXEL_DECODE_PIXELS_RESULT_ALPHA_OPAQUE) == 0U) {
64!
374
            fprintf(stderr, "%s did not report opaque alpha\n",
×
UNCOV
375
                    g_output_format_cases[i].name);
×
UNCOV
376
            goto end;
×
377
        }
378

379
        sixel_allocator_free(allocator, result.pixels);
64✔
380
        result.pixels = NULL;
64✔
381
    }
4✔
382
    for (i = 0U; i < dequantize_cases; ++i) {
96✔
383
        if (!decoder_pixels_check_dequantize(
80!
384
                g_output_format_dequantize_cases[i],
80✔
385
                allocator)) {
5✔
UNCOV
386
            goto end;
×
387
        }
388
        if (!decoder_pixels_check_dequantize_alpha(
80!
389
                g_output_format_dequantize_cases[i],
45✔
390
                allocator)) {
5✔
UNCOV
391
            goto end;
×
392
        }
393
        if (!decoder_pixels_check_dequantize_transparent_neighbor(
80!
394
                g_output_format_dequantize_cases[i],
45✔
395
                allocator)) {
5✔
UNCOV
396
            goto end;
×
397
        }
398
    }
5✔
399

400
    ok = 1;
9✔
401

402
end:
15✔
403
    if (allocator != NULL) {
16!
404
        if (result.pixels != NULL) {
16!
UNCOV
405
            sixel_allocator_free(allocator, result.pixels);
×
406
        }
407
        sixel_allocator_unref(allocator);
16✔
408
    }
1✔
409
    return ok ? EXIT_SUCCESS : EXIT_FAILURE;
16✔
410
}
411

412
/* emacs Local Variables:      */
413
/* emacs mode: c               */
414
/* emacs tab-width: 4          */
415
/* emacs indent-tabs-mode: nil */
416
/* emacs c-basic-offset: 4     */
417
/* emacs End:                  */
418
/* vim: set expandtab ts=4 sts=4 sw=4 : */
419
/* EOF */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc