1 /* Copyright (C) 2003 artofcode LLC. 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: zfjbig2.c,v 1.3 2003/07/30 00:25:37 giles Exp $ */
18
19 /* this is the ps interpreter interface to the jbig2decode filter
20 used for (1bpp) scanned image compression. PDF only specifies
21 a decoder filter, and we don't currently implement anything else */
22
23 #include "memory_.h"
24 #include "ghost.h"
25 #include "oper.h"
26 #include "gsstruct.h"
27 #include "gstypes.h"
28 #include "ialloc.h"
29 #include "idict.h"
30 #include "store.h"
31 #include "stream.h"
32 #include "strimpl.h"
33 #include "ifilter.h"
34 #include "sjbig2.h"
35
36
37 /* We define a structure, allocated in the postscript
38 memory space, to hold a pointer to the global decoder
39 context (which is allocated by libjbig2). This allows
40 us to pass the reference through postscript code to
41 the filter initializer. The global_ctx pointer is not
42 enumerated and will not be garbage collected. We use
43 a finalize method to deallocate it when the reference
44 is no longer in use. */
45
46 typedef struct jbig2_global_data_s {
47 Jbig2GlobalCtx *global_ctx;
48 } jbig2_global_data_t;
49
50 private void jbig2_global_data_finalize(void *vptr);
51 gs_private_st_simple_final(st_jbig2_global_data_t, jbig2_global_data_t,
52 "jbig2globalctx", jbig2_global_data_finalize);
53
54
55 /* <source> /JBIG2Decode <file> */
56 /* <source> <dict> /JBIG2Decode <file> */
57 private int
z_jbig2decode(i_ctx_t * i_ctx_p)58 z_jbig2decode(i_ctx_t * i_ctx_p)
59 {
60 os_ptr op = osp;
61 ref *sop = NULL;
62 jbig2_global_data_t *gref;
63 stream_jbig2decode_state state;
64
65 /* Extract the global context reference, if any, from the parameter
66 dictionary. The original object ref is under the JBIG2Globals key.
67 We expect the postscript code to resolve this and call
68 z_jbig2makeglobalctx() below to create an astruct wrapping the
69 global decoder context and store it under the .jbig2globalctx key
70 */
71 s_jbig2decode_set_global_ctx((stream_state*)&state, NULL);
72 if (r_has_type(op, t_dictionary)) {
73 check_dict_read(*op);
74 if ( dict_find_string(op, ".jbig2globalctx", &sop) > 0) {
75 gref = r_ptr(sop, jbig2_global_data_t);
76 s_jbig2decode_set_global_ctx((stream_state*)&state, gref->global_ctx);
77 }
78 }
79
80 /* we pass npop=0, since we've no arguments left to consume */
81 /* we pass 0 instead of the usual rspace(sop) which will allocate storage
82 for filter state from the same memory pool as the stream it's coding.
83 this causes no trouble because we maintain no pointers */
84 return filter_read(i_ctx_p, 0, &s_jbig2decode_template,
85 (stream_state *) & state, 0);
86 }
87
88
89 /* <bytestring> .jbig2makeglobalctx <jbig2globalctx> */
90 /* we call this from ps code to instantiate a jbig2_global_context
91 object which the JBIG2Decode filter uses if available. The
92 pointer to the global context is stored in an astruct object
93 and returned that way since it lives outside the interpreters
94 memory management */
95 private int
z_jbig2makeglobalctx(i_ctx_t * i_ctx_p)96 z_jbig2makeglobalctx(i_ctx_t * i_ctx_p)
97 {
98 Jbig2GlobalCtx *global_ctx = NULL;
99 jbig2_global_data_t *st;
100 os_ptr op = osp;
101 byte *data;
102 int size;
103 int code = 0;
104
105 check_type(*op, t_astruct);
106 size = gs_object_size(imemory, op->value.pstruct);
107 data = r_ptr(op, byte);
108
109 code = s_jbig2decode_make_global_ctx(data, size,
110 &global_ctx);
111 if (size > 0 && global_ctx == NULL) {
112 dlprintf("failed to create parsed JBIG2GLOBALS object.");
113 return_error(e_unknownerror);
114 }
115
116 st = ialloc_struct(jbig2_global_data_t,
117 &st_jbig2_global_data_t,
118 "jbig2decode parsed global context");
119 if (st == NULL) return_error(e_VMerror);
120
121 st->global_ctx = global_ctx;
122 make_astruct(op, a_readonly | icurrent_space, (byte*)st);
123
124 return code;
125 }
126
127 /* free our referenced global context data */
jbig2_global_data_finalize(void * vptr)128 private void jbig2_global_data_finalize(void *vptr)
129 {
130 jbig2_global_data_t *st = vptr;
131
132 if (st->global_ctx) jbig2_global_ctx_free(st->global_ctx);
133 st->global_ctx = NULL;
134 }
135
136 /* match the above routine to the corresponding filter name
137 this is how our 'private' routines get called externally */
138 const op_def zfjbig2_op_defs[] = {
139 {"1.jbig2makeglobalctx", z_jbig2makeglobalctx},
140 op_def_begin_filter(),
141 {"2JBIG2Decode", z_jbig2decode},
142 op_def_end(0)
143 };
144