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

saitoha / libsixel / 19391148264

15 Nov 2025 02:12PM UTC coverage: 43.89% (+0.5%) from 43.379%
19391148264

push

github

saitoha
reorganize dithering headers

8474 of 27760 branches covered (30.53%)

322 of 1019 new or added lines in 4 files covered. (31.6%)

2 existing lines in 1 file now uncovered.

11759 of 26792 relevant lines covered (43.89%)

1075858.54 hits per line

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

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

23
#include "config.h"
24

25
#include <stdlib.h>
26
#include <string.h>
27
#include <stdint.h>
28
#include <limits.h>
29

30
#include "dither-diffusion-adaptive.h"
31
#include "dither-common-pipeline.h"
32

33
/*
34
 * Local helper describing serpentine scan conversion.  Adaptive diffusion
35
 * adjusts its error propagation dynamically, so keeping the traversal logic
36
 * here documents the row order without exposing another shared header.
37
 */
38
static void
NEW
39
sixel_dither_scanline_params(int serpentine,
×
40
                             int index,
41
                             int limit,
42
                             int *start,
43
                             int *end,
44
                             int *step,
45
                             int *direction)
46
{
NEW
47
    if (serpentine && (index & 1)) {
×
NEW
48
        *start = limit - 1;
×
NEW
49
        *end = -1;
×
NEW
50
        *step = -1;
×
NEW
51
        *direction = -1;
×
52
    } else {
NEW
53
        *start = 0;
×
NEW
54
        *end = limit;
×
NEW
55
        *step = 1;
×
NEW
56
        *direction = 1;
×
57
    }
NEW
58
}
×
59

60
static const int (*
NEW
61
lso2_table(void))[7]
×
62
{
63
#include "lso2.h"
64
    return var_coefs;
65
}
66

67
#define VARERR_SCALE_SHIFT 12
68
#define VARERR_SCALE       (1 << VARERR_SCALE_SHIFT)
69
#define VARERR_ROUND       (1 << (VARERR_SCALE_SHIFT - 1))
70
#define VARERR_MAX_VALUE   (255 * VARERR_SCALE)
71

72
typedef void (*diffuse_varerr_mode)(unsigned char *data,
73
                                    int width,
74
                                    int height,
75
                                    int x,
76
                                    int y,
77
                                    int depth,
78
                                    int32_t error,
79
                                    int index,
80
                                    int direction);
81

82
typedef void (*diffuse_varerr_carry_mode)(int32_t *carry_curr,
83
                                          int32_t *carry_next,
84
                                          int32_t *carry_far,
85
                                          int width,
86
                                          int height,
87
                                          int depth,
88
                                          int x,
89
                                          int y,
90
                                          int32_t error,
91
                                          int index,
92
                                          int direction,
93
                                          int channel);
94

95

96
static int32_t
NEW
97
diffuse_varerr_term(int32_t error, int weight, int denom)
×
98
{
99
    int64_t delta;
100

NEW
101
    delta = (int64_t)error * (int64_t)weight;
×
NEW
102
    if (delta >= 0) {
×
NEW
103
        delta = (delta + denom / 2) / denom;
×
104
    } else {
NEW
105
        delta = (delta - denom / 2) / denom;
×
106
    }
107

NEW
108
    return (int32_t)delta;
×
109
}
110

111
static void
NEW
112
diffuse_varerr_apply_direct(unsigned char *target, int depth, size_t offset,
×
113
                            int32_t delta)
114
{
115
    int64_t value;
116
    int result;
117

NEW
118
    value = (int64_t)target[offset * depth] << VARERR_SCALE_SHIFT;
×
NEW
119
    value += delta;
×
NEW
120
    if (value < 0) {
×
NEW
121
        value = 0;
×
122
    } else {
123
        int64_t max_value;
124

NEW
125
        max_value = VARERR_MAX_VALUE;
×
NEW
126
        if (value > max_value) {
×
NEW
127
            value = max_value;
×
128
        }
129
    }
130

NEW
131
    result = (int)((value + VARERR_ROUND) >> VARERR_SCALE_SHIFT);
×
NEW
132
    if (result < 0) {
×
NEW
133
        result = 0;
×
134
    }
NEW
135
    if (result > 255) {
×
NEW
136
        result = 255;
×
137
    }
NEW
138
    target[offset * depth] = (unsigned char)result;
×
NEW
139
}
×
140

