Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8619 maxcodehac 1
/*
2
    jbig2dec
3
 
4
    Copyright (C) 2002-2005 Artifex Software, Inc.
5
 
6
    This software is provided AS-IS with no warranty,
7
    either express or implied.
8
 
9
    This software is distributed under license and may not
10
    be copied, modified or distributed except as expressly
11
    authorized under the terms of the license contained in
12
    the file LICENSE in this distribution.
13
 
14
    For further licensing information refer to http://artifex.com/ or
15
    contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
16
    San Rafael, CA  94903, U.S.A., +1(415)492-9861.
17
*/
18
 
19
/**
20
 * Generic region handlers.
21
 **/
22
 
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
#include "os_types.h"
27
 
28
#include 
29
#include  /* memcpy(), memset() */
30
 
31
#ifdef OUTPUT_PBM
32
#include 
33
#endif
34
 
35
#include "jbig2.h"
36
#include "jbig2_priv.h"
37
#include "jbig2_image.h"
38
#include "jbig2_arith.h"
39
#include "jbig2_generic.h"
40
#include "jbig2_mmr.h"
41
 
42
/* return the appropriate context size for the given template */
43
int
44
jbig2_generic_stats_size(Jbig2Ctx *ctx, int template)
45
{
46
  int stats_size = template == 0 ? 1 << 16 :
47
        template == 1 ? 1 << 1 << 13 : 1 << 10;
48
  return stats_size;
49
}
50
 
51
 
52
static int
53
jbig2_decode_generic_template0(Jbig2Ctx *ctx,
54
			       Jbig2Segment *segment,
55
			       const Jbig2GenericRegionParams *params,
56
			       Jbig2ArithState *as,
57
			       Jbig2Image *image,
58
			       Jbig2ArithCx *GB_stats)
59
{
60
  const int GBW = image->width;
61
  const int GBH = image->height;
62
  const int rowstride = image->stride;
63
  int x, y;
64
  byte *gbreg_line = (byte *)image->data;
65
 
66
  /* todo: currently we only handle the nominal gbat location */
67
 
68
#ifdef OUTPUT_PBM
69
  printf("P4\n%d %d\n", GBW, GBH);
70
#endif
71
 
72
  for (y = 0; y < GBH; y++)
73
    {
74
      uint32_t CONTEXT;
75
      uint32_t line_m1;
76
      uint32_t line_m2;
77
      int padded_width = (GBW + 7) & -8;
78
 
79
      line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
80
      line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 6 : 0;
81
      CONTEXT = (line_m1 & 0x7f0) | (line_m2 & 0xf800);
82
 
83
      /* 6.2.5.7 3d */
84
      for (x = 0; x < padded_width; x += 8)
85
	{
86
	  byte result = 0;
87
	  int x_minor;
88
	  int minor_width = GBW - x > 8 ? 8 : GBW - x;
89
 
90
	  if (y >= 1)
91
	    line_m1 = (line_m1 << 8) |
92
	      (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
93
 
94
	  if (y >= 2)
95
	    line_m2 = (line_m2 << 8) |
96
	      (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 6: 0);
97
 
98
	  /* This is the speed-critical inner loop. */
99
	  for (x_minor = 0; x_minor < minor_width; x_minor++)
100
	    {
101
	      bool bit;
102
 
103
	      bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
104
	      result |= bit << (7 - x_minor);
105
	      CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit |
106
		((line_m1 >> (7 - x_minor)) & 0x10) |
107
		((line_m2 >> (7 - x_minor)) & 0x800);
108
	    }
109
	  gbreg_line[x >> 3] = result;
110
	}
111
#ifdef OUTPUT_PBM
112
      fwrite(gbreg_line, 1, rowstride, stdout);
113
#endif
114
      gbreg_line += rowstride;
115
    }
116
 
117
  return 0;
118
}
119
 
120
static int
121
jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx,
122
                               Jbig2Segment *segment,
123
                               const Jbig2GenericRegionParams *params,
124
                               Jbig2ArithState *as,
125
                               Jbig2Image *image,
126
                               Jbig2ArithCx *GB_stats)
