Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8436 maxcodehac 1
/*
2
    jbig2dec
3
 
4
    Copyright (C) 2005 Artifex Software, Inc.
5
 
6
    This software is distributed under license and may not
7
    be copied, modified or distributed except as expressly
8
    authorized under the terms of the license contained in
9
    the file LICENSE in this distribution.
10
 
11
    For further licensing information refer to http://artifex.com/ or
12
    contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
13
    San Rafael, CA  94903, U.S.A., +1(415)492-9861.
14
*/
15
 
16
/* JBIG2 Pattern Dictionary and Halftone Region decoding */
17
 
18
#ifdef HAVE_CONFIG_H
19
#include "config.h"
20
#endif
21
#include "os_types.h"
22
 
23
#include  /* memset() */
24
 
25
#include "jbig2.h"
26
#include "jbig2_priv.h"
27
#include "jbig2_arith.h"
28
#include "jbig2_generic.h"
29
#include "jbig2_mmr.h"
30
 
31
typedef struct {
32
  int n_patterns;
33
  Jbig2Image **patterns;
34
  int HPW, HPH;
35
} Jbig2PatternDict;
36
 
37
/* Table 24 */
38
typedef struct {
39
  bool HDMMR;
40
  uint32_t HDPW;
41
  uint32_t HDPH;
42
  uint32_t GRAYMAX;
43
  int HDTEMPLATE;
44
} Jbig2PatternDictParams;
45
 
46
/* Table 33 */
47
typedef struct {
48
  byte flags;
49
  uint32_t HGW;
50
  uint32_t HGH;
51
  int32_t  HGX;
52
  int32_t  HGY;
53
  uint16_t HRX;
54
  uint16_t HRY;
55
  bool HMMR;
56
  int HTEMPLATE;
57
  bool HENABLESKIP;
58
  Jbig2ComposeOp op;
59
  bool HDEFPIXEL;
60
} Jbig2HalftoneRegionParams;
61
 
62
 
63
/**
64
 * jbig2_hd_new: create a new dictionary from a collective bitmap
65
 */
66
Jbig2PatternDict *
67
jbig2_hd_new(Jbig2Ctx *ctx,
68
		const Jbig2PatternDictParams *params,
69
		Jbig2Image *image)
70
{
71
  Jbig2PatternDict *new;
72
  const int N = params->GRAYMAX + 1;
73
  const int HPW = params->HDPW;
74
  const int HPH = params->HDPH;
75
  int i;
76
 
77
  /* allocate a new struct */
78
  new = (Jbig2PatternDict *)jbig2_alloc(ctx->allocator,
79
				sizeof(Jbig2PatternDict));
80
  if (new != NULL) {
81
    new->patterns = (Jbig2Image **)jbig2_alloc(ctx->allocator,
82
				N*sizeof(Jbig2Image*));
83
    if (new->patterns == NULL) {
84
      jbig2_free(ctx->allocator, new);
85
      return NULL;
86
    }
87
    new->n_patterns = N;
88
    new->HPW = HPW;
89
    new->HPH = HPH;
90
 
91
    /* 6.7.5(4) - copy out the individual pattern images */
92
    for (i = 0; i < N; i++) {
93
      new->patterns[i] = jbig2_image_new(ctx, HPW, HPH);
94
      if (new->patterns[i] == NULL) {
95
        int j;
96
        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
97
            "failed to allocate pattern element image");
98
        for (j = 0; j < i; j++)
99
          jbig2_free(ctx->allocator, new->patterns[j]);
100
        jbig2_free(ctx->allocator, new);
101
        return NULL;
102
      }
103
      /* compose with the REPLACE operator; the source
104
         will be clipped to the destintion, selecting the
105
         proper sub image */
106
      jbig2_image_compose(ctx, new->patterns[i], image,
107
			  -i * HPW, 0, JBIG2_COMPOSE_REPLACE);
108
    }
109
  }
110
 
111
  return new;
112
}
113
 
114
/**
115
 * jbig2_hd_release: release a pattern dictionary
116
 */
117
void
118
jbig2_hd_release(Jbig2Ctx *ctx, Jbig2PatternDict *dict)
119
{
120
  int i;
121
 
122
  if (dict == NULL) return;
123
  for (i = 0; i < dict->n_patterns; i++)
124
    if (dict->patterns[i]) jbig2_image_release(ctx, dict->patterns[i]);
125
  jbig2_free(ctx->allocator, dict->patterns);
126
  jbig2_free(ctx->allocator, dict);
127
}
128
 
