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

saitoha / libsixel / 19491472869

19 Nov 2025 06:00AM UTC coverage: 39.633% (-2.0%) from 41.622%
19491472869

push

github

saitoha
feat: add new pixelformat SIXEL_PIXELFORMAT_LINEARRGBFLOAT32/SIXEL_PIXELFORMAT_OKLABFLOAT32

8886 of 32084 branches covered (27.7%)

77 of 868 new or added lines in 14 files covered. (8.87%)

197 existing lines in 20 files now uncovered.

11758 of 29667 relevant lines covered (39.63%)

669587.74 hits per line

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

3.1
/src/pixelformat.c
1
/*
2
 * Copyright (c) 2021-2025 libsixel developers. See `AUTHORS`.
3
 * Copyright (c) 2014-2019 Hayaki Saito
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6
 * this software and associated documentation files (the "Software"), to deal in
7
 * the Software without restriction, including without limitation the rights to
8
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
 * the Software, and to permit persons to whom the Software is furnished to do so,
10
 * subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included in all
13
 * copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
 */
22

23
#include "config.h"
24

25
/* STDC_HEADERS */
26
#include <stdio.h>
27
#include <stdlib.h>
28

29
#if HAVE_MATH_H
30
# include <math.h>
31
#endif  /* HAVE_MATH_H */
32

33
#if HAVE_MEMORY_H
34
# include <memory.h>
35
#endif  /* HAVE_MEMORY_H */
36

37
#include <sixel.h>
38

39
#include "pixelformat.h"
40

41
#define SIXEL_OKLAB_AB_FLOAT_MIN (-0.5f)
42
#define SIXEL_OKLAB_AB_FLOAT_MAX (0.5f)
43

44
/*
45
 * Normalize a float32 channel stored in the 0.0-1.0 range and convert
46
 * the value to an 8-bit sample. Out-of-range or NaN inputs are clamped
47
 * to sane defaults so downstream conversions always receive valid bytes.
48
 */
49
static unsigned char
50
sixel_pixelformat_float_to_byte(float value)
×
51
{
52
#if HAVE_MATH_H
53
    if (!isfinite(value)) {
×
54
        value = 0.0f;
×
55
    }
56
#endif  /* HAVE_MATH_H */
57

58
    if (value <= 0.0f) {
×
59
        return 0;
×
60
    }
61
    if (value >= 1.0f) {
×
62
        return 255;
×
63
    }
64

65
    return (unsigned char)(value * 255.0f + 0.5f);
×
66
}
67

68
static unsigned char
NEW
69
sixel_pixelformat_oklab_L_to_byte(float value)
×
70
{
71
#if HAVE_MATH_H
NEW
72
    if (!isfinite(value)) {
×
NEW
73
        value = 0.0f;
×
74
    }
75
#endif  /* HAVE_MATH_H */
76

NEW
77
    if (value <= 0.0f) {
×
NEW
78
        return 0;
×
79
    }
NEW
80
    if (value >= 1.0f) {
×
NEW
81
        return 255;
×
82
    }
83

NEW
84
    return (unsigned char)(value * 255.0f + 0.5f);
×
85
}
86

87
static unsigned char
NEW
88
sixel_pixelformat_oklab_ab_to_byte(float value)
×
89
{
90
    float encoded;
91

92
#if HAVE_MATH_H
NEW
93
    if (!isfinite(value)) {
×
NEW
94
        value = 0.0f;
×
95
    }
96
#endif  /* HAVE_MATH_H */
97

NEW
98
    encoded = value + 0.5f;
×
NEW
99
    if (encoded <= 0.0f) {
×
NEW
100
        return 0;
×
101
    }
NEW
102
    if (encoded >= 1.0f) {
×
NEW
103
        return 255;
×
104
    }
105

NEW
106
    return (unsigned char)(encoded * 255.0f + 0.5f);
×
107
}
108

109
static float
NEW
110
sixel_pixelformat_float_channel_min_internal(int pixelformat,
×
111
                                             int channel)
112
{
113
    (void)channel;
NEW
114
    if (pixelformat == SIXEL_PIXELFORMAT_OKLABFLOAT32) {
×
NEW
115
        if (channel == 0) {
×
NEW
116
            return 0.0f;
×
117
        }
NEW
118
        return SIXEL_OKLAB_AB_FLOAT_MIN;
×
119
    }
NEW
120
    return 0.0f;
×
121
}
122