127
{
128
  const int GBW = image->width;
129
  const int GBH = image->height;
130
  uint32_t CONTEXT;
131
  int x,y;
132
  bool bit;
133
 
134
  /* this version is generic and easy to understand, but very slow */
135
 
136
  for (y = 0; y < GBH; y++) {
137
    for (x = 0; x < GBW; x++) {
138
      CONTEXT = 0;
139
      CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
140
      CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
141
      CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
142
      CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
143
      CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
144
	y + params->gbat[1]) << 4;
145
      CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
146
      CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
147
      CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 7;
148
      CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
149
      CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
150
      CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
151
	y + params->gbat[3]) << 10;
152
      CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
153
	y + params->gbat[5]) << 11;
154
      CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
155
      CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13;
156
      CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
157
      CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
158
	y + params->gbat[7]) << 15;
159
      bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
160
      jbig2_image_set_pixel(image, x, y, bit);
161
    }
162
  }
163
  return 0;
164
}
165
 
166
static int
167
jbig2_decode_generic_template1(Jbig2Ctx *ctx,
168
			       Jbig2Segment *segment,
169
			       const Jbig2GenericRegionParams *params,
170
			       Jbig2ArithState *as,
171
			       Jbig2Image *image,
172
			       Jbig2ArithCx *GB_stats)