129
/**
130
 * jbig2_decode_pattern_dict: decode pattern dictionary data
131
 *
132
 * @ctx: jbig2 decoder context
133
 * @segment: jbig2 segment (header) structure
134
 * @params: parameters from the pattern dictionary header
135
 * @data: pointer to text region data to be decoded
136
 * @size: length of text region data
137
 * @GB_stats: artimetic coding context to use
138
 *
139
 * Implements the patten dictionary decoding proceedure
140
 * described in section 6.7 of the JBIG2 spec.
141
 *
142
 * returns: a pointer to the resulting dictionary on success
143
 * returns: 0 on failure
144
 **/
145
static Jbig2PatternDict *
146
jbig2_decode_pattern_dict(Jbig2Ctx *ctx, Jbig2Segment *segment,
147
                             const Jbig2PatternDictParams *params,
148
                             const byte *data, const size_t size,
149
			     Jbig2ArithCx *GB_stats)
150
{
151
  Jbig2PatternDict *hd = NULL;
152
  Jbig2Image *image;
153
  Jbig2GenericRegionParams rparams;
154
  int code;
155
 
156
  /* allocate the collective image */
157
  image = jbig2_image_new(ctx,
158
	params->HDPW * (params->GRAYMAX + 1), params->HDPH);
159
  if (image == NULL) {
160
    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
161
	"failed to allocate collective bitmap for halftone dict!");
162
    return NULL;
163
  }
164
 
165
  /* fill out the generic region decoder parameters */
166
  rparams.MMR = params->HDMMR;
167
  rparams.GBTEMPLATE = params->HDTEMPLATE;
168
  rparams.TPGDON = 0;	/* not used if HDMMR = 1 */
169
  rparams.USESKIP = 0;
170
  rparams.gbat[0] = -params->HDPW;
171
  rparams.gbat[1] = 0;
172
  rparams.gbat[2] = -3;
173
  rparams.gbat[3] = -1;
174
  rparams.gbat[4] = 2;
175
  rparams.gbat[5] = -2;
176
  rparams.gbat[6] = -2;
177
  rparams.gbat[7] = -2;
178
 
179
  if (params->HDMMR) {
180
    code = jbig2_decode_generic_mmr(ctx, segment, &rparams,
181
		data, size, image);
182
  } else {
183
    Jbig2WordStream *ws = jbig2_word_stream_buf_new(ctx, data, size);
184
    Jbig2ArithState *as = jbig2_arith_new(ctx, ws);
185
 
186
    code = jbig2_decode_generic_region(ctx, segment, &rparams,
187
		as, image, GB_stats);
188
 
189
    jbig2_free(ctx->allocator, as);
190
    jbig2_word_stream_buf_free(ctx, ws);
191
  }
192
  if (code != 0) {
193
    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
194
	"error decoding collective pattern dictionary bitmap!");
195
  }
196
 
197
  hd = jbig2_hd_new(ctx, params, image);
198
  jbig2_image_release(ctx, image);
199
 
200
  return hd;
201
}
202
 
203
/* 7.4.4 */
204
int
205
jbig2_pattern_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment,
206
			 const byte *segment_data)
207
{
208
  Jbig2PatternDictParams params;
209
  Jbig2ArithCx *GB_stats = NULL;
210
  byte flags;
211
  int offset = 0;
212
 
213
  /* 7.4.4.1 - Data header */
214
  if (segment->data_length < 7) {
215
    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
216
		       "Segment too short");
217
  }
218
  flags = segment_data[0];
219
  params.HDMMR = flags & 1;
220
  params.HDTEMPLATE = (flags & 6) >> 1;
221
  params.HDPW = segment_data[1];
222
  params.HDPH = segment_data[2];
223
  params.GRAYMAX = jbig2_get_int32(segment_data + 3);
224
  offset += 7;
225
 
226
  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
227
	"pattern dictionary, flags=%02x, %d grays (%dx%d cell)",
228
	flags, params.GRAYMAX + 1, params.HDPW, params.HDPH);
229
 
230
  if (params.HDMMR && params.HDTEMPLATE) {
231
    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
232
	"HDTEMPLATE is %d when HDMMR is %d, contrary to spec",
233
	params.HDTEMPLATE, params.HDMMR);
234
  }
235
  if (flags & 0xf8) {
236
    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
237
	"Reserved flag bits non-zero");
238
  }
239
 
240
  /* 7.4.4.2 */
241
  if (!params.HDMMR) {
242
    /* allocate and zero arithmetic coding stats */
243
    int stats_size = jbig2_generic_stats_size(ctx, params.HDTEMPLATE);
244
    GB_stats = jbig2_alloc(ctx->allocator, stats_size);
245
    memset(GB_stats, 0, stats_size);
246
  }
247
 
248
  segment->result = jbig2_decode_pattern_dict(ctx, segment, ¶ms,
249
			segment_data + offset,
250
			segment->data_length - offset, GB_stats);
