jbig2_text.c
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 763 行 · 第 1/2 页
C
763 行
NINSTANCES++;
jbig2_image_release(ctx, IB);
}
/* end strip */
}
/* 6.4.5 (4) */
if (params->SBHUFF) {
jbig2_release_huffman_table(ctx, SBSYMCODES);
}
return 0;
}
/**
* jbig2_parse_text_region: read a text region segment header
**/
int
jbig2_parse_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
{
int offset = 0;
Jbig2RegionSegmentInfo region_info;
Jbig2TextRegionParams params;
Jbig2Image *image;
Jbig2SymbolDict **dicts;
int n_dicts;
uint16_t flags;
uint16_t huffman_flags = 0;
Jbig2ArithCx *GR_stats = NULL;
int code = 0;
Jbig2WordStream *ws = NULL;
Jbig2ArithState *as = NULL;
/* 7.4.1 */
if (segment->data_length < 17)
goto too_short;
jbig2_get_region_segment_info(®ion_info, segment_data);
offset += 17;
/* 7.4.3.1.1 */
flags = jbig2_get_int16(segment_data + offset);
offset += 2;
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"text region header flags 0x%04x", flags);
params.SBHUFF = flags & 0x0001;
params.SBREFINE = flags & 0x0002;
params.LOGSBSTRIPS = (flags & 0x000c) >> 2;
params.SBSTRIPS = 1 << params.LOGSBSTRIPS;
params.REFCORNER = (flags & 0x0030) >> 4;
params.TRANSPOSED = flags & 0x0040;
params.SBCOMBOP = (flags & 0x0180) >> 7;
params.SBDEFPIXEL = flags & 0x0200;
/* SBDSOFFSET is a signed 5 bit integer */
params.SBDSOFFSET = (flags & 0x7C00) >> 10;
if (params.SBDSOFFSET > 0x0f) params.SBDSOFFSET -= 0x20;
params.SBRTEMPLATE = flags & 0x8000;
if (params.SBDSOFFSET) {
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"text region has SBDSOFFSET %d", params.SBDSOFFSET);
}
if (params.SBHUFF) /* Huffman coding */
{
/* 7.4.3.1.2 */
huffman_flags = jbig2_get_int16(segment_data + offset);
offset += 2;
if (huffman_flags & 0x8000)
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
"reserved bit 15 of text region huffman flags is not zero");
}
else /* arithmetic coding */
{
/* 7.4.3.1.3 */
if ((params.SBREFINE) && !(params.SBRTEMPLATE))
{
params.sbrat[0] = segment_data[offset];
params.sbrat[1] = segment_data[offset + 1];
params.sbrat[2] = segment_data[offset + 2];
params.sbrat[3] = segment_data[offset + 3];
offset += 4;
}
}
/* 7.4.3.1.4 */
params.SBNUMINSTANCES = jbig2_get_int32(segment_data + offset);
offset += 4;
if (params.SBHUFF) {
/* 7.4.3.1.5 - Symbol ID Huffman table */
/* ...this is handled in the segment body decoder */
/* 7.4.3.1.6 - Other Huffman table selection */
switch (huffman_flags & 0x0003) {
case 0: /* Table B.6 */
params.SBHUFFFS = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_F);
break;
case 1: /* Table B.7 */
params.SBHUFFFS = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_G);
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,
"text region uses custom FS huffman table (NYI)");
break;
case 2: /* invalid */
default:
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"text region specified invalid FS huffman table");
break;
}
switch ((huffman_flags & 0x000c) >> 2) {
case 0: /* Table B.8 */
params.SBHUFFDS = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_H);
break;
case 1: /* Table B.9 */
params.SBHUFFDS = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_I);
break;
case 2: /* Table B.10 */
params.SBHUFFDS = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_J);
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,
"text region uses custom DS huffman table (NYI)");
break;
}
switch ((huffman_flags & 0x0030) >> 4) {
case 0: /* Table B.11 */
params.SBHUFFDT = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_K);
break;
case 1: /* Table B.12 */
params.SBHUFFDT = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_L);
break;
case 2: /* Table B.13 */
params.SBHUFFDT = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_M);
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,
"text region uses custom DT huffman table (NYI)");
break;
}
switch ((huffman_flags & 0x00c0) >> 6) {
case 0: /* Table B.14 */
params.SBHUFFRDW = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_N);
break;
case 1: /* Table B.15 */
params.SBHUFFRDW = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_O);
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,
"text region uses custom RDW huffman table (NYI)");
break;
case 2: /* invalid */
default:
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"text region specified invalid RDW huffman table");
break;
}
switch ((huffman_flags & 0x0300) >> 8) {
case 0: /* Table B.14 */
params.SBHUFFRDH = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_N);
break;
case 1: /* Table B.15 */
params.SBHUFFRDH = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_O);
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,
"text region uses custom RDH huffman table (NYI)");
break;
case 2: /* invalid */
default:
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"text region specified invalid RDH huffman table");
break;
}
switch ((huffman_flags & 0x0c00) >> 10) {
case 0: /* Table B.14 */
params.SBHUFFRDX = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_N);
break;
case 1: /* Table B.15 */
params.SBHUFFRDX = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_O);
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,
"text region uses custom RDX huffman table (NYI)");
break;
case 2: /* invalid */
default:
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"text region specified invalid RDX huffman table");
break;
}
switch ((huffman_flags & 0x3000) >> 12) {
case 0: /* Table B.14 */
params.SBHUFFRDY = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_N);
break;
case 1: /* Table B.15 */
params.SBHUFFRDY = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_O);
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,
"text region uses custom RDY huffman table (NYI)");
break;
case 2: /* invalid */
default:
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"text region specified invalid RDY huffman table");
break;
}
switch ((huffman_flags & 0x4000) >> 14) {
case 0: /* Table B.1 */
params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx,
&jbig2_huffman_params_A);
break;
case 1: /* 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,
"text region uses custom RSIZE huffman table (NYI)");
break;
}
if (huffman_flags & 0x8000) {
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
"text region huffman flags bit 15 is set, contrary to spec");
}
/* 7.4.3.1.7 */
/* For convenience this is done in the body decoder routine */
}
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
"text region: %d x %d @ (%d,%d) %d symbols",
region_info.width, region_info.height,
region_info.x, region_info.y, params.SBNUMINSTANCES);
/* 7.4.3.2 (2) - compose the list of symbol dictionaries */
n_dicts = jbig2_sd_count_referred(ctx, segment);
if (n_dicts != 0) {
dicts = jbig2_sd_list_referred(ctx, segment);
} else {
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"text region refers to no symbol dictionaries!");
}
if (dicts == NULL) {
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"unable to retrive symbol dictionaries!"
" previous parsing error?");
} else {
int index;
if (dicts[0] == NULL) {
return jbig2_error(ctx, JBIG2_SEVERITY_WARNING,
segment->number,
"unable to find first referenced symbol dictionary!");
}
for (index = 1; index < n_dicts; index++)
if (dicts[index] == NULL) {
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
"unable to find all referenced symbol dictionaries!");
n_dicts = index;
}
}
/* 7.4.3.2 (3) */
if (!params.SBHUFF && params.SBREFINE) {
int stats_size = params.SBRTEMPLATE ? 1 << 10 : 1 << 13;
GR_stats = jbig2_alloc(ctx->allocator, stats_size);
memset(GR_stats, 0, stats_size);
}
image = jbig2_image_new(ctx, region_info.width, region_info.height);
ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
if (!params.SBHUFF) {
int SBSYMCODELEN, index;
int SBNUMSYMS = 0;
for (index = 0; index < n_dicts; index++) {
SBNUMSYMS += dicts[index]->n_symbols;
}
as = jbig2_arith_new(ctx, ws);
ws = 0;
params.IADT = jbig2_arith_int_ctx_new(ctx);
params.IAFS = jbig2_arith_int_ctx_new(ctx);
params.IADS = jbig2_arith_int_ctx_new(ctx);
params.IAIT = jbig2_arith_int_ctx_new(ctx);
/* Table 31 */
for (SBSYMCODELEN = 0; (1 << SBSYMCODELEN) < SBNUMSYMS; SBSYMCODELEN++);
params.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
params.IARI = jbig2_arith_int_ctx_new(ctx);
params.IARDW = jbig2_arith_int_ctx_new(ctx);
params.IARDH = jbig2_arith_int_ctx_new(ctx);
params.IARDX = jbig2_arith_int_ctx_new(ctx);
params.IARDY = jbig2_arith_int_ctx_new(ctx);
}
code = jbig2_decode_text_region(ctx, segment, ¶ms,
(const Jbig2SymbolDict * const *)dicts, n_dicts, image,
segment_data + offset, segment->data_length - offset,
GR_stats, as, ws);
if (!params.SBHUFF && params.SBREFINE) {
jbig2_free(ctx->allocator, GR_stats);
}
if (params.SBHUFF) {
jbig2_release_huffman_table(ctx, params.SBHUFFFS);
jbig2_release_huffman_table(ctx, params.SBHUFFDS);
jbig2_release_huffman_table(ctx, params.SBHUFFDT);
jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
}
else {
jbig2_arith_int_ctx_free(ctx, params.IADT);
jbig2_arith_int_ctx_free(ctx, params.IAFS);
jbig2_arith_int_ctx_free(ctx, params.IADS);
jbig2_arith_int_ctx_free(ctx, params.IAIT);
jbig2_arith_iaid_ctx_free(ctx, params.IAID);
jbig2_arith_int_ctx_free(ctx, params.IARI);
jbig2_arith_int_ctx_free(ctx, params.IARDW);
jbig2_arith_int_ctx_free(ctx, params.IARDH);
jbig2_arith_int_ctx_free(ctx, params.IARDX);
jbig2_arith_int_ctx_free(ctx, params.IARDY);
jbig2_free(ctx->allocator, as);
jbig2_word_stream_buf_free(ctx, ws);
}
jbig2_free(ctx->allocator, dicts);
/* todo: check errors */
if ((segment->flags & 63) == 4) {
/* we have an intermediate region here. save it for later */
segment->result = image;
} else {
/* otherwise composite onto the page */
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"composing %dx%d decoded text region onto page at (%d, %d)",
region_info.width, region_info.height, region_info.x, region_info.y);
jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image,
region_info.x, region_info.y, region_info.op);
jbig2_image_release(ctx, image);
}
/* success */
return 0;
too_short:
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Segment too short");
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?