173
{
174
  const int GBW = image->width;
175
  const int GBH = image->height;
176
  const int rowstride = image->stride;
177
  int x, y;
178
  byte *gbreg_line = (byte *)image->data;
179
 
180
  /* todo: currently we only handle the nominal gbat location */
181
 
182
#ifdef OUTPUT_PBM
183
  printf("P4\n%d %d\n", GBW, GBH);
184
#endif
185
 
186
  for (y = 0; y < GBH; y++)
187
    {
188
      uint32_t CONTEXT;
189
      uint32_t line_m1;
190
      uint32_t line_m2;
191
      int padded_width = (GBW + 7) & -8;
192
 
193
      line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
194
      line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 5 : 0;
195
      CONTEXT = ((line_m1 >> 1) & 0x1f8) | ((line_m2 >> 1) & 0x1e00);
196
 
197
      /* 6.2.5.7 3d */
198
      for (x = 0; x < padded_width; x += 8)
199
	{
200
	  byte result = 0;
201
	  int x_minor;
202
	  int minor_width = GBW - x > 8 ? 8 : GBW - x;
203
 
204
	  if (y >= 1)
205
	    line_m1 = (line_m1 << 8) |
206
	      (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
207
 
208
	  if (y >= 2)
209
	    line_m2 = (line_m2 << 8) |
210
	      (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 5: 0);
211
 
212
	  /* This is the speed-critical inner loop. */
213
	  for (x_minor = 0; x_minor < minor_width; x_minor++)
214
	    {
215
	      bool bit;
216
 
217
	      bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
218
	      result |= bit << (7 - x_minor);
219
	      CONTEXT = ((CONTEXT & 0xefb) << 1) | bit |
220
		((line_m1 >> (8 - x_minor)) & 0x8) |
221
		((line_m2 >> (8 - x_minor)) & 0x200);
222
	    }
223
	  gbreg_line[x >> 3] = result;
224
	}
225
#ifdef OUTPUT_PBM
226
      fwrite(gbreg_line, 1, rowstride, stdout);
227
#endif
228
      gbreg_line += rowstride;
229
    }
230
 
231
  return 0;
232
}
233
 
234
static int
235
jbig2_decode_generic_template2(Jbig2Ctx *ctx,
236
			       Jbig2Segment *segment,
237
			       const Jbig2GenericRegionParams *params,
238
			       Jbig2ArithState *as,
239
			       Jbig2Image *image,
240
			       Jbig2ArithCx *GB_stats)
241
{
242
  const int GBW = image->width;
243
  const int GBH = image->height;
244
  const int rowstride = image->stride;
245
  int x, y;
246
  byte *gbreg_line = (byte *)image->data;
247
 
248
  /* todo: currently we only handle the nominal gbat location */
249
 
250
#ifdef OUTPUT_PBM
251
  printf("P4\n%d %d\n", GBW, GBH);
252
#endif
253
 
254
  for (y = 0; y < GBH; y++)
255
    {
256
      uint32_t CONTEXT;
257
      uint32_t line_m1;
258
      uint32_t line_m2;
259
      int padded_width = (GBW + 7) & -8;
260
 
261
      line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
262
      line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
263
      CONTEXT = ((line_m1 >> 3) & 0x7c) | ((line_m2 >> 3) & 0x380);
264
 
265
      /* 6.2.5.7 3d */
266
      for (x = 0; x < padded_width; x += 8)
267
	{
268
	  byte result = 0;
269
	  int x_minor;
270
	  int minor_width = GBW - x > 8 ? 8 : GBW - x;
271
 
272
	  if (y >= 1)
273
	    line_m1 = (line_m1 << 8) |
274
	      (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
275
 
276
	  if (y >= 2)
277
	    line_m2 = (line_m2 << 8) |
278
	      (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0);
279
 
280
	  /* This is the speed-critical inner loop. */
281
	  for (x_minor = 0; x_minor < minor_width; x_minor++)
282
	    {
283
	      bool bit;
284
 
285
	      bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
286
	      result |= bit << (7 - x_minor);
287
	      CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit |
288
		((line_m1 >> (10 - x_minor)) & 0x4) |
289
		((line_m2 >> (10 - x_minor)) & 0x80);
290
	    }
291
	  gbreg_line[x >> 3] = result;
292
	}
293
#ifdef OUTPUT_PBM
294
      fwrite(gbreg_line, 1, rowstride, stdout);
295
#endif
296
      gbreg_line += rowstride;
297
    }
298
 
299
  return 0;
300
}
301
 
302
static int
303
jbig2_decode_generic_template2a(Jbig2Ctx *ctx,
304
			       Jbig2Segment *segment,
305
			       const Jbig2GenericRegionParams *params,
306
			       Jbig2ArithState *as,
307
			       Jbig2Image *image,
308
			       Jbig2ArithCx *GB_stats)
309
{
310
  const int GBW = image->width;
311
  const int GBH = image->height;
312
  const int rowstride = image->stride;
313
  int x, y;
314
  byte *gbreg_line = (byte *)image->data;
315
 
316
  /* This is a special case for GBATX1 = 3, GBATY1 = -1 */
317
 
318
#ifdef OUTPUT_PBM
319
  printf("P4\n%d %d\n", GBW, GBH);
320
#endif
321
 
322
  for (y = 0; y < GBH; y++)
323
    {
324
      uint32_t CONTEXT;
325
      uint32_t line_m1;
326
      uint32_t line_m2;
327
      int padded_width = (GBW + 7) & -8;
328
 
329
      line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
330
      line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
331
      CONTEXT = ((line_m1 >> 3) & 0x78) | ((line_m1 >> 2) & 0x4) | ((line_m2 >> 3) & 0x380);
332
 
333
      /* 6.2.5.7 3d */
334
      for (x = 0; x < padded_width; x += 8)
335
	{
336
	  byte result = 0;
337
	  int x_minor;
338
	  int minor_width = GBW - x > 8 ? 8 : GBW - x;
339
 
340
	  if (y >= 1)
341
	    line_m1 = (line_m1 << 8) |
342
	      (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
343
 
344
	  if (y >= 2)
345
	    line_m2 = (line_m2 << 8) |
346
	      (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0);
347
 
348
	  /* This is the speed-critical inner loop. */
349
	  for (x_minor = 0; x_minor < minor_width; x_minor++)
350
	    {
351
	      bool bit;
352
 
353
	      bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
354
	      result |= bit << (7 - x_minor);
355
	      CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit |
356
		((line_m1 >> (10 - x_minor)) & 0x8) |
357
		((line_m1 >> (9 - x_minor)) & 0x4) |
358
		((line_m2 >> (10 - x_minor)) & 0x80);
359
	    }
360
	  gbreg_line[x >> 3] = result;
361
	}
362
#ifdef OUTPUT_PBM
363
      fwrite(gbreg_line, 1, rowstride, stdout);
364
#endif
365
      gbreg_line += rowstride;
366
    }
367
 
368
  return 0;
369
}
370
 
371
static int
372
jbig2_decode_generic_template3(Jbig2Ctx *ctx,
373
			       Jbig2Segment *segment,
374
			       const Jbig2GenericRegionParams *params,
375
			       Jbig2ArithState *as,
376
			       Jbig2Image *image,
377
			       Jbig2ArithCx *GB_stats)
378
{
379
  const int GBW = image->width;
380
  const int GBH = image->height;
381
  const int rowstride = image->stride;
382
  byte *gbreg_line = (byte *)image->data;
383
  int x, y;
384
 
385
  /* this routine only handles the nominal AT location */
386
 
387
#ifdef OUTPUT_PBM
388
  printf("P4\n%d %d\n", GBW, GBH);
389
#endif
390
 
391
  for (y = 0; y < GBH; y++)
392
    {
393
      uint32_t CONTEXT;
394
      uint32_t line_m1;
395
      int padded_width = (GBW + 7) & -8;
396
 
397
      line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
398
      CONTEXT = (line_m1 >> 1) & 0x3f0;
399
 
400
      /* 6.2.5.7 3d */
401
      for (x = 0; x < padded_width; x += 8)
402
	{
403
	  byte result = 0;
404
	  int x_minor;
405
	  int minor_width = GBW - x > 8 ? 8 : GBW - x;
406
 
407
	  if (y >= 1)
408
	    line_m1 = (line_m1 << 8) |
409
	      (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
410
 
411
	  /* This is the speed-critical inner loop. */
412
	  for (x_minor = 0; x_minor < minor_width; x_minor++)
413
	    {
414
	      bool bit;
415
 
416
	      bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
417
	      result |= bit << (7 - x_minor);
418
	      CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit |
419
		((line_m1 >> (10 - x_minor)) & 0x010);
420
	    }
421
	  gbreg_line[x >> 3] = result;
422
	}
423
#ifdef OUTPUT_PBM
424
      fwrite(gbreg_line, 1, rowstride, stdout);
425
#endif
426
      gbreg_line += rowstride;
427
    }
428
 
429
  return 0;
430
}
431
 
432
static int
433
jbig2_decode_generic_template3_unopt(Jbig2Ctx *ctx,
434
                               Jbig2Segment *segment,
435
                               const Jbig2GenericRegionParams *params,
436
                               Jbig2ArithState *as,
437
                               Jbig2Image *image,
438
                               Jbig2ArithCx *GB_stats)
439
{
440
  const int GBW = image->width;
441
  const int GBH = image->height;
442
  uint32_t CONTEXT;
443
  int x,y;
444
  bool bit;
445
 
446
  /* this version is generic and easy to understand, but very slow */
447
 
448
  for (y = 0; y < GBH; y++) {
449
    for (x = 0; x < GBW; x++) {
450
      CONTEXT = 0;
451
      CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
452
      CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
453
      CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
454
      CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
455
      CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
456
	y + params->gbat[1]) << 4;
457
      CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
458
      CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6;
459
      CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
460
      CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
461
      CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
462
      bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
463
      jbig2_image_set_pixel(image, x, y, bit);
464
    }
465
  }
466
  return 0;
467
}
468
 
469
static void
470
copy_prev_row(Jbig2Image *image, int row)
471
{
472
  if (!row) {
473
    /* no previous row */
474
    memset( image->data, 0, image->stride );
475
  } else {
476
    /* duplicate data from the previous row */
477
    uint8_t *src = image->data + (row - 1) * image->stride;
478
    memcpy( src + image->stride, src, image->stride );
479
  }
480
}
481
 
482
static int
483
jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
484
				Jbig2Segment *segment,
485
				const Jbig2GenericRegionParams *params,
486
				Jbig2ArithState *as,
487
				Jbig2Image *image,
488
				Jbig2ArithCx *GB_stats)
489
{
490
  const int GBW = image->width;
491
  const int GBH = image->height;
492
  uint32_t CONTEXT;
493
  int x, y;
494
  bool bit;
495
  int LTP = 0;
496
 
497
  for (y = 0; y < GBH; y++)
498
  {
499
    LTP ^= jbig2_arith_decode(as, &GB_stats[0x9B25]);
500
    if (!LTP) {
501
      for (x = 0; x < GBW; x++) {
502
        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
503
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
504
        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
505
        CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
506
        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
507
					y + params->gbat[1]) << 4;
508
        CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
509
        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
510
        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 7;
511
        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
512
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
513
        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
514
					y + params->gbat[3]) << 10;
515
        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
516
					y + params->gbat[5]) << 11;
517
        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
518
        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 13;
519
        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
520
        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
521
					y + params->gbat[7]) << 15;
522
        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
523
        jbig2_image_set_pixel(image, x, y, bit);
524
      }
525
    } else {
526
      copy_prev_row(image, y);
527
    }