251
 
252
  /* todo: retain GB_stats? */
253
  if (!params.HDMMR) {
254
    jbig2_free(ctx->allocator, GB_stats);
255
  }
256
 
257
  return (segment->result != NULL) ? 0 : 1;
258
}
259
 
260
 
261
 
262
/**
263
 * jbig2_decode_halftone_region: decode a halftone region
264
 **/
265
int
266
jbig2_decode_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
267
			     Jbig2HalftoneRegionParams *params,
268
			     const byte *data, const size_t size,
269
			     Jbig2Image *image,
270
			     Jbig2ArithCx *GB_stats)
271
{
272
  int code = 0;
273
 
274
  /* todo: implement */
275
  return code;
276
}
277
 
278
/**
279
 * jbig2_halftone_region: read a halftone region segment header
280
 **/
281
int
282
jbig2_halftone_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
283
{
284
  int offset = 0;
285
  Jbig2RegionSegmentInfo region_info;
286
  Jbig2HalftoneRegionParams params;
287
  Jbig2Image *image;
288
  Jbig2ArithCx *GB_stats;
289
  int code;
290
 
291
  /* 7.4.5.1 */
292
  if (segment->data_length < 17) goto too_short;
293
  jbig2_get_region_segment_info(®ion_info, segment_data);
294
  offset += 17;
295
 
296
  if (segment->data_length < 18) goto too_short;
297
 
298
  /* 7.4.5.1.1 */
299
  params.flags = segment_data[offset];
300
  params.HMMR = params.flags & 1;
301
  params.HTEMPLATE = (params.flags & 6) >> 1;
302
  params.HENABLESKIP = (params.flags & 8) >> 3;
303
  params.op = (params.flags & 0x70) >> 4;
304
  params.HDEFPIXEL = (params.flags &0x80) >> 7;
305
  offset += 1;
306
 
307
  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
308
	"halftone region: %d x %d @ (%x,%d) flags=%02x",
309
	region_info.width, region_info.height,
310
        region_info.x, region_info.y, params.flags);
311
 
312
  if (params.HMMR && params.HTEMPLATE) {
313
    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
314
	"HTEMPLATE is %d when HMMR is %d, contrary to spec",
315
	params.HTEMPLATE, params.HMMR);
316
  }
317
  if (params.HMMR && params.HENABLESKIP) {
318
    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
319
	"HENABLESKIP is %d when HMMR is %d, contrary to spec",
320
	params.HENABLESKIP, params.HMMR);
321
  }
322
 
323
  /* Figure 43 */
324
  if (segment->data_length - offset < 16) goto too_short;
325
  params.HGW = jbig2_get_int32(segment_data + offset);
326
  params.HGH = jbig2_get_int32(segment_data + offset + 4);
327
  params.HGX = jbig2_get_int32(segment_data + offset + 8);
328
  params.HGY = jbig2_get_int32(segment_data + offset + 12);
329
  offset += 16;
330
 
331
  /* Figure 44 */
332
  if (segment->data_length - offset < 4) goto too_short;
333
  params.HRX = jbig2_get_int16(segment_data + offset);
334
  params.HRY = jbig2_get_int16(segment_data + offset + 2);
335
  offset += 4;
336
 
337
  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
338
	" grid %d x %d @ (%d.%d,%d.%d) vector (%d.%d,%d.%d)",
339
	params.HGW, params.HGH,
340
	params.HGX >> 8, params.HGX & 0xff,
341
	params.HGY >> 8, params.HGY & 0xff,
342
	params.HRX >> 8, params.HRX & 0xff,
343
	params.HRY >> 8, params.HRY & 0xff);
344
 
345
  /* 7.4.5.2.2 */
346
  if (!params.HMMR) {
347
    /* allocate and zero arithmetic coding stats */
348
    int stats_size = jbig2_generic_stats_size(ctx, params.HTEMPLATE);
349
    GB_stats = jbig2_alloc(ctx->allocator, stats_size);
350
    memset(GB_stats, 0, stats_size);
351
  }
352
 
353
  image = jbig2_image_new(ctx, region_info.width, region_info.height);
354
  if (image == NULL)
355
    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
356
             "unable to allocate halftone image");
357
 
358
  code = jbig2_decode_halftone_region(ctx, segment, ¶ms,
359
		segment_data + offset, segment->data_length - offset,
360
		image, GB_stats);
361
 
362
  /* todo: retain GB_stats? */
363
  if (!params.HMMR) {
364
    jbig2_free(ctx->allocator, GB_stats);
365
  }
366
 
367
  return code;
368
 
369
too_short:
370
    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
371
                       "Segment too short");
372
}