1 /* Copyright (C) 2001-2012 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., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, 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
dcte_get_samples(gs_param_list * plist,gs_param_name key,int num_colors,const jpeg_compress_data * jcdp,gs_memory_t * mem,bool is_vert,bool all)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 {
67 const jpeg_component_info *comp_info = jcdp->cinfo.comp_info;
68 int samples[4];
69 bool write = all;
70 int i;
71
72 for (i = 0; i < num_colors; ++i)
73 write |= (samples[i] = (is_vert ? comp_info[i].v_samp_factor :
74 comp_info[i].h_samp_factor)) != 1;
75 if (write) {
76 int *data = (int *)gs_alloc_byte_array(mem, num_colors, sizeof(int),
77 "dcte_get_samples");
78 gs_param_int_array sa;
79
80 if (data == 0)
81 return_error(gs_error_VMerror);
82 sa.data = data;
83 sa.size = num_colors;
84 sa.persistent = true;
85 memcpy(data, samples, num_colors * sizeof(samples[0]));
86 return param_write_int_array(plist, key, &sa);
87 }
88 return 0;
89 }
90
91 int
s_DCTE_get_params(gs_param_list * plist,const stream_DCT_state * ss,bool all)92 s_DCTE_get_params(gs_param_list * plist, const stream_DCT_state * ss, bool all)
93 {
94 gs_memory_t *mem = ss->memory;
95 stream_DCT_state dcts_defaults;
96 const stream_DCT_state *defaults = 0;
97 dcte_scalars_t params;
98 const jpeg_compress_data *jcdp = ss->data.compress;
99 int code;
100
101 if (!all) {
102 jpeg_compress_data *jcdp_default = gs_alloc_struct_immovable(mem,
103 jpeg_compress_data, &st_jpeg_compress_data, "s_DCTE_get_params");
104 if (jcdp_default == 0)
105 return_error(gs_error_VMerror);
106 defaults = &dcts_defaults;
107 (*s_DCTE_template.set_defaults) ((stream_state *) & dcts_defaults);
108 dcts_defaults.data.compress = jcdp_default;
109 jcdp_default->memory = dcts_defaults.jpeg_memory = mem;
110 if ((code = gs_jpeg_create_compress(&dcts_defaults)) < 0)
111 goto fail; /* correct to do jpeg_destroy here */
112 /****** SET DEFAULTS HERE ******/
113 dcts_defaults.data.common->Picky = 0;
114 dcts_defaults.data.common->Relax = 0;
115 }
116 params.Columns = jcdp->cinfo.image_width;
117 params.Rows = jcdp->cinfo.image_height;
118 params.Colors = jcdp->cinfo.input_components;
119 params.Markers.data = ss->Markers.data;
120 params.Markers.size = ss->Markers.size;
121 params.Markers.persistent = false;
122 params.NoMarker = ss->NoMarker;
123 params.Resync = jcdp->cinfo.restart_interval;
124 /* What about Blend?? */
125 if ((code = s_DCT_get_params(plist, ss, defaults)) < 0 ||
126 (code = gs_param_write_items(plist, ¶ms,
127 &dcte_scalars_default,
128 s_DCTE_param_items)) < 0 ||
129 (code = dcte_get_samples(plist, "HSamples", params.Colors,
130 jcdp, mem, false, all)) < 0 ||
131 (code = dcte_get_samples(plist, "VSamples", params.Colors,
132 jcdp, mem, true, all)) < 0 ||
133 (code = s_DCT_get_quantization_tables(plist, ss, defaults, true)) < 0 ||
134 (code = s_DCT_get_huffman_tables(plist, ss, defaults, true)) < 0
135 )
136 DO_NOTHING;
137 /****** NYI ******/
138 fail:if (defaults) {
139 gs_jpeg_destroy(&dcts_defaults);
140 gs_free_object(mem, dcts_defaults.data.compress,
141 "s_DCTE_get_params");
142 }
143 return code;
144 }
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
dcte_put_samples(gs_param_list * plist,gs_param_name key,int num_colors,jpeg_compress_data * jcdp,bool is_vert)152 dcte_put_samples(gs_param_list * plist, gs_param_name key, int num_colors,
153 jpeg_compress_data * jcdp, bool is_vert)
154 {
155 int code;
156 int i;
157 jpeg_component_info *comp_info = jcdp->cinfo.comp_info;
158 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 switch ((code = s_DCT_byte_params(plist, key, 0, num_colors,
165 samples))
166 ) {
167 default: /* error */
168 return code;
169 case 0:
170 break;
171 case 1:
172 samples[0] = samples[1] = samples[2] = samples[3] = 1;
173 }
174 for (i = 0; i < num_colors; i++) {
175 if (samples[i] < 1 || samples[i] > 4)
176 return_error(gs_error_rangecheck);
177 if (is_vert)
178 comp_info[i].v_samp_factor = samples[i];
179 else
180 comp_info[i].h_samp_factor = samples[i];
181 }
182 return 0;
183 }
184
185 /* Main procedure */
186 int
s_DCTE_put_params(gs_param_list * plist,stream_DCT_state * pdct)187 s_DCTE_put_params(gs_param_list * plist, stream_DCT_state * pdct)
188 {
189 jpeg_compress_data *jcdp = pdct->data.compress;
190 dcte_scalars_t params;
191 int i;
192 int code;
193
194 params = dcte_scalars_default;
195 /*
196 * Required parameters for DCTEncode.
197 * (DCTDecode gets the equivalent info from the SOF marker.)
198 */
199 code = gs_param_read_items(plist, ¶ms, s_DCTE_param_items);
200 if (code < 0)
201 return code;
202 if (params.Columns <= 0 || params.Columns > 0xffff ||
203 params.Rows <= 0 || params.Rows > 0xffff ||
204 params.Colors <= 0 || params.Colors == 2 || params.Colors > 4 ||
205 params.Resync < 0 || params.Resync > 0xffff ||
206 params.Blend < 0 || params.Blend > 1
207 )
208 return_error(gs_error_rangecheck);
209 jcdp->Picky = 0;
210 jcdp->Relax = 0;
211 if ((code = s_DCT_put_params(plist, pdct)) < 0)
212 return code;
213 /* Set up minimal image description & call set_defaults */
214 jcdp->cinfo.image_width = params.Columns;
215 jcdp->cinfo.image_height = params.Rows;
216 jcdp->cinfo.input_components = params.Colors;
217 switch (params.Colors) {
218 case 1:
219 jcdp->cinfo.in_color_space = JCS_GRAYSCALE;
220 break;
221 case 3:
222 jcdp->cinfo.in_color_space = JCS_RGB;
223 break;
224 case 4:
225 jcdp->cinfo.in_color_space = JCS_CMYK;
226 break;
227 default:
228 jcdp->cinfo.in_color_space = JCS_UNKNOWN;
229 }
230 if ((code = gs_jpeg_set_defaults(pdct)) < 0)
231 return code;
232 if ((code = s_DCT_put_huffman_tables(plist, pdct, true)) < 0)
233 return code;
234 switch ((code = s_DCT_put_quantization_tables(plist, pdct, true))) {
235 case 0:
236 break;
237 default:
238 return code;
239 case 1:
240 /* No QuantTables, but maybe a QFactor to apply to default. */
241 if (pdct->QFactor != 1.0) {
242 code = gs_jpeg_set_linear_quality(pdct,
243 (int)(min(pdct->QFactor, 100.0)
244 * 100.0 + 0.5),
245 TRUE);
246 if (code < 0)
247 return code;
248 }
249 }
250 /* Change IJG colorspace defaults as needed;
251 * set ColorTransform to what will go in the Adobe marker.
252 */
253 switch (params.Colors) {
254 case 3:
255 if (pdct->ColorTransform < 0)
256 pdct->ColorTransform = 1; /* default */
257 if (pdct->ColorTransform == 0) {
258 if ((code = gs_jpeg_set_colorspace(pdct, JCS_RGB)) < 0)
259 return code;
260 } else
261 pdct->ColorTransform = 1; /* flag YCC xform */
262 break;
263 case 4:
264 if (pdct->ColorTransform < 0)
265 pdct->ColorTransform = 0; /* default */
266 if (pdct->ColorTransform != 0) {
267 if ((code = gs_jpeg_set_colorspace(pdct, JCS_YCCK)) < 0)
268 return code;
269 pdct->ColorTransform = 2; /* flag YCCK xform */
270 } else {
271 if ((code = gs_jpeg_set_colorspace(pdct, JCS_CMYK)) < 0)
272 return code;
273 }
274 break;
275 default:
276 pdct->ColorTransform = 0; /* no transform otherwise */
277 break;
278 }
279 /* Optional encoding-only parameters */
280 pdct->Markers.data = params.Markers.data;
281 pdct->Markers.size = params.Markers.size;
282 pdct->NoMarker = params.NoMarker;
283 if ((code = dcte_put_samples(plist, "HSamples", params.Colors,
284 jcdp, false)) < 0 ||
285 (code = dcte_put_samples(plist, "VSamples", params.Colors,
286 jcdp, true)) < 0
287 )
288 return code;
289 jcdp->cinfo.write_JFIF_header = FALSE;
290 jcdp->cinfo.write_Adobe_marker = FALSE; /* must do it myself */
291 jcdp->cinfo.restart_interval = params.Resync;
292 /* What to do with Blend ??? */
293 if (pdct->data.common->Relax == 0) {
294 jpeg_component_info *comp_info = jcdp->cinfo.comp_info;
295 int num_samples;
296
297 for (i = 0, num_samples = 0; i < params.Colors; i++)
298 num_samples += comp_info[i].h_samp_factor *
299 comp_info[i].v_samp_factor;
300 if (num_samples > 10)
301 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 }
309 return 0;
310 }
311