528
  }
529
 
530
  return 0;
531
}
532
 
533
static int
534
jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx,
535
				Jbig2Segment *segment,
536
				const Jbig2GenericRegionParams *params,
537
				Jbig2ArithState *as,
538
				Jbig2Image *image,
539
				Jbig2ArithCx *GB_stats)
540
{
541
  const int GBW = image->width;
542
  const int GBH = image->height;
543
  uint32_t CONTEXT;
544
  int x, y;
545
  bool bit;
546
  int LTP = 0;
547
 
548
  for (y = 0; y < GBH; y++) {
549
    LTP ^= jbig2_arith_decode(as, &GB_stats[0x0795]);
550
    if (!LTP) {
551
      for (x = 0; x < GBW; x++) {
552
        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
553
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
554
        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
555
        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
556
					y + params->gbat[1]) << 3;
557
        CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4;
558
        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
559
        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 6;
560
        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
561
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
562
        CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9;
563
        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
564
        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 11;
565
        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
566
        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
567
        jbig2_image_set_pixel(image, x, y, bit);
568
      }
569
    } else {
570
      copy_prev_row(image, y);
571
    }
572
  }
573
 
574
  return 0;
575
}
576
 
577
static int
578
jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx,
579
				Jbig2Segment *segment,
580
				const Jbig2GenericRegionParams *params,
