Subversion Repositories Kolibri OS

Rev

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

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