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