Blame jbig2_refinement.c

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, &params, 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
}