Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gxdevndi.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
#include "gx.h"
18
#include "gsstruct.h"
19
#include "gsdcolor.h"
20
#include "gxdevice.h"
21
#include "gxlum.h"
22
#include "gxcmap.h"
23
#include "gxdither.h"
24
#include "gzht.h"
25
#include "gxfrac.h"
26
27
/*
28
 * Binary halftoning algorithms.
29
 *
30
 * The procedures in this file use halftoning (if necessary)
31
 * to implement a given device color that has already gone through
32
 * the transfer function.  There are two major cases: gray and color.
33
 * Gray halftoning always uses a binary screen.  Color halftoning
34
 * uses either a fast algorithm with a binary screen that produces
35
 * relatively poor approximations, or a very slow algorithm with a
36
 * general colored screen (or screens) that faithfully implements
37
 * the Adobe specifications.
38
 */
39
40
/* Tables for fast computation of fractional color levels. */
41
/* We have to put the table before any uses of it because of a bug */
42
/* in the VAX C compiler. */
43
/* We have to split up the definition of the table itself because of a bug */
44
/*  in the IBM AIX 3.2 C compiler. */
45
static const gx_color_value q0[] = {
46
    0
47
};
48
static const gx_color_value q1[] = {
49
    0, frac_color_(1, 1)
50
};
51
static const gx_color_value q2[] = {
52
    0, frac_color_(1, 2), frac_color_(2, 2)
53
};
54
static const gx_color_value q3[] = {
55
    0, frac_color_(1, 3), frac_color_(2, 3), frac_color_(3, 3)
56
};
57
static const gx_color_value q4[] = {
58
    0, frac_color_(1, 4), frac_color_(2, 4), frac_color_(3, 4),
59
    frac_color_(4, 4)
60
};
61
static const gx_color_value q5[] = {
62
    0, frac_color_(1, 5), frac_color_(2, 5), frac_color_(3, 5),
63
    frac_color_(4, 5), frac_color_(5, 5)
64
};
65
static const gx_color_value q6[] = {
66
    0, frac_color_(1, 6), frac_color_(2, 6), frac_color_(3, 6),
67
    frac_color_(4, 6), frac_color_(5, 6), frac_color_(6, 6)
68
};
69
static const gx_color_value q7[] = {
70
    0, frac_color_(1, 7), frac_color_(2, 7), frac_color_(3, 7),
71
    frac_color_(4, 7), frac_color_(5, 7), frac_color_(6, 7), frac_color_(7, 7)
72
};
73
74
/* We export fc_color_quo for the fractional_color macro in gzht.h. */
75
const gx_color_value *const fc_color_quo[8] = {
76
    q0, q1, q2, q3, q4, q5, q6, q7
77
};
78
79
/*
80
 * Render DeviceN possibly by halftoning.
81
 *  pcolors = pointer to an array color values (as fracs)
82
 *  pdevc - pointer to device color structure
83
 *  dev = pointer to device data structure
84
 *  pht = pointer to halftone data structure
85
 *  ht_phase  = halftone phase
86
 *  gray_colorspace = true -> current color space is DeviceGray.
87
 *  This is part of a kludge to minimize differences in the
88
 *  regression testing.
89
 */
90
int
91
gx_render_device_DeviceN(frac * pcolor,
92
        gx_device_color * pdevc, gx_device * dev,
93
        gx_device_halftone * pdht, const gs_int_point * ht_phase)
