|
Packit |
3f21c4 |
/* Copyright (C) 2001-2012 Artifex Software, Inc.
|
|
Packit |
3f21c4 |
All Rights Reserved.
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
This software is provided AS-IS with no warranty, either express or
|
|
Packit |
3f21c4 |
implied.
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
This software is distributed under license and may not be copied,
|
|
Packit |
3f21c4 |
modified or distributed except as expressly authorized under the terms
|
|
Packit |
3f21c4 |
of the license contained in the file LICENSE in this distribution.
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
Refer to licensing information at http://www.artifex.com or contact
|
|
Packit |
3f21c4 |
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
|
|
Packit |
3f21c4 |
CA 94903, U.S.A., +1(415)492-9861, for further information.
|
|
Packit |
3f21c4 |
*/
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/*
|
|
Packit |
3f21c4 |
jbig2dec
|
|
Packit |
3f21c4 |
*/
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/**
|
|
Packit |
3f21c4 |
* Generic Refinement region handlers.
|
|
Packit |
3f21c4 |
**/
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
3f21c4 |
#include "config.h"
|
|
Packit |
3f21c4 |
#endif
|
|
Packit |
3f21c4 |
#include "os_types.h"
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
#include <stddef.h>
|
|
Packit |
3f21c4 |
#include <string.h> /* memcpy(), memset() */
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
#include <stdio.h>
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
#include "jbig2.h"
|
|
Packit |
3f21c4 |
#include "jbig2_priv.h"
|
|
Packit |
3f21c4 |
#include "jbig2_arith.h"
|
|
Packit |
3f21c4 |
#include "jbig2_generic.h"
|
|
Packit |
3f21c4 |
#include "jbig2_image.h"
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
#if 0 /* currently not used */
|
|
Packit |
3f21c4 |
static int
|
|
Packit |
3f21c4 |
jbig2_decode_refinement_template0(Jbig2Ctx *ctx,
|
|
Packit |
3f21c4 |
Jbig2Segment *segment,
|
|
Packit |
3f21c4 |
const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "refinement region template 0 NYI");
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
#endif
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
static int
|
|
Packit |
3f21c4 |
jbig2_decode_refinement_template0_unopt(Jbig2Ctx *ctx,
|
|
Packit |
3f21c4 |
Jbig2Segment *segment,
|
|
Packit |
3f21c4 |
const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
const int GRW = image->width;
|
|
Packit |
3f21c4 |
const int GRH = image->height;
|
|
Packit |
3f21c4 |
const int dx = params->DX;
|
|
Packit |
3f21c4 |
const int dy = params->DY;
|
|
Packit |
3f21c4 |
Jbig2Image *ref = params->reference;
|
|
Packit |
3f21c4 |
uint32_t CONTEXT;
|
|
Packit |
3f21c4 |
int x, y;
|
|
Packit |
3f21c4 |
bool bit;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
for (y = 0; y < GRH; y++) {
|
|
Packit |
3f21c4 |
for (x = 0; x < GRW; x++) {
|
|
Packit |
3f21c4 |
CONTEXT = 0;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], y + params->grat[1]) << 3;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 1) << 6;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 7;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 8;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 9;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
|
|
Packit |
3f21c4 |
bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
|
|
Packit |
3f21c4 |
jbig2_image_set_pixel(image, x, y, bit);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
#ifdef JBIG2_DEBUG_DUMP
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
static count = 0;
|
|
Packit |
3f21c4 |
char name[32];
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
snprintf(name, 32, "refin-%d.pbm", count);
|
|
Packit |
3f21c4 |
jbig2_image_write_pbm_file(ref, name);
|
|
Packit |
3f21c4 |
snprintf(name, 32, "refout-%d.pbm", count);
|
|
Packit |
3f21c4 |
jbig2_image_write_pbm_file(image, name);
|
|
Packit |
3f21c4 |
count++;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
#endif
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
return 0;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
static int
|
|
Packit |
3f21c4 |
jbig2_decode_refinement_template1_unopt(Jbig2Ctx *ctx,
|
|
Packit |
3f21c4 |
Jbig2Segment *segment,
|
|
Packit |
3f21c4 |
const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
const int GRW = image->width;
|
|
Packit |
3f21c4 |
const int GRH = image->height;
|
|
Packit |
3f21c4 |
const int dx = params->DX;
|
|
Packit |
3f21c4 |
const int dy = params->DY;
|
|
Packit |
3f21c4 |
Jbig2Image *ref = params->reference;
|
|
Packit |
3f21c4 |
uint32_t CONTEXT;
|
|
Packit |
3f21c4 |
int x, y;
|
|
Packit |
3f21c4 |
bool bit;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
for (y = 0; y < GRH; y++) {
|
|
Packit |
3f21c4 |
for (x = 0; x < GRW; x++) {
|
|
Packit |
3f21c4 |
CONTEXT = 0;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y + 0) << 0;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 6;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
|
|
Packit |
3f21c4 |
bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
|
|
Packit |
3f21c4 |
jbig2_image_set_pixel(image, x, y, bit);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
#ifdef JBIG2_DEBUG_DUMP
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
static count = 0;
|
|
Packit |
3f21c4 |
char name[32];
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
snprintf(name, 32, "refin-%d.pbm", count);
|
|
Packit |
3f21c4 |
jbig2_image_write_pbm_file(ref, name);
|
|
Packit |
3f21c4 |
snprintf(name, 32, "refout-%d.pbm", count);
|
|
Packit |
3f21c4 |
jbig2_image_write_pbm_file(image, name);
|
|
Packit |
3f21c4 |
count++;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
#endif
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
return 0;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
#if 0 /* currently not used */
|
|
Packit |
3f21c4 |
static int
|
|
Packit |
3f21c4 |
jbig2_decode_refinement_template1(Jbig2Ctx *ctx,
|
|
Packit |
3f21c4 |
Jbig2Segment *segment,
|
|
Packit |
3f21c4 |
const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
const int GRW = image->width;
|
|
Packit |
3f21c4 |
const int GRH = image->height;
|
|
Packit |
3f21c4 |
const int stride = image->stride;
|
|
Packit |
3f21c4 |
const int refstride = params->reference->stride;
|
|
Packit |
3f21c4 |
const int dy = params->DY;
|
|
Packit |
3f21c4 |
byte *grreg_line = (byte *) image->data;
|
|
Packit |
3f21c4 |
byte *grref_line = (byte *) params->reference->data;
|
|
Packit |
3f21c4 |
int x, y;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
for (y = 0; y < GRH; y++) {
|
|
Packit |
3f21c4 |
const int padded_width = (GRW + 7) & -8;
|
|
Packit |
3f21c4 |
uint32_t CONTEXT;
|
|
Packit |
3f21c4 |
uint32_t refline_m1; /* previous line of the reference bitmap */
|
|
Packit |
3f21c4 |
uint32_t refline_0; /* current line of the reference bitmap */
|
|
Packit |
3f21c4 |
uint32_t refline_1; /* next line of the reference bitmap */
|
|
Packit |
3f21c4 |
uint32_t line_m1; /* previous line of the decoded bitmap */
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
line_m1 = (y >= 1) ? grreg_line[-stride] : 0;
|
|
Packit |
3f21c4 |
refline_m1 = ((y - dy) >= 1) ? grref_line[(-1 - dy) * stride] << 2 : 0;
|
|
Packit |
3f21c4 |
refline_0 = (((y - dy) > 0) && ((y - dy) < GRH)) ? grref_line[(0 - dy) * stride] << 4 : 0;
|
|
Packit |
3f21c4 |
refline_1 = (y < GRH - 1) ? grref_line[(+1 - dy) * stride] << 7 : 0;
|
|
Packit |
3f21c4 |
CONTEXT = ((line_m1 >> 5) & 0x00e) | ((refline_1 >> 5) & 0x030) | ((refline_0 >> 5) & 0x1c0) | ((refline_m1 >> 5) & 0x200);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
for (x = 0; x < padded_width; x += 8) {
|
|
Packit |
3f21c4 |
byte result = 0;
|
|
Packit |
3f21c4 |
int x_minor;
|
|
Packit |
3f21c4 |
const int minor_width = GRW - x > 8 ? 8 : GRW - x;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
if (y >= 1) {
|
|
Packit |
3f21c4 |
line_m1 = (line_m1 << 8) | (x + 8 < GRW ? grreg_line[-stride + (x >> 3) + 1] : 0);
|
|
Packit |
3f21c4 |
refline_m1 = (refline_m1 << 8) | (x + 8 < GRW ? grref_line[-refstride + (x >> 3) + 1] << 2 : 0);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
refline_0 = (refline_0 << 8) | (x + 8 < GRW ? grref_line[(x >> 3) + 1] << 4 : 0);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
if (y < GRH - 1)
|
|
Packit |
3f21c4 |
refline_1 = (refline_1 << 8) | (x + 8 < GRW ? grref_line[+refstride + (x >> 3) + 1] << 7 : 0);
|
|
Packit |
3f21c4 |
else
|
|
Packit |
3f21c4 |
refline_1 = 0;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/* this is the speed critical inner-loop */
|
|
Packit |
3f21c4 |
for (x_minor = 0; x_minor < minor_width; x_minor++) {
|
|
Packit |
3f21c4 |
bool bit;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
bit = jbig2_arith_decode(as, &GR_stats[CONTEXT]);
|
|
Packit |
3f21c4 |
result |= bit << (7 - x_minor);
|
|
Packit |
3f21c4 |
CONTEXT = ((CONTEXT & 0x0d6) << 1) | bit |
|
|
Packit |
3f21c4 |
((line_m1 >> (9 - x_minor)) & 0x002) |
|
|
Packit |
3f21c4 |
((refline_1 >> (9 - x_minor)) & 0x010) | ((refline_0 >> (9 - x_minor)) & 0x040) | ((refline_m1 >> (9 - x_minor)) & 0x200);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
grreg_line[x >> 3] = result;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
grreg_line += stride;
|
|
Packit |
3f21c4 |
grref_line += refstride;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
return 0;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
#endif
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
typedef uint32_t(*ContextBuilder)(const Jbig2RefinementRegionParams *, Jbig2Image *, int, int);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
static int
|
|
Packit |
3f21c4 |
implicit_value(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
Jbig2Image *ref = params->reference;
|
|
Packit |
3f21c4 |
int i = x - params->DX;
|
|
Packit |
3f21c4 |
int j = y - params->DY;
|
|
Packit |
3f21c4 |
int m = jbig2_image_get_pixel(ref, i, j);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
return ((jbig2_image_get_pixel(ref, i - 1, j - 1) == m) &&
|
|
Packit |
3f21c4 |
(jbig2_image_get_pixel(ref, i, j - 1) == m) &&
|
|
Packit |
3f21c4 |
(jbig2_image_get_pixel(ref, i + 1, j - 1) == m) &&
|
|
Packit |
3f21c4 |
(jbig2_image_get_pixel(ref, i - 1, j) == m) &&
|
|
Packit |
3f21c4 |
(jbig2_image_get_pixel(ref, i + 1, j) == m) &&
|
|
Packit |
3f21c4 |
(jbig2_image_get_pixel(ref, i - 1, j + 1) == m) && (jbig2_image_get_pixel(ref, i, j + 1) == m) && (jbig2_image_get_pixel(ref, i + 1, j + 1) == m)
|
|
Packit |
3f21c4 |
)? m : -1;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
static uint32_t
|
|
Packit |
3f21c4 |
mkctx0(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
const int dx = params->DX;
|
|
Packit |
3f21c4 |
const int dy = params->DY;
|
|
Packit |
3f21c4 |
Jbig2Image *ref = params->reference;
|
|
Packit |
3f21c4 |
uint32_t CONTEXT;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0);
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + params->grat[0], y + params->grat[1]) << 3;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 1) << 6;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 7;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 8;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 9;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy - 1) << 10;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 11;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + params->grat[2], y - dy + params->grat[3]) << 12;
|
|
Packit |
3f21c4 |
return CONTEXT;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
static uint32_t
|
|
Packit |
3f21c4 |
mkctx1(const Jbig2RefinementRegionParams *params, Jbig2Image *image, int x, int y)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
const int dx = params->DX;
|
|
Packit |
3f21c4 |
const int dy = params->DY;
|
|
Packit |
3f21c4 |
Jbig2Image *ref = params->reference;
|
|
Packit |
3f21c4 |
uint32_t CONTEXT;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
CONTEXT = jbig2_image_get_pixel(image, x - 1, y + 0);
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 1;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 2;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 3;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 1) << 4;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 1) << 5;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 1, y - dy + 0) << 6;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy + 0) << 7;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx - 1, y - dy + 0) << 8;
|
|
Packit |
3f21c4 |
CONTEXT |= jbig2_image_get_pixel(ref, x - dx + 0, y - dy - 1) << 9;
|
|
Packit |
3f21c4 |
return CONTEXT;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
static int
|
|
Packit |
3f21c4 |
jbig2_decode_refinement_TPGRON(const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
const int GRW = image->width;
|
|
Packit |
3f21c4 |
const int GRH = image->height;
|
|
Packit |
3f21c4 |
int x, y, iv, bit, LTP = 0;
|
|
Packit |
3f21c4 |
uint32_t start_context = (params->GRTEMPLATE ? 0x40 : 0x100);
|
|
Packit |
3f21c4 |
ContextBuilder mkctx = (params->GRTEMPLATE ? mkctx1 : mkctx0);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
for (y = 0; y < GRH; y++) {
|
|
Packit |
3f21c4 |
LTP ^= jbig2_arith_decode(as, &GR_stats[start_context]);
|
|
Packit |
3f21c4 |
if (!LTP) {
|
|
Packit |
3f21c4 |
for (x = 0; x < GRW; x++) {
|
|
Packit |
3f21c4 |
bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
|
|
Packit |
3f21c4 |
jbig2_image_set_pixel(image, x, y, bit);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
} else {
|
|
Packit |
3f21c4 |
for (x = 0; x < GRW; x++) {
|
|
Packit |
3f21c4 |
iv = implicit_value(params, image, x, y);
|
|
Packit |
3f21c4 |
if (iv < 0) {
|
|
Packit |
3f21c4 |
bit = jbig2_arith_decode(as, &GR_stats[mkctx(params, image, x, y)]);
|
|
Packit |
3f21c4 |
jbig2_image_set_pixel(image, x, y, bit);
|
|
Packit |
3f21c4 |
} else
|
|
Packit |
3f21c4 |
jbig2_image_set_pixel(image, x, y, iv);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
return 0;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/**
|
|
Packit |
3f21c4 |
* jbig2_decode_refinement_region: Decode a generic refinement region.
|
|
Packit |
3f21c4 |
* @ctx: The context for allocation and error reporting.
|
|
Packit |
3f21c4 |
* @segment: A segment reference for error reporting.
|
|
Packit |
3f21c4 |
* @params: Decoding parameter set.
|
|
Packit |
3f21c4 |
* @as: Arithmetic decoder state.
|
|
Packit |
3f21c4 |
* @image: Where to store the decoded image.
|
|
Packit |
3f21c4 |
* @GR_stats: Arithmetic stats.
|
|
Packit |
3f21c4 |
*
|
|
Packit |
3f21c4 |
* Decodes a generic refinement region, according to section 6.3.
|
|
Packit |
3f21c4 |
* an already allocated Jbig2Image object in @image for the result.
|
|
Packit |
3f21c4 |
*
|
|
Packit |
3f21c4 |
* Because this API is based on an arithmetic decoding state, it is
|
|
Packit |
3f21c4 |
* not suitable for MMR decoding.
|
|
Packit |
3f21c4 |
*
|
|
Packit |
3f21c4 |
* Return code: 0 on success.
|
|
Packit |
3f21c4 |
**/
|
|
Packit |
3f21c4 |
int
|
|
Packit |
3f21c4 |
jbig2_decode_refinement_region(Jbig2Ctx *ctx,
|
|
Packit |
3f21c4 |
Jbig2Segment *segment,
|
|
Packit |
3f21c4 |
const Jbig2RefinementRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GR_stats)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
|
|
Packit |
3f21c4 |
"decoding generic refinement region with offset %d,%x, GRTEMPLATE=%d, TPGRON=%d",
|
|
Packit |
3f21c4 |
params->DX, params->DY, params->GRTEMPLATE, params->TPGRON);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
if (params->TPGRON)
|
|
Packit |
3f21c4 |
return jbig2_decode_refinement_TPGRON(params, as, image, GR_stats);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
if (params->GRTEMPLATE)
|
|
Packit |
3f21c4 |
return jbig2_decode_refinement_template1_unopt(ctx, segment, params, as, image, GR_stats);
|
|
Packit |
3f21c4 |
else
|
|
Packit |
3f21c4 |
return jbig2_decode_refinement_template0_unopt(ctx, segment, params, as, image, GR_stats);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/**
|
|
Packit |
3f21c4 |
* Find the first referred-to intermediate region segment
|
|
Packit |
3f21c4 |
* with a non-NULL result for use as a reference image
|
|
Packit |
3f21c4 |
*/
|
|
Packit |
3f21c4 |
static Jbig2Segment *
|
|
Packit |
3f21c4 |
jbig2_region_find_referred(Jbig2Ctx *ctx, Jbig2Segment *segment)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
const int nsegments = segment->referred_to_segment_count;
|
|
Packit |
3f21c4 |
Jbig2Segment *rsegment;
|
|
Packit |
3f21c4 |
int index;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
for (index = 0; index < nsegments; index++) {
|
|
Packit |
3f21c4 |
rsegment = jbig2_find_segment(ctx, segment->referred_to_segments[index]);
|
|
Packit |
3f21c4 |
if (rsegment == NULL) {
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "could not find referred to segment %d", segment->referred_to_segments[index]);
|
|
Packit |
3f21c4 |
continue;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
switch (rsegment->flags & 63) {
|
|
Packit |
3f21c4 |
case 4: /* intermediate text region */
|
|
Packit |
3f21c4 |
case 20: /* intermediate halftone region */
|
|
Packit |
3f21c4 |
case 36: /* intermediate generic region */
|
|
Packit |
3f21c4 |
case 40: /* intermediate generic refinement region */
|
|
Packit |
3f21c4 |
if (rsegment->result)
|
|
Packit |
3f21c4 |
return rsegment;
|
|
Packit |
3f21c4 |
break;
|
|
Packit |
3f21c4 |
default: /* keep looking */
|
|
Packit |
3f21c4 |
break;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
/* no appropriate reference was found. */
|
|
Packit |
3f21c4 |
return NULL;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/**
|
|
Packit |
3f21c4 |
* Handler for generic refinement region segments
|
|
Packit |
3f21c4 |
*/
|
|
Packit |
3f21c4 |
int
|
|
Packit |
3f21c4 |
jbig2_refinement_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
Jbig2RefinementRegionParams params;
|
|
Packit |
3f21c4 |
Jbig2RegionSegmentInfo rsi;
|
|
Packit |
3f21c4 |
int offset = 0;
|
|
Packit |
3f21c4 |
byte seg_flags;
|
|
Packit |
3f21c4 |
int code = 0;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/* 7.4.7 */
|
|
Packit |
3f21c4 |
if (segment->data_length < 18)
|
|
Packit |
3f21c4 |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "Segment too short");
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
jbig2_get_region_segment_info(&rsi, segment_data);
|
|
Packit |
3f21c4 |
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);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/* 7.4.7.2 */
|
|
Packit |
3f21c4 |
seg_flags = segment_data[17];
|
|
Packit |
3f21c4 |
params.GRTEMPLATE = seg_flags & 0x01;
|
|
Packit |
3f21c4 |
params.TPGRON = seg_flags & 0x02 ? 1 : 0;
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
|
|
Packit |
3f21c4 |
"segment flags = %02x %s%s", seg_flags, params.GRTEMPLATE ? " GRTEMPLATE" : "", params.TPGRON ? " TPGRON" : "");
|
|
Packit |
3f21c4 |
if (seg_flags & 0xFC)
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "reserved segment flag bits are non-zero");
|
|
Packit |
3f21c4 |
offset += 18;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/* 7.4.7.3 */
|
|
Packit |
3f21c4 |
if (!params.GRTEMPLATE) {
|
|
Packit |
3f21c4 |
if (segment->data_length < 22)
|
|
Packit |
3f21c4 |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "Segment too short");
|
|
Packit |
3f21c4 |
params.grat[0] = segment_data[offset + 0];
|
|
Packit |
3f21c4 |
params.grat[1] = segment_data[offset + 1];
|
|
Packit |
3f21c4 |
params.grat[2] = segment_data[offset + 2];
|
|
Packit |
3f21c4 |
params.grat[3] = segment_data[offset + 3];
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
|
|
Packit |
3f21c4 |
"grat1: (%d, %d) grat2: (%d, %d)", params.grat[0], params.grat[1], params.grat[2], params.grat[3]);
|
|
Packit |
3f21c4 |
offset += 4;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/* 7.4.7.4 - set up the reference image */
|
|
Packit |
3f21c4 |
if (segment->referred_to_segment_count) {
|
|
Packit |
3f21c4 |
Jbig2Segment *ref;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
ref = jbig2_region_find_referred(ctx, segment);
|
|
Packit |
3f21c4 |
if (ref == NULL)
|
|
Packit |
3f21c4 |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not find reference bitmap!");
|
|
Packit |
3f21c4 |
/* the reference bitmap is the result of a previous
|
|
Packit |
3f21c4 |
intermediate region segment; the reference selection
|
|
Packit |
3f21c4 |
rules say to use the first one available, and not to
|
|
Packit |
3f21c4 |
reuse any intermediate result, so we simply clone it
|
|
Packit |
3f21c4 |
and free the original to keep track of this. */
|
|
Packit |
3f21c4 |
params.reference = jbig2_image_clone(ctx, (Jbig2Image *) ref->result);
|
|
Packit |
3f21c4 |
jbig2_image_release(ctx, (Jbig2Image *) ref->result);
|
|
Packit |
3f21c4 |
ref->result = NULL;
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "found reference bitmap in segment %d", ref->number);
|
|
Packit |
3f21c4 |
} else {
|
|
Packit |
3f21c4 |
/* the reference is just (a subset of) the page buffer */
|
|
Packit |
3f21c4 |
params.reference = jbig2_image_clone(ctx, ctx->pages[ctx->current_page].image);
|
|
Packit |
3f21c4 |
if (params.reference == NULL)
|
|
Packit |
3f21c4 |
return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not clone reference bitmap!");
|
|
Packit |
3f21c4 |
/* TODO: subset the image if appropriate */
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
/* 7.4.7.5 */
|
|
Packit |
3f21c4 |
params.DX = 0;
|
|
Packit |
3f21c4 |
params.DY = 0;
|
|
Packit |
3f21c4 |
{
|
|
Packit |
3f21c4 |
Jbig2WordStream *ws = NULL;
|
|
Packit |
3f21c4 |
Jbig2ArithState *as = NULL;
|
|
Packit |
3f21c4 |
Jbig2ArithCx *GR_stats = NULL;
|
|
Packit |
3f21c4 |
int stats_size;
|
|
Packit |
3f21c4 |
Jbig2Image *image = NULL;
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
image = jbig2_image_new(ctx, rsi.width, rsi.height);
|
|
Packit |
3f21c4 |
if (image == NULL) {
|
|
Packit |
3f21c4 |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unable to allocate refinement image");
|
|
Packit |
3f21c4 |
goto cleanup;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "allocated %d x %d image buffer for region decode results", rsi.width, rsi.height);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
stats_size = params.GRTEMPLATE ? 1 << 10 : 1 << 13;
|
|
Packit |
3f21c4 |
GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
|
|
Packit |
3f21c4 |
if (GR_stats == NULL) {
|
|
Packit |
3f21c4 |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate GR-stats in jbig2_refinement_region");
|
|
Packit |
3f21c4 |
goto cleanup;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
memset(GR_stats, 0, stats_size);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
|
|
Packit |
3f21c4 |
if (ws == NULL) {
|
|
Packit |
3f21c4 |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate ws in jbig2_refinement_region");
|
|
Packit |
3f21c4 |
goto cleanup;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
as = jbig2_arith_new(ctx, ws);
|
|
Packit |
3f21c4 |
if (as == NULL) {
|
|
Packit |
3f21c4 |
code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1, "failed to allocate as in jbig2_refinement_region");
|
|
Packit |
3f21c4 |
goto cleanup;
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
code = jbig2_decode_refinement_region(ctx, segment, ¶ms, as, image, GR_stats);
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
if ((segment->flags & 63) == 40) {
|
|
Packit |
3f21c4 |
/* intermediate region. save the result for later */
|
|
Packit |
3f21c4 |
segment->result = jbig2_image_clone(ctx, image);
|
|
Packit |
3f21c4 |
} else {
|
|
Packit |
3f21c4 |
/* immediate region. composite onto the page */
|
|
Packit |
3f21c4 |
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
|
|
Packit |
3f21c4 |
"composing %dx%d decoded refinement region onto page at (%d, %d)", rsi.width, rsi.height, rsi.x, rsi.y);
|
|
Packit |
3f21c4 |
jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
cleanup:
|
|
Packit |
3f21c4 |
jbig2_image_release(ctx, image);
|
|
Packit |
3f21c4 |
jbig2_image_release(ctx, params.reference);
|
|
Packit |
3f21c4 |
jbig2_free(ctx->allocator, as);
|
|
Packit |
3f21c4 |
jbig2_word_stream_buf_free(ctx, ws);
|
|
Packit |
3f21c4 |
jbig2_free(ctx->allocator, GR_stats);
|
|
Packit |
3f21c4 |
}
|
|
Packit |
3f21c4 |
|
|
Packit |
3f21c4 |
return code;
|
|
Packit |
3f21c4 |
}
|