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, &params,
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, &params, 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