141
static void
NEW
142
diffuse_lso2(unsigned char *data, int width, int height,
×
143
             int x, int y, int depth, int32_t error,
144
             int index, int direction)
145
{
146
    const int (*table)[7];
147
    const int *entry;
148
    int denom;
NEW
149
    int32_t term_r = 0;
×
NEW
150
    int32_t term_r2 = 0;
×
NEW
151
    int32_t term_dl = 0;
×
NEW
152
    int32_t term_d = 0;
×
NEW
153
    int32_t term_dr = 0;
×
NEW
154
    int32_t term_d2 = 0;
×
155
    size_t offset;
156

NEW
157
    if (error == 0) {
×
NEW
158
        return;
×
159
    }
NEW
160
    if (index < 0) {
×
NEW
161
        index = 0;
×
162
    }
NEW
163
    if (index > 255) {
×
NEW
164
        index = 255;
×
165
    }
166

NEW
167
    table = lso2_table();
×
NEW
168
    entry = table[index];
×
NEW
169
    denom = entry[6];
×
NEW
170
    if (denom == 0) {
×
NEW
171
        return;
×
172
    }
173

NEW
174
    term_r = diffuse_varerr_term(error, entry[0], denom);
×
NEW
175
    term_r2 = diffuse_varerr_term(error, entry[1], denom);
×
NEW
176
    term_dl = diffuse_varerr_term(error, entry[2], denom);
×
NEW
177
    term_d = diffuse_varerr_term(error, entry[3], denom);
×
NEW
178
    term_dr = diffuse_varerr_term(error, entry[4], denom);
×
NEW
179
    term_d2 = diffuse_varerr_term(error, entry[5], denom);
×
180

181

NEW
182
    if (direction >= 0) {
×
NEW
183
        if (x + 1 < width) {
×
NEW
184
            offset = (size_t)y * (size_t)width + (size_t)(x + 1);
×
NEW
185
            diffuse_varerr_apply_direct(data, depth, offset, term_r);
×
186
        }
NEW
187
        if (x + 2 < width) {
×
NEW
188
            offset = (size_t)y * (size_t)width + (size_t)(x + 2);
×
NEW
189
            diffuse_varerr_apply_direct(data, depth, offset, term_r2);
×
190
        }
NEW
191
        if (y + 1 < height && x - 1 >= 0) {
×
NEW
192
            offset = (size_t)(y + 1) * (size_t)width;
×
NEW
193
            offset += (size_t)(x - 1);
×
NEW
194
            diffuse_varerr_apply_direct(data, depth, offset, term_dl);
×
195
        }
NEW
196
        if (y + 1 < height) {
×
NEW
197
            offset = (size_t)(y + 1) * (size_t)width + (size_t)x;
×
NEW
198
            diffuse_varerr_apply_direct(data, depth, offset, term_d);
×
199
        }
NEW
200
        if (y + 1 < height && x + 1 < width) {
×
NEW
201
            offset = (size_t)(y + 1) * (size_t)width;
×
NEW
202
            offset += (size_t)(x + 1);
×
NEW
203
            diffuse_varerr_apply_direct(data, depth, offset, term_dr);
×
204
        }
NEW
205
        if (y + 2 < height) {
×
NEW
206
            offset = (size_t)(y + 2) * (size_t)width + (size_t)x;
×
NEW
207
            diffuse_varerr_apply_direct(data, depth, offset, term_d2);
×
208
        }
209
    } else {
NEW
210
        if (x - 1 >= 0) {
×
NEW
211
            offset = (size_t)y * (size_t)width + (size_t)(x - 1);
×
NEW
212
            diffuse_varerr_apply_direct(data, depth, offset, term_r);
×
213
        }
NEW
214
        if (x - 2 >= 0) {
×
NEW
215
            offset = (size_t)y * (size_t)width + (size_t)(x - 2);
×
NEW
216
            diffuse_varerr_apply_direct(data, depth, offset, term_r2);
×
217
        }
NEW
218
        if (y + 1 < height && x + 1 < width) {
×
NEW
219
            offset = (size_t)(y + 1) * (size_t)width;
×
NEW
220
            offset += (size_t)(x + 1);
×
NEW
221
            diffuse_varerr_apply_direct(data, depth, offset, term_dl);
×
222
        }
NEW
223
        if (y + 1 < height) {
×
NEW
224
            offset = (size_t)(y + 1) * (size_t)width + (size_t)x;
×
NEW
225
            diffuse_varerr_apply_direct(data, depth, offset, term_d);
×
226
        }
NEW
227
        if (y + 1 < height && x - 1 >= 0) {
×
NEW
228
            offset = (size_t)(y + 1) * (size_t)width;
×
NEW
229
            offset += (size_t)(x - 1);
×
NEW
230
            diffuse_varerr_apply_direct(data, depth, offset, term_dr);
×
231
        }
NEW
232
        if (y + 2 < height) {
×
NEW
233
            offset = (size_t)(y + 2) * (size_t)width + (size_t)x;
×
NEW
234
            diffuse_varerr_apply_direct(data, depth, offset, term_d2);
×
235
        }
236
    }
237
}
238

