Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <stddef.h>
  29. #include <string.h> /* memcpy(), memset() */
  30.  
  31. #ifdef OUTPUT_PBM
  32. #include <stdio.h>
  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, &params,
  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, &params,
  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. }
  855.