123
static float
NEW
124
sixel_pixelformat_float_channel_max_internal(int pixelformat,
×
125
                                             int channel)
126
{
127
    (void)channel;
NEW
128
    if (pixelformat == SIXEL_PIXELFORMAT_OKLABFLOAT32) {
×
NEW
129
        if (channel == 0) {
×
NEW
130
            return 1.0f;
×
131
        }
NEW
132
        return SIXEL_OKLAB_AB_FLOAT_MAX;
×
133
    }
NEW
134
    return 1.0f;
×
135
}
136

137
float
NEW
138
sixel_pixelformat_float_channel_clamp(int pixelformat,
×
139
                                      int channel,
140
                                      float value)
141
{
142
    float minimum;
143
    float maximum;
144

145
#if HAVE_MATH_H
NEW
146
    if (!isfinite(value)) {
×
NEW
147
        value = 0.0f;
×
148
    }
149
#endif  /* HAVE_MATH_H */
150

NEW
151
    minimum = sixel_pixelformat_float_channel_min_internal(pixelformat,
×
152
                                                           channel);
NEW
153
    maximum = sixel_pixelformat_float_channel_max_internal(pixelformat,
×
154
                                                           channel);
NEW
155
    if (value < minimum) {
×
NEW
156
        return minimum;
×
157
    }
NEW
158
    if (value > maximum) {
×
NEW
159
        return maximum;
×
160
    }
161

NEW
162
    return value;
×
163
}
164

165
unsigned char
NEW
166
sixel_pixelformat_float_channel_to_byte(int pixelformat,
×
167
                                        int channel,
168
                                        float value)
169
{
170
    float clamped;
171

NEW
172
    clamped = sixel_pixelformat_float_channel_clamp(pixelformat,
×
173
                                                    channel,
174
                                                    value);
NEW
175
    if (pixelformat == SIXEL_PIXELFORMAT_OKLABFLOAT32) {
×
NEW
176
        if (channel == 0) {
×
NEW
177
            return sixel_pixelformat_oklab_L_to_byte(clamped);
×
178
        }
NEW
179
        return sixel_pixelformat_oklab_ab_to_byte(clamped);
×
180
    }
181

182
    (void)channel;
NEW
183
    return sixel_pixelformat_float_to_byte(clamped);
×
184
}
185

186
float
NEW
187
sixel_pixelformat_byte_to_float(int pixelformat,
×
188
                                int channel,
189
                                unsigned char value)
190
{
191
    float decoded;
192

NEW
193
    if (pixelformat == SIXEL_PIXELFORMAT_OKLABFLOAT32) {
×
NEW
194
        if (channel == 0) {
×
NEW
195
            return (float)value / 255.0f;
×
196
        }
NEW
197
        decoded = (float)value / 255.0f;
×
NEW
198
        return decoded - 0.5f;
×
199
    }
200

201
    (void)channel;
NEW
202
    return (float)value / 255.0f;
×
203
}
204

205
static void
206
get_rgb(unsigned char const *data,
×
207
        int const pixelformat,
208
        int depth,
209
        unsigned char *r,
210
        unsigned char *g,
211
        unsigned char *b)