581
				Jbig2ArithState *as,
582
				Jbig2Image *image,
583
				Jbig2ArithCx *GB_stats)
584
{
585
  const int GBW = image->width;
586
  const int GBH = image->height;
587
  uint32_t CONTEXT;
588
  int x, y;
589
  bool bit;
590
  int LTP = 0;
591
 
592
  for (y = 0; y < GBH; y++) {
593
    LTP ^= jbig2_arith_decode(as, &GB_stats[0xE5]);
594
    if (!LTP) {
595
      for (x = 0; x < GBW; x++) {
596
        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
597
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
598
        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
599
					y + params->gbat[1]) << 2;
600
        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3;
601
        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 4;
602
        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5;
603
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6;
604
        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
605
        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 8;
606
        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
607
        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
608
        jbig2_image_set_pixel(image, x, y, bit);
609
      }
610
    } else {
611
      copy_prev_row(image, y);
612
    }
613
  }
614
 
615
  return 0;
616
}
617
 
618
static int
619
jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx,
620
				Jbig2Segment *segment,
621
				const Jbig2GenericRegionParams *params,
622
				Jbig2ArithState *as,
623
				Jbig2Image *image,
624
				Jbig2ArithCx *GB_stats)
625
{
626
  const int GBW = image->width;
627
  const int GBH = image->height;
628
  uint32_t CONTEXT;
629
  int x, y;
630
  bool bit;
631
  int LTP = 0;
632
 
633
  for (y = 0; y < GBH; y++) {
634
    LTP ^= jbig2_arith_decode(as, &GB_stats[0x0195]);
635
    if (!LTP) {
636
      for (x = 0; x < GBW; x++) {
637
        CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
638
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
639
        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
640
        CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
641
        CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
642
					y + params->gbat[1]) << 4;
643
        CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
644
        CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 6;
645
        CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
646
        CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
647
        CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
648
        bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
649
        jbig2_image_set_pixel(image, x, y, bit);
650
      }
651
    } else {
652
      copy_prev_row(image, y);
653
    }
654
  }
