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

saitoha / libsixel / 19776286632

29 Nov 2025 12:20AM UTC coverage: 41.017% (-0.3%) from 41.338%
19776286632

push

github

saitoha
build: remove unused status in reversible snap test

9964 of 36344 branches covered (27.42%)

13002 of 31699 relevant lines covered (41.02%)

1178071.22 hits per line

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

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

25
/*
26
 * Adaptive (variable coefficient) diffusion backend operating on RGB888
27
 * buffers.  The implementation mirrors the historical `sixel_dither_apply_
28
 * variable` helper but now consumes the shared dithering context so both the
29
 * 8bit and RGBFLOAT32 workers expose identical signatures.
30
 */
31

32
#include "config.h"
33

34
#include <stdlib.h>
35
#include <string.h>
36
#include <stdint.h>
37
#include <limits.h>
38

39
#include "dither-varcoeff-8bit.h"
40
#include "dither-common-pipeline.h"
41
#include "lookup-common.h"
42

43
static void
44
sixel_dither_scanline_params(int serpentine,
×
45
                             int index,
46
                             int limit,
47
                             int *start,
48
                             int *end,
49
                             int *step,
50
                             int *direction)
51
{
52
    if (serpentine && (index & 1)) {
×
53
        *start = limit - 1;
×
54
        *end = -1;
×
55
        *step = -1;
×
56
        *direction = -1;
×
57
    } else {
58
        *start = 0;
×
59
        *end = limit;
×
60
        *step = 1;
×
61
        *direction = 1;
×
62
    }
63
}
×
64

65
static const int (*
66
lso2_table(void))[7]
×
67
{
68
#include "lso2.h"
69
    return var_coefs;
×
70
}
71

72
#define VARERR_SCALE_SHIFT 12
73
#define VARERR_SCALE       (1 << VARERR_SCALE_SHIFT)
74
#define VARERR_ROUND       (1 << (VARERR_SCALE_SHIFT - 1))
75
#define VARERR_MAX_VALUE   (255 * VARERR_SCALE)
76

77
typedef void (*diffuse_varerr_mode)(unsigned char *data,
78
                                    int width,
79
                                    int height,
80
                                    int x,
81
                                    int y,
82
                                    int depth,
83
                                    int32_t error,
84
                                    int index,
85
                                    int direction);
86

87
typedef void (*diffuse_varerr_carry_mode)(int32_t *carry_curr,
88
                                          int32_t *carry_next,
89
                                          int32_t *carry_far,
90
                                          int width,
91
                                          int height,
92
                                          int depth,
93
                                          int x,
94
                                          int y,
95
                                          int32_t error,
96
                                          int index,
97
                                          int direction,
98
                                          int channel);
99

100
static int32_t
101
sixel_varcoeff_safe_denom(int value)
×
102
{
103
    if (value == 0) {
×
104
        /*
105
         * The first row of `lso2.h` ships a zero denominator.  Older builds
106
         * happened to avoid the division but the refactor now makes the edge
107
         * visible, so guard it explicitly.
108
         */
109
        return 1;
×
110
    }
111
    return value;
×
112
}
113

114
static int32_t
115
diffuse_varerr_term(int32_t error, int weight, int denom)
×
116
{
117
    int64_t delta;
118

119
    delta = (int64_t)error * (int64_t)weight;
×
120
    if (delta >= 0) {
×
121
        delta = (delta + denom / 2) / denom;
×
122
    } else {
123
        delta = (delta - denom / 2) / denom;
×
124
    }
125

126
    return (int32_t)delta;
×
127
}
128

129
static void
130
diffuse_varerr_apply_direct(unsigned char *target,
×
131
                            int depth,
132
                            size_t offset,
133
                            int32_t delta)
134
{
135
    int64_t value;
136
    int result;
137

138
    value = (int64_t)target[offset * depth] << VARERR_SCALE_SHIFT;
×
139
    value += delta;
×
140
    if (value < 0) {
×
141
        value = 0;
×
142
    } else {
143
        int64_t max_value;
144

145
        max_value = VARERR_MAX_VALUE;
×
146
        if (value > max_value) {
×
147
            value = max_value;
×
148
        }
149
    }
150

151
    result = (int)((value + VARERR_ROUND) >> VARERR_SCALE_SHIFT);
×
152
    if (result < 0) {
×
153
        result = 0;
×
154
    }
155
    if (result > 255) {
×
156
        result = 255;
×
157
    }
158
    target[offset * depth] = (unsigned char)result;
×
159
}
×
160

