Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/sdeparam.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 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
/* DCTEncode filter parameter setting and reading */
18
#include "memory_.h"
19
#include "jpeglib_.h"
20
#include "gserrors.h"
21
#include "gstypes.h"
22
#include "gsmemory.h"
23
#include "gsparam.h"
24
#include "strimpl.h"    /* sdct.h requires this */
25
#include "sdct.h"
26
#include "sdcparam.h"
27
#include "sjpeg.h"
28
29
/* Define a structure for the DCTEncode scalar parameters. */
30
typedef struct dcte_scalars_s {
31
    int Columns;
32
    int Rows;
33
    int Colors;
34
    gs_param_string Markers;
35
    bool NoMarker;
36
    int Resync;
37
    int Blend;
38
} dcte_scalars_t;
39
static const dcte_scalars_t dcte_scalars_default =
40
{
41
    0, 0, -1,
42
    {0, 0}, 0 /*false */ , 0, 0
43
};
44
static const gs_param_item_t s_DCTE_param_items[] =
45
{
46
#define dctp(key, type, memb) { key, type, offset_of(dcte_scalars_t, memb) }
47
    dctp("Columns", gs_param_type_int, Columns),
48
    dctp("Rows", gs_param_type_int, Rows),
49
    dctp("Colors", gs_param_type_int, Colors),
50
    dctp("Marker", gs_param_type_string, Markers),
51
    dctp("NoMarker", gs_param_type_bool, NoMarker),
52
    dctp("Resync", gs_param_type_int, Resync),
53
    dctp("Blend", gs_param_type_int, Blend),
54
#undef dctp
55
    gs_param_item_end
56
};
57
58
/* ================ Get parameters ================ */
59
60
stream_state_proc_get_params(s_DCTE_get_params, stream_DCT_state);  /* check */
61
62
/* Get a set of sampling values. */
63
static int
64
dcte_get_samples(gs_param_list * plist, gs_param_name key, int num_colors,
65
 const jpeg_compress_data * jcdp, gs_memory_t * mem, bool is_vert, bool all)
66
0
{
67
0
    const jpeg_component_info *comp_info = jcdp->cinfo.comp_info;
68
0
    int samples[4];
69
0
    bool write = all;
70
0
    int i;
71
72
0
    for (i = 0; i < num_colors; ++i)
73
0
        write |= (samples[i] = (is_vert ? comp_info[i].v_samp_factor :
74
0
                                comp_info[i].h_samp_factor)) != 1;
75
0
    if (write) {
76
0
        int *data = (int *)gs_alloc_byte_array(mem, num_colors, sizeof(int),
77
0
                                               "dcte_get_samples");
78
0
        gs_param_int_array sa;
79
80
0
        if (data == 0)
81
0
            return_error(gs_error_VMerror);
82
0
        sa.data = data;
83
0
        sa.size = num_colors;
84
0
        sa.persistent = true;
85
0
        memcpy(data, samples, num_colors * sizeof(samples[0]));
86
0
        return param_write_int_array(plist, key, &sa);
87
0
    }
88
0
    return 0;
89
0
}
90
91
int
92
s_DCTE_get_params(gs_param_list * plist, const stream_DCT_state * ss, bool all)
93
0
{
94
0
    gs_memory_t *mem = ss->memory;
95
0
    stream_DCT_state dcts_defaults;
96
0
    const stream_DCT_state *defaults = 0;
97
0
    dcte_scalars_t params;
98
0
    const jpeg_compress_data *jcdp = ss->data.compress;
99
0
    int code;
100
101
0
    if (!all) {
102
0
        jpeg_compress_data *jcdp_default = gs_alloc_struct_immovable(mem,
103
0
           jpeg_compress_data, &st_jpeg_compress_data, "s_DCTE_get_params");
104
0
        if (jcdp_default == 0)
105
0
            return_error(gs_error_VMerror);
106
0
        defaults = &dcts_defaults;
107
0
        (*s_DCTE_template.set_defaults) ((stream_state *) & dcts_defaults);
108
0
        dcts_defaults.data.compress = jcdp_default;
109
0
        jcdp_default->memory = dcts_defaults.jpeg_memory = mem;
110
0
        if ((code = gs_jpeg_create_compress(&dcts_defaults)) < 0)
111
0
            goto fail;   /* correct to do jpeg_destroy here */
112
/****** SET DEFAULTS HERE ******/
113
0
        dcts_defaults.data.common->Picky = 0;
114
0
        dcts_defaults.data.common->Relax = 0;
115
0
    }
116
0
    params.Columns = jcdp->cinfo.image_width;
117
0
    params.Rows = jcdp->cinfo.image_height;
118
0
    params.Colors = jcdp->cinfo.input_components;
119
0
    params.Markers.data = ss->Markers.data;
120
0
    params.Markers.size = ss->Markers.size;
121
0
    params.Markers.persistent = false;
122
0
    params.NoMarker = ss->NoMarker;
123
0
    params.Resync = jcdp->cinfo.restart_interval;
124
    /* What about Blend?? */
125
0
    if ((code = s_DCT_get_params(plist, ss, defaults)) < 0 ||
126
0
        (code = gs_param_write_items(plist, &params,
127
0
                                     &dcte_scalars_default,
128
0
                                     s_DCTE_param_items)) < 0 ||
129
0
        (code = dcte_get_samples(plist, "HSamples", params.Colors,
130
0
                                 jcdp, mem, false, all)) < 0 ||
131
0
        (code = dcte_get_samples(plist, "VSamples", params.Colors,
132
0
                                 jcdp, mem, true, all)) < 0 ||
133
0
    (code = s_DCT_get_quantization_tables(plist, ss, defaults, true)) < 0 ||
134
0
        (code = s_DCT_get_huffman_tables(plist, ss, defaults, true)) < 0
135
0
        )
136
0
        DO_NOTHING;
137
/****** NYI ******/
138
0
  fail:if (defaults) {
139
0
        gs_jpeg_destroy(&dcts_defaults);
140
0
        gs_free_object(mem, dcts_defaults.data.compress,
141
0
                       "s_DCTE_get_params");
142
0
    }
143
0
    return code;
144
0
}
145
146
/* ================ Put parameters ================ */
147
148
stream_state_proc_put_params(s_DCTE_put_params, stream_DCT_state);  /* check */
149
150
/* Put a set of sampling values. */
151
static int
152
dcte_put_samples(gs_param_list * plist, gs_param_name key, int num_colors,
153
                 jpeg_compress_data * jcdp, bool is_vert)