94
319M
{
95
319M
    uint max_value[GS_CLIENT_COLOR_MAX_COMPONENTS];
96
319M
    frac dither_check = 0;
97
319M
    uint int_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
98
319M
    gx_color_value vcolor[GS_CLIENT_COLOR_MAX_COMPONENTS];
99
319M
    int i;
100
319M
    int num_colors = dev->color_info.num_components;
101
319M
    uint l_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
102
103
1.27G
    for (i=0; i<num_colors; i++) {
104
957M
        max_value[i] = (dev->color_info.gray_index == i) ?
105
67.2M
             dev->color_info.dither_grays - 1 :
106
957M
             dev->color_info.dither_colors - 1;
107
957M
    }
108
109
1.27G
    for (i = 0; i < num_colors; i++) {
110
957M
        unsigned long hsize = pdht && i <= pdht->num_comp ?
111
956M
                (unsigned) pdht->components[i].corder.num_levels
112
957M
                : 1;
113
957M
        unsigned long nshades = hsize * max_value[i] + 1;
114
957M
        long shade = pcolor[i] * nshades / (frac_1_long + 1);
115
957M
        int_color[i] = shade / hsize;
116
957M
        l_color[i] = shade % hsize;
117
957M
        if (max_value[i] < MIN_CONTONE_LEVELS)
118
957M
            dither_check |= l_color[i];
119
957M
    }
120
121
#ifdef DEBUG
122
    if (gs_debug_c('c')) {
123
        dmlprintf1(dev->memory, "[c]ncomp=%d ", num_colors);
124
        for (i = 0; i < num_colors; i++)
125
            dmlprintf1(dev->memory, "0x%x, ", pcolor[i]);
126
        dmlprintf(dev->memory, "-->   ");
127
        for (i = 0; i < num_colors; i++)
128
            dmlprintf2(dev->memory, "%x+0x%x, ", int_color[i], l_color[i]);
129
        dmlprintf(dev->memory, "\n");
130
    }
131
#endif
132
133
    /* Check for no dithering required */
134
319M
    if (!dither_check) {
135
567M
        for (i = 0; i < num_colors; i++)
136
429M
            vcolor[i] = fractional_color(int_color[i], max_value[i]);
137
137M
        color_set_pure(pdevc, dev_proc(dev, encode_color)(dev, vcolor));
138
137M
        return 0;
139
137M
    }
140
141
    /* Use the slow, general colored halftone algorithm. */
142
143
710M
    for (i = 0; i < num_colors; i++)
144
527M
        _color_set_c(pdevc, i, int_color[i], l_color[i]);
145
182M
    gx_complete_halftone(pdevc, num_colors, pdht);
146
147
182M
    if (pdht)
148
182M
        color_set_phase_mod(pdevc, ht_phase->x, ht_phase->y,
149
182M
                            pdht->lcm_width, pdht->lcm_height);
150
151
    /* Determine if we are using only one component */
152
182M
    if (!(pdevc->colors.colored.plane_mask &
153
182M
         (pdevc->colors.colored.plane_mask - 1))) {
154
        /* We can reduce this color to a binary halftone or pure color. */
155
44.9M
        return gx_devn_reduce_colored_halftone(pdevc, dev);
156
44.9M
    }
157
158
137M
    return 1;
159
182M
}
160
161
/* Reduce a colored halftone to a binary halftone or pure color. */
162
/* This routine is called when only one component is being halftoned. */
163
int
164
gx_devn_reduce_colored_halftone(gx_device_color *pdevc, gx_device *dev)
165
44.9M
{
166
44.9M
    int planes = pdevc->colors.colored.plane_mask;
167
44.9M
    int num_colors = dev->color_info.num_components;
168
44.9M
    uint max_value[GS_CLIENT_COLOR_MAX_COMPONENTS];
169
44.9M
    uint b[GX_DEVICE_COLOR_MAX_COMPONENTS];
170
44.9M
    gx_color_value v[GX_DEVICE_COLOR_MAX_COMPONENTS];
171
44.9M
    gx_color_index c0, c1;
172
44.9M
    int i;
173
174
145M
    for (i = 0; i < num_colors; i++) {
175
100M
        max_value[i] = (dev->color_info.gray_index == i) ?
176
25.4M
             dev->color_info.dither_grays - 1 :
177
100M
             dev->color_info.dither_colors - 1;
178
100M
        b[i] = pdevc->colors.colored.c_base[i];
179
100M
        v[i] = fractional_color(b[i], max_value[i]);
180
100M
    }
181
44.9M
    c0 = dev_proc(dev, encode_color)(dev, v);
182
183
44.9M
    if (planes == 0) {
184
        /*
185
         * Use a pure color.  This case is unlikely, but it can occur if
186
         * (and only if) the difference of each component from the nearest
187
         * device color is less than one halftone level.
188
         */
189
0
        color_set_pure(pdevc, c0);
190
0
        return 0;
191
44.9M
    } else {
192
        /* Use a binary color. */
193
44.9M
        int i = 0;
194
44.9M
        uint bi;
195
44.9M
        const gx_device_halftone *pdht = pdevc->colors.colored.c_ht;
196
        /*
197
         * NB: the halftone orders are all set up for an additive color
198
         *     space.  To use these work with a subtractive color space, it is
199
         *     necessary to invert both the color level and the color
200
         *     pair. Note that if the original color was provided an
201
         *     additive space, this will reverse (in an approximate sense)
202
         *     the color conversion performed to express the color in
203
         *     subtractive space.
204
         */
205
44.9M
        bool invert = dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE;
206
44.9M
        uint level;
207
208
        /* Convert plane mask bit position to component number */
209
        /* Determine i = log2(planes);  This works for powers of two */
210
45.7M
        while (planes > 7) {
211
815k
            i += 3;
212
815k
            planes >>= 3;
213
815k
        }
214
44.9M
        i += planes >> 1;  /* log2 for 1,2,4 */
215
216
44.9M
        bi = b[i] + 1;
217
44.9M
        v[i] = fractional_color(bi, max_value[i]);
218
44.9M
        level = pdevc->colors.colored.c_level[i];
219
44.9M
        c1 = dev_proc(dev, encode_color)(dev, v);
220
44.9M
        if (invert) {
221
5.48M
            level = pdht->components[i].corder.num_levels - level;
222
5.48M
            color_set_binary_halftone_component(pdevc, pdht, i, c1, c0, level);
223
5.48M
        } else
224
39.4M
            color_set_binary_halftone_component(pdevc, pdht, i, c0, c1, level);
225
226
44.9M
        return 1;
227
44.9M
    }
228
44.9M
}