212
{
213
    unsigned int pixels = 0;
×
214
#if SWAP_BYTES
215
    unsigned int low;
216
    unsigned int high;
217
#endif
218
    int count = 0;
×
219

NEW
220
    if (pixelformat == SIXEL_PIXELFORMAT_RGBFLOAT32
×
NEW
221
            || pixelformat == SIXEL_PIXELFORMAT_LINEARRGBFLOAT32) {
×
UNCOV
222
        float const *fpixels = (float const *)(void const *)data;
×
223

224
        *r = sixel_pixelformat_float_to_byte(fpixels[0]);
×
225
        *g = sixel_pixelformat_float_to_byte(fpixels[1]);
×
226
        *b = sixel_pixelformat_float_to_byte(fpixels[2]);
×
227
        return;
×
228
    }
NEW
229
    if (pixelformat == SIXEL_PIXELFORMAT_OKLABFLOAT32) {
×
NEW
230
        float const *fpixels = (float const *)(void const *)data;
×
231

NEW
232
        *r = sixel_pixelformat_oklab_L_to_byte(fpixels[0]);
×
NEW
233
        *g = sixel_pixelformat_oklab_ab_to_byte(fpixels[1]);
×
NEW
234
        *b = sixel_pixelformat_oklab_ab_to_byte(fpixels[2]);
×
NEW
235
        return;
×
236
    }
237

238
    while (count < depth) {
×
239
        pixels = *(data + count) | (pixels << 8);
×
240
        count++;
×
241
    }
242

243
    /* TODO: we should swap bytes (only necessary on LSByte first hardware?) */
244
#if SWAP_BYTES
245
    if (depth == 2) {
246
        low    = pixels & 0xff;
247
        high   = (pixels >> 8) & 0xff;
248
        pixels = (low << 8) | high;
249
    }
250
#endif
251

252
    switch (pixelformat) {
×
253
    case SIXEL_PIXELFORMAT_RGB555:
254
        *r = ((pixels >> 10) & 0x1f) << 3;
×
255
        *g = ((pixels >>  5) & 0x1f) << 3;
×
256
        *b = ((pixels >>  0) & 0x1f) << 3;
×
257
        break;
×
258
    case SIXEL_PIXELFORMAT_RGB565:
259
        *r = ((pixels >> 11) & 0x1f) << 3;
×
260
        *g = ((pixels >>  5) & 0x3f) << 2;
×
261
        *b = ((pixels >>  0) & 0x1f) << 3;
×
262
        break;
×
263
    case SIXEL_PIXELFORMAT_RGB888:
264
        *r = (pixels >> 16) & 0xff;
×
265
        *g = (pixels >>  8) & 0xff;
×
266
        *b = (pixels >>  0) & 0xff;
×
267
        break;
×
268
    case SIXEL_PIXELFORMAT_BGR555:
269
        *r = ((pixels >>  0) & 0x1f) << 3;
×
270
        *g = ((pixels >>  5) & 0x1f) << 3;
×
271
        *b = ((pixels >> 10) & 0x1f) << 3;
×
272
        break;
×
273
    case SIXEL_PIXELFORMAT_BGR565:
274
        *r = ((pixels >>  0) & 0x1f) << 3;
×
275
        *g = ((pixels >>  5) & 0x3f) << 2;
×
276
        *b = ((pixels >> 11) & 0x1f) << 3;
×
277
        break;
×
278
    case SIXEL_PIXELFORMAT_BGR888:
279
        *r = (pixels >>  0) & 0xff;
×
280
        *g = (pixels >>  8) & 0xff;
×
281
        *b = (pixels >> 16) & 0xff;
×
282
        break;
×
283
    case SIXEL_PIXELFORMAT_RGBA8888:
284
        *r = (pixels >> 24) & 0xff;
×
285
        *g = (pixels >> 16) & 0xff;
×
286
        *b = (pixels >>  8) & 0xff;
×
287
        break;
×
288
    case SIXEL_PIXELFORMAT_ARGB8888:
289
        *r = (pixels >> 16) & 0xff;
×
290
        *g = (pixels >>  8) & 0xff;
×
291
        *b = (pixels >>  0) & 0xff;
×
292
        break;
×
293
    case SIXEL_PIXELFORMAT_BGRA8888:
294
        *r = (pixels >>  8) & 0xff;
×
295
        *g = (pixels >> 16) & 0xff;
×
296
        *b = (pixels >> 24) & 0xff;
×
297
        break;
×
298
    case SIXEL_PIXELFORMAT_ABGR8888:
299
        *r = (pixels >>  0) & 0xff;
×
300
        *g = (pixels >>  8) & 0xff;
×
301
        *b = (pixels >> 16) & 0xff;
×
302
        break;
×
303
    case SIXEL_PIXELFORMAT_GA88:
304
        *r = *g = *b = (pixels >> 8) & 0xff;
×
305
        break;
×
306
    case SIXEL_PIXELFORMAT_G8:
307
    case SIXEL_PIXELFORMAT_AG88:
308
        *r = *g = *b = pixels & 0xff;
×
309
        break;
×
310
    default:
311
        *r = *g = *b = 0;
×
312
        break;
×
313
    }
314
}
315

316

