1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: zfjbig2.c 9514 2009-03-02 06:13:02Z alexcher $ */
15 
16 /* this is the ps interpreter interface to the jbig2decode filter
17    used for (1bpp) scanned image compression. PDF only specifies
18    a decoder filter, and we don't currently implement anything else */
19 
20 #include "memory_.h"
21 #include "ghost.h"
22 #include "oper.h"
23 #include "gsstruct.h"
24 #include "gstypes.h"
25 #include "ialloc.h"
26 #include "idict.h"
27 #include "store.h"
28 #include "stream.h"
29 #include "strimpl.h"
30 #include "ifilter.h"
31 
32 #ifdef USE_LDF_JB2
33 #include "sjbig2_luratech.h"
34 #else
35 #include "sjbig2.h"
36 #endif
37 
38 /* We define a structure, s_jbig2_global_data_t,
39    allocated in the postscript
40    memory space, to hold a pointer to the global decoder
41    context (which is allocated by libjbig2). This allows
42    us to pass the reference through postscript code to
43    the filter initializer. The opaque data pointer is not
44    enumerated and will not be garbage collected. We use
45    a finalize method to deallocate it when the reference
46    is no longer in use. */
47 
48 static void jbig2_global_data_finalize(void *vptr);
49 gs_private_st_simple_final(st_jbig2_global_data_t, s_jbig2_global_data_t,
50 	"jbig2globaldata", jbig2_global_data_finalize);
51 
52 
53 /* <source> /JBIG2Decode <file> */
54 /* <source> <dict> /JBIG2Decode <file> */
55 static int
z_jbig2decode(i_ctx_t * i_ctx_p)56 z_jbig2decode(i_ctx_t * i_ctx_p)
57 {
58     os_ptr op = osp;
59     ref *sop = NULL;
60     s_jbig2_global_data_t *gref;
61     stream_jbig2decode_state state;
62 
63     /* Extract the global context reference, if any, from the parameter
64        dictionary and embed it in our stream state. The original object
65        ref is under the JBIG2Globals key.
66        We expect the postscript code to resolve this and call
67        z_jbig2makeglobalctx() below to create an astruct wrapping the
68        global decoder data and store it under the .jbig2globalctx key
69      */
70     s_jbig2decode_set_global_data((stream_state*)&state, NULL);
71     if (r_has_type(op, t_dictionary)) {
72         check_dict_read(*op);
73         if ( dict_find_string(op, ".jbig2globalctx", &sop) > 0) {
74 	    gref = r_ptr(sop, s_jbig2_global_data_t);
75 	    s_jbig2decode_set_global_data((stream_state*)&state, gref);
76         }
77     }
78 
79     /* we pass npop=0, since we've no arguments left to consume */
80     return filter_read(i_ctx_p, 0, &s_jbig2decode_template,
81 		       (stream_state *) & state, (sop ? r_space(sop) : 0));
82 }
83 
84 
85 /* <bytestring> .jbig2makeglobalctx <jbig2globalctx> */
86 /* we call this from ps code to instantiate a jbig2_global_context
87    object which the JBIG2Decode filter uses if available. The
88    pointer to the global context is stored in an astruct object
89    and returned that way since it lives outside the interpreters
90    memory management */
91 static int
z_jbig2makeglobalctx(i_ctx_t * i_ctx_p)92 z_jbig2makeglobalctx(i_ctx_t * i_ctx_p)
93 {
94 	void *global = NULL;
95 	s_jbig2_global_data_t *st;
96 	os_ptr op = osp;
97 	byte *data;
98 	int size;
99 	int code = 0;
100 
101 	check_type(*op, t_astruct);
102 	size = gs_object_size(imemory, op->value.pstruct);
103 	data = r_ptr(op, byte);
104 
105  	code = s_jbig2decode_make_global_data(data, size,
106 			&global);
107 	if (size > 0 && global == NULL) {
108 	    dlprintf("failed to create parsed JBIG2GLOBALS object.");
109 	    return_error(e_unknownerror);
110 	}
111 
112 	st = ialloc_struct(s_jbig2_global_data_t,
113 		&st_jbig2_global_data_t,
114 		"jbig2decode parsed global context");
115 	if (st == NULL) return_error(e_VMerror);
116 
117 	st->data = global;
118 	make_astruct(op, a_readonly | icurrent_space, (byte*)st);
119 
120 	return code;
121 }
122 
123 /* free our referenced global context data */
jbig2_global_data_finalize(void * vptr)124 static void jbig2_global_data_finalize(void *vptr)
125 {
126 	s_jbig2_global_data_t *st = vptr;
127 
128 	if (st->data) s_jbig2decode_free_global_data(st->data);
129 	st->data = NULL;
130 }
131 
132 /* Match the above routine to the corresponding filter name.
133    This is how our static routines get called externally. */
134 const op_def zfjbig2_op_defs[] = {
135     {"1.jbig2makeglobalctx", z_jbig2makeglobalctx},
136     op_def_begin_filter(),
137     {"2JBIG2Decode", z_jbig2decode},
138     op_def_end(0)
139 };
140