jbig2_text.c.svn-base

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

SVN-BASE
763
字号
/*
    jbig2dec

    Copyright (C) 2002-2008 Artifex Software, Inc.

    This software is distributed under license and may not
    be copied, modified or distributed except as expressly
    authorized under the terms of the license contained in
    the file LICENSE in this distribution.

    For information on commercial licensing, go to
    http://www.artifex.com/licensing/ or contact
    Artifex Software, Inc.,  101 Lucas Valley Road #110,
    San Rafael, CA  94903, U.S.A., +1(415)492-9861.

    $Id: jbig2_text.c 466 2008-05-16 23:58:59Z giles $
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "os_types.h"

#include <stddef.h>
#include <string.h> /* memset() */

#include "jbig2.h"
#include "jbig2_priv.h"
#include "jbig2_arith.h"
#include "jbig2_arith_int.h"
#include "jbig2_arith_iaid.h"
#include "jbig2_huffman.h"
#include "jbig2_generic.h"
#include "jbig2_symbol_dict.h"
#include "jbig2_text.h"


/**
 * jbig2_decode_text_region: decode a text region segment
 *
 * @ctx: jbig2 decoder context
 * @segment: jbig2 segment (header) structure
 * @params: parameters from the text region header
 * @dicts: an array of referenced symbol dictionaries
 * @n_dicts: the number of referenced symbol dictionaries
 * @image: image structure in which to store the decoded region bitmap
 * @data: pointer to text region data to be decoded
 * @size: length of text region data
 *
 * Implements the text region decoding procedure
 * described in section 6.4 of the JBIG2 spec.
 *
 * returns: 0 on success
 **/