161
static void
162
diffuse_lso2(unsigned char *data,
×
163
             int width,
164
             int height,
165
             int x,
166
             int y,
167
             int depth,
168
             int32_t error,
169
             int index,
170
             int direction)
171
{
172
    const int (*table)[7];
173
    const int *entry;
174
    int denom;
175
    int32_t term_r;
176
    int32_t term_r2;
177
    int32_t term_dl;
178
    int32_t term_d;
179
    int32_t term_dr;
180
    int32_t term_d2;
181
    size_t offset;
182

183
    if (error == 0) {
×
184
        return;
×
185
    }
186
    if (index < 0) {
×
187
        index = 0;
×
188
    }
189
    if (index > 255) {
×
190
        index = 255;
×
191
    }
192

193
    table = lso2_table();
×
194
    entry = table[index];
×
195
    denom = sixel_varcoeff_safe_denom(entry[6]);
×
196

197
    term_r = diffuse_varerr_term(error, entry[0], denom);
×
198
    term_r2 = diffuse_varerr_term(error, entry[1], denom);
×
199
    term_dl = diffuse_varerr_term(error, entry[2], denom);
×
200
    term_d = diffuse_varerr_term(error, entry[3], denom);
×
201
    term_dr = diffuse_varerr_term(error, entry[4], denom);
×
202
    term_d2 = diffuse_varerr_term(error, entry[5], denom);
×
203

204
    if (direction >= 0) {
×
205
        if (x + 1 < width) {
×
206
            offset = (size_t)y * (size_t)width + (size_t)(x + 1);
×
207
            diffuse_varerr_apply_direct(data, depth, offset, term_r);
×
208
        }
209
        if (x + 2 < width) {
×
210
            offset = (size_t)y * (size_t)width + (size_t)(x + 2);
×
211
            diffuse_varerr_apply_direct(data, depth, offset, term_r2);
×
212
        }
213
        if (y + 1 < height && x - 1 >= 0) {
×
214
            offset = (size_t)(y + 1) * (size_t)width;
×
215
            offset += (size_t)(x - 1);
×
216
            diffuse_varerr_apply_direct(data, depth, offset, term_dl);
×
217
        }
218
        if (y + 1 < height) {
×
219
            offset = (size_t)(y + 1) * (size_t)width + (size_t)x;
×
220
            diffuse_varerr_apply_direct(data, depth, offset, term_d);
×
221
        }
222
        if (y + 1 < height && x + 1 < width) {
×
223
            offset = (size_t)(y + 1) * (size_t)width;
×
224
            offset += (size_t)(x + 1);
×
225
            diffuse_varerr_apply_direct(data, depth, offset, term_dr);
×
226
        }
227
        if (y + 2 < height) {
×
228
            offset = (size_t)(y + 2) * (size_t)width + (size_t)x;
×
229
            diffuse_varerr_apply_direct(data, depth, offset, term_d2);
×
230
        }
231
    } else {
232
        if (x - 1 >= 0) {
×
233
            offset = (size_t)y * (size_t)width + (size_t)(x - 1);
×
234
            diffuse_varerr_apply_direct(data, depth, offset, term_r);
×
235
        }
236
        if (x - 2 >= 0) {
×
237
            offset = (size_t)y * (size_t)width + (size_t)(x - 2);
×
238
            diffuse_varerr_apply_direct(data, depth, offset, term_r2);
×
239
        }
240
        if (y + 1 < height && x + 1 < width) {
×
241
            offset = (size_t)(y + 1) * (size_t)width;
×
242
            offset += (size_t)(x + 1);
×
243
            diffuse_varerr_apply_direct(data, depth, offset, term_dl);
×
244
        }
245
        if (y + 1 < height) {
×
246
            offset = (size_t)(y + 1) * (size_t)width + (size_t)x;
×
247
            diffuse_varerr_apply_direct(data, depth, offset, term_d);
×
248
        }
249
        if (y + 1 < height && x - 1 >= 0) {
×
250
            offset = (size_t)(y + 1) * (size_t)width;
×
251
            offset += (size_t)(x - 1);
×
252
            diffuse_varerr_apply_direct(data, depth, offset, term_dr);
×
253
        }
254
        if (y + 2 < height) {
×
255
            offset = (size_t)(y + 2) * (size_t)width + (size_t)x;
×
256
            diffuse_varerr_apply_direct(data, depth, offset, term_d2);
×
257
        }
258
    }
259
}
260