655
 
656
  return 0;
657
}
658
 
659
static int
660
jbig2_decode_generic_region_TPGDON(Jbig2Ctx *ctx,
661
				Jbig2Segment *segment,
662
				const Jbig2GenericRegionParams *params,
663
				Jbig2ArithState *as,
664
				Jbig2Image *image,
665
				Jbig2ArithCx *GB_stats)
666
{
667
  switch (params->GBTEMPLATE) {
668
    case 0:
669
      return jbig2_decode_generic_template0_TPGDON(ctx, segment,
670
			params, as, image, GB_stats);
671
    case 1:
672
      return jbig2_decode_generic_template1_TPGDON(ctx, segment,
673
			params, as, image, GB_stats);
674
    case 2:
675
      return jbig2_decode_generic_template2_TPGDON(ctx, segment,
676
			params, as, image, GB_stats);
677
    case 3:
678
      return jbig2_decode_generic_template3_TPGDON(ctx, segment,
679
			params, as, image, GB_stats);
680
  }
681
 
682
  return -1;
683
}
684
 
685
/**
686
 * jbig2_decode_generic_region: Decode a generic region.
687
 * @ctx: The context for allocation and error reporting.
688
 * @segment: A segment reference for error reporting.
689
 * @params: Decoding parameter set.
690
 * @as: Arithmetic decoder state.
691
 * @image: Where to store the decoded data.
692
 * @GB_stats: Arithmetic stats.
693
 *
694
 * Decodes a generic region, according to section 6.2. The caller should
695
 * pass an already allocated Jbig2Image object for @image
696
 *
697
 * Because this API is based on an arithmetic decoding state, it is
698
 * not suitable for MMR decoding.
699
 *
700
 * Return code: 0 on success.
701
 **/
702
int
703
jbig2_decode_generic_region(Jbig2Ctx *ctx,
704
			    Jbig2Segment *segment,
705
			    const Jbig2GenericRegionParams *params,
706
			    Jbig2ArithState *as,
707
			    Jbig2Image *image,
708
			    Jbig2ArithCx *GB_stats)
709
{
710
  const int8_t *gbat = params->gbat;
711
 
712
  if (!params->MMR && params->TPGDON)
713
     return jbig2_decode_generic_region_TPGDON(ctx, segment, params,
714
		as, image, GB_stats);
715
 
716
  if (!params->MMR && params->GBTEMPLATE == 0) {
717
    if (gbat[0] == +3 && gbat[1] == -1 &&
718
        gbat[2] == -3 && gbat[3] == -1 &&
719
        gbat[4] == +2 && gbat[5] == -2 &&
720
        gbat[6] == -2 && gbat[7] == -2)
721
      return jbig2_decode_generic_template0(ctx, segment, params,
722
                                          as, image, GB_stats);
723
    else
724
      return jbig2_decode_generic_template0_unopt(ctx, segment, params,
725
                                          as, image, GB_stats);
726
  } else if (!params->MMR && params->GBTEMPLATE == 1)
727
    return jbig2_decode_generic_template1(ctx, segment, params,
728
					  as, image, GB_stats);
729
  else if (!params->MMR && params->GBTEMPLATE == 2)
730
    {
731
      if (gbat[0] == 3 && gbat[1] == -1)
732
	return jbig2_decode_generic_template2a(ctx, segment, params,
733
					       as, image, GB_stats);
734
      else
735
	return jbig2_decode_generic_template2(ctx, segment, params,
736
                                              as, image, GB_stats);
737
    }
738
  else if (!params->MMR && params->GBTEMPLATE == 3) {
739
   if (gbat[0] == 2 && gbat[1] == -1)
740
     return jbig2_decode_generic_template3_unopt(ctx, segment, params,
741
                                         as, image, GB_stats);
742
   else
743
     return jbig2_decode_generic_template3_unopt(ctx, segment, params,
744
                                         as, image, GB_stats);
745
  }
746
 
747
  {
748
    int i;
749
    for (i = 0; i < 8; i++)
750
      jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
751
        "gbat[%d] = %d", i, params->gbat[i]);
752
  }
