| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519 |
- /* Copyright (C) 2001-2023 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., 39 Mesa Street, Suite 108A, San Francisco,
- CA 94129, USA, for further information.
- */
- /*
- jbig2dec
- */
- /**
- * 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_arith.h"
- #include "jbig2_generic.h"
- #include "jbig2_image.h"
- #include "jbig2_mmr.h"
- #include "jbig2_page.h"
- #include "jbig2_segment.h"
- /*
- This is an explanation of the unoptimized and optimized generic
- region decoder implementations below, wherein we try to explain
- all the magic numbers.
- The generic region decoders decode the output pixels one row at a
- time, top to bottom. Within each row the pixels are decoded left
- to right. The input for the arithmetic integer decoder used to
- decode each pixel is a context consisting of up to 16 previously
- decoded pixels. These pixels are chosen according to a predefined
- template placed relative to the location of the pixel to be
- decoded (6.2.5.3 figures 3, 4, 5 and 6). There are four different
- template that may be used (6.2.5.3). The template to use is
- determined by GBTEMPLATE. GBTEMPLATE is set in the symbol
- dictionary (6.5.8.1), generic region (7.4.6.4), or when decoding
- a halftone region's gray-scale image (annex C.5).
- Most of the pixels in each template have fixed locations relative
- to the pixel to be decoded. However, all templates have at least
- one adaptive pixel. The adaptive pixels have nominal locations,
- but these locations may be changed by GBAT. GBAT is set in the
- symbol dictionary (7.4.2.1.2), generic region (7.4.6.1), or hard
- coded as for halftone patterns (6.7.5).
- Adaptive pixels are restricted to fall within a field of
- previously decoded pixels relative to the pixel to be decoded
- (figure 7). The relative Y-coordinate for these adaptive pixels
- may vary between -128 and 0. The relative X-coordinate may vary
- between -128 and +127 (however, if the Y-coordinate is 0 the
- range of the X-coordinate is further restricted to -128 to -1
- since the pixels at locations 0 to +127 have not yet been
- decoded). If a template refers to a pixel location that reside
- outside of the image boundaries its value is assumed to be 0.
- UNOPTIMIZED DECODER
- The unoptimized decoders first check the contents of GBAT. If
- GBAT specifies that any of the adaptive pixels reside outside the
- allowed field the decoding is aborted. Next, each row is
- processed top to bottom, left to right, one pixel at a time. For
- each pixel a context is created containing the bit values of the
- pixels that fall inside the template.
- The order these bits are stored in the context is implementation
- dependent (6.2.5.3). We store the bit values in the CONTEXT
- variable from LSB to MSB, starting with the value of the pixel to
- the left of the current pixel, continuing right to left, bottom
- to top following the template. Using the CONTEXT created from
- these pixel values, the arithmetic integer decoder retrieves the
- pixel value, which is then written into the output image.
- Example when GBTEMPLATE is 2:
- The figure below represents a pixel grid of the output image.
- Each pixel is a single bit in the image. The pixel "OO" in the
- figure below is about to be decoded. The pixels "??" have not
- been decoded yet. The CONTEXT variable is constructed by
- combining the bit values from the pixels referred to by the
- template, shifted to their corresponding bit position.
- . . . . . . . .
- . . . . . . . .
- ...+----+----+----+----+----+----+----+...
- | | | X9 | X8 | X7 | | |
- ...+----+----+----+----+----+----+----+...
- | | X6 | X5 | X4 | X3 | A1 | |
- ...+----+----+----+----+----+----+----+...
- | | X2 | X1 | OO | ?? | ?? | ?? |
- ...+----+----+----+----+----+----+----+...
- . . . . . . . .
- . . . . . . . .
- In the table below pixel OO is assumed to be at coordinate (x, y).
- Bit 9: Pixel at location (x-1, y-2) (This is fixed pixel X9)
- Bit 8: Pixel at location (x , y-2) (This is fixed pixel X8)
- Bit 7: Pixel at location (x+1, y-2) (This is fixed pixel X7)
- Bit 6: Pixel at location (x-2, y-1) (This is fixed pixel X6)
- Bit 5: Pixel at location (x-1, y-1) (This is fixed pixel X5)
- Bit 4: Pixel at location (x , y-1) (This is fixed pixel X4)
- Bit 3: Pixel at location (x+1, y-1) (This is fixed pixel X3)
- Bit 2: Pixel at location (x+2, y-1) (This is adaptive pixel A1)
- Bit 1: Pixel at location (x-2, y ) (This is fixed pixel X2)
- Bit 0: Pixel at location (x-1, y ) (This is fixed pixel X1)
- The location of adaptive pixel A1 may not always be at the
- nominal location (x+2, y-1). It could be at any pixel location to
- the left or above OO as specified by GBAT, e.g. at the location
- (x-128, y+127).
- OPTIMIZED DECODER
- The optimized decoders work differently. They strive to avoid
- recreating the arithmetic integer decoder context from scratch
- for every pixel decoded. Instead they reuse part of the CONTEXT
- used to compute the previous pixel (the pixel to left of the one
- now being decoded). They also keep two sliding windows of pixel
- bit values from the two rows of pixels immediately above the
- pixel to be decoded. These are stored in the 32-bit variables
- line_m1 (row above the pixel to be decoded) and line_m2 (row
- above that of line_m1). These optimized decoders ONLY work for
- the nominal adaptive pixel locations since these locations are
- hard-coded into the implementation.
- The bit ordering in the CONTEXT variable is identical to the
- unoptimized case described above.
- The optimized decoders decode the output pixels one row at a
- time, top to bottom. Within each row the pixels are decoded in
- batches of up to eight pixels at a time (except possibly the
- right most batch which may be less than eight pixels). The
- batches in a row are decoded in sequence from left to right.
- Within each such batch the pixels are decoded in sequence from
- left to right.
- Before decoding the pixels in a row the two sliding windows of
- pixel values are reset. The first eight pixels of the row above
- the pixel to be decoded is stored in line_m1, while line_m2
- stores the first eight pixels of the row above that of line_m1.
- The figure below illustrates the situation where the template has
- been placed so that the decoded pixel OO is the very first pixel
- of a row. It also gives labels to various pixels that we will
- refer to below.
- . . . . . . . . . . .
- | . . . . . . . . . .
- + + +----+----+----+----+----+----+----+----+----+----+...
- X9 | X8 | X7 | m1 | m2 | m3 | m4 | m5 | m6 | m7 | |
- + + +----+----+----+----+----+----+----+----+----+----+...
- X6 X5 | X4 | X3 | A1 | n1 | n2 | n3 | n4 | n5 | n6 | n7 |
- + + +----+----+----+----+----+----+----+----+----+----+...
- X2 X1 | OO | | | | | | | | | |
- + + +----+----+----+----+----+----+----+----+----+----+...
- | . . . . . . . . . .
- . . . . . . . . . . .
- The pixels X1, X2, X5, X6 and X9 all reside outside the left edge
- of the image. These pixels (like all others outside the image)
- can according to 6.2.5.2 be assumed to be 0. line_m1 stores n5
- through n1 as well as A1, and X3 through X6. line_m2 stores m6
- through m1 as well as X7 through X9. The bits in line_m2 are also
- shifted left four bits as seen below.
- 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | bit position
- ------------------------------------------------+------------------
- 0 0 0 0 0 0 X6 X5 X4 X3 A1 n1 n2 n3 n4 n5 | line_m1
- 0 0 0 X9 X8 X7 m1 m2 m3 m4 m5 m6 0 0 0 0 | line_m2
- The way line_m1 and line_m2 are stored means we can simply shift
- them by the same amount to move the sliding window.
- The bit order in line_m1 and line_m2 matches the ordering in the
- CONTEXT variable. Each bit for the 'A' and 'X' pixels in line_m1
- and line_m2 correspond to the equivalent bits in CONTEXT, only
- shifted right by 3 bits. Thus X3 is bit 3 in CONTEXT and bit 6 in
- line_m1, etc.
- The initial arithmetic integer decoder context is created and
- stored in the CONTEXT variable by masking, shifting, and bitwise
- ORing the contents of line_m1 and line_m2. The "CONTEXT contents"
- row is only shown for clarity, it is not present in the code.
- 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | bit position
- ------------------------------------------------+---------------------------
- 0 0 0 0 0 0 0 0 0 X6 X5 X4 X3 A1 n1 n2 | line_m1 >> 3
- 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 | mask for line_m1 (0x7c)
- 0 0 0 0 0 0 0 0 0 X6 X5 X4 X3 A1 0 0 | line_m1 AND mask
- ------------------------------------------------+---------------------------
- 0 0 0 0 0 0 X9 X8 X7 m1 m2 m3 m4 m5 m6 0 | line_m2 >> 3
- 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 | mask for line_m2 (0x380)
- 0 0 0 0 0 0 X9 X8 X7 0 0 0 0 0 0 0 | line_m2 AND mask
- ------------------------------------------------+---------------------------
- 0 0 0 0 0 0 X9 X8 X7 X6 X5 X4 X3 A1 0 0 | CONTEXT = line_m1 OR line_m2
- ------------------------------------------------+---------------------------
- 0 0 0 0 0 0 X9 X8 X7 X6 X5 X4 X3 A1 X2 X1 | CONTEXT contents
- Each batch is normally 8 bits, but at the right edge of the image
- we may have fewer pixels to decode. The minor_width is how many
- pixels the current batch should decode, with a counter variable
- x_minor to keep track of the current pixel being decoded.
- In order to process a new batch of pixels, unless we're at the
- rightmost batch of pixels, we need to refill the sliding window
- variables with eight new bits. Looking at the diagram above we
- can see that in order to decode eight pixels starting with O0
- we'll need to have bits up to pixel 'n7' for line_m1 and 'm7' for
- line_m2 available (A1 and X7 moved right 7 times). To do this
- simply and quickly, we shift line_m1 left by 8 bits, and OR in
- the next byte from corresponding row. Likewise for line_m2, but
- the next byte from the image is also shifted left by 4 bits to
- compensate for line_m2 having the four least significant bits
- unused.
- These new eight bits contain the bit values of the eight pixels
- to the right of those already present in line_m1 and line_m2. We
- call these new bits m7 through mE, and n6 through nD, as
- illustrated below.
- 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | bit position
- ------------------------------------------------------------------------+-------------
- 0 0 0 0 0 0 0 0 0 0 0 0 0 0 X6 X5 X4 X3 A1 n1 n2 n3 n4 n5 | original line_m1
- 0 0 0 0 0 0 X6 X5 X4 X3 A1 n1 n2 n3 n4 n5 0 0 0 0 0 0 0 0 | line_m1 shifted left by 8
- 0 0 0 0 0 0 X6 X5 X4 X3 A1 n1 n2 n3 n4 n5 n6 n7 n8 n9 nA nB nC nD | line_m1 with new bits ORed in
- ------------------------------------------------------------------------+-------------
- 0 0 0 0 0 0 0 0 0 0 0 X9 X8 X7 m1 m2 m3 m4 m5 m6 0 0 0 0 | original line_m2
- 0 0 0 X9 X8 X7 m1 m2 m3 m4 m5 m6 0 0 0 0 0 0 0 0 0 0 0 0 | line_m2 shifted left by 8
- 0 0 0 X9 X8 X7 m1 m2 m3 m4 m5 m6 m7 m8 m9 mA mB mC mD mE 0 0 0 0 | line_m2 with new bits ORed in
- . . . . . . . . . . . . . . . . . . . .
- | . . . . . . . . . . . . . . . . . . .
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- X9 | X8 | X7 | m1 | m2 | m3 | m4 | m5 | m6 | m7 | m8 | m9 | mA | mB | mC | mD | mE | | | |
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- X6 X5 | X4 | X3 | A1 | n1 | n2 | n3 | n4 | n5 | n6 | n7 | n8 | n9 | nA | nB | nC | nD | | | |
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- X2 X1 | OO | | | | | | | | | | | | | | | | | | |
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- | . . . . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . . . . . .
- CONTEXT, line_m1 and line_m2 now contain all necessary bits to
- decode a full batch of eight pixels.
- The first pixel in the batch is decoded using this CONTEXT. After
- that, for each following pixel we need to update the CONTEXT
- using both the last decoded pixel value and new bits from line_m1
- and line_m2.
- . . . . . . . . . . . . . . . . . . . .
- | . . . . . . . . . . . . . . . . . . .
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- (X9)|_X8_|_X7_|>m1<| m2 | m3 | m4 | m5 | m6 | m7 | m8 | m9 | mA | mB | mC | mD | mE | | | |
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- (X6) _X5_|_X4_|_X3_|_A1_|>n1<| n2 | n3 | n4 | n5 | n6 | n7 | n8 | n9 | nA | nB | nC | nD | | | |
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- (X2) _X1_|>OO<| oo | | | | | | | | | | | | | | | | | |
- + + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+...
- | . . . . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . . . . . .
- This figure illustrates what happens when the same template is
- overlaid on itself shifted one pixel to the right in order to
- decode the next pixel. Pixels marked with _ _ are pixels that
- are present in both templates' CONTEXTs and can be reused. Pixels
- marked with ( ) are pixels from the first template that are no
- longer necessary and can be removed from CONTEXT. Pixels marked
- with > < are new pixels that were not part of the original
- CONTEXT, and so need to be moved into the CONTEXT at the
- appropriate locations. In general the leftmost pixels of each
- template row can be forgotten, while new pixels are needed at the
- right most location of each row.
- The CONTEXT corresponding to the current pixel OO and how it is
- masked is shown below. Note how the left most pixel of each row
- of the template is NOT propagated to the CONTEXT, these pixels
- are X2, X6 and X9. This is done by having the mask being 0 at the
- corresponding locations.
- 9 8 7 6 5 4 3 2 1 0 | bit position
- ------------------------------+-------------
- X9 X8 X7 X6 X5 X4 X3 A1 X2 X1 | pixel values from CONTEXT
- 0 1 1 0 1 1 1 1 0 1 | reused pixel bit value mask (0x1bd)
- 0 X8 X7 0 X5 X4 X3 A1 0 X1 | reused pixel values from CONTEXT
- Next the CONTEXT is shifted left by one bit to make it reference
- the next pixel to be decoded. The pixel bit value we just decoded
- is then written into the bit corresponding to X1. The sliding
- windows in line_m1 and line_m2 are both shifted (10 - x_minor)
- bits to the right to make the needed pixels' bit values appear at
- the correct positions to be ORed into CONTEXT. Note that this
- shift amount depends on which bit in the batch is currently being
- computed, as is given by the x_minor counter. In the example
- below we assume that x_minor is 0.
- 9 8 7 6 5 4 3 2 1 0 | bit position
- ------------------------------+--------------
- 0 X8 X7 0 X5 X4 X3 A1 0 0 | reused pixels from CONTEXT
- X8 X7 0 X5 X4 X3 A1 0 0 0 | reused pixels shifted left 1 bit
- ------------------------------+--------------
- X8 X7 0 X5 X4 X3 A1 0 X1 OO | new CONTEXT with current pixel at LSB
- ------------------------------+--------------
- 0 0 X6 X5 X4 X3 A1 n1 n2 n3 | line_m1 shifted (10 - x_minor) bits to the right
- 0 0 0 0 0 0 0 1 0 0 | mask for new adaptive pixel one row above (0x4)
- X8 X7 0 X5 X4 X3 A1 n1 X1 OO | new CONTEXT with new adaptive pixel
- ------------------------------+--------------
- X8 X7 m1 m2 m3 m4 m5 m6 m7 m8 | line_m2 with new bits ORed in
- 0 0 1 0 0 0 0 0 0 0 | mask for new pixel two rows above (0x80)
- X8 X7 m1 X5 X4 X3 A1 n1 X1 OO | new CONTEXT with new pixel
- This makes the computation of the new CONTEXT be:
- NEWCONTEXT = (CONTEXT & 0x1bd) << 1
- NEWCONTEXT |= newbit;
- NEWCONTEXT |= (line_m1 >> (10-x_minor)) & 0x4;
- NEWCONTEXT |= (line_m2 >> (10-x_minor)) & 0x80;
- The optimized decoding functions for GBTEMPLATE 0, 1 and 3 all
- work similarly. */
- /* Get a bit. No bounds checking. */
- static inline int
- jbig2_image_get_pixel_fast(Jbig2Image *image, int x, int y)
- {
- const int byte = (x >> 3) + y * image->stride;
- const int bit = 7 - (x & 7);
- return ((image->data[byte] >> bit) & 1);
- }
- /* 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 << 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 uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- const uint32_t rowstride = image->stride;
- uint32_t x, y;
- byte *line2 = NULL;
- byte *line1 = NULL;
- byte *gbreg_line = (byte *) image->data;
- #ifdef OUTPUT_PBM
- printf("P4\n%d %d\n", GBW, GBH);
- #endif
- if (GBW <= 0)
- return 0;
- for (y = 0; y < GBH; y++) {
- uint32_t CONTEXT;
- uint32_t line_m1;
- uint32_t line_m2;
- uint32_t padded_width = (GBW + 7) & -8;
- line_m1 = line1 ? line1[0] : 0;
- line_m2 = line2 ? line2[0] << 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 (line1)
- line_m1 = (line_m1 << 8) | (x + 8 < GBW ? line1[(x >> 3) + 1] : 0);
- if (line2)
- line_m2 = (line_m2 << 8) | (x + 8 < GBW ? line2[(x >> 3) + 1] << 6 : 0);
- /* This is the speed-critical inner loop. */
- for (x_minor = 0; x_minor < minor_width; x_minor++) {
- int bit;
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 optimized");
- 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
- line2 = line1;
- line1 = gbreg_line;
- gbreg_line += rowstride;
- }
- return 0;
- }
- #define pixel_outside_field(x, y) \
- ((y) < -128 || (y) > 0 || (x) < -128 || ((y) < 0 && (x) > 127) || ((y) == 0 && (x) >= 0))
- static int
- jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int bit;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]) ||
- pixel_outside_field(params->gbat[2], params->gbat[3]) ||
- pixel_outside_field(params->gbat[4], params->gbat[5]) ||
- pixel_outside_field(params->gbat[6], params->gbat[7]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- for (y = 0; y < GBH; y++) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint8_t *ppline = &image->data[image->stride * (y-2)];
- uint32_t pd = 0;
- uint32_t ppd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- if (y > 1) {
- ppd = (*ppline++ << 8);
- if (GBW > 8)
- ppd |= *ppline++;
- }
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x000F; /* First 4 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= (pd>>8) & 0x03E0; /* Next 5 pixels */
- 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 |= (ppd>>2) & 0x7000; /* Next 3 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6], y + params->gbat[7]) << 15;
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 unoptimized");
- }
- pd = pd<<1;
- ppd = ppd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0) {
- pd |= *pline++;
- if (y > 1)
- ppd |= *ppline++;
- }
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- }
- return 0;
- }
- static int
- jbig2_decode_generic_template1_unopt(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int bit;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- for (y = 0; y < GBH; y++) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint8_t *ppline = &image->data[image->stride * (y-2)];
- uint32_t pd = 0;
- uint32_t ppd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- if (y > 1) {
- ppd = (*ppline++ << 8);
- if (GBW > 8)
- ppd |= *ppline++;
- }
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x0007; /* First 3 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
- CONTEXT |= (pd>>9) & 0x01F0; /* Next 5 pixels */
- CONTEXT |= (ppd>>4) & 0x1E00; /* Next 4 pixels */
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 unoptimized");
- }
- pd = pd<<1;
- ppd = ppd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0) {
- pd |= *pline++;
- if (y > 1)
- ppd |= *ppline++;
- }
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- }
- return 0;
- }
- static int
- jbig2_decode_generic_template1(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- const uint32_t rowstride = image->stride;
- uint32_t x, y;
- byte *line2 = NULL;
- byte *line1 = NULL;
- byte *gbreg_line = (byte *) image->data;
- #ifdef OUTPUT_PBM
- printf("P4\n%d %d\n", GBW, GBH);
- #endif
- if (GBW <= 0)
- return 0;
- for (y = 0; y < GBH; y++) {
- uint32_t CONTEXT;
- uint32_t line_m1;
- uint32_t line_m2;
- uint32_t padded_width = (GBW + 7) & -8;
- line_m1 = line1 ? line1[0] : 0;
- line_m2 = line2 ? line2[0] << 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 (line1)
- line_m1 = (line_m1 << 8) | (x + 8 < GBW ? line1[(x >> 3) + 1] : 0);
- if (line2)
- line_m2 = (line_m2 << 8) | (x + 8 < GBW ? line2[(x >> 3) + 1] << 5 : 0);
- /* This is the speed-critical inner loop. */
- for (x_minor = 0; x_minor < minor_width; x_minor++) {
- int bit;
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 optimized");
- 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
- line2 = line1;
- line1 = gbreg_line;
- gbreg_line += rowstride;
- }
- return 0;
- }
- static int
- jbig2_decode_generic_template2_unopt(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int bit;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- for (y = 0; y < GBH; y++) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint8_t *ppline = &image->data[image->stride * (y-2)];
- uint32_t pd = 0;
- uint32_t ppd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- if (y > 1) {
- ppd = (*ppline++ << 8);
- if (GBW > 8)
- ppd |= *ppline++;
- }
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x003; /* First 2 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
- CONTEXT |= (pd>>11) & 0x078; /* Next 4 pixels */
- CONTEXT |= (ppd>>7) & 0x380; /* Next 3 pixels */
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 unoptimized");
- }
- pd = pd<<1;
- ppd = ppd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0) {
- pd |= *pline++;
- if (y > 1)
- ppd |= *ppline++;
- }
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- }
- return 0;
- }
- static int
- jbig2_decode_generic_template2(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- const uint32_t rowstride = image->stride;
- uint32_t x, y;
- byte *line2 = NULL;
- byte *line1 = NULL;
- byte *gbreg_line = (byte *) image->data;
- #ifdef OUTPUT_PBM
- printf("P4\n%d %d\n", GBW, GBH);
- #endif
- if (GBW <= 0)
- return 0;
- for (y = 0; y < GBH; y++) {
- uint32_t CONTEXT;
- uint32_t line_m1;
- uint32_t line_m2;
- uint32_t padded_width = (GBW + 7) & -8;
- line_m1 = line1 ? line1[0] : 0;
- line_m2 = line2 ? line2[0] << 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 (line1)
- line_m1 = (line_m1 << 8) | (x + 8 < GBW ? line1[(x >> 3) + 1] : 0);
- if (line2)
- line_m2 = (line_m2 << 8) | (x + 8 < GBW ? line2[(x >> 3) + 1] << 4 : 0);
- /* This is the speed-critical inner loop. */
- for (x_minor = 0; x_minor < minor_width; x_minor++) {
- int bit;
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 optimized");
- 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
- line2 = line1;
- line1 = gbreg_line;
- 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 uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- const uint32_t rowstride = image->stride;
- byte *line1 = NULL;
- byte *gbreg_line = (byte *) image->data;
- uint32_t x, y;
- #ifdef OUTPUT_PBM
- printf("P4\n%d %d\n", GBW, GBH);
- #endif
- if (GBW <= 0)
- return 0;
- for (y = 0; y < GBH; y++) {
- uint32_t CONTEXT;
- uint32_t line_m1;
- uint32_t padded_width = (GBW + 7) & -8;
- line_m1 = line1 ? line1[0] : 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 (line1)
- line_m1 = (line_m1 << 8) | (x + 8 < GBW ? line1[(x >> 3) + 1] : 0);
- /* This is the speed-critical inner loop. */
- for (x_minor = 0; x_minor < minor_width; x_minor++) {
- int bit;
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 optimized");
- result |= bit << (7 - x_minor);
- CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit | ((line_m1 >> (8 - x_minor)) & 0x10);
- }
- gbreg_line[x >> 3] = result;
- }
- #ifdef OUTPUT_PBM
- fwrite(gbreg_line, 1, rowstride, stdout);
- #endif
- line1 = gbreg_line;
- 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 uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int bit;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- for (y = 0; y < GBH; y++) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint32_t pd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x00F; /* First 4 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= (pd>>9) & 0x3E0; /* Next 5 pixels */
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 unoptimized");
- }
- pd = pd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0)
- pd |= *pline++;
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- }
- return 0;
- }
- static void
- copy_prev_row(Jbig2Image *image, int row)
- {
- if (!row) {
- /* no previous row */
- memset(image->data, 0, image->stride);
- } else {
- /* duplicate data from the previous row */
- uint8_t *src = image->data + (row - 1) * image->stride;
- memcpy(src + image->stride, src, image->stride);
- }
- }
- static int
- jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int LTP = 0;
- int gmin, gmax;
- uint32_t left, right, top;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]) ||
- pixel_outside_field(params->gbat[2], params->gbat[3]) ||
- pixel_outside_field(params->gbat[4], params->gbat[5]) ||
- pixel_outside_field(params->gbat[6], params->gbat[7]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- /* JBig2 has 'standard' values for gbat (see 6.2.5.4 of the spec).
- * Have an optimised version for those locations. This greatly
- * simplifies some of the fetches. It's almost like they thought
- * it through. */
- if (params->gbat[0] == 3 && params->gbat[1] == -1 &&
- params->gbat[2] == -3 && params->gbat[3] == -1 &&
- params->gbat[4] == 2 && params->gbat[5] == -2 &&
- params->gbat[6] == -2 && params->gbat[7] == -2)
- {
- for (y = 0; y < GBH; y++) {
- int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x9B25]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
- LTP ^= bit;
- if (!LTP) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint8_t *ppline = &image->data[image->stride * (y-2)];
- uint32_t pd = 0;
- uint32_t ppd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- if (y > 1) {
- ppd = (*ppline++ << 8);
- if (GBW > 8)
- ppd |= *ppline++;
- }
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x00F; /* First 4 pixels */
- CONTEXT |= (pd>>8) & 0x7F0; /* Next 7 pixels */
- CONTEXT |= (ppd>>2) & 0xF800; /* Final 5 pixels */
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
- }
- pd = pd<<1;
- ppd = ppd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- *d++ = (uint8_t)out_byte;
- if (x+9 < GBW && y > 0) {
- pd |= *pline++;
- if (y > 1)
- ppd |= *ppline++;
- }
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- } else {
- copy_prev_row(image, y);
- }
- }
- return 0;
- }
- /* We divide the width into 3 regions 0..left...right...GBW,
- * between left and right, we know that our accesses will never
- * step outside the image, enabling us to use faster accessors. */
- left = 4;
- right = 2;
- gmin = gmax = params->gbat[0];
- if (params->gbat[2] < gmin)
- gmin = params->gbat[2];
- if (gmax < params->gbat[2])
- gmax = params->gbat[2];
- if (params->gbat[4] < gmin)
- gmin = params->gbat[4];
- if (gmax < params->gbat[4])
- gmax = params->gbat[4];
- if (params->gbat[6] < gmin)
- gmin = params->gbat[6];
- if (gmax < params->gbat[6])
- gmax = params->gbat[6];
- if ((int)left < -gmin)
- left = -gmin;
- if ((int)right < gmax)
- right = gmax;
- if (right > GBW)
- right = GBW;
- right = GBW - right;
- /* So 0 <= x < left or right <= x < GBW needs bounds checking. */
- /* Now we do the same for the height, but here there is no bottom
- * region, as we only ever look up for y. */
- top = 2;
- gmin = params->gbat[1];
- if (params->gbat[3] < gmin)
- gmin = params->gbat[3];
- if (params->gbat[5] < gmin)
- gmin = params->gbat[5];
- if (params->gbat[7] < gmin)
- gmin = params->gbat[7];
- if ((int)top < -gmin)
- top = -gmin;
- /* So 0 <= y < top needs bounds checking. */
- for (y = 0; y < GBH; y++) {
- int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x9B25]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON1");
- LTP ^= bit;
- if (!LTP) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint8_t *ppline = &image->data[image->stride * (y-2)];
- uint32_t pd = 0;
- uint32_t ppd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- if (y > 1) {
- ppd = (*ppline++ << 8);
- if (GBW > 8)
- ppd |= *ppline++;
- }
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x000F; /* First 4 pixels */
- CONTEXT |= (pd>>8) & 0x03E0; /* Skip one, next 5 pixels */
- CONTEXT |= (ppd>>2) & 0x7000; /* Skip 2, next 3 pixels, skip one */
- if (y >= top && x >= left && x < right)
- {
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[2], y + params->gbat[3]) << 10;
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[4], y + params->gbat[5]) << 11;
- CONTEXT |= jbig2_image_get_pixel_fast(image, x + params->gbat[6], y + params->gbat[7]) << 15;
- }
- else
- {
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- 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 + params->gbat[6], y + params->gbat[7]) << 15;
- }
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template0 TPGDON2");
- }
- pd = pd<<1;
- ppd = ppd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0) {
- pd |= *pline++;
- if (y > 1)
- ppd |= *ppline++;
- }
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- } else {
- copy_prev_row(image, y);
- }
- }
- return 0;
- }
- static int
- jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int LTP = 0;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- for (y = 0; y < GBH; y++) {
- int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x0795]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON1");
- LTP ^= bit;
- if (!LTP) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint8_t *ppline = &image->data[image->stride * (y-2)];
- uint32_t pd = 0;
- uint32_t ppd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- if (y > 1) {
- ppd = (*ppline++ << 8);
- if (GBW > 8)
- ppd |= *ppline++;
- }
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x0007; /* First 3 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 3;
- CONTEXT |= (pd>>9) & 0x01F0; /* next 5 pixels */
- CONTEXT |= (ppd>>4) & 0x1E00; /* next 4 pixels */
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template1 TPGDON2");
- }
- pd = pd<<1;
- ppd = ppd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0) {
- pd |= *pline++;
- if (y > 1)
- ppd |= *ppline++;
- }
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- } else {
- copy_prev_row(image, y);
- }
- }
- return 0;
- }
- static int
- jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int LTP = 0;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- for (y = 0; y < GBH; y++) {
- int bit = jbig2_arith_decode(ctx, as, &GB_stats[0xE5]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON1");
- LTP ^= bit;
- if (!LTP) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint8_t *ppline = &image->data[image->stride * (y-2)];
- uint32_t pd = 0;
- uint32_t ppd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- if (y > 1) {
- ppd = (*ppline++ << 8);
- if (GBW > 8)
- ppd |= *ppline++;
- }
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x003; /* First 2 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 2;
- CONTEXT |= (pd>>11) & 0x078; /* next 4 pixels */
- CONTEXT |= (ppd>>7) & 0x380; /* next 3 pixels */
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template2 TPGDON2");
- }
- pd = pd<<1;
- ppd = ppd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0) {
- pd |= *pline++;
- if (y > 1)
- ppd |= *ppline++;
- }
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- } else {
- copy_prev_row(image, y);
- }
- }
- return 0;
- }
- static int
- jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- const uint32_t GBW = image->width;
- const uint32_t GBH = image->height;
- uint32_t CONTEXT;
- uint32_t x, y;
- int LTP = 0;
- if (pixel_outside_field(params->gbat[0], params->gbat[1]))
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
- "adaptive template pixel is out of field");
- for (y = 0; y < GBH; y++) {
- int bit = jbig2_arith_decode(ctx, as, &GB_stats[0x0195]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON1");
- LTP ^= bit;
- if (!LTP) {
- uint32_t out_byte = 0;
- int out_bits_to_go_in_byte = 8;
- uint8_t *d = &image->data[image->stride * y];
- uint8_t *pline = &image->data[image->stride * (y-1)];
- uint32_t pd = 0;
- if (y > 0) {
- pd = (*pline++ << 8);
- if (GBW > 8)
- pd |= *pline++;
- }
- for (x = 0; x < GBW; x++) {
- if (params->USESKIP && jbig2_image_get_pixel(params->SKIP, x, y)) {
- bit = 0;
- } else {
- CONTEXT = out_byte & 0x0F; /* First 4 pixels */
- CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0], y + params->gbat[1]) << 4;
- CONTEXT |= (pd>>9) & 0x3E0; /* next 5 pixels */
- bit = jbig2_arith_decode(ctx, as, &GB_stats[CONTEXT]);
- if (bit < 0)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode arithmetic code when handling generic template3 TPGDON2");
- }
- pd = pd<<1;
- out_byte = (out_byte<<1) | bit;
- out_bits_to_go_in_byte--;
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- if (out_bits_to_go_in_byte == 0) {
- out_bits_to_go_in_byte = 8;
- d++;
- if (x+9 < GBW && y > 0)
- pd |= *pline++;
- }
- }
- if (out_bits_to_go_in_byte != 8)
- *d = (uint8_t)out_byte<<out_bits_to_go_in_byte;
- } else {
- copy_prev_row(image, y);
- }
- }
- return 0;
- }
- static int
- jbig2_decode_generic_region_TPGDON(Jbig2Ctx *ctx,
- Jbig2Segment *segment,
- const Jbig2GenericRegionParams *params, Jbig2ArithState *as, Jbig2Image *image, Jbig2ArithCx *GB_stats)
- {
- switch (params->GBTEMPLATE) {
- case 0:
- return jbig2_decode_generic_template0_TPGDON(ctx, segment, params, as, image, GB_stats);
- case 1:
- return jbig2_decode_generic_template1_TPGDON(ctx, segment, params, as, image, GB_stats);
- case 2:
- return jbig2_decode_generic_template2_TPGDON(ctx, segment, params, as, image, GB_stats);
- case 3:
- return jbig2_decode_generic_template3_TPGDON(ctx, segment, params, as, image, GB_stats);
- }
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unsupported GBTEMPLATE (%d)", params->GBTEMPLATE);
- }
- /**
- * 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->TPGDON)
- return jbig2_decode_generic_region_TPGDON(ctx, segment, params, as, image, GB_stats);
- if (!params->MMR && params->GBTEMPLATE == 0) {
- if (!params->USESKIP && 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) {
- if (!params->USESKIP && gbat[0] == +3 && gbat[1] == -1)
- return jbig2_decode_generic_template1(ctx, segment, params, as, image, GB_stats);
- else
- return jbig2_decode_generic_template1_unopt(ctx, segment, params, as, image, GB_stats);
- }
- else if (!params->MMR && params->GBTEMPLATE == 2) {
- if (!params->USESKIP && gbat[0] == 2 && gbat[1] == -1)
- return jbig2_decode_generic_template2(ctx, segment, params, as, image, GB_stats);
- else
- return jbig2_decode_generic_template2_unopt(ctx, segment, params, as, image, GB_stats);
- } else if (!params->MMR && params->GBTEMPLATE == 3) {
- if (!params->USESKIP && gbat[0] == 2 && gbat[1] == -1)
- return jbig2_decode_generic_template3(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]);
- }
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unsupported generic region (MMR=%d, GBTEMPLATE=%d)", params->MMR, params->GBTEMPLATE);
- }
- /**
- * 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;
- uint32_t gbat_bytes = 0;
- Jbig2GenericRegionParams params;
- int code = 0;
- Jbig2Image *image = NULL;
- Jbig2WordStream *ws = NULL;
- Jbig2ArithState *as = NULL;
- Jbig2ArithCx *GB_stats = NULL;
- uint32_t height;
- Jbig2Page *page = &ctx->pages[ctx->current_page];
- /* 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: %u x %u @ (%u, %u), flags = %02x", rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
- /* 7.4.6.4 */
- height = rsi.height;
- if (segment->rows != UINT32_MAX) {
- if (segment->rows > rsi.height)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment contains more rows than stated in header");
- height = segment->rows;
- }
- /* 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;
- /* Check for T.88 amendment 2 */
- if ((seg_flags >> 5) & 1)
- return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment uses 12 adaptive template pixels (NYI)");
- /* 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);
- if (page->height == 0xffffffff && page->striped && page->stripe_size > 0) {
- if (rsi.y >= page->end_row + page->stripe_size) {
- jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "ignoring %u x %u region at (%u, %u) outside of stripe at row %u covering %u rows, on page of height %u", rsi.width, rsi.height, rsi.x, rsi.y, page->end_row, page->stripe_size, page->image->height);
- return 0;
- }
- if (height > page->end_row + page->stripe_size) {
- height = page->end_row + page->stripe_size;
- }
- } else {
- if (rsi.y >= page->height) {
- jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "ignoring %u x %u region at (%u, %u) outside of page of height %u", rsi.width, rsi.height, rsi.x, rsi.y, page->height);
- return 0;
- }
- if (height > page->height - rsi .y) {
- height = page->height - rsi.y;
- }
- }
- if (height == 0) {
- jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "nothing remains of region, ignoring");
- return 0;
- }
- image = jbig2_image_new(ctx, rsi.width, height);
- if (image == NULL)
- return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate generic image");
- jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "allocated %d x %d image buffer for region decode results", rsi.width, height);
- if (params.MMR) {
- code = jbig2_decode_generic_mmr(ctx, segment, ¶ms, segment_data + offset, segment->data_length - offset, image);
- if (code < 0) {
- code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode MMR-coded generic region");
- goto cleanup;
- }
- } else {
- int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE);
- GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
- if (GB_stats == NULL) {
- code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate arithmetic decoder states when handling immediate generic region");
- goto cleanup;
- }
- memset(GB_stats, 0, stats_size);
- ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
- if (ws == NULL) {
- code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocated word stream when handling immediate generic region");
- goto cleanup;
- }
- as = jbig2_arith_new(ctx, ws);
- if (as == NULL) {
- code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding state when handling immediate generic region");
- goto cleanup;
- }
- code = jbig2_decode_generic_region(ctx, segment, ¶ms, as, image, GB_stats);
- if (code < 0) {
- code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode immediate generic region");
- goto cleanup;
- }
- }
- code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, rsi.x, rsi.y, rsi.op);
- if (code < 0)
- code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add result to page");
- cleanup:
- jbig2_free(ctx->allocator, as);
- jbig2_word_stream_buf_free(ctx, ws);
- jbig2_free(ctx->allocator, GB_stats);
- jbig2_image_release(ctx, image);
- return code;
- }
|