jbig2_symbol_dict.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 932 行 · 第 1/2 页

SVN-BASE
932
字号
			  tparams->SBSTRIPS = 1;
			  tparams->SBDEFPIXEL = 0;
			  tparams->SBCOMBOP = JBIG2_COMPOSE_OR;
			  tparams->TRANSPOSED = 0;
			  tparams->REFCORNER = JBIG2_CORNER_TOPLEFT;
			  tparams->SBDSOFFSET = 0;
			  tparams->SBRTEMPLATE = params->SDRTEMPLATE;
		      }
		      tparams->SBNUMINSTANCES = REFAGGNINST;

      		      image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);
		      if (image == NULL) {
			  code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
			   "Out of memory creating symbol image");
		          jbig2_free(ctx->allocator, tparams);
			  jbig2_sd_release(ctx, refagg_dicts[0]);
		          jbig2_free(ctx->allocator, refagg_dicts);
		          return NULL;
		      }

		      /* multiple symbols are handled as a text region */
		      jbig2_decode_text_region(ctx, segment, tparams, (const Jbig2SymbolDict * const *)refagg_dicts, 
			  n_refagg_dicts, image, data, size, GR_stats, as, (Jbig2WordStream *)NULL);

		      SDNEWSYMS->glyphs[NSYMSDECODED] = image;
		      refagg_dicts[0]->glyphs[params->SDNUMINSYMS + NSYMSDECODED] = jbig2_image_clone(ctx, SDNEWSYMS->glyphs[NSYMSDECODED]);
		  } else {
		      /* 6.5.8.2.2 */
		      /* bool SBHUFF = params->SDHUFF; */
		      Jbig2RefinementRegionParams rparams;
		      Jbig2Image *image;
		      uint32_t ID;
		      int32_t RDX, RDY;
		      int ninsyms = params->SDINSYMS->n_symbols;

		      if (params->SDHUFF) {
			  ID = jbig2_huffman_get_bits(hs, SBSYMCODELEN);
			  RDX = jbig2_huffman_get(hs, SDHUFFRDX, &code);
			  RDY = jbig2_huffman_get(hs, SDHUFFRDX, &code);
		      } else {
			  code = jbig2_arith_iaid_decode(IAID, as, (int32_t*)&ID);
		          code = jbig2_arith_int_decode(IARDX, as, &RDX);
		          code = jbig2_arith_int_decode(IARDY, as, &RDY);
		      }

		      if (ID >= ninsyms+NSYMSDECODED) {
			code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
			  "refinement references unknown symbol %d", ID);
			return NULL;
		      }

		      jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
			"symbol is a refinement of id %d with the refinement applied at (%d,%d)",
			ID, RDX, RDY);

		      image = jbig2_image_new(ctx, SYMWIDTH, HCHEIGHT);

		      /* Table 18 */
		      rparams.GRTEMPLATE = params->SDRTEMPLATE;
		      rparams.reference = (ID < ninsyms) ?
					params->SDINSYMS->glyphs[ID] :
					SDNEWSYMS->glyphs[ID-ninsyms];
		      rparams.DX = RDX;
		      rparams.DY = RDY;
		      rparams.TPGRON = 0;
		      memcpy(rparams.grat, params->sdrat, 4);
		      jbig2_decode_refinement_region(ctx, segment,
		          &rparams, as, image, GR_stats);

		      SDNEWSYMS->glyphs[NSYMSDECODED] = image;

		  }
               }

#ifdef OUTPUT_PBM
		  {
		    char name[64];
		    FILE *out;
		    snprintf(name, 64, "sd.%04d.%04d.pbm",
		             segment->number, NSYMSDECODED);
		    out = fopen(name, "wb");
                    jbig2_image_write_pbm(SDNEWSYMS->glyphs[NSYMSDECODED], out);
		    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
			"writing out glyph as '%s' ...", name);
		    fclose(out);
		  }