261
static void
262
diffuse_lso2_carry(int32_t *carry_curr,
×
263
                   int32_t *carry_next,
264
                   int32_t *carry_far,
265
                   int width,
266
                   int height,
267
                   int depth,
268
                   int x,
269
                   int y,
270
                   int32_t error,
271
                   int index,
272
                   int direction,
273
                   int channel)
274
{
275
    const int (*table)[7];
276
    const int *entry;
277
    int denom;
278
    int32_t term_r;
279
    int32_t term_r2;
280
    int32_t term_dl;
281
    int32_t term_d;
282
    int32_t term_dr;
283
    int32_t term_d2;
284
    size_t base;
285

286
    if (error == 0) {
×
287
        return;
×
288
    }
289
    if (index < 0) {
×
290
        index = 0;
×
291
    }
292
    if (index > 255) {
×
293
        index = 255;
×
294
    }
295

296
    table = lso2_table();
×
297
    entry = table[index];
×
298
    denom = sixel_varcoeff_safe_denom(entry[6]);
×
299

300
    term_r = diffuse_varerr_term(error, entry[0], denom);
×
301
    term_r2 = diffuse_varerr_term(error, entry[1], denom);
×
302
    term_dl = diffuse_varerr_term(error, entry[2], denom);
×
303
    term_d = diffuse_varerr_term(error, entry[3], denom);
×
304
    term_dr = diffuse_varerr_term(error, entry[4], denom);
×
305
    term_d2 = error - term_r - term_r2 - term_dl - term_d - term_dr;
×
306

307
    if (direction >= 0) {
×
308
        if (x + 1 < width) {
×
309
            base = ((size_t)(x + 1) * (size_t)depth)
×
310
                 + (size_t)channel;
×
311
            carry_curr[base] += term_r;
×
312
        }
313
        if (x + 2 < width) {
×
314
            base = ((size_t)(x + 2) * (size_t)depth)
×
315
                 + (size_t)channel;
×
316
            carry_curr[base] += term_r2;
×
317
        }
318
        if (y + 1 < height && x - 1 >= 0) {
×
319
            base = ((size_t)(x - 1) * (size_t)depth)
×
320
                 + (size_t)channel;
×
321
            carry_next[base] += term_dl;
×
322
        }
323
        if (y + 1 < height) {
×
324
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
325
            carry_next[base] += term_d;
×
326
        }
327
        if (y + 1 < height && x + 1 < width) {
×
328
            base = ((size_t)(x + 1) * (size_t)depth)
×
329
                 + (size_t)channel;
×
330
            carry_next[base] += term_dr;
×
331
        }
332
        if (y + 2 < height) {
×
333
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
334
            carry_far[base] += term_d2;
×
335
        }
336
    } else {
337
        if (x - 1 >= 0) {
×
338
            base = ((size_t)(x - 1) * (size_t)depth)
×
339
                 + (size_t)channel;
×
340
            carry_curr[base] += term_r;
×
341
        }
342
        if (x - 2 >= 0) {
×
343
            base = ((size_t)(x - 2) * (size_t)depth)
×
344
                 + (size_t)channel;
×
345
            carry_curr[base] += term_r2;
×
346
        }
347
        if (y + 1 < height && x + 1 < width) {
×
348
            base = ((size_t)(x + 1) * (size_t)depth)
×
349
                 + (size_t)channel;
×
350
            carry_next[base] += term_dl;
×
351
        }
352
        if (y + 1 < height) {
×
353
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
354
            carry_next[base] += term_d;
×
355
        }
356
        if (y + 1 < height && x - 1 >= 0) {
×
357
            base = ((size_t)(x - 1) * (size_t)depth)
×
358
                 + (size_t)channel;
×
359
            carry_next[base] += term_dr;
×
360
        }
361
        if (y + 2 < height) {
×
362
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
363
            carry_far[base] += term_d2;
×
364
        }
365
    }
366
}
367

