jbig2_generic.c.svn-base
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 637 行 · 第 1/2 页
SVN-BASE
637 行
#ifdef OUTPUT_PBM
printf("P4\n%d %d\n", GBW, GBH);
#endif
for (y = 0; y < GBH; y++)
{
uint32_t CONTEXT;
uint32_t line_m1;
uint32_t line_m2;
int padded_width = (GBW + 7) & -8;
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
CONTEXT = ((line_m1 >> 3) & 0x78) | ((line_m1 >> 2) & 0x4) | ((line_m2 >> 3) & 0x380);
/* 6.2.5.7 3d */
for (x = 0; x < padded_width; x += 8)
{
byte result = 0;
int x_minor;
int minor_width = GBW - x > 8 ? 8 : GBW - x;
if (y >= 1)
line_m1 = (line_m1 << 8) |
(x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
if (y >= 2)
line_m2 = (line_m2 << 8) |
(x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0);
/* This is the speed-critical inner loop. */
for (x_minor = 0; x_minor < minor_width; x_minor++)
{
bool bit;
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit |
((line_m1 >> (10 - x_minor)) & 0x8) |
((line_m1 >> (9 - x_minor)) & 0x4) |
((line_m2 >> (10 - x_minor)) & 0x80);
}
gbreg_line[x >> 3] = result;
}
#ifdef OUTPUT_PBM
fwrite(gbreg_line, 1, rowstride, stdout);
#endif
gbreg_line += rowstride;
}
return 0;
}
static int
jbig2_decode_generic_template3(Jbig2Ctx *ctx,
Jbig2Segment *segment,
const Jbig2GenericRegionParams *params,
Jbig2ArithState *as,
Jbig2Image *image,
Jbig2ArithCx *GB_stats)
{
const int GBW = image->width;
const int GBH = image->height;
const int rowstride = image->stride;
byte *gbreg_line = (byte *)image->data;
int x, y;
/* this routine only handles the nominal AT location */
#ifdef OUTPUT_PBM
printf("P4\n%d %d\n", GBW, GBH);
#endif
for (y = 0; y < GBH; y++)
{
uint32_t CONTEXT;
uint32_t line_m1;
int padded_width = (GBW + 7) & -8;
line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
CONTEXT = (line_m1 >> 1) & 0x3f0;
/* 6.2.5.7 3d */
for (x = 0; x < padded_width; x += 8)
{
byte result = 0;
int x_minor;
int minor_width = GBW - x > 8 ? 8 : GBW - x;
if (y >= 1)
line_m1 = (line_m1 << 8) |
(x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
/* This is the speed-critical inner loop. */
for (x_minor = 0; x_minor < minor_width; x_minor++)
{
bool bit;
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
result |= bit << (7 - x_minor);
CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit |
((line_m1 >> (10 - x_minor)) & 0x010);
}
gbreg_line[x >> 3] = result;
}
#ifdef OUTPUT_PBM
fwrite(gbreg_line, 1, rowstride, stdout);
#endif
gbreg_line += rowstride;
}
return 0;
}
static int
jbig2_decode_generic_template3_unopt(Jbig2Ctx *ctx,
Jbig2Segment *segment,
const Jbig2GenericRegionParams *params,
Jbig2ArithState *as,
Jbig2Image *image,
Jbig2ArithCx *GB_stats)
{
const int GBW = image->width;
const int GBH = image->height;
uint32_t CONTEXT;
int x,y;
bool bit;
/* this version is generic and easy to understand, but very slow */
for (y = 0; y < GBH; y++) {
for (x = 0; x < GBW; x++) {
CONTEXT = 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
y + params->gbat[1]) << 4;
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
jbig2_image_set_pixel(image, x, y, bit);
}
}
return 0;
}
/**
* jbig2_decode_generic_region: Decode a generic region.
* @ctx: The context for allocation and error reporting.
* @segment: A segment reference for error reporting.
* @params: Decoding parameter set.
* @as: Arithmetic decoder state.
* @image: Where to store the decoded data.
* @GB_stats: Arithmetic stats.
*
* Decodes a generic region, according to section 6.2. The caller should
* pass an already allocated Jbig2Image object for @image
*
* Because this API is based on an arithmetic decoding state, it is
* not suitable for MMR decoding.
*
* Return code: 0 on success.
**/
int
jbig2_decode_generic_region(Jbig2Ctx *ctx,
Jbig2Segment *segment,
const Jbig2GenericRegionParams *params,
Jbig2ArithState *as,
Jbig2Image *image,
Jbig2ArithCx *GB_stats)
{
const int8_t *gbat = params->gbat;
if (!params->MMR && params->GBTEMPLATE == 0) {
if (gbat[0] == +3 && gbat[1] == -1 &&
gbat[2] == -3 && gbat[3] == -1 &&
gbat[4] == +2 && gbat[5] == -2 &&
gbat[6] == -2 && gbat[7] == -2)
return jbig2_decode_generic_template0(ctx, segment, params,
as, image, GB_stats);
else
return jbig2_decode_generic_template0_unopt(ctx, segment, params,
as, image, GB_stats);
} else if (!params->MMR && params->GBTEMPLATE == 1)
return jbig2_decode_generic_template1(ctx, segment, params,
as, image, GB_stats);
else if (!params->MMR && params->GBTEMPLATE == 2)
{
if (gbat[0] == 3 && gbat[1] == -1)
return jbig2_decode_generic_template2a(ctx, segment, params,
as, image, GB_stats);
else
return jbig2_decode_generic_template2(ctx, segment, params,
as, image, GB_stats);
}
else if (!params->MMR && params->GBTEMPLATE == 3) {
if (gbat[0] == 2 && gbat[1] == -1)
return jbig2_decode_generic_template3_unopt(ctx, segment, params,
as, image, GB_stats);
else
return jbig2_decode_generic_template3_unopt(ctx, segment, params,
as, image, GB_stats);
}
{
int i;
for (i = 0; i < 8; i++)
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"gbat[%d] = %d", i, params->gbat[i]);
}
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
"decode_generic_region: MMR=%d, GBTEMPLATE=%d NYI",
params->MMR, params->GBTEMPLATE);
return -1;
}
/**
* Handler for immediate generic region segments
*/
int
jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
const byte *segment_data)
{
Jbig2RegionSegmentInfo rsi;
byte seg_flags;
int8_t gbat[8];
int offset;
int gbat_bytes = 0;
Jbig2GenericRegionParams params;
int code;
Jbig2Image *image;
Jbig2WordStream *ws;
Jbig2ArithState *as;
Jbig2ArithCx *GB_stats = NULL;
/* 7.4.6 */
if (segment->data_length < 18)
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Segment too short");
jbig2_get_region_segment_info(&rsi, segment_data);
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
"generic region: %d x %d @ (%d, %d), flags = %02x",
rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
/* 7.4.6.2 */
seg_flags = segment_data[17];
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
"segment flags = %02x", seg_flags);
if ((seg_flags & 1) && (seg_flags & 6))
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
"MMR is 1, but GBTEMPLATE is not 0");
/* 7.4.6.3 */
if (!(seg_flags & 1))
{
gbat_bytes = (seg_flags & 6) ? 2 : 8;
if (18 + gbat_bytes > segment->data_length)
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
"Segment too short");
memcpy(gbat, segment_data + 18, gbat_bytes);
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
"gbat: %d, %d", gbat[0], gbat[1]);
}
offset = 18 + gbat_bytes;
/* Table 34 */
params.MMR = seg_flags & 1;
params.GBTEMPLATE = (seg_flags & 6) >> 1;
params.TPGDON = (seg_flags & 8) >> 3;
params.USESKIP = 0;
memcpy (params.gbat, gbat, gbat_bytes);
image = jbig2_image_new(ctx, rsi.width, rsi.height);
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
"allocated %d x %d image buffer for region decode results",
rsi.width, rsi.height);
if (params.MMR)
{
code = jbig2_decode_generic_mmr(ctx, segment, ¶ms,
segment_data + offset, segment->data_length - offset,
image);
}
else
{
int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE);
GB_stats = jbig2_alloc(ctx->allocator, stats_size);
memset(GB_stats, 0, stats_size);
ws = jbig2_word_stream_buf_new(ctx,
segment_data + offset,
segment->data_length - offset);
as = jbig2_arith_new(ctx, ws);
code = jbig2_decode_generic_region(ctx, segment, ¶ms,
as, image, GB_stats);
jbig2_free(ctx->allocator, as);
jbig2_word_stream_buf_free(ctx, ws);
jbig2_free(ctx->allocator, GB_stats);
}
jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page],
image, rsi.x, rsi.y, JBIG2_COMPOSE_OR);
jbig2_image_release(ctx, image);
return code;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?