317
SIXELAPI int
318
sixel_helper_compute_depth(int pixelformat)
2,006✔
319
{
320
    int depth = (-1);  /* unknown */
2,006✔
321

322
    switch (pixelformat) {
2,006!
323
    case SIXEL_PIXELFORMAT_ARGB8888:
324
    case SIXEL_PIXELFORMAT_RGBA8888:
325
    case SIXEL_PIXELFORMAT_ABGR8888:
326
    case SIXEL_PIXELFORMAT_BGRA8888:
327
        depth = 4;
×
328
        break;
×
329
    case SIXEL_PIXELFORMAT_RGB888:
880✔
330
    case SIXEL_PIXELFORMAT_BGR888:
331
        depth = 3;
1,324✔
332
        break;
1,324✔
333
    case SIXEL_PIXELFORMAT_RGB555:
334
    case SIXEL_PIXELFORMAT_RGB565:
335
    case SIXEL_PIXELFORMAT_BGR555:
336
    case SIXEL_PIXELFORMAT_BGR565:
337
    case SIXEL_PIXELFORMAT_AG88:
338
    case SIXEL_PIXELFORMAT_GA88:
339
        depth = 2;
×
340
        break;
×
341
    case SIXEL_PIXELFORMAT_G1:
152✔
342
    case SIXEL_PIXELFORMAT_G2:
343
    case SIXEL_PIXELFORMAT_G4:
344
    case SIXEL_PIXELFORMAT_G8:
345
    case SIXEL_PIXELFORMAT_PAL1:
346
    case SIXEL_PIXELFORMAT_PAL2:
347
    case SIXEL_PIXELFORMAT_PAL4:
348
    case SIXEL_PIXELFORMAT_PAL8:
349
        depth = 1;
228✔
350
        break;
228✔
351
    case SIXEL_PIXELFORMAT_RGBFLOAT32:
302✔
352
    case SIXEL_PIXELFORMAT_LINEARRGBFLOAT32:
353
    case SIXEL_PIXELFORMAT_OKLABFLOAT32:
354
        depth = (int)(sizeof(float) * 3);
454✔
355
        break;
454✔
356
    default:
357
        break;
×
358
    }
359

360
    return depth;
2,006✔
361
}
362

363

364
static void
365
expand_rgb(unsigned char *dst,
×
366
           unsigned char const *src,
367
           int width, int height,
368
           int pixelformat, int depth)
369
{
370
    int x;
371
    int y;
372
    int dst_offset;
373
    int src_offset;
374
    unsigned char r, g, b;
375

376
    for (y = 0; y < height; y++) {
×
377
        for (x = 0; x < width; x++) {
×
378
            src_offset = depth * (y * width + x);
×
379
            dst_offset = 3 * (y * width + x);
×
380
            get_rgb(src + src_offset, pixelformat, depth, &r, &g, &b);
×
381

382
            *(dst + dst_offset + 0) = r;
×
383
            *(dst + dst_offset + 1) = g;
×
384
            *(dst + dst_offset + 2) = b;
×
385
        }
386
    }
387
}
×
388

389

390
static SIXELSTATUS
391
expand_palette(unsigned char *dst, unsigned char const *src,
×
392
               int width, int height, int const pixelformat)
393
{
394
    SIXELSTATUS status = SIXEL_FALSE;
×
395
    int x;
396
    int y;
397
    int i;
398
    int bpp;  /* bit per plane */
399

400
    switch (pixelformat) {
×
401
    case SIXEL_PIXELFORMAT_PAL1:
402
    case SIXEL_PIXELFORMAT_G1:
403
        bpp = 1;
×
404
        break;
×
405
    case SIXEL_PIXELFORMAT_PAL2:
406
    case SIXEL_PIXELFORMAT_G2:
407
        bpp = 2;
×
408
        break;
×
409
    case SIXEL_PIXELFORMAT_PAL4:
410
    case SIXEL_PIXELFORMAT_G4:
411
        bpp = 4;
×
412
        break;
×
413
    case SIXEL_PIXELFORMAT_PAL8:
414
    case SIXEL_PIXELFORMAT_G8:
415
        for (i = 0; i < width * height; ++i, ++src) {
×
416
            *dst++ = *src;
×
417
        }
418
        status = SIXEL_OK;
×
419
        goto end;
×
420
    default:
421
        status = SIXEL_BAD_ARGUMENT;
×
422
        sixel_helper_set_additional_message(
×
423
            "expand_palette: invalid pixelformat.");
424
        goto end;
×
425
    }
426

427
#if HAVE_DEBUG
428
    fprintf(stderr, "expanding PAL%d to PAL8...\n", bpp);
×
429
#endif
430

431
    for (y = 0; y < height; ++y) {
×
432
        for (x = 0; x < width * bpp / 8; ++x) {
×
433
            for (i = 0; i < 8 / bpp; ++i) {
×
434
                *dst++ = *src >> (8 / bpp - 1 - i) * bpp & ((1 << bpp) - 1);
×
435
            }
436
            src++;
×
437
        }
438
        x = width - x * 8 / bpp;
×
439
        if (x > 0) {
×
440
            for (i = 0; i < x; ++i) {
×
441
                *dst++ = *src >> (8 - (i + 1) * bpp) & ((1 << bpp) - 1);
×
442
            }
443
            src++;
×
444
        }
445
    }
446

447
    status = SIXEL_OK;
×
448

449
end:
450
    return status;
×
451
}
452