239
static void
NEW
240
diffuse_lso2_carry(int32_t *carry_curr, int32_t *carry_next, int32_t *carry_far,
×
241
                   int width, int height, int depth,
242
                   int x, int y, int32_t error,
243
                   int index, int direction, int channel)
244
{
245
    const int (*table)[7];
246
    const int *entry;
247
    int denom;
NEW
248
    int32_t term_r = 0;
×
NEW
249
    int32_t term_r2 = 0;
×
NEW
250
    int32_t term_dl = 0;
×
NEW
251
    int32_t term_d = 0;
×
NEW
252
    int32_t term_dr = 0;
×
NEW
253
    int32_t term_d2 = 0;
×
254
    size_t base;
255

NEW
256
    if (error == 0) {
×
NEW
257
        return;
×
258
    }
NEW
259
    if (index < 0) {
×
NEW
260
        index = 0;
×
261
    }
NEW
262
    if (index > 255) {
×
NEW
263
        index = 255;
×
264
    }
265

NEW
266
    table = lso2_table();
×
NEW
267
    entry = table[index];
×
NEW
268
    denom = entry[6];
×
NEW
269
    if (denom == 0) {
×
NEW
270
        return;
×
271
    }
272

NEW
273
    term_r = diffuse_varerr_term(error, entry[0], denom);
×
NEW
274
    term_r2 = diffuse_varerr_term(error, entry[1], denom);
×
NEW
275
    term_dl = diffuse_varerr_term(error, entry[2], denom);
×
NEW
276
    term_d = diffuse_varerr_term(error, entry[3], denom);
×
NEW
277
    term_dr = diffuse_varerr_term(error, entry[4], denom);
×
NEW
278
    term_d2 = error - term_r - term_r2 - term_dl - term_d - term_dr;
×
279

NEW
280
    if (direction >= 0) {
×
NEW
281
        if (x + 1 < width) {
×
NEW
282
            base = ((size_t)(x + 1) * (size_t)depth) + (size_t)channel;
×
NEW
283
            carry_curr[base] += term_r;
×
284
        }
NEW
285
        if (x + 2 < width) {
×
NEW
286
            base = ((size_t)(x + 2) * (size_t)depth) + (size_t)channel;
×
NEW
287
            carry_curr[base] += term_r2;
×
288
        }
NEW
289
        if (y + 1 < height && x - 1 >= 0) {
×
NEW
290
            base = ((size_t)(x - 1) * (size_t)depth) + (size_t)channel;
×
NEW
291
            carry_next[base] += term_dl;
×
292
        }
NEW
293
        if (y + 1 < height) {
×
NEW
294
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
NEW
295
            carry_next[base] += term_d;
×
296
        }
NEW
297
        if (y + 1 < height && x + 1 < width) {
×
NEW
298
            base = ((size_t)(x + 1) * (size_t)depth) + (size_t)channel;
×
NEW
299
            carry_next[base] += term_dr;
×
300
        }
NEW
301
        if (y + 2 < height) {
×
NEW
302
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
NEW
303
            carry_far[base] += term_d2;
×
304
        }
305
    } else {
NEW
306
        if (x - 1 >= 0) {
×
NEW
307
            base = ((size_t)(x - 1) * (size_t)depth) + (size_t)channel;
×
NEW
308
            carry_curr[base] += term_r;
×
309
        }
NEW
310
        if (x - 2 >= 0) {
×
NEW
311
            base = ((size_t)(x - 2) * (size_t)depth) + (size_t)channel;
×
NEW
312
            carry_curr[base] += term_r2;
×
313
        }
NEW
314
        if (y + 1 < height && x + 1 < width) {
×
NEW
315
            base = ((size_t)(x + 1) * (size_t)depth) + (size_t)channel;
×
NEW
316
            carry_next[base] += term_dl;
×
317
        }
NEW
318
        if (y + 1 < height) {
×
NEW
319
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
NEW
320
            carry_next[base] += term_d;
×
321
        }
NEW
322
        if (y + 1 < height && x - 1 >= 0) {
×
NEW
323
            base = ((size_t)(x - 1) * (size_t)depth) + (size_t)channel;
×
NEW
324
            carry_next[base] += term_dr;
×
325
        }
NEW
326
        if (y + 2 < height) {
×
NEW
327
            base = ((size_t)x * (size_t)depth) + (size_t)channel;
×
NEW
328
            carry_far[base] += term_d2;
×
329
        }
330
    }
331
}
332

