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

saitoha / libsixel / 19765269522

28 Nov 2025 01:30PM UTC coverage: 39.983% (-1.6%) from 41.616%
19765269522

push

github

web-flow
Merge pull request #214 from saitoha/codex/add-logging-to-resize-processing

Limit scale logging and add timeline window controls

9788 of 35562 branches covered (27.52%)

9 of 63 new or added lines in 1 file covered. (14.29%)

281 existing lines in 19 files now uncovered.

12991 of 32491 relevant lines covered (39.98%)

619662.16 hits per line

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

0.0
/src/dither-positional-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
#include "config.h"
26

27
#include <string.h>
28

29
#include "dither-positional-8bit.h"
30
#include "dither-common-pipeline.h"
31
#include "lookup-common.h"
32

33
static void
34
sixel_dither_scanline_params(int serpentine,
×
35
                             int index,
36
                             int limit,
37
                             int *start,
38
                             int *end,
39
                             int *step,
40
                             int *direction)
41
{
42
    if (serpentine && (index & 1)) {
×
43
        *start = limit - 1;
×
44
        *end = -1;
×
45
        *step = -1;
×
46
        *direction = -1;
×
47
    } else {
48
        *start = 0;
×
49
        *end = limit;
×
50
        *step = 1;
×
51
        *direction = 1;
×
52
    }
53
}
×
54

55
static float mask_a(int x, int y, int c);
56
static float mask_x(int x, int y, int c);
57

58
static float
59
mask_a(int x, int y, int c)
×
60
{
61
    return ((((x + c * 67) + y * 236) * 119) & 255) / 128.0f - 1.0f;
×
62
}
63

64
static float
65
mask_x(int x, int y, int c)
×
66
{
67
    return ((((x + c * 29) ^ (y * 149)) * 1234) & 511) / 256.0f - 1.0f;
×
68
}
69

70
SIXELSTATUS
71
sixel_dither_apply_positional_8bit(sixel_dither_t *dither,
×
72
                                   sixel_dither_context_t *context)