453

454
SIXELAPI SIXELSTATUS
455
sixel_helper_normalize_pixelformat(
×
456
    unsigned char       /* out */ *dst,             /* destination buffer */
457
    int                 /* out */ *dst_pixelformat, /* converted pixelformat */
458
    unsigned char const /* in */  *src,             /* source pixels */
459
    int                 /* in */  src_pixelformat,  /* format of source image */
460
    int                 /* in */  width,            /* width of source image */
461
    int                 /* in */  height)           /* height of source image */
462
{
463
    SIXELSTATUS status = SIXEL_FALSE;
×
464
    int depth;
465

466
    switch (src_pixelformat) {
×
467
    case SIXEL_PIXELFORMAT_G8:
468
        expand_rgb(dst, src, width, height, src_pixelformat, 1);
×
469
        *dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
470
        break;
×
471
    case SIXEL_PIXELFORMAT_RGB565:
472
    case SIXEL_PIXELFORMAT_RGB555:
473
    case SIXEL_PIXELFORMAT_BGR565:
474
    case SIXEL_PIXELFORMAT_BGR555:
475
    case SIXEL_PIXELFORMAT_GA88:
476
    case SIXEL_PIXELFORMAT_AG88:
477
        expand_rgb(dst, src, width, height, src_pixelformat, 2);
×
478
        *dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
479
        break;
×
480
    case SIXEL_PIXELFORMAT_RGB888:
481
    case SIXEL_PIXELFORMAT_BGR888:
482
        expand_rgb(dst, src, width, height, src_pixelformat, 3);
×
483
        *dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
484
        break;
×
485
    case SIXEL_PIXELFORMAT_RGBFLOAT32:
486
    case SIXEL_PIXELFORMAT_LINEARRGBFLOAT32:
487
    case SIXEL_PIXELFORMAT_OKLABFLOAT32:
488
        depth = sixel_helper_compute_depth(src_pixelformat);
×
489
        if (depth <= 0) {
×
490
            status = SIXEL_BAD_ARGUMENT;
×
491
            goto end;
×
492
        }
493
        expand_rgb(dst, src, width, height, src_pixelformat, depth);
×
494
        *dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
495
        break;
×
496
    case SIXEL_PIXELFORMAT_RGBA8888:
497
    case SIXEL_PIXELFORMAT_ARGB8888:
498
    case SIXEL_PIXELFORMAT_BGRA8888:
499
    case SIXEL_PIXELFORMAT_ABGR8888:
500
        expand_rgb(dst, src, width, height, src_pixelformat, 4);
×
501
        *dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
502
        break;
×
503
    case SIXEL_PIXELFORMAT_PAL1:
504
    case SIXEL_PIXELFORMAT_PAL2:
505
    case SIXEL_PIXELFORMAT_PAL4:
506
        *dst_pixelformat = SIXEL_PIXELFORMAT_PAL8;
×
507
        status = expand_palette(dst, src, width, height, src_pixelformat);
×
508
        if (SIXEL_FAILED(status)) {
×
509
            goto end;
×
510
        }
511
        break;
×
512
    case SIXEL_PIXELFORMAT_G1:
513
    case SIXEL_PIXELFORMAT_G2:
514
    case SIXEL_PIXELFORMAT_G4:
515
        *dst_pixelformat = SIXEL_PIXELFORMAT_G8;
×
516
        status = expand_palette(dst, src, width, height, src_pixelformat);
×
517
        if (SIXEL_FAILED(status)) {
×
518
            goto end;
×
519
        }
520
        break;
×
521
    case SIXEL_PIXELFORMAT_PAL8:
522
        memcpy(dst, src, (size_t)(width * height));
×
523
        *dst_pixelformat = src_pixelformat;
×
524
        break;
×
525
    default:
526
        status = SIXEL_BAD_ARGUMENT;
×
527
        goto end;
×
528
    }
529

530
    status = SIXEL_OK;
×
531

532
end:
533
    return status;
×
534
}
535