368
SIXELSTATUS
369
sixel_dither_apply_varcoeff_8bit(sixel_dither_t *dither,
×
370
                                 sixel_dither_context_t *context)
371
{
×
372
#if _MSC_VER
373
    enum { max_channels = 4 };
374
#else
375
    const int max_channels = 4;
×
376
#endif
377
    SIXELSTATUS status;
378
    unsigned char *data;
379
    unsigned char *palette;
380
    unsigned char *new_palette;
381
    unsigned char *source_pixel;
382
    unsigned char palette_value;
383
    unsigned char corrected[max_channels];
×
384
    int32_t sample_scaled[max_channels];
×
385
    int32_t accum_scaled[max_channels];
×
386
    int32_t target_scaled;
387
    int32_t error_scaled;
388
    int32_t *carry_curr;
389
    int32_t *carry_next;
390
    int32_t *carry_far;
391
    int serpentine;
392
    int use_carry;
393
    size_t carry_len;
394
    int method_for_diffuse;
395
    int method_for_carry;
396
    int method_for_scan;
397
    diffuse_varerr_mode varerr_diffuse;
398
    diffuse_varerr_carry_mode varerr_diffuse_carry;
399
    int optimize_palette;
400
    int y;
401
    int absolute_y;
402
    int start;
403
    int end;
404
    int step;
405
    int direction;
406
    int x;
407
    int pos;
408
    size_t base;
409
    size_t carry_base;
410
    int depth;
411
    int reqcolor;
412
    int n;
413
    int color_index;
414
    int output_index;
415
    int diff;
416
    int table_index;
417
    unsigned short *indextable;
418
    unsigned short *migration_map;
419
    int *ncolors;
420
    int (*lookup)(const unsigned char *,
421
                  int,
422
                  const unsigned char *,
423
                  int,
424
                  unsigned short *,
425
                  int);
426
    sixel_lut_t *fast_lut;
427
    int use_fast_lut;
428
    float *palette_float;
429
    float *new_palette_float;
430
    int float_depth;
431
    int float_index;
432

433
    if (dither == NULL || context == NULL) {
×
434
        return SIXEL_BAD_ARGUMENT;
×
435
    }
436

437
    status = SIXEL_BAD_ARGUMENT;
×
438
    data = context->pixels;
×
439
    palette = context->palette;
×
440
    new_palette = context->new_palette;
×
441
    indextable = context->indextable;
×
442
    migration_map = context->migration_map;
×
443
    ncolors = context->ncolors;
×
444
    depth = context->depth;
×
445
    reqcolor = context->reqcolor;
×
446
    lookup = context->lookup;
×
447
    fast_lut = context->lut;
×
448
    use_fast_lut = (fast_lut != NULL);
×
449
    palette_float = context->palette_float;
×
450
    new_palette_float = context->new_palette_float;
×
451
    float_depth = context->float_depth;
×
452
    optimize_palette = context->optimize_palette;
×
453
    method_for_diffuse = context->method_for_diffuse;
×
454
    method_for_carry = context->method_for_carry;
×
455
    method_for_scan = context->method_for_scan;
×
456
    if (data == NULL || palette == NULL || context->result == NULL) {
×
457
        return SIXEL_BAD_ARGUMENT;
×
458
    }
459
    if (optimize_palette) {
×
460
        if (new_palette == NULL || migration_map == NULL || ncolors == NULL) {
×
461
            return SIXEL_BAD_ARGUMENT;
×
462
        }
463
    } else if (ncolors == NULL) {
×
464
        return SIXEL_BAD_ARGUMENT;
×
465
    }
466

467
    if (depth <= 0 || depth > max_channels) {
×
468
        return SIXEL_BAD_ARGUMENT;
×
469
    }
470

471
    switch (method_for_diffuse) {
×
472
    case SIXEL_DIFFUSE_LSO2:
×
473
    default:
474
        varerr_diffuse = diffuse_lso2;
×
475
        varerr_diffuse_carry = diffuse_lso2_carry;
×
476
        break;
×
477
    }
478

479
    use_carry = (method_for_carry == SIXEL_CARRY_ENABLE);
×
480
    carry_curr = NULL;
×
481
    carry_next = NULL;
×
482
    carry_far = NULL;
×
483
    carry_len = 0;
×
484

485
    if (use_carry) {
×
486
        carry_len = (size_t)context->width * (size_t)depth;
×
487
        carry_curr = (int32_t *)calloc(carry_len, sizeof(int32_t));
×
488
        carry_next = (int32_t *)calloc(carry_len, sizeof(int32_t));
×
489
        carry_far = (int32_t *)calloc(carry_len, sizeof(int32_t));
×
490
        if (carry_curr == NULL || carry_next == NULL || carry_far == NULL) {
×
491
            goto end;
×
492
        }
493
    }
494

495
    serpentine = (method_for_scan == SIXEL_SCAN_SERPENTINE);
×
496
    if (optimize_palette) {
×
497
        *ncolors = 0;
×
498
        memset(new_palette, 0x00,
×
499
               (size_t)SIXEL_PALETTE_MAX * (size_t)depth);
×
500
        if (new_palette_float != NULL && float_depth > 0) {
×
501
            memset(new_palette_float, 0x00,
×
502
                   (size_t)SIXEL_PALETTE_MAX
503
                       * (size_t)float_depth * sizeof(float));
×
504
        }
505
        memset(migration_map, 0x00,
×
506
               sizeof(unsigned short) * (size_t)SIXEL_PALETTE_MAX);
507
    }
508

509
    for (y = 0; y < context->height; ++y) {
×
510
        absolute_y = context->band_origin + y;
×
511
        sixel_dither_scanline_params(serpentine,
×
512
                                     absolute_y,
513
                                     context->width,
514
                                     &start,
515
                                     &end,
516
                                     &step,
517
                                     &direction);
518
        for (x = start; x != end; x += step) {
×
519
            pos = y * context->width + x;
×
520
            base = (size_t)pos * (size_t)depth;
×
521
            carry_base = (size_t)x * (size_t)depth;
×
522
            if (use_carry) {
×
523
                for (n = 0; n < depth; ++n) {
×
524
                    int64_t accum;
525
                    int32_t clamped;
526

527
                    accum = ((int64_t)data[base + (size_t)n]
×
528
                             << VARERR_SCALE_SHIFT)
×
529
                          + carry_curr[carry_base + (size_t)n];
×
530
                    if (accum < INT32_MIN) {
×
531
                        accum = INT32_MIN;
×
532
                    } else if (accum > INT32_MAX) {
×
533
                        accum = INT32_MAX;
×
534
                    }
535
                    carry_curr[carry_base + (size_t)n] = 0;
×
536
                    clamped = (int32_t)accum;
×
537
                    if (clamped < 0) {
×
538
                        clamped = 0;
×
539
                    } else if (clamped > VARERR_MAX_VALUE) {
×
540
                        clamped = VARERR_MAX_VALUE;
×
541
                    }
542
                    accum_scaled[n] = clamped;
×
543
                    corrected[n]
544
                        = (unsigned char)((clamped + VARERR_ROUND)
×
545
                                          >> VARERR_SCALE_SHIFT);
×
546
                }
547
                source_pixel = corrected;
×
548
            } else {
549
                for (n = 0; n < depth; ++n) {
×
550
                    sample_scaled[n]
551
                        = (int32_t)data[base + (size_t)n]
×
552
                        << VARERR_SCALE_SHIFT;
×
553
                }
554
                source_pixel = data + base;
×
555
            }
556

557
            if (use_fast_lut) {
×
558
                color_index = sixel_lut_map_pixel(fast_lut, source_pixel);
×
559
            } else {
560
                color_index = lookup(source_pixel,
×
561
                                      depth,
562
                                      palette,
563
                                      reqcolor,
564
                                      indextable,
565
                                      context->complexion);
566
            }
567

568
            if (optimize_palette) {
×
569
                if (migration_map[color_index] == 0) {
×
570
                    output_index = *ncolors;
×
571
                    for (n = 0; n < depth; ++n) {
×
572
                        new_palette[output_index * depth + n]
×
573
                            = palette[color_index * depth + n];
×
574
                    }
575
                    if (palette_float != NULL
×
576
                            && new_palette_float != NULL
×
577
                            && float_depth > 0) {
×
578
                        for (float_index = 0;
×
579
                                float_index < float_depth;
×
580
                                ++float_index) {
×
581
                            new_palette_float[output_index * float_depth
×
582
                                              + float_index]
×
583
                                = palette_float[color_index * float_depth
×
584
                                                + float_index];
×
585
                        }
586
                    }
587
                    ++*ncolors;
×
588
                    migration_map[color_index] = *ncolors;
×
589
                } else {
590
                    output_index = migration_map[color_index] - 1;
×
591
                }
592
                if (absolute_y >= context->output_start) {
×
593
                    context->result[pos] = output_index;
×
594
                }
595
            } else {
596
                output_index = color_index;
×
597
                if (absolute_y >= context->output_start) {
×
598
                    context->result[pos] = output_index;
×
599
                }
600
            }
601

602
            for (n = 0; n < depth; ++n) {
×
603
                if (optimize_palette) {
×
604
                    palette_value = new_palette[output_index * depth + n];
×
605
                } else {
606
                    palette_value = palette[color_index * depth + n];
×
607
                }
608
                diff = (int)source_pixel[n] - (int)palette_value;
×
609
                if (diff < 0) {
×
610
                    diff = -diff;
×
611
                }
612
                if (diff > 255) {
×
613
                    diff = 255;
×
614
                }
615
                table_index = diff;
×
616
                if (use_carry) {
×
617
                    target_scaled = (int32_t)palette_value
×
618
                                  << VARERR_SCALE_SHIFT;
619
                    error_scaled = accum_scaled[n] - target_scaled;
×
620
                    varerr_diffuse_carry(carry_curr,
×
621
                                         carry_next,
622
                                         carry_far,
623
                                         context->width,
624
                                         context->height,
625
                                         depth,
626
                                         x,
627
                                         y,
628
                                         error_scaled,
629
                                         table_index,
630
                                         direction,
631
                                         n);
632
                } else {
633
                    target_scaled = (int32_t)palette_value
×
634
                                  << VARERR_SCALE_SHIFT;
635
                    error_scaled = sample_scaled[n] - target_scaled;
×
636
                    varerr_diffuse(data + n,
×
637
                                   context->width,
638
                                   context->height,
639
                                   x,
640
                                   y,
641
                                   depth,
642
                                   error_scaled,
643
                                   table_index,
644
                                   direction);
645
                }
646
            }
647
        }
648

649
        if (use_carry) {
×
650
            int32_t *tmp;
651

652
            tmp = carry_curr;
×
653
            carry_curr = carry_next;
×
654
            carry_next = carry_far;
×
655
            carry_far = tmp;
×
656
            if (carry_len > 0) {
×
657
                memset(carry_far, 0x00, carry_len * sizeof(int32_t));
×
658
            }
659
        }
660
        if (absolute_y >= context->output_start) {
×
661
            sixel_dither_pipeline_row_notify(dither, absolute_y);
×
662
        }
663
    }
664

665
    if (optimize_palette) {
×
666
        memcpy(palette, new_palette, (size_t)(*ncolors * depth));
×
667
        if (palette_float != NULL
×
668
                && new_palette_float != NULL
×
669
                && float_depth > 0) {
×
670
            memcpy(palette_float,
×
671
                   new_palette_float,
672
                   (size_t)(*ncolors * float_depth)
×
673
                       * sizeof(float));
674
        }
675
    } else {
676
        *ncolors = reqcolor;
×
677
    }
678

679
    status = SIXEL_OK;
×
680

681
end:
×
682
    free(carry_curr);
×
683
    free(carry_next);
×
684
    free(carry_far);
×
685
    return status;
×
686
}
687

688
/* emacs Local Variables:      */
689
/* emacs mode: c               */
690
/* emacs tab-width: 4          */
691
/* emacs indent-tabs-mode: nil */
692
/* emacs c-basic-offset: 4     */
693
/* emacs End:                  */
694
/* vim: set expandtab ts=4 sts=4 sw=4 : */
695
/* 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