#endif

	  }

	  /* 6.5.5 (4c.iii) */
	  if (params->SDHUFF && !params->SDREFAGG) {
	    SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
	  }

	  jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
            "decoded symbol %d of %d (%dx%d)",
		NSYMSDECODED, params->SDNUMNEWSYMS,
		SYMWIDTH, HCHEIGHT);

	  /* 6.5.5 (4c.iv) */
	  NSYMSDECODED = NSYMSDECODED + 1;

      } /* end height class decode loop */

      /* 6.5.5 (4d) */
      if (params->SDHUFF && !params->SDREFAGG) {
	/* 6.5.9 */
	Jbig2Image *image;
	int BMSIZE = jbig2_huffman_get(hs, params->SDHUFFBMSIZE, &code);
	int j, x;

	if (code || (BMSIZE < 0)) {
	  jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "error decoding size of collective bitmap!");
	  /* todo: memory cleanup */
	  return NULL;
	}

	/* skip any bits before the next byte boundary */
	jbig2_huffman_skip(hs);

	image = jbig2_image_new(ctx, TOTWIDTH, HCHEIGHT);
	if (image == NULL) {
	  jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "could not allocate collective bitmap image!");
	  /* todo: memory cleanup */
	  return NULL;
	}

	if (BMSIZE == 0) {
	  /* if BMSIZE == 0 bitmap is uncompressed */
	  const byte *src = data + jbig2_huffman_offset(hs);
	  const int stride = (image->width >> 3) +
		((image->width & 7) ? 1 : 0);
	  byte *dst = image->data;

	  BMSIZE = image->height * stride;
	  jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
	    "reading %dx%d uncompressed bitmap"
	    " for %d symbols (%d bytes)",
	    image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE);

	  for (j = 0; j < image->height; j++) {
	    memcpy(dst, src, stride);
	    dst += image->stride;
	    src += stride;
	  }
	} else {
	  Jbig2GenericRegionParams rparams;

	  jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
	    "reading %dx%d collective bitmap for %d symbols (%d bytes)",
	    image->width, image->height, NSYMSDECODED - HCFIRSTSYM, BMSIZE);

	  rparams.MMR = 1;
	  code = jbig2_decode_generic_mmr(ctx, segment, &rparams,
	    data + jbig2_huffman_offset(hs), BMSIZE, image);
	  if (code) {
	    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	      "error decoding MMR bitmap image!");
	    /* todo: memory cleanup */
	    return NULL;
	  }
	}

	/* advance past the data we've just read */
	jbig2_huffman_advance(hs, BMSIZE);

	/* copy the collective bitmap into the symbol dictionary */
	x = 0;
	for (j = HCFIRSTSYM; j < NSYMSDECODED; j++) {
	  Jbig2Image *glyph;
	  glyph = jbig2_image_new(ctx, SDNEWSYMWIDTHS[j], HCHEIGHT);
	  jbig2_image_compose(ctx, glyph, image,
		-x, 0, JBIG2_COMPOSE_REPLACE);
	  x += SDNEWSYMWIDTHS[j];
	  SDNEWSYMS->glyphs[j] = glyph;
	}
	jbig2_image_release(ctx, image);
      }

  } /* end of symbol decode loop */

  if (tparams != NULL)
  {
      if (!params->SDHUFF)
      {
          jbig2_arith_int_ctx_free(ctx, tparams->IADT);
          jbig2_arith_int_ctx_free(ctx, tparams->IAFS);
          jbig2_arith_int_ctx_free(ctx, tparams->IADS);
          jbig2_arith_int_ctx_free(ctx, tparams->IAIT);
          jbig2_arith_iaid_ctx_free(ctx, tparams->IAID);
          jbig2_arith_int_ctx_free(ctx, tparams->IARI);
          jbig2_arith_int_ctx_free(ctx, tparams->IARDW);
          jbig2_arith_int_ctx_free(ctx, tparams->IARDH);
          jbig2_arith_int_ctx_free(ctx, tparams->IARDX);
          jbig2_arith_int_ctx_free(ctx, tparams->IARDY);
      }
      else
      {
          jbig2_release_huffman_table(ctx, tparams->SBHUFFFS);
          jbig2_release_huffman_table(ctx, tparams->SBHUFFDS);
          jbig2_release_huffman_table(ctx, tparams->SBHUFFDT);
          jbig2_release_huffman_table(ctx, tparams->SBHUFFRDX);
          jbig2_release_huffman_table(ctx, tparams->SBHUFFRDY);
          jbig2_release_huffman_table(ctx, tparams->SBHUFFRDW);
          jbig2_release_huffman_table(ctx, tparams->SBHUFFRDH);
      }
      jbig2_free(ctx->allocator, tparams);
      tparams = NULL;
      jbig2_sd_release(ctx, refagg_dicts[0]);
      jbig2_free(ctx->allocator, refagg_dicts);
  }

  jbig2_free(ctx->allocator, GB_stats);

  /* 6.5.10 */
  SDEXSYMS = jbig2_sd_new(ctx, params->SDNUMEXSYMS);
  {
    int i = 0;
    int j = 0;
    int k, m, exflag = 0;
    int32_t exrunlength;

    if (params->SDINSYMS != NULL)
      m = params->SDINSYMS->n_symbols;
    else
      m = 0;
    while (j < params->SDNUMEXSYMS) {
      if (params->SDHUFF)
      	/* FIXME: implement reading from huff table B.1 */
        exrunlength = params->SDNUMEXSYMS;
      else
        code = jbig2_arith_int_decode(IAEX, as, &exrunlength);
      for(k = 0; k < exrunlength; k++)
        if (exflag) {
          SDEXSYMS->glyphs[j++] = (i < m) ? 
            jbig2_image_clone(ctx, params->SDINSYMS->glyphs[i]) :
            jbig2_image_clone(ctx, SDNEWSYMS->glyphs[i-m]);
          i++;
        }
        exflag = !exflag;
    }
  }

  jbig2_sd_release(ctx, SDNEWSYMS);

  if (!params->SDHUFF) {
      jbig2_arith_int_ctx_free(ctx, IADH);
      jbig2_arith_int_ctx_free(ctx, IADW);
      jbig2_arith_int_ctx_free(ctx, IAEX);
      jbig2_arith_int_ctx_free(ctx, IAAI);
      if (params->SDREFAGG) {
        jbig2_arith_iaid_ctx_free(ctx, IAID);
        jbig2_arith_int_ctx_free(ctx, IARDX);
        jbig2_arith_int_ctx_free(ctx, IARDY);
      }
      jbig2_free(ctx->allocator, as);
  } else {
      if (params->SDREFAGG) {
	jbig2_free(ctx->allocator, SDNEWSYMWIDTHS);
      }
      jbig2_release_huffman_table(ctx, SDHUFFRDX);
      jbig2_free(ctx->allocator, hs);
  }

  jbig2_word_stream_buf_free(ctx, ws);

  return SDEXSYMS;
}