536

537
#if HAVE_TESTS
538
static int
539
test1(void)
×
540
{
541
    unsigned char dst[3];
542
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
543
    int src_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
544
    unsigned char src[] = { 0x46, 0xf3, 0xe5 };
×
545
    int ret = 0;
×
546

547
    int nret = EXIT_FAILURE;
×
548

549
    ret = sixel_helper_normalize_pixelformat(dst,
×
550
                                             &dst_pixelformat,
551
                                             src,
552
                                             src_pixelformat,
553
                                             1,
554
                                             1);
555
    if (ret != 0) {
×
556
        goto error;
×
557
    }
558
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
559
        goto error;
×
560
    }
561
    if ((dst[0] << 16 | dst[1] << 8 | dst[2]) != (src[0] << 16 | src[1] << 8 | src[2])) {
×
562
        goto error;
×
563
    }
564
    return EXIT_SUCCESS;
×
565

566
error:
567
    perror("test1");
×
568
    return nret;
×
569
}
570

571

572
static int
573
test2(void)
×
574
{
575
    unsigned char dst[3];
576
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
577
    int src_pixelformat = SIXEL_PIXELFORMAT_RGB555;
×
578
    unsigned char src[] = { 0x47, 0x9c };
×
579
    int ret = 0;
×
580

581
    int nret = EXIT_FAILURE;
×
582

583
    ret = sixel_helper_normalize_pixelformat(dst,
×
584
                                             &dst_pixelformat,
585
                                             src,
586
                                             src_pixelformat,
587
                                             1,
588
                                             1);
589
    if (ret != 0) {
×
590
        goto error;
×
591
    }
592
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
593
        goto error;
×
594
    }
595
    if ((dst[0] >> 3 << 10 | dst[1] >> 3 << 5 | dst[2] >> 3) != (src[0] << 8 | src[1])) {
×
596
        goto error;
×
597
    }
598
    return EXIT_SUCCESS;
×
599

600
error:
601
    perror("test2");
×
602
    return nret;
×
603
}
604

605

606
static int
607
test3(void)
×
608
{
609
    unsigned char dst[3];
610
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
611
    int src_pixelformat = SIXEL_PIXELFORMAT_RGB565;
×
612
    unsigned char src[] = { 0x47, 0x9c };
×
613
    int ret = 0;
×
614

615
    int nret = EXIT_FAILURE;
×
616

617
    ret = sixel_helper_normalize_pixelformat(dst,
×
618
                                             &dst_pixelformat,
619
                                             src,
620
                                             src_pixelformat,
621
                                             1,
622
                                             1);
623
    if (ret != 0) {
×
624
        goto error;
×
625
    }
626
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
627
        goto error;
×
628
    }
629
    if ((dst[0] >> 3 << 11 | dst[1] >> 2 << 5 | dst[2] >> 3) != (src[0] << 8 | src[1])) {
×
630
        goto error;
×
631
    }
632
    return EXIT_SUCCESS;
×
633

634
error:
635
    perror("test3");
×
636
    return nret;
×
637
}
638

639

640
static int
641
test4(void)
×
642
{
643
    unsigned char dst[3];
644
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
645
    int src_pixelformat = SIXEL_PIXELFORMAT_BGR888;
×
646
    unsigned char src[] = { 0x46, 0xf3, 0xe5 };
×
647
    int ret = 0;
×
648

649
    int nret = EXIT_FAILURE;
×
650

651
    ret = sixel_helper_normalize_pixelformat(dst,
×
652
                                             &dst_pixelformat,
653
                                             src,
654
                                             src_pixelformat,
655
                                             1,
656
                                             1);
657
    if (ret != 0) {
×
658
        goto error;
×
659
    }
660
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
661
        goto error;
×
662
    }
663
    if ((dst[2] << 16 | dst[1] << 8 | dst[0]) != (src[0] << 16 | src[1] << 8 | src[2])) {
×
664
        goto error;
×
665
    }
666
    return EXIT_SUCCESS;
×
667

668
error:
669
    perror("test4");
×
670
    return nret;
×
671
}
672

