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