333
SIXELSTATUS
NEW
334
sixel_dither_apply_variable(
×
335
    sixel_index_t *result,
336
    unsigned char *data,
337
    int width,
338
    int height,
339
    int depth,
340
    unsigned char *palette,
341
    int reqcolor,
342
    int method_for_scan,
343
    int optimize_palette,
344
    int (*f_lookup)(const unsigned char *pixel,
345
                    int depth,
346
                    const unsigned char *palette,
347
                    int reqcolor,
348
                    unsigned short *cachetable,
349
                    int complexion),
350
    unsigned short *indextable,
351
    int complexion,
352
    unsigned char new_palette[],
353
    unsigned short migration_map[],
354
    int *ncolors,
355
    int method_for_diffuse,
356
    int method_for_carry,
357
    sixel_dither_t *dither)
358
{
NEW
359
    SIXELSTATUS status = SIXEL_FALSE;
×
360
#if _MSC_VER
361
    enum { max_channels = 4 };
362
#else
NEW
363
    const int max_channels = 4;
×
364
#endif
365
    int serpentine;
366
    int y;
367
    diffuse_varerr_mode varerr_diffuse;
368
    diffuse_varerr_carry_mode varerr_diffuse_carry;
369
    int use_carry;
370
    size_t carry_len;
NEW
371
    int32_t *carry_curr = NULL;
×
NEW
372
    int32_t *carry_next = NULL;
×
NEW
373
    int32_t *carry_far = NULL;
×
374
    unsigned char corrected[max_channels];
375
    int32_t sample_scaled[max_channels];
376
    int32_t accum_scaled[max_channels];
377
    int start;
378
    int end;
379
    int step;
380
    int direction;
381
    int x;
382
    int pos;
383
    size_t base;
384
    size_t carry_base;
385
    const unsigned char *source_pixel;
386
    int color_index;
387
    int output_index;
388
    int n;
389
    int palette_value;
390
    int diff;
391
    int table_index;
392
    int64_t accum;
393
    int64_t clamped;
394
    int32_t target_scaled;
395
    int32_t error_scaled;
396
    int32_t *tmp;
397

NEW
398
    if (depth > max_channels) {
×
NEW
399
        status = SIXEL_BAD_ARGUMENT;
×
NEW
400
        goto end;
×
401
    }
402

NEW
403
    use_carry = (method_for_carry == SIXEL_CARRY_ENABLE);
×
NEW
404
    carry_len = 0;
×
405

NEW
406
    switch (method_for_diffuse) {
×
407
    case SIXEL_DIFFUSE_LSO2:
NEW
408
        varerr_diffuse = diffuse_lso2;
×
NEW
409
        varerr_diffuse_carry = diffuse_lso2_carry;
×
NEW
410
        break;
×
411
    default:
NEW
412
        varerr_diffuse = diffuse_lso2;
×
NEW
413
        varerr_diffuse_carry = diffuse_lso2_carry;
×
NEW
414
        break;
×
415
    }
416

NEW
417
    if (use_carry) {
×
NEW
418
        carry_len = (size_t)width * (size_t)depth;
×
NEW
419
        carry_curr = (int32_t *)calloc(carry_len, sizeof(int32_t));
×
NEW
420
        if (carry_curr == NULL) {
×
NEW
421
            status = SIXEL_BAD_ALLOCATION;
×
NEW
422
            goto end;
×
423
        }
NEW
424
        carry_next = (int32_t *)calloc(carry_len, sizeof(int32_t));
×
NEW
425
        if (carry_next == NULL) {
×
NEW
426
            status = SIXEL_BAD_ALLOCATION;
×
NEW
427
            goto end;
×
428
        }
NEW
429
        carry_far = (int32_t *)calloc(carry_len, sizeof(int32_t));
×
NEW
430
        if (carry_far == NULL) {
×
NEW
431
            status = SIXEL_BAD_ALLOCATION;
×
NEW
432
            goto end;
×
433
        }
434
    }
435

NEW
436
    serpentine = (method_for_scan == SIXEL_SCAN_SERPENTINE);
×
437

NEW
438
    if (optimize_palette) {
×
NEW
439
        *ncolors = 0;
×
NEW
440
        memset(new_palette, 0x00,
×
441
               (size_t)SIXEL_PALETTE_MAX * (size_t)depth);
NEW
442
        memset(migration_map, 0x00,
×
443
               sizeof(unsigned short) * (size_t)SIXEL_PALETTE_MAX);
444
    }
445

NEW
446
    for (y = 0; y < height; ++y) {
×
NEW
447
        sixel_dither_scanline_params(serpentine, y, width,
×
448
                        &start, &end, &step, &direction);
NEW
449
        for (x = start; x != end; x += step) {
×
NEW
450
            pos = y * width + x;
×
NEW
451
            base = (size_t)pos * (size_t)depth;
×
NEW
452
            carry_base = (size_t)x * (size_t)depth;
×
NEW
453
            if (use_carry) {
×
NEW
454
                for (n = 0; n < depth; ++n) {
×
NEW
455
                    accum = ((int64_t)data[base + n]
×
NEW
456
                             << VARERR_SCALE_SHIFT)
×
NEW
457
                          + carry_curr[carry_base + (size_t)n];
×
NEW
458
                    if (accum < INT32_MIN) {
×
NEW
459
                        accum = INT32_MIN;
×
NEW
460
                    } else if (accum > INT32_MAX) {
×
NEW
461
                        accum = INT32_MAX;
×
462
                    }
NEW
463
                    carry_curr[carry_base + (size_t)n] = 0;
×
NEW
464
                    clamped = accum;
×
NEW
465
                    if (clamped < 0) {
×
NEW
466
                        clamped = 0;
×
NEW
467
                    } else if (clamped > VARERR_MAX_VALUE) {
×
NEW
468
                        clamped = VARERR_MAX_VALUE;
×
469
                    }
NEW
470
                    accum_scaled[n] = (int32_t)clamped;
×
471
                    corrected[n]
NEW
472
                        = (unsigned char)((clamped + VARERR_ROUND)
×
NEW
473
                                          >> VARERR_SCALE_SHIFT);
×
474
                }
NEW
475
                source_pixel = corrected;
×
476
            } else {
NEW
477
                for (n = 0; n < depth; ++n) {
×
478
                    sample_scaled[n]
NEW
479
                        = (int32_t)data[base + n]
×
NEW
480
                        << VARERR_SCALE_SHIFT;
×
NEW
481
                    corrected[n] = data[base + n];
×
482
                }
NEW
483
                source_pixel = data + base;
×
484
            }
485

NEW
486
            color_index = f_lookup(source_pixel, depth, palette,
×
487
                                   reqcolor, indextable,
488
                                   complexion);
489

NEW
490
            if (optimize_palette) {
×
NEW
491
                if (migration_map[color_index] == 0) {
×
NEW
492
                    output_index = *ncolors;
×
NEW
493
                    for (n = 0; n < depth; ++n) {
×
NEW
494
                        new_palette[output_index * depth + n]
×
NEW
495
                            = palette[color_index * depth + n];
×
496
                    }
NEW
497
                    ++*ncolors;
×
NEW
498
                    migration_map[color_index] = *ncolors;
×
499
                } else {
NEW
500
                    output_index = migration_map[color_index] - 1;
×
501
                }
NEW
502
                result[pos] = output_index;
×
503
            } else {
NEW
504
                output_index = color_index;
×
NEW
505
                result[pos] = output_index;
×
506
            }
507

NEW
508
            for (n = 0; n < depth; ++n) {
×
NEW
509
                if (optimize_palette) {
×
NEW
510
                    palette_value = new_palette[output_index * depth + n];
×
511
                } else {
NEW
512
                    palette_value = palette[color_index * depth + n];
×
513
                }
NEW
514
                diff = (int)source_pixel[n] - palette_value;
×
NEW
515
                if (diff < 0) {
×
NEW
516
                    diff = -diff;
×
517
                }
NEW
518
                if (diff > 255) {
×
NEW
519
                    diff = 255;
×
520
                }
NEW
521
                table_index = diff;
×
NEW
522
                if (use_carry) {
×
NEW
523
                    target_scaled = (int32_t)palette_value
×
524
                                  << VARERR_SCALE_SHIFT;
NEW
525
                    error_scaled = accum_scaled[n] - target_scaled;
×
NEW
526
                    varerr_diffuse_carry(carry_curr, carry_next, carry_far,
×
527
                                         width, height, depth,
528
                                         x, y, error_scaled,
529
                                         table_index,
530
                                         direction, n);
531
                } else {
NEW
532
                    target_scaled = (int32_t)palette_value
×
533
                                  << VARERR_SCALE_SHIFT;
NEW
534
                    error_scaled = sample_scaled[n] - target_scaled;
×
NEW
535
                    varerr_diffuse(data + n, width, height,
×
536
                                   x, y, depth, error_scaled,
537
                                   table_index,
538
                                   direction);
539
                }
540
            }
541
        }
NEW
542
        if (use_carry) {
×
NEW
543
            tmp = carry_curr;
×
NEW
544
            carry_curr = carry_next;
×
NEW
545
            carry_next = carry_far;
×
NEW
546
            carry_far = tmp;
×
NEW
547
            if (carry_len > 0) {
×
NEW
548
                memset(carry_far, 0x00, carry_len * sizeof(int32_t));
×
549
            }
550
        }
NEW
551
        sixel_dither_pipeline_row_notify(dither, y);
×
552
    }
553

NEW
554
    if (optimize_palette) {
×
NEW
555
        memcpy(palette, new_palette, (size_t)(*ncolors * depth));
×
556
    } else {
NEW
557
        *ncolors = reqcolor;
×
558
    }
559

NEW
560
    status = SIXEL_OK;
×
561

562
end:
NEW
563
    free(carry_next);
×
NEW
564
    free(carry_curr);
×
NEW
565
    free(carry_far);
×
NEW
566
    return status;
×
567
}
568

569
/* emacs Local Variables:      */
570
/* emacs mode: c               */
571
/* emacs tab-width: 4          */
572
/* emacs indent-tabs-mode: nil */
573
/* emacs c-basic-offset: 4     */
574
/* emacs End:                  */
575
/* vim: set expandtab ts=4 sts=4 sw=4 : */
576
/* 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