673

674
static int
675
test5(void)
×
676
{
677
    unsigned char dst[3];
678
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
679
    int src_pixelformat = SIXEL_PIXELFORMAT_BGR555;
×
680
    unsigned char src[] = { 0x23, 0xc8 };
×
681
    int ret = 0;
×
682

683
    int nret = EXIT_FAILURE;
×
684

685
    ret = sixel_helper_normalize_pixelformat(dst,
×
686
                                             &dst_pixelformat,
687
                                             src,
688
                                             src_pixelformat,
689
                                             1,
690
                                             1);
691
    if (ret != 0) {
×
692
        goto error;
×
693
    }
694
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
695
        goto error;
×
696
    }
697
    if ((dst[2] >> 3 << 10 | dst[1] >> 3 << 5 | dst[0] >> 3) != (src[0] << 8 | src[1])) {
×
698
        goto error;
×
699
    }
700
    return EXIT_SUCCESS;
×
701

702
error:
703
    perror("test5");
×
704
    return nret;
×
705
}
706

707

708
static int
709
test6(void)
×
710
{
711
    unsigned char dst[3];
712
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
713
    int src_pixelformat = SIXEL_PIXELFORMAT_BGR565;
×
714
    unsigned char src[] = { 0x47, 0x88 };
×
715
    int ret = 0;
×
716

717
    int nret = EXIT_FAILURE;
×
718

719
    ret = sixel_helper_normalize_pixelformat(dst,
×
720
                                             &dst_pixelformat,
721
                                             src,
722
                                             src_pixelformat,
723
                                             1,
724
                                             1);
725
    if (ret != 0) {
×
726
        goto error;
×
727
    }
728
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
729
        goto error;
×
730
    }
731
    if ((dst[2] >> 3 << 11 | dst[1] >> 2 << 5 | dst[0] >> 3) != (src[0] << 8 | src[1])) {
×
732
        goto error;
×
733
    }
734
    return EXIT_SUCCESS;
×
735

736
error:
737
    perror("test6");
×
738
    return nret;
×
739
}
740

741

742
static int
743
test7(void)
×
744
{
745
    unsigned char dst[3];
746
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
747
    int src_pixelformat = SIXEL_PIXELFORMAT_AG88;
×
748
    unsigned char src[] = { 0x47, 0x88 };
×
749
    int ret = 0;
×
750

751
    int nret = EXIT_FAILURE;
×
752

753
    ret = sixel_helper_normalize_pixelformat(dst,
×
754
                                             &dst_pixelformat,
755
                                             src,
756
                                             src_pixelformat,
757
                                             1,
758
                                             1);
759
    if (ret != 0) {
×
760
        goto error;
×
761
    }
762
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
763
        goto error;
×
764
    }
765
    if (dst[0] != src[1]) {
×
766
        goto error;
×
767
    }
768
    return EXIT_SUCCESS;
×
769

770
error:
771
    perror("test7");
×
772
    return nret;
×
773
}
774

775

776
static int
777
test8(void)
×
778
{
779
    unsigned char dst[3];
780
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
781
    int src_pixelformat = SIXEL_PIXELFORMAT_GA88;
×
782
    unsigned char src[] = { 0x47, 0x88 };
×
783
    int ret = 0;
×
784

785
    int nret = EXIT_FAILURE;
×
786

787
    ret = sixel_helper_normalize_pixelformat(dst,
×
788
                                             &dst_pixelformat,
789
                                             src,
790
                                             src_pixelformat,
791
                                             1,
792
                                             1);
793
    if (ret != 0) {
×
794
        goto error;
×
795
    }
796
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
797
        goto error;
×
798
    }
799
    if (dst[0] != src[0]) {
×
800
        goto error;
×
801
    }
802
    return EXIT_SUCCESS;
×
803

804
error:
805
    perror("test8");
×
806
    return nret;
×
807
}
808

809

810
static int
811
test9(void)
×
812
{
813
    unsigned char dst[3];
814
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
815
    int src_pixelformat = SIXEL_PIXELFORMAT_RGBA8888;
×
816
    unsigned char src[] = { 0x46, 0xf3, 0xe5, 0xf0 };
×
817
    int ret = 0;
×
818

819
    int nret = EXIT_FAILURE;
×
820

821
    ret = sixel_helper_normalize_pixelformat(dst,
×
822
                                             &dst_pixelformat,
823
                                             src,
824
                                             src_pixelformat,
825
                                             1,
826
                                             1);
827
    if (ret != 0) {
×
828
        goto error;
×
829
    }
830
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
831
        goto error;
×
832
    }
