jbig2_generic.c.svn-base
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 637 行 · 第 1/2 页
SVN-BASE
637 行
/*
jbig2dec
Copyright (C) 2002-2005 Artifex Software, Inc.
This software is provided AS-IS with no warranty,
either express or implied.
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_generic.c 465 2008-05-16 23:48:20Z giles $
*/
/**
* Generic region handlers.
**/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "os_types.h"
#include <stddef.h>
#include <string.h> /* memcpy(), memset() */
#ifdef OUTPUT_PBM
#include <stdio.h>
#endif
#include "jbig2.h"
#include "jbig2_priv.h"
#include "jbig2_image.h"
#include "jbig2_arith.h"
#include "jbig2_generic.h"
#include "jbig2_mmr.h"
/* return the appropriate context size for the given template */
int
jbig2_generic_stats_size(Jbig2Ctx *ctx, int template)
{
int stats_size = template == 0 ? 1 << 16 :
template == 1 ? 1 << 1 << 13 : 1 << 10;
return stats_size;
}
static int
jbig2_decode_generic_template0(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;
int x, y;
byte *gbreg_line = (byte *)image->data;
/* todo: currently we only handle the nominal gbat 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;
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)] << 6 : 0;
CONTEXT = (line_m1 & 0x7f0) | (line_m2 & 0xf800);
/* 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] << 6: 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 & 0x7bf7) << 1) | bit |
((line_m1 >> (7 - x_minor)) & 0x10) |
((line_m2 >> (7 - x_minor)) & 0x800);
}
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_template0_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 + 2, y - 1) << 5;
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 7;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
y + params->gbat[3]) << 10;
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
y + params->gbat[5]) << 11;
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13;
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
y + params->gbat[7]) << 15;
bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
jbig2_image_set_pixel(image, x, y, bit);
}
}
return 0;
}
static int
jbig2_decode_generic_template1(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;
int x, y;
byte *gbreg_line = (byte *)image->data;
/* todo: currently we only handle the nominal gbat 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;
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)] << 5 : 0;
CONTEXT = ((line_m1 >> 1) & 0x1f8) | ((line_m2 >> 1) & 0x1e00);
/* 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] << 5: 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 & 0xefb) << 1) | bit |
((line_m1 >> (8 - x_minor)) & 0x8) |
((line_m2 >> (8 - x_minor)) & 0x200);
}
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_template2(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;
int x, y;
byte *gbreg_line = (byte *)image->data;
/* todo: currently we only handle the nominal gbat 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;
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) & 0x7c) | ((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 & 0x1bd) << 1) | bit |
((line_m1 >> (10 - 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_template2a(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;
int x, y;
byte *gbreg_line = (byte *)image->data;
/* This is a special case for GBATX1 = 3, GBATY1 = -1 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?