17dd7cddfSDavid du Colombier /* Copyright (C) 1994, 1997, 1999 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: sjpegc.c,v 1.7 2002/03/30 23:55:15 giles Exp $ */
187dd7cddfSDavid du Colombier /* Interface routines for IJG code, common to encode/decode. */
197dd7cddfSDavid du Colombier #include "stdio_.h"
207dd7cddfSDavid du Colombier #include "string_.h"
217dd7cddfSDavid du Colombier #include "jpeglib_.h"
227dd7cddfSDavid du Colombier #include "jerror_.h"
237dd7cddfSDavid du Colombier #include "gx.h"
247dd7cddfSDavid du Colombier #include "gserrors.h"
257dd7cddfSDavid du Colombier #include "strimpl.h"
267dd7cddfSDavid du Colombier #include "sdct.h"
277dd7cddfSDavid du Colombier #include "sjpeg.h"
287dd7cddfSDavid du Colombier
29*593dc095SDavid du Colombier /*
30*593dc095SDavid du Colombier Ghostscript uses a non-public interface to libjpeg in order to
31*593dc095SDavid du Colombier override the library's default memory manager implementation.
32*593dc095SDavid du Colombier Since many users will want to compile Ghostscript using the
33*593dc095SDavid du Colombier shared jpeg library, we provide these prototypes so that a copy
34*593dc095SDavid du Colombier of the libjpeg source distribution is not needed.
35*593dc095SDavid du Colombier
36*593dc095SDavid du Colombier The presence of the jmemsys.h header file is detected in
37*593dc095SDavid du Colombier unix-aux.mak, and written to gconfig_.h
38*593dc095SDavid du Colombier */
39*593dc095SDavid du Colombier
40*593dc095SDavid du Colombier #include "gconfig_.h"
41*593dc095SDavid du Colombier #ifdef DONT_HAVE_JMEMSYS_H
42*593dc095SDavid du Colombier
43*593dc095SDavid du Colombier void *
44*593dc095SDavid du Colombier jpeg_get_small(j_common_ptr cinfo, size_t size);
45*593dc095SDavid du Colombier
46*593dc095SDavid du Colombier void
47*593dc095SDavid du Colombier jpeg_free_small(j_common_ptr cinfo, void *object, size_t size);
48*593dc095SDavid du Colombier
49*593dc095SDavid du Colombier void FAR *
50*593dc095SDavid du Colombier jpeg_get_large(j_common_ptr cinfo, size_t size);
51*593dc095SDavid du Colombier
52*593dc095SDavid du Colombier void
53*593dc095SDavid du Colombier jpeg_free_large(j_common_ptr cinfo, void FAR * object, size_t size);
54*593dc095SDavid du Colombier typedef void *backing_store_ptr;
55*593dc095SDavid du Colombier
56*593dc095SDavid du Colombier long
57*593dc095SDavid du Colombier jpeg_mem_available(j_common_ptr cinfo, long min_bytes_needed,
58*593dc095SDavid du Colombier long max_bytes_needed, long already_allocated);
59*593dc095SDavid du Colombier
60*593dc095SDavid du Colombier void
61*593dc095SDavid du Colombier jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
62*593dc095SDavid du Colombier long total_bytes_needed);
63*593dc095SDavid du Colombier
64*593dc095SDavid du Colombier long
65*593dc095SDavid du Colombier jpeg_mem_init(j_common_ptr cinfo);
66*593dc095SDavid du Colombier
67*593dc095SDavid du Colombier void
68*593dc095SDavid du Colombier jpeg_mem_term(j_common_ptr cinfo);
69*593dc095SDavid du Colombier
70*593dc095SDavid du Colombier #else
71*593dc095SDavid du Colombier #include "jmemsys.h" /* for prototypes */
72*593dc095SDavid du Colombier #endif
73*593dc095SDavid du Colombier
743ff48bf5SDavid du Colombier private_st_jpeg_block();
753ff48bf5SDavid du Colombier
767dd7cddfSDavid du Colombier /*
777dd7cddfSDavid du Colombier * Error handling routines (these replace corresponding IJG routines from
787dd7cddfSDavid du Colombier * jpeg/jerror.c). These are used for both compression and decompression.
797dd7cddfSDavid du Colombier * We assume
807dd7cddfSDavid du Colombier * offset_of(jpeg_compress_data, cinfo)==offset_of(jpeg_decompress_data, dinfo)
817dd7cddfSDavid du Colombier */
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier private void
gs_jpeg_error_exit(j_common_ptr cinfo)847dd7cddfSDavid du Colombier gs_jpeg_error_exit(j_common_ptr cinfo)
857dd7cddfSDavid du Colombier {
867dd7cddfSDavid du Colombier jpeg_stream_data *jcomdp =
877dd7cddfSDavid du Colombier (jpeg_stream_data *) ((char *)cinfo -
887dd7cddfSDavid du Colombier offset_of(jpeg_compress_data, cinfo));
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier longjmp(jcomdp->exit_jmpbuf, 1);
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier private void
gs_jpeg_emit_message(j_common_ptr cinfo,int msg_level)947dd7cddfSDavid du Colombier gs_jpeg_emit_message(j_common_ptr cinfo, int msg_level)
957dd7cddfSDavid du Colombier {
967dd7cddfSDavid du Colombier if (msg_level < 0) { /* GS policy is to ignore IJG warnings when Picky=0,
977dd7cddfSDavid du Colombier * treat them as errors when Picky=1.
987dd7cddfSDavid du Colombier */
997dd7cddfSDavid du Colombier jpeg_stream_data *jcomdp =
1007dd7cddfSDavid du Colombier (jpeg_stream_data *) ((char *)cinfo -
1017dd7cddfSDavid du Colombier offset_of(jpeg_compress_data, cinfo));
1027dd7cddfSDavid du Colombier
1037dd7cddfSDavid du Colombier if (jcomdp->Picky)
1047dd7cddfSDavid du Colombier gs_jpeg_error_exit(cinfo);
1057dd7cddfSDavid du Colombier }
1067dd7cddfSDavid du Colombier /* Trace messages are always ignored. */
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier /*
1107dd7cddfSDavid du Colombier * This routine initializes the error manager fields in the JPEG object.
1117dd7cddfSDavid du Colombier * It is based on jpeg_std_error from jpeg/jerror.c.
1127dd7cddfSDavid du Colombier */
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier void
gs_jpeg_error_setup(stream_DCT_state * st)1157dd7cddfSDavid du Colombier gs_jpeg_error_setup(stream_DCT_state * st)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier struct jpeg_error_mgr *err = &st->data.common->err;
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier /* Initialize the JPEG compression object with default error handling */
1207dd7cddfSDavid du Colombier jpeg_std_error(err);
1217dd7cddfSDavid du Colombier
1227dd7cddfSDavid du Colombier /* Replace some methods with our own versions */
1237dd7cddfSDavid du Colombier err->error_exit = gs_jpeg_error_exit;
1247dd7cddfSDavid du Colombier err->emit_message = gs_jpeg_emit_message;
1257dd7cddfSDavid du Colombier
1267dd7cddfSDavid du Colombier st->data.compress->cinfo.err = err; /* works for decompress case too */
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier /* Stuff the IJG error message into errorinfo after an error exit. */
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier int
gs_jpeg_log_error(stream_DCT_state * st)1327dd7cddfSDavid du Colombier gs_jpeg_log_error(stream_DCT_state * st)
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier j_common_ptr cinfo = (j_common_ptr) & st->data.compress->cinfo;
1357dd7cddfSDavid du Colombier char buffer[JMSG_LENGTH_MAX];
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier /* Format the error message */
1387dd7cddfSDavid du Colombier (*cinfo->err->format_message) (cinfo, buffer);
1397dd7cddfSDavid du Colombier (*st->report_error) ((stream_state *) st, buffer);
1407dd7cddfSDavid du Colombier return gs_error_ioerror; /* caller will do return_error() */
1417dd7cddfSDavid du Colombier }
1427dd7cddfSDavid du Colombier
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier /*
1457dd7cddfSDavid du Colombier * Interface routines. This layer of routines exists solely to limit
1467dd7cddfSDavid du Colombier * side-effects from using setjmp.
1477dd7cddfSDavid du Colombier */
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier JQUANT_TBL *
gs_jpeg_alloc_quant_table(stream_DCT_state * st)1517dd7cddfSDavid du Colombier gs_jpeg_alloc_quant_table(stream_DCT_state * st)
1527dd7cddfSDavid du Colombier {
1537dd7cddfSDavid du Colombier if (setjmp(st->data.common->exit_jmpbuf)) {
1547dd7cddfSDavid du Colombier gs_jpeg_log_error(st);
1557dd7cddfSDavid du Colombier return NULL;
1567dd7cddfSDavid du Colombier }
1577dd7cddfSDavid du Colombier return jpeg_alloc_quant_table((j_common_ptr)
1587dd7cddfSDavid du Colombier & st->data.compress->cinfo);
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier JHUFF_TBL *
gs_jpeg_alloc_huff_table(stream_DCT_state * st)1627dd7cddfSDavid du Colombier gs_jpeg_alloc_huff_table(stream_DCT_state * st)
1637dd7cddfSDavid du Colombier {
1647dd7cddfSDavid du Colombier if (setjmp(st->data.common->exit_jmpbuf)) {
1657dd7cddfSDavid du Colombier gs_jpeg_log_error(st);
1667dd7cddfSDavid du Colombier return NULL;
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier return jpeg_alloc_huff_table((j_common_ptr)
1697dd7cddfSDavid du Colombier & st->data.compress->cinfo);
1707dd7cddfSDavid du Colombier }
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier int
gs_jpeg_destroy(stream_DCT_state * st)1737dd7cddfSDavid du Colombier gs_jpeg_destroy(stream_DCT_state * st)
1747dd7cddfSDavid du Colombier {
1757dd7cddfSDavid du Colombier if (setjmp(st->data.common->exit_jmpbuf))
1767dd7cddfSDavid du Colombier return_error(gs_jpeg_log_error(st));
1777dd7cddfSDavid du Colombier jpeg_destroy((j_common_ptr) & st->data.compress->cinfo);
1787dd7cddfSDavid du Colombier return 0;
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier /*
1837dd7cddfSDavid du Colombier * These routines replace the low-level memory manager of the IJG library.
1847dd7cddfSDavid du Colombier * They pass malloc/free calls to the Ghostscript memory manager.
1857dd7cddfSDavid du Colombier * Note we do not need these to be declared in any GS header file.
1867dd7cddfSDavid du Colombier */
1877dd7cddfSDavid du Colombier
1883ff48bf5SDavid du Colombier private inline jpeg_compress_data *
cinfo2jcd(j_common_ptr cinfo)1893ff48bf5SDavid du Colombier cinfo2jcd(j_common_ptr cinfo)
1903ff48bf5SDavid du Colombier { /* We use the offset of cinfo in jpeg_compress data here, but we */
1913ff48bf5SDavid du Colombier /* could equally well have used jpeg_decompress_data. */
1923ff48bf5SDavid du Colombier return (jpeg_compress_data *)
1933ff48bf5SDavid du Colombier ((byte *)cinfo - offset_of(jpeg_compress_data, cinfo));
1943ff48bf5SDavid du Colombier }
1957dd7cddfSDavid du Colombier
1963ff48bf5SDavid du Colombier private void *
jpeg_alloc(j_common_ptr cinfo,size_t size,const char * info)1973ff48bf5SDavid du Colombier jpeg_alloc(j_common_ptr cinfo, size_t size, const char *info)
1983ff48bf5SDavid du Colombier {
1993ff48bf5SDavid du Colombier jpeg_compress_data *jcd = cinfo2jcd(cinfo);
2003ff48bf5SDavid du Colombier gs_memory_t *mem = jcd->memory;
2013ff48bf5SDavid du Colombier
2023ff48bf5SDavid du Colombier jpeg_block_t *p = gs_alloc_struct_immovable(mem, jpeg_block_t,
2033ff48bf5SDavid du Colombier &st_jpeg_block, "jpeg_alloc(block)");
2043ff48bf5SDavid du Colombier void *data = gs_alloc_bytes_immovable(mem, size, info);
2053ff48bf5SDavid du Colombier
2063ff48bf5SDavid du Colombier if (p == 0 || data == 0) {
2073ff48bf5SDavid du Colombier gs_free_object(mem, data, info);
2083ff48bf5SDavid du Colombier gs_free_object(mem, p, "jpeg_alloc(block)");
2093ff48bf5SDavid du Colombier return 0;
2103ff48bf5SDavid du Colombier }
2113ff48bf5SDavid du Colombier p->data = data;
2123ff48bf5SDavid du Colombier p->next = jcd->blocks;
2133ff48bf5SDavid du Colombier jcd->blocks = p;
2143ff48bf5SDavid du Colombier return data;
2153ff48bf5SDavid du Colombier }
2163ff48bf5SDavid du Colombier
2173ff48bf5SDavid du Colombier private void
jpeg_free(j_common_ptr cinfo,void * data,const char * info)2183ff48bf5SDavid du Colombier jpeg_free(j_common_ptr cinfo, void *data, const char *info)
2193ff48bf5SDavid du Colombier {
2203ff48bf5SDavid du Colombier jpeg_compress_data *jcd = cinfo2jcd(cinfo);
2213ff48bf5SDavid du Colombier gs_memory_t *mem = jcd->memory;
2223ff48bf5SDavid du Colombier jpeg_block_t *p = jcd->blocks;
2233ff48bf5SDavid du Colombier jpeg_block_t **pp = &jcd->blocks;
2243ff48bf5SDavid du Colombier
2253ff48bf5SDavid du Colombier gs_free_object(mem, data, info);
2263ff48bf5SDavid du Colombier while(p && p->data != data)
2273ff48bf5SDavid du Colombier { pp = &p->next;
2283ff48bf5SDavid du Colombier p = p->next;
2293ff48bf5SDavid du Colombier }
2303ff48bf5SDavid du Colombier if(p == 0)
2313ff48bf5SDavid du Colombier lprintf1("Freeing unrecorded JPEG data 0x%lx!\n", (ulong)data);
2323ff48bf5SDavid du Colombier else
2333ff48bf5SDavid du Colombier *pp = p->next;
2343ff48bf5SDavid du Colombier gs_free_object(mem, p, "jpeg_free(block)");
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier
2377dd7cddfSDavid du Colombier void *
jpeg_get_small(j_common_ptr cinfo,size_t size)2383ff48bf5SDavid du Colombier jpeg_get_small(j_common_ptr cinfo, size_t size)
2397dd7cddfSDavid du Colombier {
2403ff48bf5SDavid du Colombier return jpeg_alloc(cinfo, size, "JPEG small internal data allocation");
2417dd7cddfSDavid du Colombier }
2427dd7cddfSDavid du Colombier
2437dd7cddfSDavid du Colombier void
jpeg_free_small(j_common_ptr cinfo,void * object,size_t size)2443ff48bf5SDavid du Colombier jpeg_free_small(j_common_ptr cinfo, void *object, size_t size)
2457dd7cddfSDavid du Colombier {
2463ff48bf5SDavid du Colombier jpeg_free(cinfo, object, "Freeing JPEG small internal data");
2477dd7cddfSDavid du Colombier }
2487dd7cddfSDavid du Colombier
2497dd7cddfSDavid du Colombier void FAR *
jpeg_get_large(j_common_ptr cinfo,size_t size)2503ff48bf5SDavid du Colombier jpeg_get_large(j_common_ptr cinfo, size_t size)
2517dd7cddfSDavid du Colombier {
2523ff48bf5SDavid du Colombier return jpeg_alloc(cinfo, size, "JPEG large internal data allocation");
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier void
jpeg_free_large(j_common_ptr cinfo,void FAR * object,size_t size)2563ff48bf5SDavid du Colombier jpeg_free_large(j_common_ptr cinfo, void FAR * object, size_t size)
2577dd7cddfSDavid du Colombier {
2583ff48bf5SDavid du Colombier jpeg_free(cinfo, object, "Freeing JPEG large internal data");
2597dd7cddfSDavid du Colombier }
2607dd7cddfSDavid du Colombier
2617dd7cddfSDavid du Colombier long
jpeg_mem_available(j_common_ptr cinfo,long min_bytes_needed,long max_bytes_needed,long already_allocated)2627dd7cddfSDavid du Colombier jpeg_mem_available(j_common_ptr cinfo, long min_bytes_needed,
2637dd7cddfSDavid du Colombier long max_bytes_needed, long already_allocated)
2647dd7cddfSDavid du Colombier {
2657dd7cddfSDavid du Colombier return max_bytes_needed;
2667dd7cddfSDavid du Colombier }
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier void
jpeg_open_backing_store(j_common_ptr cinfo,backing_store_ptr info,long total_bytes_needed)2697dd7cddfSDavid du Colombier jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
2707dd7cddfSDavid du Colombier long total_bytes_needed)
2717dd7cddfSDavid du Colombier {
2727dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_NO_BACKING_STORE);
2737dd7cddfSDavid du Colombier }
2747dd7cddfSDavid du Colombier
2757dd7cddfSDavid du Colombier long
jpeg_mem_init(j_common_ptr cinfo)2767dd7cddfSDavid du Colombier jpeg_mem_init(j_common_ptr cinfo)
2777dd7cddfSDavid du Colombier {
2787dd7cddfSDavid du Colombier return 0; /* just set max_memory_to_use to 0 */
2797dd7cddfSDavid du Colombier }
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier void
jpeg_mem_term(j_common_ptr cinfo)2827dd7cddfSDavid du Colombier jpeg_mem_term(j_common_ptr cinfo)
2837dd7cddfSDavid du Colombier {
2847dd7cddfSDavid du Colombier /* no work */
2857dd7cddfSDavid du Colombier }
286