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

saitoha / libsixel / 19460693151

18 Nov 2025 09:18AM UTC coverage: 40.311% (-1.3%) from 41.649%
19460693151

push

github

saitoha
tests: simplify invalid option test

8950 of 31723 branches covered (28.21%)

11828 of 29342 relevant lines covered (40.31%)

674846.97 hits per line

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

0.0
/src/dither-positional-float32.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
12
 * all 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
#if HAVE_MATH_H
26
# include <math.h>
27
#endif  /* HAVE_MATH_H */
28
#include <string.h>
29

30
#include "dither-positional-float32.h"
31
#include "dither-common-pipeline.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
56
mask_a(int x, int y, int c)
×
57
{
58
    return ((((x + c * 67) + y * 236) * 119) & 255) / 128.0f - 1.0f;
×
59
}
60

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

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

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

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

86
SIXELSTATUS
87
sixel_dither_apply_positional_float32(sixel_dither_t *dither,
×
88
                                      sixel_dither_context_t *context)
89
{
90
    int serpentine;
91
    int y;
92
    float (*f_mask)(int x, int y, int c);
93
    float jitter_scale;
94
    float *palette_float;
95
    float *new_palette_float;
96
    int float_depth;
97
    int float_index;
98

99
    palette_float = NULL;
×
100
    new_palette_float = NULL;
×
101
    float_depth = 0;
×
102

103
    if (dither == NULL || context == NULL) {
×
104
        return SIXEL_BAD_ARGUMENT;
×
105
    }
106
    if (context->pixels_float == NULL || context->scratch == NULL) {
×
107
        return SIXEL_BAD_ARGUMENT;
×
108
    }
109
    if (context->palette == NULL || context->result == NULL) {
×
110
        return SIXEL_BAD_ARGUMENT;
×
111
    }
112

113
    switch (context->method_for_diffuse) {
×
114
    case SIXEL_DIFFUSE_A_DITHER:
×
115
        f_mask = mask_a;
×
116
        break;
×
117
    case SIXEL_DIFFUSE_X_DITHER:
×
118
    default:
119
        f_mask = mask_x;
×
120
        break;
×
121
    }
122

123
    serpentine = (context->method_for_scan == SIXEL_SCAN_SERPENTINE);
×
124
    jitter_scale = 32.0f / 255.0f;
×
125
    palette_float = context->palette_float;
×
126
    new_palette_float = context->new_palette_float;
×
127
    float_depth = context->float_depth;
×
128

129
    if (context->optimize_palette) {
×
130
        int x;
131

132
        *context->ncolors = 0;
×
133
        memset(context->new_palette, 0x00,
×
134
               (size_t)SIXEL_PALETTE_MAX * (size_t)context->depth);
×
135
        if (new_palette_float != NULL && float_depth > 0) {
×
136
            memset(new_palette_float, 0x00,
×
137
                   (size_t)SIXEL_PALETTE_MAX
138
                       * (size_t)float_depth * sizeof(float));
×
139
        }
140
        memset(context->migration_map, 0x00,
×
141
               sizeof(unsigned short) * (size_t)SIXEL_PALETTE_MAX);
142
        for (y = 0; y < context->height; ++y) {
×
143
            int start;
144
            int end;
145
            int step;
146
            int direction;
147

148
            sixel_dither_scanline_params(serpentine, y, context->width,
×
149
                                         &start, &end, &step, &direction);
150
            (void)direction;
151
            for (x = start; x != end; x += step) {
×
152
                int pos;
153
                int d;
154
                int color_index;
155

156
                pos = y * context->width + x;
×
157
                for (d = 0; d < context->depth; ++d) {
×
158
                    float val;
159

160
                    val = context->pixels_float[pos * context->depth + d]
×
161
                        + f_mask(x, y, d) * jitter_scale;
×
162
                    context->scratch[d] =
×
163
                        sixel_dither_float_channel_to_byte(val);
×
164
                }
165
                color_index = context->lookup(context->scratch,
×
166
                                              context->depth,
167
                                              context->palette,
×
168
                                              context->reqcolor,
169
                                              context->indextable,
170
                                              context->complexion);
171
                if (context->migration_map[color_index] == 0) {
×
172
                    context->result[pos] = *context->ncolors;
×
173
                    for (d = 0; d < context->depth; ++d) {
×
174
                        context->new_palette[*context->ncolors
×
175
                                             * context->depth + d]
×
176
                            = context->palette[color_index
×
177
                                               * context->depth + d];
×
178
                    }
179
                    if (palette_float != NULL
×
180
                            && new_palette_float != NULL
×
181
                            && float_depth > 0) {
×
182
                        for (float_index = 0;
×
183
                                float_index < float_depth;
×
184
                                ++float_index) {
×
185
                            new_palette_float[*context->ncolors
×
186
                                               * float_depth
×
187
                                               + float_index]
×
188
                                = palette_float[color_index * float_depth
×
189
                                                + float_index];
×
190
                        }
191
                    }
192
                    ++*context->ncolors;
×
193
                    context->migration_map[color_index] = *context->ncolors;
×
194
                } else {
195
                    context->result[pos] =
×
196
                        context->migration_map[color_index] - 1;
×
197
                }
198
            }
199
            sixel_dither_pipeline_row_notify(dither, y);
×
200
        }
201
        memcpy(context->palette, context->new_palette,
×
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,
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
            int start;
216
            int end;
217
            int step;
218
            int direction;
219

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

227
                pos = y * context->width + x;
×
228
                for (d = 0; d < context->depth; ++d) {
×
229
                    float val;
230

231
                    val = context->pixels_float[pos * context->depth + d]
×
232
                        + f_mask(x, y, d) * jitter_scale;
×
233
                    context->scratch[d] =
×
234
                        sixel_dither_float_channel_to_byte(val);
×
235
                }
236
                context->result[pos] = context->lookup(context->scratch,
×
237
                                                       context->depth,
238
                                                       context->palette,
×
239
                                                       context->reqcolor,
240
                                                       context->indextable,
241
                                                       context->complexion);
242
            }
243
            sixel_dither_pipeline_row_notify(dither, y);
×
244
        }
245
        *context->ncolors = context->reqcolor;
×
246
    }
247

248
    return SIXEL_OK;
×
249
}
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