Sigrid Solveig Haflínudóttirplan 9 port0a396e45 years agoHistory
1047 lines · 42.5 KB · C
RawDownload
/* Copyright (C) 2001-2020 Artifex Software, Inc.   All Rights Reserved.    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.    Refer to licensing information at http://www.artifex.com or contact   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,   CA 94945, U.S.A., +1(415)492-9861, for further information.*/ /*    jbig2dec*/ #ifdef HAVE_CONFIG_H#include "config.h"#endif#include "os_types.h" #include <stddef.h>#include <string.h>             /* memset() */ #include "jbig2.h"#include "jbig2_priv.h"#include "jbig2_arith.h"#include "jbig2_arith_int.h"#include "jbig2_arith_iaid.h"#include "jbig2_generic.h"#include "jbig2_huffman.h"#include "jbig2_image.h"#include "jbig2_page.h"#include "jbig2_refinement.h"#include "jbig2_segment.h"#include "jbig2_symbol_dict.h"#include "jbig2_text.h" /** * jbig2_decode_text_region: decode a text region segment * * @ctx: jbig2 decoder context * @segment: jbig2 segment (header) structure * @params: parameters from the text region header * @dicts: an array of referenced symbol dictionaries * @n_dicts: the number of referenced symbol dictionaries * @image: image structure in which to store the decoded region bitmap * @data: pointer to text region data to be decoded * @size: length of text region data * * Implements the text region decoding procedure * described in section 6.4 of the JBIG2 spec. * * returns: 0 on success **/intjbig2_decode_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment,                         const Jbig2TextRegionParams *params,                         const Jbig2SymbolDict *const *dicts, const uint32_t n_dicts,                         Jbig2Image *image, const byte *data, const size_t size, Jbig2ArithCx *GR_stats, Jbig2ArithState *as, Jbig2WordStream *ws){    /* relevant bits of 6.4.4 */    uint32_t NINSTANCES;    uint32_t ID;    int32_t STRIPT;    int32_t FIRSTS;    int32_t DT;    int32_t DFS;    int32_t IDS;    int32_t CURS = 0;    int32_t CURT;    int S, T;    int x, y;    bool first_symbol;    uint32_t index, SBNUMSYMS;    Jbig2Image *IB = NULL;    Jbig2Image *IBO = NULL;    Jbig2Image *refimage = NULL;    Jbig2HuffmanState *hs = NULL;    Jbig2HuffmanTable *SBSYMCODES = NULL;    int code = 0;    int RI;     USED(size, data);    SBNUMSYMS = 0;    for (index = 0; index < n_dicts; index++) {        SBNUMSYMS += dicts[index]->n_symbols;    }    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "symbol list contains %d glyphs in %d dictionaries", SBNUMSYMS, n_dicts);     if (params->SBHUFF) {        Jbig2HuffmanTable *runcodes = NULL;        Jbig2HuffmanParams runcodeparams;        Jbig2HuffmanLine runcodelengths[35];        Jbig2HuffmanLine *symcodelengths = NULL;        Jbig2HuffmanParams symcodeparams;        int err, len, range = 0, r;         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded text region");        hs = jbig2_huffman_new(ctx, ws);        if (hs == NULL)            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region");         /* 7.4.3.1.7 - decode symbol ID Huffman table */        /* this is actually part of the segment header, but it is more           convenient to handle it here */         /* parse and build the runlength code huffman table */        for (index = 0; index < 35; index++) {            runcodelengths[index].PREFLEN = jbig2_huffman_get_bits(hs, 4, &code);            if (code < 0) {                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman runcode lengths");                goto cleanup1;            }            if (code > 0) {                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding huffman runcode lengths");                goto cleanup1;            }            runcodelengths[index].RANGELEN = 0;            runcodelengths[index].RANGELOW = index;            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d length %d", index, runcodelengths[index].PREFLEN);        }        runcodeparams.HTOOB = 0;        runcodeparams.lines = runcodelengths;        runcodeparams.n_lines = 35;        runcodes = jbig2_build_huffman_table(ctx, &runcodeparams);        if (runcodes == NULL) {            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error constructing symbol ID runcode table");            goto cleanup1;        }         /* decode the symbol ID code lengths using the runlength table */        symcodelengths = jbig2_new(ctx, Jbig2HuffmanLine, SBNUMSYMS);        if (symcodelengths == NULL) {            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate memory when reading symbol ID huffman table");            goto cleanup1;        }        index = 0;        while (index < SBNUMSYMS) {            code = jbig2_huffman_get(hs, runcodes, &err);            if (err < 0) {                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error reading symbol ID huffman table");                goto cleanup1;            }            if (err > 0) {                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding symbol ID huffman table");                goto cleanup1;            }            if (code < 0 || code >= 35) {                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol ID huffman table out of range");                goto cleanup1;            }             if (code < 32) {                len = code;                range = 1;            } else {                if (code == 32) {                    if (index < 1) {                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error decoding symbol ID table: run length with no antecedent");                        goto cleanup1;                    }                    len = symcodelengths[index - 1].PREFLEN;                } else {                    len = 0;    /* code == 33 or 34 */                }                err = 0;                if (code == 32)                    range = jbig2_huffman_get_bits(hs, 2, &err) + 3;                else if (code == 33)                    range = jbig2_huffman_get_bits(hs, 3, &err) + 3;                else if (code == 34)                    range = jbig2_huffman_get_bits(hs, 7, &err) + 11;                if (err < 0) {                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman code");                    goto cleanup1;                }                if (err > 0) {                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding huffman code");                    goto cleanup1;                }            }            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d at index %d (length %d range %d)", code, index, len, range);            if (index + range > SBNUMSYMS) {                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,                            "runlength extends %d entries beyond the end of symbol ID table", index + range - SBNUMSYMS);                range = SBNUMSYMS - index;            }            for (r = 0; r < range; r++) {                symcodelengths[index + r].PREFLEN = len;                symcodelengths[index + r].RANGELEN = 0;                symcodelengths[index + r].RANGELOW = index + r;            }            index += r;        }         if (index < SBNUMSYMS) {            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "runlength codes do not cover the available symbol set");            goto cleanup1;        }         symcodeparams.HTOOB = 0;        symcodeparams.lines = symcodelengths;        symcodeparams.n_lines = SBNUMSYMS;         /* skip to byte boundary */        err = jbig2_huffman_skip(hs);        if (err < 0)        {            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to skip to next byte when building huffman table");            goto cleanup1;        }         /* finally, construct the symbol ID huffman table itself */        SBSYMCODES = jbig2_build_huffman_table(ctx, &symcodeparams); cleanup1:        jbig2_free(ctx->allocator, symcodelengths);        jbig2_release_huffman_table(ctx, runcodes);         if (SBSYMCODES == NULL) {            jbig2_huffman_free(ctx, hs);            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to construct symbol ID huffman table");        }    }     /* 6.4.5 (1) */    jbig2_image_clear(ctx, image, params->SBDEFPIXEL);     /* 6.4.6 */    if (params->SBHUFF) {        STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);    } else {        code = jbig2_arith_int_decode(ctx, params->IADT, as, &STRIPT);    }    if (code < 0) {        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode strip T");        goto cleanup2;    }    if (code > 0) {        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding strip T");        goto cleanup2;    }     /* 6.4.5 (2) */    STRIPT *= -(params->SBSTRIPS);    FIRSTS = 0;    NINSTANCES = 0;     /* 6.4.5 (3) */    while (NINSTANCES < params->SBNUMINSTANCES) {        /* (3b) */        if (params->SBHUFF) {            DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);        } else {            code = jbig2_arith_int_decode(ctx, params->IADT, as, &DT);        }        if (code < 0) {            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode delta T");            goto cleanup2;        }        if (code > 0) {            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding delta T");            goto cleanup2;        }        DT *= params->SBSTRIPS;        STRIPT += DT;         first_symbol = TRUE;        /* 6.4.5 (3c) - decode symbols in strip */        for (;;) {            /* (3c.i) */            if (first_symbol) {                /* 6.4.7 */                if (params->SBHUFF) {                    DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);                } else {                    code = jbig2_arith_int_decode(ctx, params->IAFS, as, &DFS);                }                if (code < 0) {                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode strip symbol S-difference");                    goto cleanup2;                }                if (code > 0) {                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding strip symbol S-difference");                    goto cleanup2;                }                FIRSTS += DFS;                CURS = FIRSTS;                first_symbol = FALSE;            } else {                if (NINSTANCES > params->SBNUMINSTANCES) {                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "too many NINSTANCES (%d) decoded", NINSTANCES);                    break;                }                /* (3c.ii) / 6.4.8 */                if (params->SBHUFF) {                    IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code);                } else {                    code = jbig2_arith_int_decode(ctx, params->IADS, as, &IDS);                }                if (code < 0) {                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol instance S coordinate");                    goto cleanup2;                }                if (code > 0) {                    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "OOB obtained when decoding symbol instance S coordinate signals end of strip with T value %d", DT);                    break;                }                CURS += IDS + params->SBDSOFFSET;            }             /* (3c.iii) / 6.4.9 */            if (params->SBSTRIPS == 1) {                CURT = 0;            } else if (params->SBHUFF) {                CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS, &code);            } else {                code = jbig2_arith_int_decode(ctx, params->IAIT, as, &CURT);            }            if (code < 0) {                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol instance T coordinate");                goto cleanup2;            }            if (code > 0) {                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "OOB obtained when decoding symbol instance T coordinate");                goto cleanup2;            }            T = STRIPT + CURT;             /* (3b.iv) / 6.4.10 - decode the symbol ID */            if (params->SBHUFF) {                ID = jbig2_huffman_get(hs, SBSYMCODES, &code);            } else {                code = jbig2_arith_iaid_decode(ctx, params->IAID, as, (int *)&ID);            }            if (code < 0) {                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance symbol ID");                goto cleanup2;            }            if (code > 0) {                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol instance symbol ID");                goto cleanup2;            }            if (ID >= SBNUMSYMS) {                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "ignoring out of range symbol ID (%d/%d)", ID, SBNUMSYMS);                IB = NULL;            } else {                /* (3c.v) / 6.4.11 - look up the symbol bitmap IB */                uint32_t id = ID;                 index = 0;                while (id >= dicts[index]->n_symbols)                    id -= dicts[index++]->n_symbols;                if (dicts[index]->glyphs[id] == NULL) {                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "missing glyph (%d/%d), ignoring", index, id);                } else {                    IB = jbig2_image_reference(ctx, dicts[index]->glyphs[id]);                }            }            if (params->SBREFINE) {                if (params->SBHUFF) {                    RI = jbig2_huffman_get_bits(hs, 1, &code);                } else {                    code = jbig2_arith_int_decode(ctx, params->IARI, as, &RI);                }                if (code < 0) {                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol bitmap refinement indicator");                    goto cleanup2;                }                if (code > 0) {                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol bitmap refinement indicator");                    goto cleanup2;                }            } else {                RI = 0;            }            if (RI) {                Jbig2RefinementRegionParams rparams;                int32_t RDW, RDH, RDX, RDY;                size_t BMSIZE = 0;                int code1 = 0;                int code2 = 0;                int code3 = 0;                int code4 = 0;                int code5 = 0;                int code6 = 0;                 /* 6.4.11 (1, 2, 3, 4) */                if (!params->SBHUFF) {                    code1 = jbig2_arith_int_decode(ctx, params->IARDW, as, &RDW);                    code2 = jbig2_arith_int_decode(ctx, params->IARDH, as, &RDH);                    code3 = jbig2_arith_int_decode(ctx, params->IARDX, as, &RDX);                    code4 = jbig2_arith_int_decode(ctx, params->IARDY, as, &RDY);                } else {                    RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code1);                    RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code2);                    RDX = jbig2_huffman_get(hs, params->SBHUFFRDX, &code3);                    RDY = jbig2_huffman_get(hs, params->SBHUFFRDY, &code4);                    BMSIZE = jbig2_huffman_get(hs, params->SBHUFFRSIZE, &code5);                    code6 = jbig2_huffman_skip(hs);                }                 if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0 || code5 < 0 || code6 < 0) {                    jbig2_image_release(ctx, IB);                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode data");                    goto cleanup2;                }                if (code1 > 0 || code2 > 0 || code3 > 0 || code4 > 0 || code5 > 0 || code6 > 0) {                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol instance refinement data");                    goto cleanup2;                }                 /* 6.4.11 (6) */                if (IB) {                    IBO = IB;                    IB = NULL;                    if (((int32_t) IBO->width) + RDW < 0 || ((int32_t) IBO->height) + RDH < 0) {                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "reference image dimensions negative");                        goto cleanup2;                    }                    refimage = jbig2_image_new(ctx, IBO->width + RDW, IBO->height + RDH);                    if (refimage == NULL) {                        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate reference image");                        goto cleanup2;                    }                    jbig2_image_clear(ctx, refimage, 0x00);                     /* Table 12 */                    rparams.GRTEMPLATE = params->SBRTEMPLATE;                    rparams.GRREFERENCE = IBO;                    rparams.GRREFERENCEDX = (RDW >> 1) + RDX;                    rparams.GRREFERENCEDY = (RDH >> 1) + RDY;                    rparams.TPGRON = 0;                    memcpy(rparams.grat, params->sbrat, 4);                    code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, refimage, GR_stats);                    if (code < 0) {                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");                        goto cleanup2;                    }                     jbig2_image_release(ctx, IBO);                    IBO = NULL;                    IB = refimage;                    refimage = NULL;                }                 /* 6.4.11 (7) */                if (params->SBHUFF) {                    code = jbig2_huffman_advance(hs, BMSIZE);                    if (code < 0) {                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to advance after huffman decoding refinement region");                        goto cleanup2;                    }                }            }             /* (3c.vi) */            if ((!params->TRANSPOSED) && (params->REFCORNER > 1) && IB) {                CURS += IB->width - 1;            } else if ((params->TRANSPOSED) && !(params->REFCORNER & 1) && IB) {                CURS += IB->height - 1;            }             /* (3c.vii) */            S = CURS;             /* (3c.viii) */            if (!params->TRANSPOSED) {                switch (params->REFCORNER) {                case JBIG2_CORNER_TOPLEFT:                    x = S;                    y = T;                    break;                case JBIG2_CORNER_TOPRIGHT:                    if (IB)                        x = S - IB->width + 1;                    else                        x = S + 1;                    y = T;                    break;                case JBIG2_CORNER_BOTTOMLEFT:                    x = S;                    if (IB)                        y = T - IB->height + 1;                    else                        y = T + 1;                    break;                default:                case JBIG2_CORNER_BOTTOMRIGHT:                    if (IB ) {                        x = S - IB->width + 1;                        y = T - IB->height + 1;                    } else {                        x = S + 1;                        y = T + 1;                    }

Lines 1–500 of 1047.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t