73
{
74
    int serpentine;
75
    int y;
76
    int absolute_y;
77
    float *palette_float;
78
    float *new_palette_float;
79
    int float_depth;
80
    int float_index;
81
    sixel_lut_t *fast_lut;
82
    int use_fast_lut;
83
    float (*f_mask)(int x, int y, int c);
84

85
    palette_float = NULL;
×
86
    new_palette_float = NULL;
×
87
    float_depth = 0;
×
88

89
    if (dither == NULL || context == NULL) {
×
90
        return SIXEL_BAD_ARGUMENT;
×
91
    }
92
    if (context->pixels == NULL || context->palette == NULL) {
×
93
        return SIXEL_BAD_ARGUMENT;
×
94
    }
95
    if (context->result == NULL || context->scratch == NULL) {
×
96
        return SIXEL_BAD_ARGUMENT;
×
97
    }
98

99
    switch (context->method_for_diffuse) {
×
UNCOV
100
    case SIXEL_DIFFUSE_A_DITHER:
×
101
        f_mask = mask_a;
×
102
        break;
×
103
    case SIXEL_DIFFUSE_X_DITHER:
×
104
    default:
105
        f_mask = mask_x;
×
106
        break;
×
107
    }
108

109
    serpentine = (context->method_for_scan == SIXEL_SCAN_SERPENTINE);
×
110
    palette_float = context->palette_float;
×
111
    new_palette_float = context->new_palette_float;
×
112
    float_depth = context->float_depth;
×
113
    fast_lut = context->lut;
×
114
    use_fast_lut = (fast_lut != NULL);
×
115

116
    if (context->optimize_palette) {
×
117
        int x;
118

119
        *context->ncolors = 0;
×
120
        memset(context->new_palette, 0x00,
×
UNCOV
121
               (size_t)SIXEL_PALETTE_MAX * (size_t)context->depth);
×
122
        if (new_palette_float != NULL && float_depth > 0) {
×
123
            memset(new_palette_float, 0x00,
×
124
                   (size_t)SIXEL_PALETTE_MAX
UNCOV
125
                       * (size_t)float_depth * sizeof(float));
×
126
        }
127
        memset(context->migration_map, 0x00,
×
128
               sizeof(unsigned short) * (size_t)SIXEL_PALETTE_MAX);
129
        for (y = 0; y < context->height; ++y) {
×
130
            absolute_y = context->band_origin + y;
×
131
            int start;
132
            int end;
133
            int step;
134
            int direction;
135

136
            sixel_dither_scanline_params(serpentine, absolute_y,
×
137
                                         context->width,
138
                                         &start, &end, &step, &direction);
139
            (void)direction;
140
            for (x = start; x != end; x += step) {
×
141
                int pos;
142
                int d;
143
                int color_index;
144

145
                pos = y * context->width + x;
×
146
                for (d = 0; d < context->depth; ++d) {
×
147
                    int val;
148

149
                    val = context->pixels[pos * context->depth + d]
×
150
                        + (int)(f_mask(x, y, d) * 32.0f);
×
151
                    context->scratch[d] = val < 0 ? 0
×
152
                                       : val > 255 ? 255 : val;
×
153
                }
154
                if (use_fast_lut) {
×
155
                    color_index = sixel_lut_map_pixel(fast_lut,
×
156
                                                     context->scratch);
×
157
                } else {
158
                    color_index = context->lookup(context->scratch,
×
159
                                                  context->depth,
160
                                                  context->palette,
×
161
                                                  context->reqcolor,
162
                                                  context->indextable,
163
                                                  context->complexion);
164
                }
165
                if (context->migration_map[color_index] == 0) {
×
166
                    if (absolute_y >= context->output_start) {
×
167
                        context->result[pos] = *context->ncolors;
×
168
                    }
169
                    for (d = 0; d < context->depth; ++d) {
×
170
                        context->new_palette[*context->ncolors
×
171
                                             * context->depth + d]
×
172
                            = context->palette[color_index
×
173
                                               * context->depth + d];
×
174
                    }
175
                    if (palette_float != NULL
×
176
                            && new_palette_float != NULL
×
177
                            && float_depth > 0) {
×
178
                        for (float_index = 0;
×
179
                                float_index < float_depth;
×
180
                                ++float_index) {
×
181
                            new_palette_float[*context->ncolors
×
182
                                               * float_depth
×
183
                                               + float_index]
×
184
                                = palette_float[color_index * float_depth
×
185
                                                + float_index];
×
186
                        }
187
                    }
188
                    ++*context->ncolors;
×
189
                    context->migration_map[color_index] = *context->ncolors;
×
190
                } else {
191
                    if (absolute_y >= context->output_start) {
×
192
                        context->result[pos] =
×
193
                            context->migration_map[color_index] - 1;
×
194
                    }
195
                }
196
            }
197
            if (absolute_y >= context->output_start) {
×
198
                sixel_dither_pipeline_row_notify(dither, absolute_y);
×
199
            }
200
        }
201
        memcpy(context->palette, context->new_palette,
×
UNCOV
202
               (size_t)(*context->ncolors * context->depth));
×
203
        if (palette_float != NULL
×
204
                && new_palette_float != NULL
×
205
                && float_depth > 0) {
×
206
            memcpy(palette_float,
×
207
                   new_palette_float,
UNCOV
208
                   (size_t)(*context->ncolors * float_depth)
×
209
                       * sizeof(float));
210
        }
211
    } else {
212
        int x;
213

214
        for (y = 0; y < context->height; ++y) {
×
215
            absolute_y = context->band_origin + y;
×
216
            int start;
217
            int end;
218
            int step;
219
            int direction;
220

221
            sixel_dither_scanline_params(serpentine, absolute_y,
×
222
                                         context->width,
223
                                         &start, &end, &step, &direction);
224
            (void)direction;
225
            for (x = start; x != end; x += step) {
×
226
                int pos;
227
                int d;
228

229
                pos = y * context->width + x;
×
230
                for (d = 0; d < context->depth; ++d) {
×
231
                    int val;
232

233
                    val = context->pixels[pos * context->depth + d]
×
234
                        + (int)(f_mask(x, y, d) * 32.0f);
×
235
                    context->scratch[d] = val < 0 ? 0
×
236
                                       : val > 255 ? 255 : val;
×
237
                }
238
                if (absolute_y >= context->output_start) {
×
239
                    context->result[pos] =
×
240
                        context->lookup(context->scratch,
×
241
                                        context->depth,
242
                                        context->palette,
×
243
                                        context->reqcolor,
244
                                        context->indextable,
245
                                        context->complexion);
246
                }
247
            }
248
            if (absolute_y >= context->output_start) {
×
249
                sixel_dither_pipeline_row_notify(dither, absolute_y);
×
250
            }
251
        }
252
        *context->ncolors = context->reqcolor;
×
253
    }
254

255
    return SIXEL_OK;
×
256
}
257

258
/* emacs Local Variables:      */
259
/* emacs mode: c               */
260
/* emacs tab-width: 4          */
261
/* emacs indent-tabs-mode: nil */
262
/* emacs c-basic-offset: 4     */
263
/* emacs End:                  */
264
/* vim: set expandtab ts=4 sts=4 sw=4 : */
265
/* 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