jbig2_symbol_dict.c
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 932 行 · 第 1/2 页
C
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,
¶ms,
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 + -
显示快捷键?