154
12.3k
{
155
12.3k
    int code;
156
12.3k
    int i;
157
12.3k
    jpeg_component_info *comp_info = jcdp->cinfo.comp_info;
158
12.3k
    UINT8 samples[4];
159
160
    /*
161
     * Adobe default is all sampling factors = 1,
162
     * which is NOT the IJG default, so we must always assign values.
163
     */
164
12.3k
    switch ((code = s_DCT_byte_params(plist, key, 0, num_colors,
165
12.3k
                                      samples))
166
12.3k
        ) {
167
0
        default:    /* error */
168
0
            return code;
169
12.3k
        case 0:
170
12.3k
            break;
171
0
        case 1:
172
0
            samples[0] = samples[1] = samples[2] = samples[3] = 1;
173
12.3k
    }
174
37.1k
    for (i = 0; i < num_colors; i++) {
175
24.8k
        if (samples[i] < 1 || samples[i] > 4)
176
0
            return_error(gs_error_rangecheck);
177
24.8k
        if (is_vert)
178
12.4k
            comp_info[i].v_samp_factor = samples[i];
179
12.4k
        else
180
12.4k
            comp_info[i].h_samp_factor = samples[i];
181
24.8k
    }
182
12.3k
    return 0;
183
12.3k
}
184
185
/* Main procedure */
186
int
187
s_DCTE_put_params(gs_param_list * plist, stream_DCT_state * pdct)
188
6.15k
{
189
6.15k
    jpeg_compress_data *jcdp = pdct->data.compress;
190
6.15k
    dcte_scalars_t params;
191
6.15k
    int i;
192
6.15k
    int code;
193
194
6.15k
    params = dcte_scalars_default;
195
    /*
196
     * Required parameters for DCTEncode.
197
     * (DCTDecode gets the equivalent info from the SOF marker.)
198
     */
199
6.15k
    code = gs_param_read_items(plist, &params, s_DCTE_param_items, NULL);
200
6.15k
    if (code < 0)
201
0
        return code;
202
6.15k
    if (params.Columns <= 0 || params.Columns > 0xffff ||
203
6.15k
        params.Rows <= 0 || params.Rows > 0xffff ||
204
6.15k
        params.Colors <= 0 || params.Colors == 2 || params.Colors > 4 ||
205
6.15k
        params.Resync < 0 || params.Resync > 0xffff ||
206
6.15k
        params.Blend < 0 || params.Blend > 1
207
6.15k
        )
208
0
        return_error(gs_error_rangecheck);
209
6.15k
    jcdp->Picky = 0;
210
6.15k
    jcdp->Relax = 0;
211
6.15k
    if ((code = s_DCT_put_params(plist, pdct)) < 0)
212
0
        return code;
213
    /* Set up minimal image description & call set_defaults */
214
6.15k
    jcdp->cinfo.image_width = params.Columns;
215
6.15k
    jcdp->cinfo.image_height = params.Rows;
216
6.15k
    jcdp->cinfo.input_components = params.Colors;
217
6.15k
    switch (params.Colors) {
218
3.01k
        case 1:
219
3.01k
            jcdp->cinfo.in_color_space = JCS_GRAYSCALE;
220
3.01k
            break;
221
3.13k
        case 3:
222
3.13k
            jcdp->cinfo.in_color_space = JCS_RGB;
223
3.13k
            break;
224
0
        case 4:
225
0
            jcdp->cinfo.in_color_space = JCS_CMYK;
226
0
            break;
227
0
        default:
228
0
            jcdp->cinfo.in_color_space = JCS_UNKNOWN;
229
6.15k
    }
230
6.15k
    if ((code = gs_jpeg_set_defaults(pdct)) < 0)
231
0
        return code;
232
6.15k
    if ((code = s_DCT_put_huffman_tables(plist, pdct, true)) < 0)
233
0
        return code;
234
6.15k
    switch ((code = s_DCT_put_quantization_tables(plist, pdct, true))) {
235
0
        case 0:
236
0
            break;
237
0
        default:
238
0
            return code;
239
6.15k
        case 1:
240
            /* No QuantTables, but maybe a QFactor to apply to default. */
241
6.15k
            code = gs_jpeg_set_linear_quality(pdct,
242
6.15k
                                         (int)(min(pdct->QFactor, 100.0)
243
6.15k
                                               * 100.0 + 0.5),
244
6.15k
                                              TRUE);
245
6.15k
            if (code < 0)
246
0
                return code;
247
6.15k
    }
248
    /* Change IJG colorspace defaults as needed;
249
     * set ColorTransform to what will go in the Adobe marker.
250
     */
251
6.15k
    switch (params.Colors) {
252
3.13k
        case 3:
253
3.13k
            if (pdct->ColorTransform < 0)
254
0
                pdct->ColorTransform = 1; /* default */
255
3.13k
            if (pdct->ColorTransform == 0) {
256
0
                if ((code = gs_jpeg_set_colorspace(pdct, JCS_RGB)) < 0)
257
0
                    return code;
258
0
            } else
259
3.13k
                pdct->ColorTransform = 1; /* flag YCC xform */
260
3.13k
            break;
261
3.13k
        case 4:
262
0
            if (pdct->ColorTransform < 0)
263
0
                pdct->ColorTransform = 0; /* default */
264
0
            if (pdct->ColorTransform != 0) {
265
0
                if ((code = gs_jpeg_set_colorspace(pdct, JCS_YCCK)) < 0)
266
0
                    return code;
267
0
                pdct->ColorTransform = 2; /* flag YCCK xform */
268
0
            } else {
269
0
                if ((code = gs_jpeg_set_colorspace(pdct, JCS_CMYK)) < 0)
270
0
                    return code;
271
0
            }
272
0
            break;
273
3.01k
        default:
274
3.01k
            pdct->ColorTransform = 0; /* no transform otherwise */
275
3.01k
            break;
276
6.15k
    }
277
    /* Optional encoding-only parameters */
278
    /* FIXME: This relies on the 'Markers' value in the param list
279
     * being persistent enough. */
280
6.15k
    pdct->Markers.data = params.Markers.data;
281
6.15k
    pdct->Markers.size = params.Markers.size;
282
6.15k
    pdct->NoMarker = params.NoMarker;
283
6.15k
    if ((code = dcte_put_samples(plist, "HSamples", params.Colors,
284
6.15k
                                 jcdp, false)) < 0 ||
285
6.15k
        (code = dcte_put_samples(plist, "VSamples", params.Colors,
286
6.15k
                                 jcdp, true)) < 0
287
6.15k
        )
288
0
        return code;
289
6.15k
    jcdp->cinfo.write_JFIF_header = FALSE;
290
6.15k
    jcdp->cinfo.write_Adobe_marker = FALSE; /* must do it myself */
291
6.15k
    jcdp->cinfo.restart_interval = params.Resync;
292
    /* What to do with Blend ??? */
293
6.15k
    if (pdct->data.common->Relax == 0) {
294
6.15k
        jpeg_component_info *comp_info = jcdp->cinfo.comp_info;
295
6.15k
        int num_samples;
296
297
18.5k
        for (i = 0, num_samples = 0; i < params.Colors; i++)
298
12.4k
            num_samples += comp_info[i].h_samp_factor *
299
12.4k
                comp_info[i].v_samp_factor;
300
6.15k
        if (num_samples > 10)
301
0
            return_error(gs_error_rangecheck);
302
        /*
303
         * Note: by default the IJG software does not allow
304
         * num_samples to exceed 10, Relax or no.  For full
305
         * compatibility with Adobe's non-JPEG-compliant
306
         * software, set MAX_BLOCKS_IN_MCU to 64 in jpeglib.h.
307
         */
308
6.15k
    }
309
6.15k
    return 0;
310
6.15k
}