]>
Commit | Line | Data |
---|---|---|
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) } | |
45 | private const gs_param_item_t s_DCT_param_items[] = | |
46 | { | |
47 | dctp("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 | }; | |
51 | private 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 */ | |
67 | static 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 */ | |
81 | static 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 | ||
101 | private int | |
102 | quant_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 | ||
124 | private int | |
125 | quant_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 | ||
144 | int | |
145 | s_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 | ||
248 | private int | |
249 | pack_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 | ||
269 | int | |
270 | s_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 | ||
318 | int | |
319 | s_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 | ||
335 | stream_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 | */ | |
343 | int | |
344 | s_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. */ | |
385 | private int | |
386 | quant_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. */ | |
431 | int | |
432 | s_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. */ | |
452 | int | |
453 | s_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. */ | |
520 | private int | |
521 | find_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 | } | |
533 | int | |
534 | s_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 */ |