xref: /plan9/sys/src/cmd/gs/src/sdcparam.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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