1 /* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: sdcparam.c,v 1.6 2003/08/26 15:38:50 igor Exp $ */
18 /* DCT filter parameter setting and reading */
19 #include "memory_.h"
20 #include "jpeglib_.h"
21 #include "gserror.h"
22 #include "gserrors.h"
23 #include "gstypes.h"
24 #include "gsmemory.h"
25 #include "gsparam.h"
26 #include "strimpl.h" /* sdct.h requires this */
27 #include "sdct.h"
28 #include "sdcparam.h"
29 #include "sjpeg.h"
30
31 /* Define the DCT parameters. */
32 #define dctp(key, type, stype, memb) { key, type, offset_of(stype, memb) }
33 private const gs_param_item_t s_DCT_param_items[] =
34 {
35 dctp("ColorTransform", gs_param_type_int, stream_DCT_state, ColorTransform),
36 dctp("QFactor", gs_param_type_float, stream_DCT_state, QFactor),
37 gs_param_item_end
38 };
39 private const gs_param_item_t jsd_param_items[] =
40 {
41 dctp("Picky", gs_param_type_int, jpeg_stream_data, Picky),
42 dctp("Relax", gs_param_type_int, jpeg_stream_data, Relax),
43 gs_param_item_end
44 };
45
46 #undef dctp
47
48 /*
49 * Adobe specifies the values to be supplied in zigzag order.
50 * For IJG versions newer than v6, we need to convert this order
51 * to natural array order. Older IJG versions want zigzag order.
52 */
53 #if JPEG_LIB_VERSION >= 61
54 /* natural array position of n'th element of JPEG zigzag order */
55 static const byte natural_order[DCTSIZE2] =
56 {
57 0, 1, 8, 16, 9, 2, 3, 10,
58 17, 24, 32, 25, 18, 11, 4, 5,
59 12, 19, 26, 33, 40, 48, 41, 34,
60 27, 20, 13, 6, 7, 14, 21, 28,
61 35, 42, 49, 56, 57, 50, 43, 36,
62 29, 22, 15, 23, 30, 37, 44, 51,
63 58, 59, 52, 45, 38, 31, 39, 46,
64 53, 60, 61, 54, 47, 55, 62, 63
65 };
66
67 #define jpeg_order(x) natural_order[x]
68 /* invert natural_order for getting parameters */
69 static const byte inverse_natural_order[DCTSIZE2] =
70 {
71 0, 1, 5, 6, 14, 15, 27, 28,
72 2, 4, 7, 13, 16, 26, 29, 42,
73 3, 8, 12, 17, 25, 30, 41, 43,
74 9, 11, 18, 24, 31, 40, 44, 53,
75 10, 19, 23, 32, 39, 45, 52, 54,
76 20, 22, 33, 38, 46, 51, 55, 60,
77 21, 34, 37, 47, 50, 56, 59, 61,
78 35, 36, 48, 49, 57, 58, 62, 63
79 };
80
81 #define jpeg_inverse_order(x) inverse_natural_order[x]
82 #else
83 #define jpeg_order(x) (x)
84 #define jpeg_inverse_order(x) (x)
85 #endif
86
87 /* ================ Get parameters ================ */
88
89 private int
quant_param_string(gs_param_string * pstr,int count,const UINT16 * pvals,floatp QFactor,gs_memory_t * mem)90 quant_param_string(gs_param_string * pstr, int count, const UINT16 * pvals,
91 floatp QFactor, gs_memory_t * mem)
92 {
93 byte *data;
94 int code = 0;
95 int i;
96
97 data = gs_alloc_string(mem, count, "quant_param_string");
98 if (data == 0)
99 return_error(gs_error_VMerror);
100 for (i = 0; i < count; ++i) {
101 floatp val = pvals[jpeg_inverse_order(i)] / QFactor;
102
103 data[i] =
104 (val < 1 ? (code = 1) : val > 255 ? (code = 255) : (byte) val);
105 }
106 pstr->data = data;
107 pstr->size = count;
108 pstr->persistent = true;
109 return code & 1;
110 }
111
112 private int
quant_param_array(gs_param_float_array * pfa,int count,const UINT16 * pvals,floatp QFactor,gs_memory_t * mem)113 quant_param_array(gs_param_float_array * pfa, int count, const UINT16 * pvals,
114 floatp QFactor, gs_memory_t * mem)
115 {
116 float *data;
117 int i;
118
119 data = (float *)gs_alloc_byte_array(mem, count, sizeof(float),
120 "quant_param_array");
121
122 if (data == 0)
123 return_error(gs_error_VMerror);
124 for (i = 0; i < count; ++i)
125 data[i] = pvals[jpeg_inverse_order(i)] / QFactor;
126 pfa->data = data;
127 pfa->size = count;
128 pfa->persistent = true;
129 return 0;
130 }
131
132 int
s_DCT_get_quantization_tables(gs_param_list * plist,const stream_DCT_state * pdct,const stream_DCT_state * defaults,bool is_encode)133 s_DCT_get_quantization_tables(gs_param_list * plist,
134 const stream_DCT_state * pdct, const stream_DCT_state * defaults,
135 bool is_encode)
136 {
137 gs_memory_t *mem = pdct->memory;
138 jpeg_component_info d_comp_info[4];
139 int num_in_tables;
140 const jpeg_component_info *comp_info;
141 const jpeg_component_info *default_comp_info;
142 JQUANT_TBL **table_ptrs;
143 JQUANT_TBL **default_table_ptrs;
144 gs_param_array quant_tables;
145 floatp QFactor = pdct->QFactor;
146 int i;
147 int code;
148
149 if (is_encode) {
150 num_in_tables = pdct->data.compress->cinfo.num_components;
151 comp_info = pdct->data.compress->cinfo.comp_info;
152 table_ptrs = pdct->data.compress->cinfo.quant_tbl_ptrs;
153 if (defaults) {
154 default_comp_info = defaults->data.compress->cinfo.comp_info;
155 default_table_ptrs = defaults->data.compress->cinfo.quant_tbl_ptrs;
156 }
157 } else {
158 quant_tables.size = count_of(d_comp_info);
159 num_in_tables = quant_tables.size;
160 for (i = 0; i < num_in_tables; ++i)
161 d_comp_info[i].quant_tbl_no = i;
162 comp_info = d_comp_info;
163 table_ptrs = pdct->data.decompress->dinfo.quant_tbl_ptrs;
164 if (defaults) {
165 default_comp_info = d_comp_info;
166 default_table_ptrs =
167 defaults->data.decompress->dinfo.quant_tbl_ptrs;
168 }
169 }
170
171 /* Check whether all tables match defaults. */
172 if (defaults) {
173 bool match = true;
174
175 for (i = 0; i < num_in_tables; ++i) {
176 JQUANT_TBL *tbl = table_ptrs[comp_info[i].quant_tbl_no];
177 JQUANT_TBL *default_tbl =
178 (default_comp_info == 0 || default_table_ptrs == 0 ? 0 :
179 default_table_ptrs[default_comp_info[i].quant_tbl_no]);
180
181 if (tbl == default_tbl)
182 continue;
183 if (tbl == 0 || default_tbl == 0 ||
184 memcmp(tbl->quantval, default_tbl->quantval,
185 DCTSIZE2 * sizeof(UINT16))
186 ) {
187 match = false;
188 break;
189 }
190 }
191 if (match)
192 return 0;
193 }
194 quant_tables.size = num_in_tables;
195 code = param_begin_write_collection(plist, "QuantTables",
196 &quant_tables,
197 gs_param_collection_array);
198 if (code < 0)
199 return code;
200 for (i = 0; i < num_in_tables; ++i) {
201 char key[3];
202 gs_param_string str;
203 gs_param_float_array fa;
204
205 sprintf(key, "%d", i);
206 if (QFactor == 1.0) {
207 code = quant_param_string(&str, DCTSIZE2,
208 table_ptrs[comp_info[i].quant_tbl_no]->quantval,
209 QFactor, mem);
210 switch (code) {
211 case 0:
212 code = param_write_string(quant_tables.list, key, &str);
213 if (code < 0)
214 return code; /* should dealloc */
215 continue;
216 default:
217 return code; /* should dealloc */
218 case 1:
219 break;
220 }
221 /* break const to free the string */
222 gs_free_string(mem, (byte *) str.data, str.size,
223 "quant_param_string");
224 }
225 code = quant_param_array(&fa, DCTSIZE2,
226 table_ptrs[comp_info[i].quant_tbl_no]->quantval,
227 QFactor, mem);
228 if (code < 0)
229 return code; /* should dealloc */
230 code = param_write_float_array(quant_tables.list, key, &fa);
231 if (code < 0)
232 return code; /* should dealloc */
233 }
234 return param_end_write_dict(plist, "QuantTables", &quant_tables);
235 }
236
237 private int
pack_huff_table(gs_param_string * pstr,const JHUFF_TBL * table,gs_memory_t * mem)238 pack_huff_table(gs_param_string * pstr, const JHUFF_TBL * table,
239 gs_memory_t * mem)
240 {
241 int total;
242 int i;
243 byte *data;
244
245 for (i = 1, total = 0; i <= 16; ++i)
246 total += table->bits[i];
247 data = gs_alloc_string(mem, 16 + total, "pack_huff_table");
248 if (data == 0)
249 return_error(gs_error_VMerror);
250 memcpy(data, table->bits + 1, 16);
251 memcpy(data + 16, table->huffval, total);
252 pstr->data = data;
253 pstr->size = 16 + total;
254 pstr->persistent = true;
255 return 0;
256 }
257
258 int
s_DCT_get_huffman_tables(gs_param_list * plist,const stream_DCT_state * pdct,const stream_DCT_state * defaults,bool is_encode)259 s_DCT_get_huffman_tables(gs_param_list * plist,
260 const stream_DCT_state * pdct, const stream_DCT_state * defaults,
261 bool is_encode)
262 {
263 gs_memory_t *mem = pdct->memory;
264 gs_param_string *huff_data;
265 gs_param_string_array hta;
266 int num_in_tables;
267 jpeg_component_info *comp_info;
268 JHUFF_TBL **dc_table_ptrs;
269 JHUFF_TBL **ac_table_ptrs;
270 int i;
271 int code = 0;
272
273 if (is_encode) {
274 dc_table_ptrs = pdct->data.compress->cinfo.dc_huff_tbl_ptrs;
275 ac_table_ptrs = pdct->data.compress->cinfo.ac_huff_tbl_ptrs;
276 num_in_tables = pdct->data.compress->cinfo.input_components * 2;
277 comp_info = pdct->data.compress->cinfo.comp_info;
278 } else {
279 dc_table_ptrs = pdct->data.decompress->dinfo.dc_huff_tbl_ptrs;
280 ac_table_ptrs = pdct->data.decompress->dinfo.ac_huff_tbl_ptrs;
281 for (i = 2; i > 0; --i)
282 if (dc_table_ptrs[i - 1] || ac_table_ptrs[i - 1])
283 break;
284 num_in_tables = i * 2;
285 comp_info = NULL; /* do not set for decompress case */
286 }
287 /****** byte_array IS WRONG ******/
288 huff_data = (gs_param_string *)
289 gs_alloc_byte_array(mem, num_in_tables, sizeof(gs_param_string),
290 "get huffman tables");
291 if (huff_data == 0)
292 return_error(gs_error_VMerror);
293 for (i = 0; i < num_in_tables; i += 2) {
294 if ((code = pack_huff_table(huff_data + i, ac_table_ptrs[i >> 1], mem)) < 0 ||
295 (code = pack_huff_table(huff_data + i + 1, dc_table_ptrs[i >> 1], mem))
296 )
297 break;
298 }
299 if (code < 0)
300 return code;
301 hta.data = huff_data;
302 hta.size = num_in_tables;
303 hta.persistent = true;
304 return param_write_string_array(plist, "HuffTables", &hta);
305 }
306
307 int
s_DCT_get_params(gs_param_list * plist,const stream_DCT_state * ss,const stream_DCT_state * defaults)308 s_DCT_get_params(gs_param_list * plist, const stream_DCT_state * ss,
309 const stream_DCT_state * defaults)
310 {
311 int code =
312 gs_param_write_items(plist, ss, defaults, s_DCT_param_items);
313
314 if (code >= 0)
315 code = gs_param_write_items(plist, ss->data.common,
316 (defaults ? defaults->data.common :
317 NULL),
318 jsd_param_items);
319 return code;
320 }
321
322 /* ================ Put parameters ================ */
323
324 stream_state_proc_put_params(s_DCT_put_params, stream_DCT_state); /* check */
325
326 /* ---------------- Utilities ---------------- */
327
328 /*
329 * Get N byte-size values from an array or a string.
330 * Used for HuffTables, HSamples, VSamples.
331 */
332 int
s_DCT_byte_params(gs_param_list * plist,gs_param_name key,int start,int count,UINT8 * pvals)333 s_DCT_byte_params(gs_param_list * plist, gs_param_name key, int start,
334 int count, UINT8 * pvals)
335 {
336 int i;
337 gs_param_string bytes;
338 gs_param_float_array floats;
339 int code = param_read_string(plist, key, &bytes);
340
341 switch (code) {
342 case 0:
343 if (bytes.size < start + count) {
344 code = gs_note_error(gs_error_rangecheck);
345 break;
346 }
347 for (i = 0; i < count; ++i)
348 pvals[i] = (UINT8) bytes.data[start + i];
349 return 0;
350 default: /* might be a float array */
351 code = param_read_float_array(plist, key, &floats);
352 if (!code) {
353 if (floats.size < start + count) {
354 code = gs_note_error(gs_error_rangecheck);
355 break;
356 }
357 for (i = 0; i < count; ++i) {
358 float v = floats.data[start + i];
359
360 if (v < 0 || v > 255) {
361 code = gs_note_error(gs_error_rangecheck);
362 break;
363 }
364 pvals[i] = (UINT8) (v + 0.5);
365 }
366 }
367 }
368 if (code < 0)
369 param_signal_error(plist, key, code);
370 return code;
371 }
372
373 /* Get N quantization values from an array or a string. */
374 private int
quant_params(gs_param_list * plist,gs_param_name key,int count,UINT16 * pvals,floatp QFactor)375 quant_params(gs_param_list * plist, gs_param_name key, int count,
376 UINT16 * pvals, floatp QFactor)
377 {
378 int i;
379 gs_param_string bytes;
380 gs_param_float_array floats;
381 int code = param_read_string(plist, key, &bytes);
382
383 switch (code) {
384 case 0:
385 if (bytes.size != count) {
386 code = gs_note_error(gs_error_rangecheck);
387 break;
388 }
389 for (i = 0; i < count; ++i) {
390 double v = bytes.data[i] * QFactor;
391
392 pvals[jpeg_order(i)] =
393 (UINT16) (v < 1 ? 1 : v > 255 ? 255 : v + 0.5);
394 }
395 return 0;
396 default: /* might be a float array */
397 code = param_read_float_array(plist, key, &floats);
398 if (!code) {
399 if (floats.size != count) {
400 code = gs_note_error(gs_error_rangecheck);
401 break;
402 }
403 for (i = 0; i < count; ++i) {
404 double v = floats.data[i] * QFactor;
405
406 pvals[jpeg_order(i)] =
407 (UINT16) (v < 1 ? 1 : v > 255 ? 255 : v + 0.5);
408 }
409 }
410 }
411 if (code < 0)
412 param_signal_error(plist, key, code);
413 return code;
414 #undef jpeg_order
415 }
416
417 /* ---------------- Main procedures ---------------- */
418
419 /* Put common scalars. */
420 int
s_DCT_put_params(gs_param_list * plist,stream_DCT_state * pdct)421 s_DCT_put_params(gs_param_list * plist, stream_DCT_state * pdct)
422 {
423 int code =
424 gs_param_read_items(plist, pdct, s_DCT_param_items);
425
426 if (code < 0)
427 return code;
428 code = gs_param_read_items(plist, pdct->data.common, jsd_param_items);
429 if (code < 0)
430 return code;
431 if (pdct->data.common->Picky < 0 || pdct->data.common->Picky > 1 ||
432 pdct->data.common->Relax < 0 || pdct->data.common->Relax > 1 ||
433 pdct->ColorTransform < -1 || pdct->ColorTransform > 2 ||
434 pdct->QFactor < 0.0 || pdct->QFactor > 1000000.0
435 )
436 return_error(gs_error_rangecheck);
437 return 0;
438 }
439
440 /* Put quantization tables. */
441 int
s_DCT_put_quantization_tables(gs_param_list * plist,stream_DCT_state * pdct,bool is_encode)442 s_DCT_put_quantization_tables(gs_param_list * plist, stream_DCT_state * pdct,
443 bool is_encode)
444 {
445 int code;
446 int i, j;
447 gs_param_array quant_tables; /* array of strings/arrays */
448 int num_in_tables;
449 int num_out_tables;
450 jpeg_component_info *comp_info;
451 JQUANT_TBL **table_ptrs;
452 JQUANT_TBL *this_table;
453
454 switch ((code = param_begin_read_dict(plist, "QuantTables",
455 &quant_tables, true))
456 ) {
457 case 1:
458 return 1;
459 default:
460 return param_signal_error(plist, "QuantTables", code);
461 case 0:
462 ;
463 }
464 if (is_encode) {
465 num_in_tables = pdct->data.compress->cinfo.num_components;
466 if (quant_tables.size < num_in_tables)
467 return_error(gs_error_rangecheck);
468 comp_info = pdct->data.compress->cinfo.comp_info;
469 table_ptrs = pdct->data.compress->cinfo.quant_tbl_ptrs;
470 } else {
471 num_in_tables = quant_tables.size;
472 comp_info = NULL; /* do not set for decompress case */
473 table_ptrs = pdct->data.decompress->dinfo.quant_tbl_ptrs;
474 }
475 num_out_tables = 0;
476 for (i = 0; i < num_in_tables; ++i) {
477 char istr[5]; /* i converted to string key */
478 UINT16 values[DCTSIZE2];
479
480 sprintf(istr, "%d", i);
481 code = quant_params(quant_tables.list, istr, DCTSIZE2, values,
482 pdct->QFactor);
483 if (code < 0)
484 return code;
485 /* Check for duplicate tables. */
486 for (j = 0; j < num_out_tables; j++) {
487 if (!memcmp(table_ptrs[j]->quantval, values, sizeof(values)))
488 break;
489 }
490 if (comp_info != NULL)
491 comp_info[i].quant_tbl_no = j;
492 if (j < num_out_tables) /* found a duplicate */
493 continue;
494 if (++num_out_tables > NUM_QUANT_TBLS)
495 return_error(gs_error_rangecheck);
496 this_table = table_ptrs[j];
497 if (this_table == NULL) {
498 this_table = gs_jpeg_alloc_quant_table(pdct);
499 if (this_table == NULL)
500 return_error(gs_error_VMerror);
501 table_ptrs[j] = this_table;
502 }
503 memcpy(this_table->quantval, values, sizeof(values));
504 }
505 return 0;
506 }
507
508 /* Put Huffman tables. */
509 private int
find_huff_values(JHUFF_TBL ** table_ptrs,int num_tables,const UINT8 counts[16],const UINT8 * values,int codes_size)510 find_huff_values(JHUFF_TBL ** table_ptrs, int num_tables,
511 const UINT8 counts[16], const UINT8 * values, int codes_size)
512 {
513 int j;
514
515 for (j = 0; j < num_tables; ++j)
516 if (!memcmp(table_ptrs[j]->bits, counts, sizeof(counts)) &&
517 !memcmp(table_ptrs[j]->huffval, values,
518 codes_size * sizeof(values[0])))
519 break;
520 return j;
521 }
522 int
s_DCT_put_huffman_tables(gs_param_list * plist,stream_DCT_state * pdct,bool is_encode)523 s_DCT_put_huffman_tables(gs_param_list * plist, stream_DCT_state * pdct,
524 bool is_encode)
525 {
526 int code;
527 int i, j;
528 gs_param_array huff_tables;
529 int num_in_tables;
530 int ndc, nac;
531 int codes_size;
532 jpeg_component_info *comp_info;
533 JHUFF_TBL **dc_table_ptrs;
534 JHUFF_TBL **ac_table_ptrs;
535 JHUFF_TBL **this_table_ptr;
536 JHUFF_TBL *this_table;
537 int max_tables = 2; /* baseline limit */
538
539 switch ((code = param_begin_read_dict(plist, "HuffTables",
540 &huff_tables, true))
541 ) {
542 case 1:
543 return 0;
544 default:
545 return param_signal_error(plist, "HuffTables", code);
546 case 0:
547 ;
548 }
549 if (is_encode) {
550 num_in_tables = pdct->data.compress->cinfo.input_components * 2;
551 if (huff_tables.size < num_in_tables)
552 return_error(gs_error_rangecheck);
553 comp_info = pdct->data.compress->cinfo.comp_info;
554 dc_table_ptrs = pdct->data.compress->cinfo.dc_huff_tbl_ptrs;
555 ac_table_ptrs = pdct->data.compress->cinfo.ac_huff_tbl_ptrs;
556 if (pdct->data.common->Relax)
557 max_tables = max(pdct->data.compress->cinfo.input_components, 2);
558 } else {
559 num_in_tables = huff_tables.size;
560 comp_info = NULL; /* do not set for decompress case */
561 dc_table_ptrs = pdct->data.decompress->dinfo.dc_huff_tbl_ptrs;
562 ac_table_ptrs = pdct->data.decompress->dinfo.ac_huff_tbl_ptrs;
563 if (pdct->data.common->Relax)
564 max_tables = NUM_HUFF_TBLS;
565 }
566 ndc = nac = 0;
567 for (i = 0; i < num_in_tables; ++i) {
568 char istr[5]; /* i converted to string key */
569 UINT8 counts[16], values[256];
570
571 /* Collect the Huffman parameters. */
572 sprintf(istr, "%d", i);
573 code = s_DCT_byte_params(huff_tables.list, istr, 0, 16, counts);
574 if (code < 0)
575 return code;
576 for (codes_size = 0, j = 0; j < 16; j++)
577 codes_size += counts[j];
578 if (codes_size > 256 /*|| r_size(pa) != codes_size+16 */ )
579 return_error(gs_error_rangecheck);
580 code = s_DCT_byte_params(huff_tables.list, istr, 16, codes_size,
581 values);
582 if (code < 0)
583 return code;
584 if (i & 1) {
585 j = find_huff_values(ac_table_ptrs, nac, counts, values,
586 codes_size);
587 if (comp_info != NULL)
588 comp_info[i >> 1].ac_tbl_no = j;
589 if (j < nac)
590 continue;
591 if (++nac > NUM_HUFF_TBLS)
592 return_error(gs_error_rangecheck);
593 this_table_ptr = ac_table_ptrs + j;
594 } else {
595 j = find_huff_values(dc_table_ptrs, ndc, counts, values,
596 codes_size);
597 if (comp_info != NULL)
598 comp_info[i >> 1].dc_tbl_no = j;
599 if (j < ndc)
600 continue;
601 if (++ndc > NUM_HUFF_TBLS)
602 return_error(gs_error_rangecheck);
603 this_table_ptr = dc_table_ptrs + j;
604 }
605 this_table = *this_table_ptr;
606 if (this_table == NULL) {
607 this_table = gs_jpeg_alloc_huff_table(pdct);
608 if (this_table == NULL)
609 return_error(gs_error_VMerror);
610 *this_table_ptr = this_table;
611 }
612 memcpy(this_table->bits, counts, sizeof(counts));
613 memcpy(this_table->huffval, values, codes_size * sizeof(values[0]));
614 }
615 if (nac > max_tables || ndc > max_tables)
616 return_error(gs_error_rangecheck);
617 return 0;
618 }
619