753
  jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
754
	      "decode_generic_region: MMR=%d, GBTEMPLATE=%d NYI",
755
	      params->MMR, params->GBTEMPLATE);
756
  return -1;
757
}
758
 
759
/**
760
 * Handler for immediate generic region segments
761
 */
762
int
763
jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
764
			       const byte *segment_data)
765
{
766
  Jbig2RegionSegmentInfo rsi;
767
  byte seg_flags;
768
  int8_t gbat[8];
769
  int offset;
770
  int gbat_bytes = 0;
771
  Jbig2GenericRegionParams params;
772
  int code;
773
  Jbig2Image *image;
774
  Jbig2WordStream *ws;
775
  Jbig2ArithState *as;
776
  Jbig2ArithCx *GB_stats = NULL;
777
 
778
  /* 7.4.6 */
779
  if (segment->data_length < 18)
780
    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
781
		       "Segment too short");
782
 
783
  jbig2_get_region_segment_info(&rsi, segment_data);
784
  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
785
	      "generic region: %d x %d @ (%d, %d), flags = %02x",
786
	      rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
787
 
788
  /* 7.4.6.2 */
789
  seg_flags = segment_data[17];
790
  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
791
	      "segment flags = %02x", seg_flags);
792
  if ((seg_flags & 1) && (seg_flags & 6))
793
    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
794
		"MMR is 1, but GBTEMPLATE is not 0");
795
 
796
  /* 7.4.6.3 */
797
  if (!(seg_flags & 1))
798
    {
799
      gbat_bytes = (seg_flags & 6) ? 2 : 8;
800
      if (18 + gbat_bytes > segment->data_length)
801
	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
802
			   "Segment too short");
803
      memcpy(gbat, segment_data + 18, gbat_bytes);
804
      jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
805
		  "gbat: %d, %d", gbat[0], gbat[1]);
806
    }
807
 
808
  offset = 18 + gbat_bytes;
809
 
810
  /* Table 34 */
811
  params.MMR = seg_flags & 1;
812
  params.GBTEMPLATE = (seg_flags & 6) >> 1;
813
  params.TPGDON = (seg_flags & 8) >> 3;
814
  params.USESKIP = 0;
815
  memcpy (params.gbat, gbat, gbat_bytes);
816
 
817
  image = jbig2_image_new(ctx, rsi.width, rsi.height);
818
  if (image == NULL)
819
    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
820
             "unable to allocate generic image");
821
  jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
822
    "allocated %d x %d image buffer for region decode results",
823
        rsi.width, rsi.height);
824
 
825
  if (params.MMR)
826
    {
827
      code = jbig2_decode_generic_mmr(ctx, segment, ¶ms,
828
				      segment_data + offset, segment->data_length - offset,
829
				      image);
830
    }
831
  else
832
    {
833
      int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE);
834
      GB_stats = jbig2_alloc(ctx->allocator, stats_size);
835
      memset(GB_stats, 0, stats_size);
836
 
837
      ws = jbig2_word_stream_buf_new(ctx,
838
				     segment_data + offset,
839
				     segment->data_length - offset);
840
      as = jbig2_arith_new(ctx, ws);
841
      code = jbig2_decode_generic_region(ctx, segment, ¶ms,
842
					 as, image, GB_stats);
843
      jbig2_free(ctx->allocator, as);
844
      jbig2_word_stream_buf_free(ctx, ws);
845
 
846
      jbig2_free(ctx->allocator, GB_stats);
847
    }
848
 
849
  jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page],
850
			image, rsi.x, rsi.y, JBIG2_COMPOSE_OR);
851
  jbig2_image_release(ctx, image);
852
 
853
  return code;
854
}