833
    if (dst[0] != src[0]) {
×
834
        goto error;
×
835
    }
836
    if (dst[1] != src[1]) {
×
837
        goto error;
×
838
    }
839
    if (dst[2] != src[2]) {
×
840
        goto error;
×
841
    }
842
    return EXIT_SUCCESS;
×
843

844
error:
845
    perror("test8");
×
846
    return nret;
×
847
}
848

849

850
static int
851
test10(void)
×
852
{
853
    unsigned char dst[3];
854
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
855
    int src_pixelformat = SIXEL_PIXELFORMAT_ARGB8888;
×
856
    unsigned char src[] = { 0x46, 0xf3, 0xe5, 0xf0 };
×
857
    int ret = 0;
×
858

859
    int nret = EXIT_FAILURE;
×
860

861
    ret = sixel_helper_normalize_pixelformat(dst,
×
862
                                             &dst_pixelformat,
863
                                             src,
864
                                             src_pixelformat,
865
                                             1,
866
                                             1);
867
    if (ret != 0) {
×
868
        goto error;
×
869
    }
870
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
871
        goto error;
×
872
    }
873
    if (dst[0] != src[1]) {
×
874
        goto error;
×
875
    }
876
    if (dst[1] != src[2]) {
×
877
        goto error;
×
878
    }
879
    if (dst[2] != src[3]) {
×
880
        goto error;
×
881
    }
882
    return EXIT_SUCCESS;
×
883

884
error:
885
    perror("test8");
×
886
    return nret;
×
887
}
888

889

890
static int
891
test11(void)
×
892
{
893
    unsigned char dst[3];
894
    int dst_pixelformat = SIXEL_PIXELFORMAT_RGB888;
×
895
    int src_pixelformat = SIXEL_PIXELFORMAT_RGBFLOAT32;
×
896
    float srcf[] = { 0.0f, 0.5f, 1.0f };
×
897
    unsigned char const *src = (unsigned char const *)srcf;
×
898
    int ret = 0;
×
899
    int depth;
900

901
    int nret = EXIT_FAILURE;
×
902

903
    ret = sixel_helper_normalize_pixelformat(dst,
×
904
                                             &dst_pixelformat,
905
                                             src,
906
                                             src_pixelformat,
907
                                             1,
908
                                             1);
909
    if (ret != 0) {
×
910
        goto error;
×
911
    }
912
    if (dst_pixelformat != SIXEL_PIXELFORMAT_RGB888) {
×
913
        goto error;
×
914
    }
915
    if (dst[0] != 0 || dst[1] != 128 || dst[2] != 255) {
×
916
        goto error;
×
917
    }
918
    depth = sixel_helper_compute_depth(src_pixelformat);
×
919
    if (depth != (int)(sizeof(float) * 3)) {
×
920
        goto error;
×
921
    }
922
    return EXIT_SUCCESS;
×
923

924
error:
925
    perror("test11");
×
926
    return nret;
×
927
}
928

929

930
SIXELAPI int
931
sixel_pixelformat_tests_main(void)
×
932
{
933
    int nret = EXIT_FAILURE;
×
934
    size_t i;
935
    typedef int (* testcase)(void);
936

937
    static testcase const testcases[] = {
938
        test1,
939
        test2,
940
        test3,
941
        test4,
942
        test5,
943
        test6,
944
        test7,
945
        test8,
946
        test9,
947
        test10,
948
        test11,
949
    };
950

951
    for (i = 0; i < sizeof(testcases) / sizeof(testcase); ++i) {
×
952
        nret = testcases[i]();
×
953
        if (nret != EXIT_SUCCESS) {
×
954
            goto error;
×
955
        }
956
    }
957

958
    nret = EXIT_SUCCESS;
×
959

960
error:
961
    return nret;
×
962
}
963
#endif  /* HAVE_TESTS */
964

965
/* emacs Local Variables:      */
966
/* emacs mode: c               */
967
/* emacs tab-width: 4          */
968
/* emacs indent-tabs-mode: nil */
969
/* emacs c-basic-offset: 4     */
970
/* emacs End:                  */
971
/* vim: set expandtab ts=4 sts=4 sw=4 : */
972
/* 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