/* 7.4.2 */
int
jbig2_symbol_dictionary(Jbig2Ctx *ctx, Jbig2Segment *segment,
			const byte *segment_data)
{
  Jbig2SymbolDictParams params;
  uint16_t flags;
  int sdat_bytes;
  int offset;
  Jbig2ArithCx *GB_stats = NULL;
  Jbig2ArithCx *GR_stats = NULL;

  if (segment->data_length < 10)
    goto too_short;

  /* 7.4.2.1.1 */
  flags = jbig2_get_int16(segment_data);
  params.SDHUFF = flags & 1;
  params.SDREFAGG = (flags >> 1) & 1;
  params.SDTEMPLATE = (flags >> 10) & 3;
  params.SDRTEMPLATE = (flags >> 12) & 1;

  params.SDHUFFDH = NULL;
  params.SDHUFFDW = NULL;
  params.SDHUFFBMSIZE = NULL;
  params.SDHUFFAGGINST = NULL;

  if (params.SDHUFF) {
    switch ((flags & 0x000c) >> 2) {
      case 0: /* Table B.4 */
	params.SDHUFFDH = jbig2_build_huffman_table(ctx,
		                       &jbig2_huffman_params_D);
	break;
      case 1: /* Table B.5 */
	params.SDHUFFDH = jbig2_build_huffman_table(ctx,
		                       &jbig2_huffman_params_E);
	break;
      case 3: /* Custom table from referred segment */
	/* We handle this case later by leaving the table as NULL */
	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "symbol dictionary uses custom DH huffman table (NYI)");
      case 2:
      default:
	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "symbol dictionary specified invalid huffman table");
	break;
    }
    switch ((flags & 0x0030) >> 4) {
      case 0: /* Table B.2 */
	params.SDHUFFDW = jbig2_build_huffman_table(ctx,
		                       &jbig2_huffman_params_B);
	break;
      case 1: /* Table B.3 */
	params.SDHUFFDW = jbig2_build_huffman_table(ctx,
		                       &jbig2_huffman_params_C);
	break;
      case 3: /* Custom table from referred segment */
	/* We handle this case later by leaving the table as NULL */
	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "symbol dictionary uses custom DW huffman table (NYI)");
      case 2:
      default:
	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "symbol dictionary specified invalid huffman table");
	break;
    }
    if (flags & 0x0040) {
        /* Custom table from referred segment */
	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "symbol dictionary uses custom BMSIZE huffman table (NYI)");
    } else {
	/* Table B.1 */
	params.SDHUFFBMSIZE = jbig2_build_huffman_table(ctx,
					&jbig2_huffman_params_A);
    }
    if (flags & 0x0080) {
        /* Custom table from referred segment */
	return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "symbol dictionary uses custom REFAGG huffman table (NYI)");
    } else {
	/* Table B.1 */
	params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx,
					&jbig2_huffman_params_A);
    }
  }

  /* FIXME: there are quite a few of these conditions to check */
  /* maybe #ifdef CONFORMANCE and a separate routine */
  if (!params.SDHUFF) {
    if (flags & 0x000c) {
      jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
		  "SDHUFF is zero, but contrary to spec SDHUFFDH is not.");
    }
    if (flags & 0x0030) {
      jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
		  "SDHUFF is zero, but contrary to spec SDHUFFDW is not.");
    }
  }

  if (flags & 0x0080) {
      jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
        "bitmap coding context is used (NYI) symbol data likely to be garbage!");
  }

  /* 7.4.2.1.2 */
  sdat_bytes = params.SDHUFF ? 0 : params.SDTEMPLATE == 0 ? 8 : 2;
  memcpy(params.sdat, segment_data + 2, sdat_bytes);
  offset = 2 + sdat_bytes;

  /* 7.4.2.1.3 */
  if (params.SDREFAGG && !params.SDRTEMPLATE) {
      if (offset + 4 > segment->data_length)
	goto too_short;
      memcpy(params.sdrat, segment_data + offset, 4);
      offset += 4;
  } else {
      /* sdrat is meaningless if SDRTEMPLATE is 1, but set a value
         to avoid confusion if anybody looks */
      memset(params.sdrat, 0, 4);
  }

  if (offset + 8 > segment->data_length)
    goto too_short;

  /* 7.4.2.1.4 */
  params.SDNUMEXSYMS = jbig2_get_int32(segment_data + offset);
  /* 7.4.2.1.5 */
  params.SDNUMNEWSYMS = jbig2_get_int32(segment_data + offset + 4);
  offset += 8;

  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
	      "symbol dictionary, flags=%04x, %d exported syms, %d new syms",
	      flags, params.SDNUMEXSYMS, params.SDNUMNEWSYMS);

  /* 7.4.2.2 (2) */
  {
    int n_dicts = jbig2_sd_count_referred(ctx, segment);
    Jbig2SymbolDict **dicts = NULL;

    params.SDINSYMS = NULL;
    if (n_dicts > 0) {
      dicts = jbig2_sd_list_referred(ctx, segment);
      params.SDINSYMS = jbig2_sd_cat(ctx, n_dicts, dicts);
    }
    if (params.SDINSYMS != NULL) {
      params.SDNUMINSYMS = params.SDINSYMS->n_symbols;
    } else {
     params.SDNUMINSYMS = 0;
    }
  }

  /* 7.4.2.2 (4) */
  if (!params.SDHUFF) {
      int stats_size = params.SDTEMPLATE == 0 ? 65536 :
	params.SDTEMPLATE == 1 ? 8192 : 1024;
      GB_stats = jbig2_alloc(ctx->allocator, stats_size);
      memset(GB_stats, 0, stats_size);
      if (params.SDREFAGG) {
	stats_size = params.SDRTEMPLATE ? 1 << 10 : 1 << 13;
	GR_stats = jbig2_alloc(ctx->allocator, stats_size);
	memset(GR_stats, 0, stats_size);
      }
  }

  if (flags & 0x0100) {
      jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
        "segment marks bitmap coding context as retained (NYI)");
  }

  segment->result = (void *)jbig2_decode_symbol_dict(ctx, segment,
				  &params,
				  segment_data + offset,
				  segment->data_length - offset,
				  GB_stats, GR_stats);
#ifdef DUMP_SYMDICT
  if (segment->result) jbig2_dump_symbol_dict(ctx, segment);
#endif

  if (params.SDHUFF) {
      jbig2_release_huffman_table(ctx, params.SDHUFFDH);
      jbig2_release_huffman_table(ctx, params.SDHUFFDW);
      jbig2_release_huffman_table(ctx, params.SDHUFFBMSIZE);
      jbig2_release_huffman_table(ctx, params.SDHUFFAGGINST);
  }

  /* todo: retain or free GB_stats, GR_stats */

  return (segment->result != NULL) ? 0 : -1;

 too_short:
  return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
		     "Segment too short");
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?