Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.     jbig2dec
  3.  
  4.     Copyright (C) 2001-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. /* symbol dictionary segment decode and support */
  17.  
  18. #ifdef HAVE_CONFIG_H
  19. #include "config.h"
  20. #endif
  21. #include "os_types.h"
  22.  
  23. #include <stddef.h>
  24. #include <string.h> /* memset() */
  25.  
  26. #include "jbig2.h"
  27. #include "jbig2_priv.h"
  28. #include "jbig2_arith.h"
  29. #include "jbig2_arith_int.h"
  30. #include "jbig2_arith_iaid.h"
  31. #include "jbig2_huffman.h"
  32. #include "jbig2_generic.h"
  33. #include "jbig2_mmr.h"
  34. #include "jbig2_symbol_dict.h"
  35. #include "jbig2_text.h"
  36.  
  37. #if defined(OUTPUT_PBM) || defined(DUMP_SYMDICT)
  38. #include <stdio.h>
  39. #include "jbig2_image.h"
  40. #endif
  41.  
  42. /* Table 13 */
  43. typedef struct {
  44.   bool SDHUFF;
  45.   bool SDREFAGG;
  46.   int32_t SDNUMINSYMS;
  47.   Jbig2SymbolDict *SDINSYMS;
  48.   uint32_t SDNUMNEWSYMS;
  49.   uint32_t SDNUMEXSYMS;
  50.   Jbig2HuffmanTable *SDHUFFDH;
  51.   Jbig2HuffmanTable *SDHUFFDW;
  52.   Jbig2HuffmanTable *SDHUFFBMSIZE;
  53.   Jbig2HuffmanTable *SDHUFFAGGINST;
  54.   int SDTEMPLATE;
  55.   int8_t sdat[8];
  56.   bool SDRTEMPLATE;
  57.   int8_t sdrat[4];
  58. } Jbig2SymbolDictParams;
  59.  
  60.  
  61. /* Utility routines */
  62.  
  63. #ifdef DUMP_SYMDICT
  64. void
  65. jbig2_dump_symbol_dict(Jbig2Ctx *ctx, Jbig2Segment *segment)
  66. {
  67.     Jbig2SymbolDict *dict = (Jbig2SymbolDict *)segment->result;
  68.     int index;
  69.     char filename[24];
  70.  
  71.     if (dict == NULL) return;
  72.     jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
  73.         "dumping symbol dict as %d individual png files\n", dict->n_symbols);
  74.     for (index = 0; index < dict->n_symbols; index++) {
  75.         snprintf(filename, sizeof(filename), "symbol_%02d-%04d.png",
  76.                 segment->number, index);
  77.         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  78.           "dumping symbol %d/%d as '%s'", index, dict->n_symbols, filename);
  79. #ifdef HAVE_LIBPNG
  80.         jbig2_image_write_png_file(dict->glyphs[index], filename);
  81. #else
  82.         jbig2_image_write_pbm_file(dict->glyphs[index], filename);
  83. #endif
  84.     }
  85. }
  86. #endif /* DUMP_SYMDICT */
  87.  
  88. /* return a new empty symbol dict */
  89. Jbig2SymbolDict *
  90. jbig2_sd_new(Jbig2Ctx *ctx, int n_symbols)
  91. {
  92.    Jbig2SymbolDict *new = NULL;
  93.  
  94.    new = (Jbig2SymbolDict *)jbig2_alloc(ctx->allocator,
  95.                                 sizeof(Jbig2SymbolDict));
  96.    if (new != NULL) {
  97.      new->glyphs = (Jbig2Image **)jbig2_alloc(ctx->allocator,
  98.                                 n_symbols*sizeof(Jbig2Image*));
  99.      new->n_symbols = n_symbols;
  100.    } else {
  101.      return NULL;
  102.    }
  103.  
  104.    if (new->glyphs != NULL) {
  105.      memset(new->glyphs, 0, n_symbols*sizeof(Jbig2Image*));
  106.    } else {
  107.      jbig2_free(ctx->allocator, new);
  108.      return NULL;
  109.    }
  110.  
  111.    return new;
  112. }
  113.  
  114. /* release the memory associated with a symbol dict */
  115. void
  116. jbig2_sd_release(Jbig2Ctx *ctx, Jbig2SymbolDict *dict)
  117. {
  118.    int i;
  119.  
  120.    if (dict == NULL) return;
  121.    for (i = 0; i < dict->n_symbols; i++)
  122.      if (dict->glyphs[i]) jbig2_image_release(ctx, dict->glyphs[i]);
  123.    jbig2_free(ctx->allocator, dict->glyphs);
  124.    jbig2_free(ctx->allocator, dict);
  125. }
  126.  
  127. /* get a particular glyph by index */
  128. Jbig2Image *
  129. jbig2_sd_glyph(Jbig2SymbolDict *dict, unsigned int id)
  130. {
  131.    if (dict == NULL) return NULL;
  132.    return dict->glyphs[id];
  133. }
  134.  
  135. /* count the number of dictionary segments referred to by the given segment */
  136. int
  137. jbig2_sd_count_referred(Jbig2Ctx *ctx, Jbig2Segment *segment)
  138. {
  139.     int index;
  140.     Jbig2Segment *rsegment;
  141.     int n_dicts = 0;
  142.  
  143.     for (index = 0; index < segment->referred_to_segment_count; index++) {
  144.         rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
  145.         if (rsegment && ((rsegment->flags & 63) == 0)) n_dicts++;
  146.     }
  147.  
  148.     return (n_dicts);
  149. }
  150.  
  151. /* return an array of pointers to symbol dictionaries referred to by the given segment */
  152. Jbig2SymbolDict **
  153. jbig2_sd_list_referred(Jbig2Ctx *ctx, Jbig2Segment *segment)
  154. {
  155.     int index;
  156.     Jbig2Segment *rsegment;
  157.     Jbig2SymbolDict **dicts;
  158.     int n_dicts = jbig2_sd_count_referred(ctx, segment);
  159.     int dindex = 0;
  160.  
  161.     dicts = jbig2_alloc(ctx->allocator, sizeof(Jbig2SymbolDict *) * n_dicts);
  162.     for (index = 0; index < segment->referred_to_segment_count; index++) {
  163.         rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
  164.         if (rsegment && ((rsegment->flags & 63) == 0)) {
  165.             /* add this referred to symbol dictionary */
  166.             dicts[dindex++] = (Jbig2SymbolDict *)rsegment->result;
  167.         }
  168.     }
  169.  
  170.     if (dindex != n_dicts) {
  171.         /* should never happen */
  172.         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  173.             "counted %d symbol dictionaries but build a list with %d.\n",
  174.             n_dicts, dindex);
  175.     }
  176.  
  177.     return (dicts);
  178. }
  179.  
  180. /* generate a new symbol dictionary by concatenating a list of
  181.    existing dictionaries */
  182. Jbig2SymbolDict *
  183. jbig2_sd_cat(Jbig2Ctx *ctx, int n_dicts, Jbig2SymbolDict **dicts)
  184. {
  185.   int i,j,k, symbols;
  186.   Jbig2SymbolDict *new = NULL;
  187.  
  188.   /* count the imported symbols and allocate a new array */
  189.   symbols = 0;
  190.   for(i = 0; i < n_dicts; i++)
  191.     symbols += dicts[i]->n_symbols;
  192.  
  193.   /* fill a new array with cloned glyph pointers */
  194.   new = jbig2_sd_new(ctx, symbols);
  195.   if (new != NULL) {
  196.     k = 0;
  197.     for (i = 0; i < n_dicts; i++)
  198.       for (j = 0; j < dicts[i]->n_symbols; j++)
  199.         new->glyphs[k++] = jbig2_image_clone(ctx, dicts[i]->glyphs[j]);
  200.   }
  201.  
  202.   return new;
  203. }
  204.  
  205.  
  206. /* Decoding routines */
  207.  
  208. /* 6.5 */
  209. static Jbig2SymbolDict *
  210. jbig2_decode_symbol_dict(Jbig2Ctx *ctx,
  211.                          Jbig2Segment *segment,
  212.                          const Jbig2SymbolDictParams *params,
  213.                          const byte *data, size_t size,
  214.                          Jbig2ArithCx *GB_stats,
  215.                          Jbig2ArithCx *GR_stats)
  216. {
  217.   Jbig2SymbolDict *SDNEWSYMS;
  218.   Jbig2SymbolDict *SDEXSYMS;
  219.   int32_t HCHEIGHT;
  220.   uint32_t NSYMSDECODED;
  221.   int32_t SYMWIDTH, TOTWIDTH;
  222.   uint32_t HCFIRSTSYM;
  223.   uint32_t *SDNEWSYMWIDTHS = NULL;
  224.   int SBSYMCODELEN = 0;
  225.   Jbig2WordStream *ws = NULL;
  226.   Jbig2HuffmanState *hs = NULL;
  227.   Jbig2HuffmanTable *SDHUFFRDX = NULL;
  228.   Jbig2ArithState *as = NULL;
  229.   Jbig2ArithIntCtx *IADH = NULL;
  230.   Jbig2ArithIntCtx *IADW = NULL;
  231.   Jbig2ArithIntCtx *IAEX = NULL;
  232.   Jbig2ArithIntCtx *IAAI = NULL;
  233.   Jbig2ArithIaidCtx *IAID = NULL;
  234.   Jbig2ArithIntCtx *IARDX = NULL;
  235.   Jbig2ArithIntCtx *IARDY = NULL;
  236.   int code = 0;
  237.   Jbig2SymbolDict **refagg_dicts;
  238.   int n_refagg_dicts = 1;
  239.  
  240.   Jbig2TextRegionParams *tparams = NULL;
  241.  
  242.   /* 6.5.5 (3) */
  243.   HCHEIGHT = 0;
  244.   NSYMSDECODED = 0;
  245.  
  246.   ws = jbig2_word_stream_buf_new(ctx, data, size);
  247.  
  248.   if (!params->SDHUFF) {
  249.       as = jbig2_arith_new(ctx, ws);
  250.       IADH = jbig2_arith_int_ctx_new(ctx);
  251.       IADW = jbig2_arith_int_ctx_new(ctx);
  252.       IAEX = jbig2_arith_int_ctx_new(ctx);
  253.       IAAI = jbig2_arith_int_ctx_new(ctx);
  254.       if (params->SDREFAGG) {
  255.           int tmp = params->SDINSYMS->n_symbols + params->SDNUMNEWSYMS;
  256.           for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < tmp; SBSYMCODELEN++);
  257.           IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
  258.           IARDX = jbig2_arith_int_ctx_new(ctx);
  259.           IARDY = jbig2_arith_int_ctx_new(ctx);
  260.       }
  261.   } else {
  262.       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  263.         "huffman coded symbol dictionary");
  264.       hs = jbig2_huffman_new(ctx, ws);
  265.       SDHUFFRDX = jbig2_build_huffman_table(ctx,
  266.                                 &jbig2_huffman_params_O);
  267.       if (!params->SDREFAGG) {
  268.           SDNEWSYMWIDTHS = jbig2_alloc(ctx->allocator,
  269.                 sizeof(*SDNEWSYMWIDTHS)*params->SDNUMNEWSYMS);
  270.           if (SDNEWSYMWIDTHS == NULL) {
  271.             jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  272.                 "could not allocate storage for symbol widths");
  273.             return NULL;
  274.           }
  275.       }
  276.   }
  277.  
  278.   SDNEWSYMS = jbig2_sd_new(ctx, params->SDNUMNEWSYMS);
  279.  
  280.   /* 6.5.5 (4a) */
  281.   while (NSYMSDECODED < params->SDNUMNEWSYMS) {
  282.       int32_t HCDH, DW;
  283.  
  284.       /* 6.5.6 */
  285.       if (params->SDHUFF) {
  286.           HCDH = jbig2_huffman_get(hs, params->SDHUFFDH, &code);
  287.       } else {
  288.           code = jbig2_arith_int_decode(IADH, as, &HCDH);
  289.       }
  290.  
  291.       if (code != 0) {
  292.         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  293.           "error or OOB decoding height class delta (%d)\n", code);
  294.       }
  295.  
  296.       /* 6.5.5 (4b) */
  297.       HCHEIGHT = HCHEIGHT + HCDH;
  298.       SYMWIDTH = 0;
  299.       TOTWIDTH = 0;
  300.       HCFIRSTSYM = NSYMSDECODED;
  301.  
  302.       if (HCHEIGHT < 0) {
  303.           /* todo: mem cleanup */
  304.           code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  305.                            "Invalid HCHEIGHT value");
  306.           return NULL;
  307.       }
  308. #ifdef JBIG2_DEBUG
  309.       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  310.         "HCHEIGHT = %d", HCHEIGHT);
  311. #endif
  312.       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  313.         "decoding height class %d with %d syms decoded", HCHEIGHT, NSYMSDECODED);
  314.  
  315.       for (;;) {
  316.           /* check for broken symbol table */
  317.           if (NSYMSDECODED > params->SDNUMNEWSYMS)
  318.             {
  319.               /* todo: mem cleanup? */
  320.               jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  321.                 "No OOB signalling end of height class %d", HCHEIGHT);
  322.               break;
  323.             }
  324.           /* 6.5.7 */
  325.           if (params->SDHUFF) {
  326.               DW = jbig2_huffman_get(hs, params->SDHUFFDW, &code);
  327.           } else {
  328.               code = jbig2_arith_int_decode(IADW, as, &DW);
  329.           }
  330.  
  331.           /* 6.5.5 (4c.i) */
  332.           if (code == 1) {
  333.             jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  334.             " OOB signals end of height class %d", HCHEIGHT);
  335.             break;
  336.           }
  337.           SYMWIDTH = SYMWIDTH + DW;
  338.           TOTWIDTH = TOTWIDTH + SYMWIDTH;
  339.           if (SYMWIDTH < 0) {
  340.               /* todo: mem cleanup */
  341.               code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  342.                 "Invalid SYMWIDTH value (%d) at symbol %d", SYMWIDTH, NSYMSDECODED+1);
  343.               return NULL;
  344.           }
  345. #ifdef JBIG2_DEBUG
  346.           jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  347.             "SYMWIDTH = %d TOTWIDTH = %d", SYMWIDTH, TOTWIDTH);
  348. #endif
  349.           /* 6.5.5 (4c.ii) */
  350.           if (!params->SDHUFF || params->SDREFAGG) {
  351. #ifdef JBIG2_DEBUG
  352.                 jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  353.                   "SDHUFF = %d; SDREFAGG = %d", params->SDHUFF, params->SDREFAGG);
  354. #endif
  355.               /* 6.5.8 */
  356.               if (!params->SDREFAGG) {
  357.                   Jbig2GenericRegionParams region_params;
  358.                   int sdat_bytes;
  359.                   Jbig2Image *image;
  360.  
  361.                   /* Table 16 */
  362.                   region_params.MMR = 0;
  363.                   region_params.GBTEMPLATE = params->SDTEMPLATE;
  364.                   region_params.TPGDON = 0;
  365.                   region_params.USESKIP = 0;
  366.                   sdat_bytes = params->SDTEMPLATE == 0 ? 8 : 2;
  367.                   memcpy(region_params.gbat, params->sdat, sdat_bytes);
  368.  
  369.                   image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
  370.  
  371.                   code = jbig2_decode_generic_region(ctx, segment, &region_params,
  372.                                                      as, image, GB_stats);
  373.                   /* todo: handle errors */
  374.  
  375.                   SDNEWSYMS->glyphs[NSYMSDECODED] = image;
  376.  
  377.               } else {
  378.                   /* 6.5.8.2 refinement/aggregate symbol */
  379.                   uint32_t REFAGGNINST;
  380.  
  381.                   if (params->SDHUFF) {
  382.                       REFAGGNINST = jbig2_huffman_get(hs, params->SDHUFFAGGINST, &code);
  383.                   } else {
  384.                       code = jbig2_arith_int_decode(IAAI, as, (int32_t*)&REFAGGNINST);
  385.                   }
  386.                   if (code || (int32_t)REFAGGNINST <= 0) {
  387.                       code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  388.                         "invalid number of symbols or OOB in aggregate glyph");
  389.                       return NULL;
  390.                   }
  391.  
  392.                   jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  393.                     "aggregate symbol coding (%d instances)", REFAGGNINST);
  394.  
  395.                   if (REFAGGNINST > 1) {
  396.                       Jbig2Image *image;
  397.                       int i;
  398.  
  399.                       if (tparams == NULL)
  400.                       {
  401.                           /* First time through, we need to initialise the */
  402.                           /* various tables for Huffman or adaptive encoding */
  403.                           /* as well as the text region parameters structure */
  404.                           refagg_dicts = jbig2_alloc(ctx->allocator, sizeof(Jbig2SymbolDict *) * n_refagg_dicts);
  405.                           if (refagg_dicts == NULL) {
  406.                               code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  407.                                "Out of memory allocating dictionary array");
  408.                               return NULL;
  409.                           }
  410.                           refagg_dicts[0] = jbig2_sd_new(ctx, params->SDNUMINSYMS + params->SDNUMNEWSYMS);
  411.                           if (refagg_dicts[0] == NULL) {
  412.                               code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  413.                                "Out of memory allocating symbol dictionary");
  414.                               jbig2_free(ctx->allocator, refagg_dicts);
  415.                               return NULL;
  416.                           }
  417.                           refagg_dicts[0]->n_symbols = params->SDNUMINSYMS + params->SDNUMNEWSYMS;
  418.                           for (i=0;i < params->SDNUMINSYMS;i++)
  419.                           {
  420.                               refagg_dicts[0]->glyphs[i] = jbig2_image_clone(ctx, params->SDINSYMS->glyphs[i]);
  421.                           }
  422.  
  423.                           tparams = jbig2_alloc(ctx->allocator, sizeof(Jbig2TextRegionParams));
  424.                           if (tparams == NULL) {
  425.                               code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  426.                               "Out of memory creating text region params");
  427.                               jbig2_sd_release(ctx, refagg_dicts[0]);
  428.                               jbig2_free(ctx->allocator, refagg_dicts);
  429.                               return NULL;
  430.                           }
  431.                           if (!params->SDHUFF) {
  432.                               /* Values from Table 17, section 6.5.8.2 (2) */
  433.                               tparams->IADT = jbig2_arith_int_ctx_new(ctx);
  434.                               tparams->IAFS = jbig2_arith_int_ctx_new(ctx);
  435.                               tparams->IADS = jbig2_arith_int_ctx_new(ctx);
  436.                               tparams->IAIT = jbig2_arith_int_ctx_new(ctx);
  437.                               /* Table 31 */
  438.                               for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) <
  439.                                   (int)(params->SDNUMINSYMS + params->SDNUMNEWSYMS); SBSYMCODELEN++);
  440.                               tparams->IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
  441.                               tparams->IARI = jbig2_arith_int_ctx_new(ctx);
  442.                               tparams->IARDW = jbig2_arith_int_ctx_new(ctx);
  443.                               tparams->IARDH = jbig2_arith_int_ctx_new(ctx);
  444.                               tparams->IARDX = jbig2_arith_int_ctx_new(ctx);
  445.                               tparams->IARDY = jbig2_arith_int_ctx_new(ctx);
  446.                           } else {
  447.                               tparams->SBHUFFFS = jbig2_build_huffman_table(ctx,
  448.                                 &jbig2_huffman_params_F);   /* Table B.6 */
  449.                               tparams->SBHUFFDS = jbig2_build_huffman_table(ctx,
  450.                                 &jbig2_huffman_params_H);  /* Table B.8 */
  451.                               tparams->SBHUFFDT = jbig2_build_huffman_table(ctx,
  452.                                 &jbig2_huffman_params_K);  /* Table B.11 */
  453.                               tparams->SBHUFFRDW = jbig2_build_huffman_table(ctx,
  454.                                 &jbig2_huffman_params_O); /* Table B.15 */
  455.                               tparams->SBHUFFRDH = jbig2_build_huffman_table(ctx,
  456.                                 &jbig2_huffman_params_O); /* Table B.15 */
  457.                               tparams->SBHUFFRDX = jbig2_build_huffman_table(ctx,
  458.                                 &jbig2_huffman_params_O); /* Table B.15 */
  459.                               tparams->SBHUFFRDY = jbig2_build_huffman_table(ctx,
  460.                                 &jbig2_huffman_params_O); /* Table B.15 */
  461.                           }
  462.                           tparams->SBHUFF = params->SDHUFF;
  463.                           tparams->SBREFINE = 1;
  464.                           tparams->SBSTRIPS = 1;
  465.                           tparams->SBDEFPIXEL = 0;
  466.                           tparams->SBCOMBOP = JBIG2_COMPOSE_OR;
  467.                           tparams->TRANSPOSED = 0;
  468.                           tparams->REFCORNER = JBIG2_CORNER_TOPLEFT;
  469.                           tparams->SBDSOFFSET = 0;
  470.                           tparams->SBRTEMPLATE = params->SDRTEMPLATE;
  471.                       }
  472.                       tparams->SBNUMINSTANCES = REFAGGNINST;
  473.  
  474.                       image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
  475.                       if (image == NULL) {
  476.                           code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  477.                            "Out of memory creating symbol image");
  478.                           jbig2_free(ctx->allocator, tparams);
  479.                           jbig2_sd_release(ctx, refagg_dicts[0]);
  480.                           jbig2_free(ctx->allocator, refagg_dicts);
  481.                           return NULL;
  482.                       }
  483.  
  484.                       /* multiple symbols are handled as a text region */
  485.                       jbig2_decode_text_region(ctx, segment, tparams, (const Jbig2SymbolDict * const *)refagg_dicts,
  486.                           n_refagg_dicts, image, data, size, GR_stats, as, (Jbig2WordStream *)NULL);
  487.  
  488.                       SDNEWSYMS->glyphs[NSYMSDECODED] = image;
  489.                       refagg_dicts[0]->glyphs[params->SDNUMINSYMS + NSYMSDECODED] = jbig2_image_clone(ctx, SDNEWSYMS->glyphs[NSYMSDECODED]);
  490.                   } else {
  491.                       /* 6.5.8.2.2 */
  492.                       /* bool SBHUFF = params->SDHUFF; */
  493.                       Jbig2RefinementRegionParams rparams;
  494.                       Jbig2Image *image;
  495.                       uint32_t ID;
  496.                       int32_t RDX, RDY;
  497.                       int ninsyms = params->SDINSYMS->n_symbols;
  498.  
  499.                       if (params->SDHUFF) {
  500.                           ID = jbig2_huffman_get_bits(hs, SBSYMCODELEN);
  501.                           RDX = jbig2_huffman_get(hs, SDHUFFRDX, &code);
  502.                           RDY = jbig2_huffman_get(hs, SDHUFFRDX, &code);
  503.                       } else {
  504.                           code = jbig2_arith_iaid_decode(IAID, as, (int32_t*)&ID);
  505.                           code = jbig2_arith_int_decode(IARDX, as, &RDX);
  506.                           code = jbig2_arith_int_decode(IARDY, as, &RDY);
  507.                       }
  508.  
  509.                       if (ID >= ninsyms+NSYMSDECODED) {
  510.                         code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  511.                           "refinement references unknown symbol %d", ID);
  512.                         return NULL;
  513.                       }
  514.  
  515.                       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  516.                         "symbol is a refinement of id %d with the refinement applied at (%d,%d)",
  517.                         ID, RDX, RDY);
  518.  
  519.                       image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
  520.  
  521.                       /* Table 18 */
  522.                       rparams.GRTEMPLATE = params->SDRTEMPLATE;
  523.                       rparams.reference = (ID < ninsyms) ?
  524.                                         params->SDINSYMS->glyphs[ID] :
  525.                                         SDNEWSYMS->glyphs[ID-ninsyms];
  526.                       rparams.DX = RDX;
  527.                       rparams.DY = RDY;
  528.                       rparams.TPGRON = 0;
  529.                       memcpy(rparams.grat, params->sdrat, 4);
  530.                       jbig2_decode_refinement_region(ctx, segment,
  531.                           &rparams, as, image, GR_stats);
  532.  
  533.                       SDNEWSYMS->glyphs[NSYMSDECODED] = image;
  534.  
  535.                   }
  536.                }
  537.  
  538. #ifdef OUTPUT_PBM
  539.                   {
  540.                     char name[64];
  541.                     FILE *out;
  542.                     snprintf(name, 64, "sd.%04d.%04d.pbm",
  543.                              segment->number, NSYMSDECODED);
  544.                     out = fopen(name, "wb");
  545.                     jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
  546.                     jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  547.                         "writing out glyph as '%s' ...", name);
  548.                     fclose(out);
  549.                   }
  550. #endif
  551.  
  552.           }
  553.  
  554.           /* 6.5.5 (4c.iii) */
  555.           if (params->SDHUFF && !params->SDREFAGG) {
  556.             SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
  557.           }
  558.  
  559.           jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  560.             "decoded symbol %d of %d (%dx%d)",
  561.                 NSYMSDECODED, params->SDNUMNEWSYMS,
  562.                 SYMWIDTH, HCHEIGHT);
  563.  
  564.           /* 6.5.5 (4c.iv) */
  565.           NSYMSDECODED = NSYMSDECODED + 1;
  566.  
  567.       } /* end height class decode loop */
  568.  
  569.       /* 6.5.5 (4d) */
  570.       if (params->SDHUFF && !params->SDREFAGG) {
  571.         /* 6.5.9 */
  572.         Jbig2Image *image;
  573.         int BMSIZE = jbig2_huffman_get(hs, params->SDHUFFBMSIZE, &code);
  574.         int j, x;
  575.  
  576.         if (code || (BMSIZE < 0)) {
  577.           jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  578.             "error decoding size of collective bitmap!");
  579.           /* todo: memory cleanup */
  580.           return NULL;
  581.         }
  582.  
  583.         /* skip any bits before the next byte boundary */
  584.         jbig2_huffman_skip(hs);
  585.  
  586.         image = jbig2_image_new(ctx, TOTWIDTH, HCHEIGHT);
  587.         if (image == NULL) {
  588.           jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  589.             "could not allocate collective bitmap image!");
  590.           /* todo: memory cleanup */
  591.           return NULL;
  592.         }
  593.  
  594.         if (BMSIZE == 0) {
  595.           /* if BMSIZE == 0 bitmap is uncompressed */
  596.           const byte *src = data + jbig2_huffman_offset(hs);
  597.           const int stride = (image->width >> 3) +
  598.                 ((image->width & 7) ? 1 : 0);
  599.           byte *dst = image->data;
  600.  
  601.           BMSIZE = image->height * stride;
  602.           jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  603.             "reading %dx%d uncompressed bitmap"
  604.             " for %d symbols (%d bytes)",
  605.             image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE);
  606.  
  607.           for (j = 0; j < image->height; j++) {
  608.             memcpy(dst, src, stride);
  609.             dst += image->stride;
  610.             src += stride;
  611.           }
  612.         } else {
  613.           Jbig2GenericRegionParams rparams;
  614.  
  615.           jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
  616.             "reading %dx%d collective bitmap for %d symbols (%d bytes)",
  617.             image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE);
  618.  
  619.           rparams.MMR = 1;
  620.           code = jbig2_decode_generic_mmr(ctx, segment, &rparams,
  621.             data + jbig2_huffman_offset(hs), BMSIZE, image);
  622.           if (code) {
  623.             jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  624.               "error decoding MMR bitmap image!");
  625.             /* todo: memory cleanup */
  626.             return NULL;
  627.           }
  628.         }
  629.  
  630.         /* advance past the data we've just read */
  631.         jbig2_huffman_advance(hs, BMSIZE);
  632.  
  633.         /* copy the collective bitmap into the symbol dictionary */
  634.         x = 0;
  635.         for (j = HCFIRSTSYM; j < NSYMSDECODED; j++) {
  636.           Jbig2Image *glyph;
  637.           glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT);
  638.           jbig2_image_compose(ctx, glyph, image,
  639.                 -x, 0, JBIG2_COMPOSE_REPLACE);
  640.           x += SDNEWSYMWIDTHS[j];
  641.           SDNEWSYMS->glyphs[j] = glyph;
  642.         }
  643.         jbig2_image_release(ctx, image);
  644.       }
  645.  
  646.   } /* end of symbol decode loop */
  647.  
  648.   if (tparams != NULL)
  649.   {
  650.       if (!params->SDHUFF)
  651.       {
  652.           jbig2_arith_int_ctx_free(ctx, tparams->IADT);
  653.           jbig2_arith_int_ctx_free(ctx, tparams->IAFS);
  654.           jbig2_arith_int_ctx_free(ctx, tparams->IADS);
  655.           jbig2_arith_int_ctx_free(ctx, tparams->IAIT);
  656.           jbig2_arith_iaid_ctx_free(ctx, tparams->IAID);
  657.           jbig2_arith_int_ctx_free(ctx, tparams->IARI);
  658.           jbig2_arith_int_ctx_free(ctx, tparams->IARDW);
  659.           jbig2_arith_int_ctx_free(ctx, tparams->IARDH);
  660.           jbig2_arith_int_ctx_free(ctx, tparams->IARDX);
  661.           jbig2_arith_int_ctx_free(ctx, tparams->IARDY);
  662.       }
  663.       else
  664.       {
  665.           jbig2_release_huffman_table(ctx, tparams->SBHUFFFS);
  666.           jbig2_release_huffman_table(ctx, tparams->SBHUFFDS);
  667.           jbig2_release_huffman_table(ctx, tparams->SBHUFFDT);
  668.           jbig2_release_huffman_table(ctx, tparams->SBHUFFRDX);
  669.           jbig2_release_huffman_table(ctx, tparams->SBHUFFRDY);
  670.           jbig2_release_huffman_table(ctx, tparams->SBHUFFRDW);
  671.           jbig2_release_huffman_table(ctx, tparams->SBHUFFRDH);
  672.       }
  673.       jbig2_free(ctx->allocator, tparams);
  674.       tparams = NULL;
  675.       jbig2_sd_release(ctx, refagg_dicts[0]);
  676.       jbig2_free(ctx->allocator, refagg_dicts);
  677.   }
  678.  
  679.   jbig2_free(ctx->allocator, GB_stats);
  680.  
  681.   /* 6.5.10 */
  682.   SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS);
  683.   {
  684.     int i = 0;
  685.     int j = 0;
  686.     int k, m, exflag = 0;
  687.     int32_t exrunlength;
  688.  
  689.     if (params->SDINSYMS != NULL)
  690.       m = params->SDINSYMS->n_symbols;
  691.     else
  692.       m = 0;
  693.     while (j < params->SDNUMEXSYMS) {
  694.       if (params->SDHUFF)
  695.         /* FIXME: implement reading from huff table B.1 */
  696.         exrunlength = params->SDNUMEXSYMS;
  697.       else
  698.         code = jbig2_arith_int_decode(IAEX, as, &exrunlength);
  699.       if (exrunlength > params->SDNUMEXSYMS - j) {
  700.         jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  701.           "runlength too large in export symbol table (%d > %d - %d)\n",
  702.           exrunlength, params->SDNUMEXSYMS, j);
  703.         jbig2_sd_release(ctx, SDEXSYMS);
  704.         /* skip to the cleanup code and return SDEXSYMS = NULL */
  705.         SDEXSYMS = NULL;
  706.         break;
  707.       }
  708.       for(k = 0; k < exrunlength; k++)
  709.         if (exflag) {
  710.           SDEXSYMS->glyphs[j++] = (i < m) ?
  711.             jbig2_image_clone(ctx, params->SDINSYMS->glyphs[i]) :
  712.             jbig2_image_clone(ctx, SDNEWSYMS->glyphs[i-m]);
  713.           i++;
  714.         }
  715.         exflag = !exflag;
  716.     }
  717.   }
  718.  
  719.   jbig2_sd_release(ctx, SDNEWSYMS);
  720.  
  721.   if (!params->SDHUFF) {
  722.       jbig2_arith_int_ctx_free(ctx, IADH);
  723.       jbig2_arith_int_ctx_free(ctx, IADW);
  724.       jbig2_arith_int_ctx_free(ctx, IAEX);
  725.       jbig2_arith_int_ctx_free(ctx, IAAI);
  726.       if (params->SDREFAGG) {
  727.         jbig2_arith_iaid_ctx_free(ctx, IAID);
  728.         jbig2_arith_int_ctx_free(ctx, IARDX);
  729.         jbig2_arith_int_ctx_free(ctx, IARDY);
  730.       }
  731.       jbig2_free(ctx->allocator, as);
  732.   } else {
  733.       if (params->SDREFAGG) {
  734.         jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
  735.       }
  736.       jbig2_release_huffman_table(ctx, SDHUFFRDX);
  737.       jbig2_free(ctx->allocator, hs);
  738.   }
  739.  
  740.   jbig2_word_stream_buf_free(ctx, ws);
  741.  
  742.   return SDEXSYMS;
  743. }
  744.  
  745. /* 7.4.2 */
  746. int
  747. jbig2_symbol_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment,
  748.                         const byte *segment_data)
  749. {
  750.   Jbig2SymbolDictParams params;
  751.   uint16_t flags;
  752.   int sdat_bytes;
  753.   int offset;
  754.   Jbig2ArithCx *GB_stats = NULL;
  755.   Jbig2ArithCx *GR_stats = NULL;
  756.  
  757.   if (segment->data_length < 10)
  758.     goto too_short;
  759.  
  760.   /* 7.4.2.1.1 */
  761.   flags = jbig2_get_int16(segment_data);
  762.   params.SDHUFF = flags & 1;
  763.   params.SDREFAGG = (flags >> 1) & 1;
  764.   params.SDTEMPLATE = (flags >> 10) & 3;
  765.   params.SDRTEMPLATE = (flags >> 12) & 1;
  766.  
  767.   params.SDHUFFDH = NULL;
  768.   params.SDHUFFDW = NULL;
  769.   params.SDHUFFBMSIZE = NULL;
  770.   params.SDHUFFAGGINST = NULL;
  771.  
  772.   if (params.SDHUFF) {
  773.     switch ((flags & 0x000c) >> 2) {
  774.       case 0: /* Table B.4 */
  775.         params.SDHUFFDH = jbig2_build_huffman_table(ctx,
  776.                                        &jbig2_huffman_params_D);
  777.         break;
  778.       case 1: /* Table B.5 */
  779.         params.SDHUFFDH = jbig2_build_huffman_table(ctx,
  780.                                        &jbig2_huffman_params_E);
  781.         break;
  782.       case 3: /* Custom table from referred segment */
  783.         /* We handle this case later by leaving the table as NULL */
  784.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  785.             "symbol dictionary uses custom DH huffman table (NYI)");
  786.       case 2:
  787.       default:
  788.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  789.             "symbol dictionary specified invalid huffman table");
  790.         break;
  791.     }
  792.     switch ((flags & 0x0030) >> 4) {
  793.       case 0: /* Table B.2 */
  794.         params.SDHUFFDW = jbig2_build_huffman_table(ctx,
  795.                                        &jbig2_huffman_params_B);
  796.         break;
  797.       case 1: /* Table B.3 */
  798.         params.SDHUFFDW = jbig2_build_huffman_table(ctx,
  799.                                        &jbig2_huffman_params_C);
  800.         break;
  801.       case 3: /* Custom table from referred segment */
  802.         /* We handle this case later by leaving the table as NULL */
  803.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  804.             "symbol dictionary uses custom DW huffman table (NYI)");
  805.       case 2:
  806.       default:
  807.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  808.             "symbol dictionary specified invalid huffman table");
  809.         break;
  810.     }
  811.     if (flags & 0x0040) {
  812.         /* Custom table from referred segment */
  813.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  814.             "symbol dictionary uses custom BMSIZE huffman table (NYI)");
  815.     } else {
  816.         /* Table B.1 */
  817.         params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx,
  818.                                         &jbig2_huffman_params_A);
  819.     }
  820.     if (flags & 0x0080) {
  821.         /* Custom table from referred segment */
  822.         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  823.             "symbol dictionary uses custom REFAGG huffman table (NYI)");
  824.     } else {
  825.         /* Table B.1 */
  826.         params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx,
  827.                                         &jbig2_huffman_params_A);
  828.     }
  829.   }
  830.  
  831.   /* FIXME: there are quite a few of these conditions to check */
  832.   /* maybe #ifdef CONFORMANCE and a separate routine */
  833.   if (!params.SDHUFF) {
  834.     if (flags & 0x000c) {
  835.       jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  836.                   "SDHUFF is zero, but contrary to spec SDHUFFDH is not.");
  837.     }
  838.     if (flags & 0x0030) {
  839.       jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  840.                   "SDHUFF is zero, but contrary to spec SDHUFFDW is not.");
  841.     }
  842.   }
  843.  
  844.   if (flags & 0x0080) {
  845.       jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  846.         "bitmap coding context is used (NYI) symbol data likely to be garbage!");
  847.   }
  848.  
  849.   /* 7.4.2.1.2 */
  850.   sdat_bytes = params.SDHUFF ? 0 : params.SDTEMPLATE == 0 ? 8 : 2;
  851.   memcpy(params.sdat, segment_data + 2, sdat_bytes);
  852.   offset = 2 + sdat_bytes;
  853.  
  854.   /* 7.4.2.1.3 */
  855.   if (params.SDREFAGG && !params.SDRTEMPLATE) {
  856.       if (offset + 4 > segment->data_length)
  857.         goto too_short;
  858.       memcpy(params.sdrat, segment_data + offset, 4);
  859.       offset += 4;
  860.   } else {
  861.       /* sdrat is meaningless if SDRTEMPLATE is 1, but set a value
  862.          to avoid confusion if anybody looks */
  863.       memset(params.sdrat, 0, 4);
  864.   }
  865.  
  866.   if (offset + 8 > segment->data_length)
  867.     goto too_short;
  868.  
  869.   /* 7.4.2.1.4 */
  870.   params.SDNUMEXSYMS = jbig2_get_int32(segment_data + offset);
  871.   /* 7.4.2.1.5 */
  872.   params.SDNUMNEWSYMS = jbig2_get_int32(segment_data + offset + 4);
  873.   offset += 8;
  874.  
  875.   jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
  876.               "symbol dictionary, flags=%04x, %d exported syms, %d new syms",
  877.               flags, params.SDNUMEXSYMS, params.SDNUMNEWSYMS);
  878.  
  879.   /* 7.4.2.2 (2) */
  880.   {
  881.     int n_dicts = jbig2_sd_count_referred(ctx, segment);
  882.     Jbig2SymbolDict **dicts = NULL;
  883.  
  884.     params.SDINSYMS = NULL;
  885.     if (n_dicts > 0) {
  886.       dicts = jbig2_sd_list_referred(ctx, segment);
  887.       params.SDINSYMS = jbig2_sd_cat(ctx, n_dicts, dicts);
  888.     }
  889.     if (params.SDINSYMS != NULL) {
  890.       params.SDNUMINSYMS = params.SDINSYMS->n_symbols;
  891.     } else {
  892.      params.SDNUMINSYMS = 0;
  893.     }
  894.   }
  895.  
  896.   /* 7.4.2.2 (4) */
  897.   if (!params.SDHUFF) {
  898.       int stats_size = params.SDTEMPLATE == 0 ? 65536 :
  899.         params.SDTEMPLATE == 1 ? 8192 : 1024;
  900.       GB_stats = jbig2_alloc(ctx->allocator, stats_size);
  901.       memset(GB_stats, 0, stats_size);
  902.       if (params.SDREFAGG) {
  903.         stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13;
  904.         GR_stats = jbig2_alloc(ctx->allocator, stats_size);
  905.         memset(GR_stats, 0, stats_size);
  906.       }
  907.   }
  908.  
  909.   if (flags & 0x0100) {
  910.       jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
  911.         "segment marks bitmap coding context as retained (NYI)");
  912.   }
  913.  
  914.   segment->result = (void *)jbig2_decode_symbol_dict(ctx, segment,
  915.                                   &params,
  916.                                   segment_data + offset,
  917.                                   segment->data_length - offset,
  918.                                   GB_stats, GR_stats);
  919. #ifdef DUMP_SYMDICT
  920.   if (segment->result) jbig2_dump_symbol_dict(ctx, segment);
  921. #endif
  922.  
  923.   if (params.SDHUFF) {
  924.       jbig2_release_huffman_table(ctx, params.SDHUFFDH);
  925.       jbig2_release_huffman_table(ctx, params.SDHUFFDW);
  926.       jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
  927.       jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
  928.   }
  929.  
  930.   /* todo: retain or free GB_stats, GR_stats */
  931.  
  932.   return (segment->result != NULL) ? 0 : -1;
  933.  
  934.  too_short:
  935.   return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
  936.                      "Segment too short");
  937. }
  938.