int
jbig2_decode_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
                             const Jbig2TextRegionParams *params,
                             const Jbig2SymbolDict * const *dicts, const int n_dicts,
                             Jbig2Image *image,
                             const byte *data, const size_t size,
			     Jbig2ArithCx *GR_stats, Jbig2ArithState *as, Jbig2WordStream *ws)
{
    /* relevent bits of 6.4.4 */
    uint32_t NINSTANCES;
    uint32_t ID;
    int32_t STRIPT;
    int32_t FIRSTS;
    int32_t DT;
    int32_t DFS;
    int32_t IDS;
    int32_t CURS;
    int32_t CURT;
    int S,T;
    int x,y;
    bool first_symbol;
    uint32_t index, SBNUMSYMS;
    Jbig2Image *IB;
    Jbig2HuffmanState *hs = NULL;
    Jbig2HuffmanTable *SBSYMCODES = NULL;
    int code = 0;
    int RI;

    SBNUMSYMS = 0;
    for (index = 0; index < n_dicts; index++) {
        SBNUMSYMS += dicts[index]->n_symbols;
    }
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
        "symbol list contains %d glyphs in %d dictionaries", SBNUMSYMS, n_dicts);

    if (params->SBHUFF) {
	Jbig2HuffmanTable *runcodes;
	Jbig2HuffmanParams runcodeparams;
	Jbig2HuffmanLine runcodelengths[35];
	Jbig2HuffmanLine *symcodelengths;
	Jbig2HuffmanParams symcodeparams;
	int code, err, len, range, r;

	jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
	  "huffman coded text region");
	hs = jbig2_huffman_new(ctx, ws);

	/* 7.4.3.1.7 - decode symbol ID Huffman table */
	/* this is actually part of the segment header, but it is more
	   convenient to handle it here */

	/* parse and build the runlength code huffman table */
	for (index = 0; index < 35; index++) {
	  runcodelengths[index].PREFLEN = jbig2_huffman_get_bits(hs, 4);
	  runcodelengths[index].RANGELEN = 0;
	  runcodelengths[index].RANGELOW = index;
	  jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
	    "  read runcode%d length %d", index, runcodelengths[index].PREFLEN);
	}
	runcodeparams.HTOOB = 0;
	runcodeparams.lines = runcodelengths;
	runcodeparams.n_lines = 35;
	runcodes = jbig2_build_huffman_table(ctx, &runcodeparams);
	if (runcodes == NULL) {
	  jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "error constructing symbol id runcode table!");
	  return -1;
	}

	/* decode the symbol id codelengths using the runlength table */
	symcodelengths = jbig2_alloc(ctx->allocator, SBNUMSYMS*sizeof(Jbig2HuffmanLine));
	if (symcodelengths == NULL) {
	  jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	    "memory allocation failure reading symbol ID huffman table!");
	  return -1;
	}
	index = 0;
	while (index < SBNUMSYMS) {
	  code = jbig2_huffman_get(hs, runcodes, &err);
	  if (err != 0 || code < 0 || code >= 35) {
	    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	      "error reading symbol ID huffman table!");
	    return err ? err : -1;
	  }

	  if (code < 32) {
	    len = code;
	    range = 1;
	  } else {
	    if (code == 32) {
	      len = symcodelengths[index-1].PREFLEN;
	      if (index < 1) {
		jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
	 	  "error decoding symbol id table: run length with no antecedent!");
	        /* todo: memory cleanup */
	        return -1;
	      }
	    } else {
	      len = 0; /* code == 33 or 34 */
	    }
	    if (code == 32) range = jbig2_huffman_get_bits(hs, 2) + 3;
	    else if (code == 33) range = jbig2_huffman_get_bits(hs, 3) + 3;
	    else if (code == 34) range = jbig2_huffman_get_bits(hs, 7) + 11;
	  }
	  jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
	    "  read runcode%d at index %d (length %d range %d)", code, index, len, range);
	  if (index+range > SBNUMSYMS) {
	    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
	      "runlength extends %d entries beyond the end of symbol id table!",
		index+range - SBNUMSYMS);
	    range = SBNUMSYMS - index;
	  }
	  for (r = 0; r < range; r++) {
	    symcodelengths[index+r].PREFLEN = len;
	    symcodelengths[index+r].RANGELEN = 0;
	    symcodelengths[index+r].RANGELOW = index + r;
	  }
	  index += r;
	}

	if (index < SBNUMSYMS) {
	  jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
	    "runlength codes do not cover the available symbol set");
	}
	symcodeparams.HTOOB = 0;
	symcodeparams.lines = symcodelengths;
	symcodeparams.n_lines = SBNUMSYMS;

	/* skip to byte boundary */
	jbig2_huffman_skip(hs);

	/* finally, construct the symbol id huffman table itself */
	SBSYMCODES = jbig2_build_huffman_table(ctx, &symcodeparams);

	jbig2_free(ctx->allocator, symcodelengths);
	jbig2_release_huffman_table(ctx, runcodes);

	if (SBSYMCODES == NULL) {
	    jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
		"could not construct Symbol ID huffman table!");
	    return -1;
	}
    }

    /* 6.4.5 (1) */
    jbig2_image_clear(ctx, image, params->SBDEFPIXEL);

    /* 6.4.6 */
    if (params->SBHUFF) {
        STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
    } else {
        code = jbig2_arith_int_decode(params->IADT, as, &STRIPT);
    }

    /* 6.4.5 (2) */
    STRIPT *= -(params->SBSTRIPS);
    FIRSTS = 0;
    NINSTANCES = 0;

    /* 6.4.5 (3) */
    while (NINSTANCES < params->SBNUMINSTANCES) {
        /* (3b) */
        if (params->SBHUFF) {
            DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
        } else {
            code = jbig2_arith_int_decode(params->IADT, as, &DT);
        }
        DT *= params->SBSTRIPS;
        STRIPT += DT;

	first_symbol = TRUE;
	/* 6.4.5 (3c) - decode symbols in strip */
	for (;;) {
	    /* (3c.i) */
	    if (first_symbol) {
		/* 6.4.7 */
		if (params->SBHUFF) {
		    DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);
		} else {
		    code = jbig2_arith_int_decode(params->IAFS, as, &DFS);
		}
		FIRSTS += DFS;
		CURS = FIRSTS;
		first_symbol = FALSE;

	    } else {
		/* (3c.ii) / 6.4.8 */
		if (params->SBHUFF) {
		    IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code);
		} else {
		    code = jbig2_arith_int_decode(params->IADS, as, &IDS);
		}
		if (code) {
		    break;
		}
		CURS += IDS + params->SBDSOFFSET;
	    }

	    /* (3c.iii) / 6.4.9 */
	    if (params->SBSTRIPS == 1) {
		CURT = 0;
	    } else if (params->SBHUFF) {
		CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS);
	    } else {
		code = jbig2_arith_int_decode(params->IAIT, as, &CURT);
	    }
	    T = STRIPT + CURT;

	    /* (3b.iv) / 6.4.10 - decode the symbol id */
	    if (params->SBHUFF) {
		ID = jbig2_huffman_get(hs, SBSYMCODES, &code);
	    } else {
		code = jbig2_arith_iaid_decode(params->IAID, as, (int *)&ID);
	    }
	    if (ID >= SBNUMSYMS) {
		return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
                    "symbol id out of range! (%d/%d)", ID, SBNUMSYMS);
	    }

	    /* (3c.v) / 6.4.11 - look up the symbol bitmap IB */
	    {
		uint32_t id = ID;

		index = 0;
		while (id >= dicts[index]->n_symbols)
		    id -= dicts[index++]->n_symbols;
		IB = jbig2_image_clone(ctx, dicts[index]->glyphs[id]);
	    }
	    if (params->SBREFINE) {
	      if (params->SBHUFF) {
		RI = jbig2_huffman_get_bits(hs, 1);
	      } else {
		code = jbig2_arith_int_decode(params->IARI, as, &RI);
	      }
	    } else {
		RI = 0;
	    }
	    if (RI) {
		Jbig2RefinementRegionParams rparams;
		Jbig2Image *IBO;
		int32_t RDW, RDH, RDX, RDY;
		Jbig2Image *image;
		int BMSIZE = 0;

		/* 6.4.11 (1, 2, 3, 4) */
		if (!params->SBHUFF) {
		  code = jbig2_arith_int_decode(params->IARDW, as, &RDW);
		  code = jbig2_arith_int_decode(params->IARDH, as, &RDH);
		  code = jbig2_arith_int_decode(params->IARDX, as, &RDX);
		  code = jbig2_arith_int_decode(params->IARDY, as, &RDY);
		} else {
		  RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code);
		  RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code);
		  RDX = jbig2_huffman_get(hs, params->SBHUFFRDX, &code);
		  RDY = jbig2_huffman_get(hs, params->SBHUFFRDY, &code);
		  BMSIZE = jbig2_huffman_get(hs, params->SBHUFFRSIZE, &code);
		  jbig2_huffman_skip(hs);
		}

		/* 6.4.11 (6) */
		IBO = IB;
		image = jbig2_image_new(ctx, IBO->width + RDW,
					     IBO->height + RDH);

		/* Table 12 */
		rparams.GRTEMPLATE = params->SBRTEMPLATE;
		rparams.reference = IBO;
		rparams.DX = (RDW >> 1) + RDX;
		rparams.DY = (RDH >> 1) + RDY;
		rparams.TPGRON = 0;
		memcpy(rparams.grat, params->sbrat, 4);
		jbig2_decode_refinement_region(ctx, segment,
		    &rparams, as, image, GR_stats);
		IB = image;

		jbig2_image_release(ctx, IBO);

		/* 6.4.11 (7) */
		if (params->SBHUFF) {
		  jbig2_huffman_advance(hs, BMSIZE);
		}

	    }

	    /* (3c.vi) */
	    if ((!params->TRANSPOSED) && (params->REFCORNER > 1)) {
		CURS += IB->width - 1;
	    } else if ((params->TRANSPOSED) && !(params->REFCORNER & 1)) {
		CURS += IB->height - 1;
	    }

	    /* (3c.vii) */
	    S = CURS;

	    /* (3c.viii) */
	    if (!params->TRANSPOSED) {
		switch (params->REFCORNER) {  /* FIXME: double check offsets */
		case JBIG2_CORNER_TOPLEFT: x = S; y = T; break;
		case JBIG2_CORNER_TOPRIGHT: x = S - IB->width + 1; y = T; break;
		case JBIG2_CORNER_BOTTOMLEFT: x = S; y = T - IB->height + 1; break;
		case JBIG2_CORNER_BOTTOMRIGHT: x = S - IB->width + 1; y = T - IB->height + 1; break;
		}
	    } else { /* TRANSPOSED */
		switch (params->REFCORNER) {
		case JBIG2_CORNER_TOPLEFT: y = S; x = T; break;
		case JBIG2_CORNER_TOPRIGHT: y = S - IB->width + 1; x = T; break;
		case JBIG2_CORNER_BOTTOMLEFT: y = S; x = T - IB->height + 1; break;
		case JBIG2_CORNER_BOTTOMRIGHT: y = S - IB->width + 1; x = T - IB->height + 1; break;
		}
	    }

	    /* (3c.ix) */
#ifdef JBIG2_DEBUG
	    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
			"composing glyph id %d: %dx%d @ (%d,%d) symbol %d/%d", 
			ID, IB->width, IB->height, x, y, NINSTANCES + 1,
			params->SBNUMINSTANCES);
#endif
	    jbig2_image_compose(ctx, image, IB, x, y, params->SBCOMBOP);

	    /* (3c.x) */
	    if ((!params->TRANSPOSED) && (params->REFCORNER < 2)) {
		CURS += IB->width -1 ;
	    } else if ((params->TRANSPOSED) && (params->REFCORNER & 1)) {
		CURS += IB->height - 1;
	    }

	    /* (3c.xi) */

⌨️ 快捷键说明

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