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