• 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-pattern.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 <string.h>
26

27
#include "dither-pattern.h"
28
#include "dither-common-pipeline.h"
29

30
/*
31
 * Helper configuring serpentine row traversal.  Keeping the helper local to
32
 * this translation unit avoids coupling pattern dithering to other
33
 * implementations while still documenting the walk order.
34
 */
35
static void
NEW
36
sixel_dither_scanline_params(int serpentine,
×
37
                             int index,
38
                             int limit,
39
                             int *start,
40
                             int *end,
41
                             int *step,
42
                             int *direction)
43
{
NEW
44
    if (serpentine && (index & 1)) {
×
NEW
45
        *start = limit - 1;
×
NEW
46
        *end = -1;
×
NEW
47
        *step = -1;
×
NEW
48
        *direction = -1;
×
49
    } else {
NEW
50
        *start = 0;
×
NEW
51
        *end = limit;
×
NEW
52
        *step = 1;
×
NEW
53
        *direction = 1;
×
54
    }
NEW
55
}
×
56

57
static float mask_a(int x, int y, int c);
58
static float mask_x(int x, int y, int c);
59

60
/*
61
 * Procedural masks used by ordered/pattern dithering.  Each channel uses a
62
 * unique scramble to avoid repeating patterns when walking serpentine rows.
63
 */
64
static float
NEW
65
mask_a(int x, int y, int c)
×
66
{
NEW
67
    return ((((x + c * 67) + y * 236) * 119) & 255) / 128.0f - 1.0f;
×
68
}
69

70
static float
NEW
71
mask_x(int x, int y, int c)
×
72
{
NEW
73
    return ((((x + c * 29) ^ (y * 149)) * 1234) & 511) / 256.0f - 1.0f;
×
74
}
75

76
SIXELSTATUS
NEW
77
sixel_dither_apply_positional(sixel_index_t *result,
×
78
                              unsigned char *data,
79
                              int width,
80
                              int height,
81
                              int depth,
82
                              unsigned char *palette,
83
                              int reqcolor,
84
                              int method_for_diffuse,
85
                              int method_for_scan,
86
                              int optimize_palette,
87
                              int (*f_lookup)(const unsigned char *pixel,
88
                                              int depth,
89
                                              const unsigned char *palette,
90
                                              int reqcolor,
91
                                              unsigned short *cachetable,
92
                                              int complexion),
93
                              unsigned short *indextable,
94
                              int complexion,
95
                              unsigned char copy[],
96
                              unsigned char new_palette[],
97
                              unsigned short migration_map[],
98
                              int *ncolors,
99
                              sixel_dither_t *dither)
100
{
101
    int serpentine;
102
    int y;
103
    float (*f_mask)(int x, int y, int c);
104

NEW
105
    switch (method_for_diffuse) {
×
106
    case SIXEL_DIFFUSE_A_DITHER:
NEW
107
        f_mask = mask_a;
×
NEW
108
        break;
×
NEW
109
    case SIXEL_DIFFUSE_X_DITHER:
×
110
    default:
NEW
111
        f_mask = mask_x;
×
NEW
112
        break;
×
113
    }
114

NEW
115
    serpentine = (method_for_scan == SIXEL_SCAN_SERPENTINE);
×
116

NEW
117
    if (optimize_palette) {
×
118
        int x;
119

NEW
120
        *ncolors = 0;
×
NEW
121
        memset(new_palette, 0x00,
×
122
               (size_t)SIXEL_PALETTE_MAX * (size_t)depth);
NEW
123
        memset(migration_map, 0x00,
×
124
               sizeof(unsigned short) * (size_t)SIXEL_PALETTE_MAX);
NEW
125
        for (y = 0; y < height; ++y) {
×
126
            int start;
127
            int end;
128
            int step;
129
            int direction;
130

NEW
131
            sixel_dither_scanline_params(serpentine, y, width,
×
132
                                         &start, &end, &step, &direction);
133
            (void)direction;
NEW
134
            for (x = start; x != end; x += step) {
×
135
                int pos;
136
                int d;
137
                int color_index;
138

NEW
139
                pos = y * width + x;
×
NEW
140
                for (d = 0; d < depth; ++d) {
×
141
                    int val;
142

NEW
143
                    val = data[pos * depth + d]
×
NEW
144
                        + (int)(f_mask(x, y, d) * 32.0f);
×
NEW
145
                    copy[d] = val < 0 ? 0
×
NEW
146
                               : val > 255 ? 255 : val;
×
147
                }
NEW
148
                color_index = f_lookup(copy, depth, palette,
×
149
                                       reqcolor, indextable,
150
                                       complexion);
NEW
151
                if (migration_map[color_index] == 0) {
×
NEW
152
                    result[pos] = *ncolors;
×
NEW
153
                    for (d = 0; d < depth; ++d) {
×
NEW
154
                        new_palette[*ncolors * depth + d]
×
NEW
155
                            = palette[color_index * depth + d];
×
156
                    }
NEW
157
                    ++*ncolors;
×
NEW
158
                    migration_map[color_index] = *ncolors;
×
159
                } else {
NEW
160
                    result[pos] = migration_map[color_index] - 1;
×
161
                }
162
            }
NEW
163
            sixel_dither_pipeline_row_notify(dither, y);
×
164
        }
NEW
165
        memcpy(palette, new_palette, (size_t)(*ncolors * depth));
×
166
    } else {
167
        int x;
168

NEW
169
        for (y = 0; y < height; ++y) {
×
170
            int start;
171
            int end;
172
            int step;
173
            int direction;
174

NEW
175
            sixel_dither_scanline_params(serpentine, y, width,
×
176
                                         &start, &end, &step, &direction);
177
            (void)direction;
NEW
178
            for (x = start; x != end; x += step) {
×
179
                int pos;
180
                int d;
181

NEW
182
                pos = y * width + x;
×
NEW
183
                for (d = 0; d < depth; ++d) {
×
184
                    int val;
185

NEW
186
                    val = data[pos * depth + d]
×
NEW
187
                        + (int)(f_mask(x, y, d) * 32.0f);
×
NEW
188
                    copy[d] = val < 0 ? 0
×
NEW
189
                               : val > 255 ? 255 : val;
×
190
                }
NEW
191
                result[pos] = f_lookup(copy, depth, palette,
×
192
                                       reqcolor, indextable,
193
                                       complexion);
194
            }
NEW
195
            sixel_dither_pipeline_row_notify(dither, y);
×
196
        }
NEW
197
        *ncolors = reqcolor;
×
198
    }
199

NEW
200
    return SIXEL_OK;
×
201
}
202

203
/* emacs Local Variables:      */
204
/* emacs mode: c               */
205
/* emacs tab-width: 4          */
206
/* emacs indent-tabs-mode: nil */
207
/* emacs c-basic-offset: 4     */
208
/* emacs End:                  */
209
/* vim: set expandtab ts=4 sts=4 sw=4 : */
210
/* 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