1//========================================================================
2//
3// JBIG2Stream.cc
4//
5// Copyright 2002-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2006 Raj Kumar <rkumar@archive.org>
17// Copyright (C) 2006 Paul Walmsley <paul@booyaka.com>
18// Copyright (C) 2006-2010, 2012, 2014-2022 Albert Astals Cid <aacid@kde.org>
19// Copyright (C) 2009 David Benjamin <davidben@mit.edu>
20// Copyright (C) 2011 Edward Jiang <ejiang@google.com>
21// Copyright (C) 2012 William Bader <williambader@hotmail.com>
22// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
23// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
24// Copyright (C) 2013, 2014 Fabio D'Urso <fabiodurso@hotmail.it>
25// Copyright (C) 2015 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
26// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
27// Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com>
28// Copyright (C) 2019-2021 Oliver Sander <oliver.sander@tu-dresden.de>
29// Copyright (C) 2019 Volker Krause <vkrause@kde.org>
30// Copyright (C) 2019-2021 Even Rouault <even.rouault@spatialys.com>
31// Copyright (C) 2014 Nelson Benítez León <nbenitezl@gmail.com>
32//
33// To see a description of the changes please see the Changelog file that
34// came with your tarball or type make ChangeLog if you are building from git
35//
36//========================================================================
37
38#include <config.h>
39
40#include <memory>
41
42#include <cstdlib>
43#include <climits>
44#include "Error.h"
45#include "JArithmeticDecoder.h"
46#include "JBIG2Stream.h"
47
48//~ share these tables
49#include "Stream-CCITT.h"
50
51//------------------------------------------------------------------------
52
53static const int contextSize[4] = { 16, 13, 10, 10 };
54static const int refContextSize[2] = { 13, 10 };
55
56//------------------------------------------------------------------------
57// JBIG2HuffmanTable
58//------------------------------------------------------------------------
59
60#define jbig2HuffmanLOW 0xfffffffd
61#define jbig2HuffmanOOB 0xfffffffe
62#define jbig2HuffmanEOT 0xffffffff
63
64struct JBIG2HuffmanTable
65{
66 int val;
67 unsigned int prefixLen;
68 unsigned int rangeLen; // can also be LOW, OOB, or EOT
69 unsigned int prefix;
70};
71
72static const JBIG2HuffmanTable huffTableA[] = { { .val: 0, .prefixLen: 1, .rangeLen: 4, .prefix: 0x000 }, { .val: 16, .prefixLen: 2, .rangeLen: 8, .prefix: 0x002 }, { .val: 272, .prefixLen: 3, .rangeLen: 16, .prefix: 0x006 }, { .val: 65808, .prefixLen: 3, .rangeLen: 32, .prefix: 0x007 }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
73
74static const JBIG2HuffmanTable huffTableB[] = { { .val: 0, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: 1, .prefixLen: 2, .rangeLen: 0, .prefix: 0x002 }, { .val: 2, .prefixLen: 3, .rangeLen: 0, .prefix: 0x006 }, { .val: 3, .prefixLen: 4, .rangeLen: 3, .prefix: 0x00e }, { .val: 11, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01e }, { .val: 75, .prefixLen: 6, .rangeLen: 32, .prefix: 0x03e }, { .val: 0, .prefixLen: 6, jbig2HuffmanOOB, .prefix: 0x03f }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
75
76static const JBIG2HuffmanTable huffTableC[] = { { .val: 0, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: 1, .prefixLen: 2, .rangeLen: 0, .prefix: 0x002 }, { .val: 2, .prefixLen: 3, .rangeLen: 0, .prefix: 0x006 },
77 { .val: 3, .prefixLen: 4, .rangeLen: 3, .prefix: 0x00e }, { .val: 11, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01e }, { .val: 0, .prefixLen: 6, jbig2HuffmanOOB, .prefix: 0x03e },
78 { .val: 75, .prefixLen: 7, .rangeLen: 32, .prefix: 0x0fe }, { .val: -256, .prefixLen: 8, .rangeLen: 8, .prefix: 0x0fe }, { .val: -257, .prefixLen: 8, jbig2HuffmanLOW, .prefix: 0x0ff },
79 { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
80
81static const JBIG2HuffmanTable huffTableD[] = { { .val: 1, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: 2, .prefixLen: 2, .rangeLen: 0, .prefix: 0x002 }, { .val: 3, .prefixLen: 3, .rangeLen: 0, .prefix: 0x006 }, { .val: 4, .prefixLen: 4, .rangeLen: 3, .prefix: 0x00e }, { .val: 12, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01e }, { .val: 76, .prefixLen: 5, .rangeLen: 32, .prefix: 0x01f }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
82
83static const JBIG2HuffmanTable huffTableE[] = { { .val: 1, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: 2, .prefixLen: 2, .rangeLen: 0, .prefix: 0x002 }, { .val: 3, .prefixLen: 3, .rangeLen: 0, .prefix: 0x006 }, { .val: 4, .prefixLen: 4, .rangeLen: 3, .prefix: 0x00e }, { .val: 12, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01e }, { .val: 76, .prefixLen: 6, .rangeLen: 32, .prefix: 0x03e }, { .val: -255, .prefixLen: 7, .rangeLen: 8, .prefix: 0x07e }, { .val: -256, .prefixLen: 7, jbig2HuffmanLOW, .prefix: 0x07f },
84 { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
85
86static const JBIG2HuffmanTable huffTableF[] = { { .val: 0, .prefixLen: 2, .rangeLen: 7, .prefix: 0x000 },
87 { .val: 128, .prefixLen: 3, .rangeLen: 7, .prefix: 0x002 },
88 { .val: 256, .prefixLen: 3, .rangeLen: 8, .prefix: 0x003 },
89 { .val: -1024, .prefixLen: 4, .rangeLen: 9, .prefix: 0x008 },
90 { .val: -512, .prefixLen: 4, .rangeLen: 8, .prefix: 0x009 },
91 { .val: -256, .prefixLen: 4, .rangeLen: 7, .prefix: 0x00a },
92 { .val: -32, .prefixLen: 4, .rangeLen: 5, .prefix: 0x00b },
93 { .val: 512, .prefixLen: 4, .rangeLen: 9, .prefix: 0x00c },
94 { .val: 1024, .prefixLen: 4, .rangeLen: 10, .prefix: 0x00d },
95 { .val: -2048, .prefixLen: 5, .rangeLen: 10, .prefix: 0x01c },
96 { .val: -128, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01d },
97 { .val: -64, .prefixLen: 5, .rangeLen: 5, .prefix: 0x01e },
98 { .val: -2049, .prefixLen: 6, jbig2HuffmanLOW, .prefix: 0x03e },
99 { .val: 2048, .prefixLen: 6, .rangeLen: 32, .prefix: 0x03f },
100 { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
101
102static const JBIG2HuffmanTable huffTableG[] = { { .val: -512, .prefixLen: 3, .rangeLen: 8, .prefix: 0x000 }, { .val: 256, .prefixLen: 3, .rangeLen: 8, .prefix: 0x001 }, { .val: 512, .prefixLen: 3, .rangeLen: 9, .prefix: 0x002 }, { .val: 1024, .prefixLen: 3, .rangeLen: 10, .prefix: 0x003 }, { .val: -1024, .prefixLen: 4, .rangeLen: 9, .prefix: 0x008 }, { .val: -256, .prefixLen: 4, .rangeLen: 7, .prefix: 0x009 }, { .val: -32, .prefixLen: 4, .rangeLen: 5, .prefix: 0x00a },
103 { .val: 0, .prefixLen: 4, .rangeLen: 5, .prefix: 0x00b }, { .val: 128, .prefixLen: 4, .rangeLen: 7, .prefix: 0x00c }, { .val: -128, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01a }, { .val: -64, .prefixLen: 5, .rangeLen: 5, .prefix: 0x01b }, { .val: 32, .prefixLen: 5, .rangeLen: 5, .prefix: 0x01c }, { .val: 64, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01d }, { .val: -1025, .prefixLen: 5, jbig2HuffmanLOW, .prefix: 0x01e },
104 { .val: 2048, .prefixLen: 5, .rangeLen: 32, .prefix: 0x01f }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
105
106static const JBIG2HuffmanTable huffTableH[] = { { .val: 0, .prefixLen: 2, .rangeLen: 1, .prefix: 0x000 }, { .val: 0, .prefixLen: 2, jbig2HuffmanOOB, .prefix: 0x001 },
107 { .val: 4, .prefixLen: 3, .rangeLen: 4, .prefix: 0x004 }, { .val: -1, .prefixLen: 4, .rangeLen: 0, .prefix: 0x00a },
108 { .val: 22, .prefixLen: 4, .rangeLen: 4, .prefix: 0x00b }, { .val: 38, .prefixLen: 4, .rangeLen: 5, .prefix: 0x00c },
109 { .val: 2, .prefixLen: 5, .rangeLen: 0, .prefix: 0x01a }, { .val: 70, .prefixLen: 5, .rangeLen: 6, .prefix: 0x01b },
110 { .val: 134, .prefixLen: 5, .rangeLen: 7, .prefix: 0x01c }, { .val: 3, .prefixLen: 6, .rangeLen: 0, .prefix: 0x03a },
111 { .val: 20, .prefixLen: 6, .rangeLen: 1, .prefix: 0x03b }, { .val: 262, .prefixLen: 6, .rangeLen: 7, .prefix: 0x03c },
112 { .val: 646, .prefixLen: 6, .rangeLen: 10, .prefix: 0x03d }, { .val: -2, .prefixLen: 7, .rangeLen: 0, .prefix: 0x07c },
113 { .val: 390, .prefixLen: 7, .rangeLen: 8, .prefix: 0x07d }, { .val: -15, .prefixLen: 8, .rangeLen: 3, .prefix: 0x0fc },
114 { .val: -5, .prefixLen: 8, .rangeLen: 1, .prefix: 0x0fd }, { .val: -7, .prefixLen: 9, .rangeLen: 1, .prefix: 0x1fc },
115 { .val: -3, .prefixLen: 9, .rangeLen: 0, .prefix: 0x1fd }, { .val: -16, .prefixLen: 9, jbig2HuffmanLOW, .prefix: 0x1fe },
116 { .val: 1670, .prefixLen: 9, .rangeLen: 32, .prefix: 0x1ff }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
117
118static const JBIG2HuffmanTable huffTableI[] = { { .val: 0, .prefixLen: 2, jbig2HuffmanOOB, .prefix: 0x000 },
119 { .val: -1, .prefixLen: 3, .rangeLen: 1, .prefix: 0x002 },
120 { .val: 1, .prefixLen: 3, .rangeLen: 1, .prefix: 0x003 },
121 { .val: 7, .prefixLen: 3, .rangeLen: 5, .prefix: 0x004 },
122 { .val: -3, .prefixLen: 4, .rangeLen: 1, .prefix: 0x00a },
123 { .val: 43, .prefixLen: 4, .rangeLen: 5, .prefix: 0x00b },
124 { .val: 75, .prefixLen: 4, .rangeLen: 6, .prefix: 0x00c },
125 { .val: 3, .prefixLen: 5, .rangeLen: 1, .prefix: 0x01a },
126 { .val: 139, .prefixLen: 5, .rangeLen: 7, .prefix: 0x01b },
127 { .val: 267, .prefixLen: 5, .rangeLen: 8, .prefix: 0x01c },
128 { .val: 5, .prefixLen: 6, .rangeLen: 1, .prefix: 0x03a },
129 { .val: 39, .prefixLen: 6, .rangeLen: 2, .prefix: 0x03b },
130 { .val: 523, .prefixLen: 6, .rangeLen: 8, .prefix: 0x03c },
131 { .val: 1291, .prefixLen: 6, .rangeLen: 11, .prefix: 0x03d },
132 { .val: -5, .prefixLen: 7, .rangeLen: 1, .prefix: 0x07c },
133 { .val: 779, .prefixLen: 7, .rangeLen: 9, .prefix: 0x07d },
134 { .val: -31, .prefixLen: 8, .rangeLen: 4, .prefix: 0x0fc },
135 { .val: -11, .prefixLen: 8, .rangeLen: 2, .prefix: 0x0fd },
136 { .val: -15, .prefixLen: 9, .rangeLen: 2, .prefix: 0x1fc },
137 { .val: -7, .prefixLen: 9, .rangeLen: 1, .prefix: 0x1fd },
138 { .val: -32, .prefixLen: 9, jbig2HuffmanLOW, .prefix: 0x1fe },
139 { .val: 3339, .prefixLen: 9, .rangeLen: 32, .prefix: 0x1ff },
140 { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
141
142static const JBIG2HuffmanTable huffTableJ[] = { { .val: -2, .prefixLen: 2, .rangeLen: 2, .prefix: 0x000 },
143 { .val: 6, .prefixLen: 2, .rangeLen: 6, .prefix: 0x001 },
144 { .val: 0, .prefixLen: 2, jbig2HuffmanOOB, .prefix: 0x002 },
145 { .val: -3, .prefixLen: 5, .rangeLen: 0, .prefix: 0x018 },
146 { .val: 2, .prefixLen: 5, .rangeLen: 0, .prefix: 0x019 },
147 { .val: 70, .prefixLen: 5, .rangeLen: 5, .prefix: 0x01a },
148 { .val: 3, .prefixLen: 6, .rangeLen: 0, .prefix: 0x036 },
149 { .val: 102, .prefixLen: 6, .rangeLen: 5, .prefix: 0x037 },
150 { .val: 134, .prefixLen: 6, .rangeLen: 6, .prefix: 0x038 },
151 { .val: 198, .prefixLen: 6, .rangeLen: 7, .prefix: 0x039 },
152 { .val: 326, .prefixLen: 6, .rangeLen: 8, .prefix: 0x03a },
153 { .val: 582, .prefixLen: 6, .rangeLen: 9, .prefix: 0x03b },
154 { .val: 1094, .prefixLen: 6, .rangeLen: 10, .prefix: 0x03c },
155 { .val: -21, .prefixLen: 7, .rangeLen: 4, .prefix: 0x07a },
156 { .val: -4, .prefixLen: 7, .rangeLen: 0, .prefix: 0x07b },
157 { .val: 4, .prefixLen: 7, .rangeLen: 0, .prefix: 0x07c },
158 { .val: 2118, .prefixLen: 7, .rangeLen: 11, .prefix: 0x07d },
159 { .val: -5, .prefixLen: 8, .rangeLen: 0, .prefix: 0x0fc },
160 { .val: 5, .prefixLen: 8, .rangeLen: 0, .prefix: 0x0fd },
161 { .val: -22, .prefixLen: 8, jbig2HuffmanLOW, .prefix: 0x0fe },
162 { .val: 4166, .prefixLen: 8, .rangeLen: 32, .prefix: 0x0ff },
163 { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
164
165static const JBIG2HuffmanTable huffTableK[] = { { .val: 1, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: 2, .prefixLen: 2, .rangeLen: 1, .prefix: 0x002 }, { .val: 4, .prefixLen: 4, .rangeLen: 0, .prefix: 0x00c }, { .val: 5, .prefixLen: 4, .rangeLen: 1, .prefix: 0x00d }, { .val: 7, .prefixLen: 5, .rangeLen: 1, .prefix: 0x01c }, { .val: 9, .prefixLen: 5, .rangeLen: 2, .prefix: 0x01d }, { .val: 13, .prefixLen: 6, .rangeLen: 2, .prefix: 0x03c },
166 { .val: 17, .prefixLen: 7, .rangeLen: 2, .prefix: 0x07a }, { .val: 21, .prefixLen: 7, .rangeLen: 3, .prefix: 0x07b }, { .val: 29, .prefixLen: 7, .rangeLen: 4, .prefix: 0x07c }, { .val: 45, .prefixLen: 7, .rangeLen: 5, .prefix: 0x07d }, { .val: 77, .prefixLen: 7, .rangeLen: 6, .prefix: 0x07e }, { .val: 141, .prefixLen: 7, .rangeLen: 32, .prefix: 0x07f }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
167
168static const JBIG2HuffmanTable huffTableL[] = { { .val: 1, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: 2, .prefixLen: 2, .rangeLen: 0, .prefix: 0x002 }, { .val: 3, .prefixLen: 3, .rangeLen: 1, .prefix: 0x006 }, { .val: 5, .prefixLen: 5, .rangeLen: 0, .prefix: 0x01c }, { .val: 6, .prefixLen: 5, .rangeLen: 1, .prefix: 0x01d }, { .val: 8, .prefixLen: 6, .rangeLen: 1, .prefix: 0x03c }, { .val: 10, .prefixLen: 7, .rangeLen: 0, .prefix: 0x07a },
169 { .val: 11, .prefixLen: 7, .rangeLen: 1, .prefix: 0x07b }, { .val: 13, .prefixLen: 7, .rangeLen: 2, .prefix: 0x07c }, { .val: 17, .prefixLen: 7, .rangeLen: 3, .prefix: 0x07d }, { .val: 25, .prefixLen: 7, .rangeLen: 4, .prefix: 0x07e }, { .val: 41, .prefixLen: 8, .rangeLen: 5, .prefix: 0x0fe }, { .val: 73, .prefixLen: 8, .rangeLen: 32, .prefix: 0x0ff }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
170
171static const JBIG2HuffmanTable huffTableM[] = { { .val: 1, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: 2, .prefixLen: 3, .rangeLen: 0, .prefix: 0x004 }, { .val: 7, .prefixLen: 3, .rangeLen: 3, .prefix: 0x005 }, { .val: 3, .prefixLen: 4, .rangeLen: 0, .prefix: 0x00c }, { .val: 5, .prefixLen: 4, .rangeLen: 1, .prefix: 0x00d }, { .val: 4, .prefixLen: 5, .rangeLen: 0, .prefix: 0x01c }, { .val: 15, .prefixLen: 6, .rangeLen: 1, .prefix: 0x03a },
172 { .val: 17, .prefixLen: 6, .rangeLen: 2, .prefix: 0x03b }, { .val: 21, .prefixLen: 6, .rangeLen: 3, .prefix: 0x03c }, { .val: 29, .prefixLen: 6, .rangeLen: 4, .prefix: 0x03d }, { .val: 45, .prefixLen: 6, .rangeLen: 5, .prefix: 0x03e }, { .val: 77, .prefixLen: 7, .rangeLen: 6, .prefix: 0x07e }, { .val: 141, .prefixLen: 7, .rangeLen: 32, .prefix: 0x07f }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
173
174static const JBIG2HuffmanTable huffTableN[] = { { .val: 0, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: -2, .prefixLen: 3, .rangeLen: 0, .prefix: 0x004 }, { .val: -1, .prefixLen: 3, .rangeLen: 0, .prefix: 0x005 }, { .val: 1, .prefixLen: 3, .rangeLen: 0, .prefix: 0x006 }, { .val: 2, .prefixLen: 3, .rangeLen: 0, .prefix: 0x007 }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
175
176static const JBIG2HuffmanTable huffTableO[] = { { .val: 0, .prefixLen: 1, .rangeLen: 0, .prefix: 0x000 }, { .val: -1, .prefixLen: 3, .rangeLen: 0, .prefix: 0x004 }, { .val: 1, .prefixLen: 3, .rangeLen: 0, .prefix: 0x005 }, { .val: -2, .prefixLen: 4, .rangeLen: 0, .prefix: 0x00c }, { .val: 2, .prefixLen: 4, .rangeLen: 0, .prefix: 0x00d }, { .val: -4, .prefixLen: 5, .rangeLen: 1, .prefix: 0x01c },
177 { .val: 3, .prefixLen: 5, .rangeLen: 1, .prefix: 0x01d }, { .val: -8, .prefixLen: 6, .rangeLen: 2, .prefix: 0x03c }, { .val: 5, .prefixLen: 6, .rangeLen: 2, .prefix: 0x03d }, { .val: -24, .prefixLen: 7, .rangeLen: 4, .prefix: 0x07c }, { .val: 9, .prefixLen: 7, .rangeLen: 4, .prefix: 0x07d }, { .val: -25, .prefixLen: 7, jbig2HuffmanLOW, .prefix: 0x07e },
178 { .val: 25, .prefixLen: 7, .rangeLen: 32, .prefix: 0x07f }, { .val: 0, .prefixLen: 0, jbig2HuffmanEOT, .prefix: 0 } };
179
180//------------------------------------------------------------------------
181// JBIG2HuffmanDecoder
182//------------------------------------------------------------------------
183
184class JBIG2HuffmanDecoder
185{
186public:
187 JBIG2HuffmanDecoder();
188 ~JBIG2HuffmanDecoder();
189 void setStream(Stream *strA) { str = strA; }
190
191 void reset();
192
193 // Returns false for OOB, otherwise sets *<x> and returns true.
194 bool decodeInt(int *x, const JBIG2HuffmanTable *table);
195
196 unsigned int readBits(unsigned int n);
197 unsigned int readBit();
198
199 // Sort the table by prefix length and assign prefix values.
200 static bool buildTable(JBIG2HuffmanTable *table, unsigned int len);
201
202 void resetByteCounter() { byteCounter = 0; }
203 unsigned int getByteCounter() const { return byteCounter; }
204
205private:
206 Stream *str;
207 unsigned int buf;
208 unsigned int bufLen;
209 unsigned int byteCounter;
210};
211
212JBIG2HuffmanDecoder::JBIG2HuffmanDecoder()
213{
214 str = nullptr;
215 byteCounter = 0;
216 reset();
217}
218
219JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() { }
220
221void JBIG2HuffmanDecoder::reset()
222{
223 buf = 0;
224 bufLen = 0;
225}
226
227//~ optimize this
228bool JBIG2HuffmanDecoder::decodeInt(int *x, const JBIG2HuffmanTable *table)
229{
230 unsigned int i, len, prefix;
231
232 i = 0;
233 len = 0;
234 prefix = 0;
235 while (table[i].rangeLen != jbig2HuffmanEOT) {
236 while (len < table[i].prefixLen) {
237 prefix = (prefix << 1) | readBit();
238 ++len;
239 }
240 if (prefix == table[i].prefix) {
241 if (table[i].rangeLen == jbig2HuffmanOOB) {
242 return false;
243 }
244 if (table[i].rangeLen == jbig2HuffmanLOW) {
245 *x = table[i].val - readBits(n: 32);
246 } else if (table[i].rangeLen > 0) {
247 *x = table[i].val + readBits(n: table[i].rangeLen);
248 } else {
249 *x = table[i].val;
250 }
251 return true;
252 }
253 ++i;
254 }
255 return false;
256}
257
258unsigned int JBIG2HuffmanDecoder::readBits(unsigned int n)
259{
260 unsigned int x, mask, nLeft;
261
262 mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
263 if (bufLen >= n) {
264 x = (buf >> (bufLen - n)) & mask;
265 bufLen -= n;
266 } else {
267 x = buf & ((1 << bufLen) - 1);
268 nLeft = n - bufLen;
269 bufLen = 0;
270 while (nLeft >= 8) {
271 x = (x << 8) | (str->getChar() & 0xff);
272 ++byteCounter;
273 nLeft -= 8;
274 }
275 if (nLeft > 0) {
276 buf = str->getChar();
277 ++byteCounter;
278 bufLen = 8 - nLeft;
279 x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
280 }
281 }
282 return x;
283}
284
285unsigned int JBIG2HuffmanDecoder::readBit()
286{
287 if (bufLen == 0) {
288 buf = str->getChar();
289 ++byteCounter;
290 bufLen = 8;
291 }
292 --bufLen;
293 return (buf >> bufLen) & 1;
294}
295
296bool JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, unsigned int len)
297{
298 unsigned int i, j, k, prefix;
299 JBIG2HuffmanTable tab;
300
301 // stable selection sort:
302 // - entries with prefixLen > 0, in ascending prefixLen order
303 // - entry with prefixLen = 0, rangeLen = EOT
304 // - all other entries with prefixLen = 0
305 // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
306 for (i = 0; i < len; ++i) {
307 for (j = i; j < len && table[j].prefixLen == 0; ++j) {
308 ;
309 }
310 if (j == len) {
311 break;
312 }
313 for (k = j + 1; k < len; ++k) {
314 if (table[k].prefixLen > 0 && table[k].prefixLen < table[j].prefixLen) {
315 j = k;
316 }
317 }
318 if (j != i) {
319 tab = table[j];
320 for (k = j; k > i; --k) {
321 table[k] = table[k - 1];
322 }
323 table[i] = tab;
324 }
325 }
326 table[i] = table[len];
327
328 // assign prefixes
329 if (table[0].rangeLen != jbig2HuffmanEOT) {
330 i = 0;
331 prefix = 0;
332 table[i++].prefix = prefix++;
333 for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
334 if (table[i].prefixLen - table[i - 1].prefixLen > 32) {
335 error(category: errSyntaxError, pos: -1, msg: "Failed to build table for JBIG2 stream");
336 return false;
337 } else {
338 prefix <<= table[i].prefixLen - table[i - 1].prefixLen;
339 }
340 table[i].prefix = prefix++;
341 }
342 }
343
344 return true;
345}
346
347//------------------------------------------------------------------------
348// JBIG2MMRDecoder
349//------------------------------------------------------------------------
350
351class JBIG2MMRDecoder
352{
353public:
354 JBIG2MMRDecoder();
355 ~JBIG2MMRDecoder();
356 void setStream(Stream *strA) { str = strA; }
357 void reset();
358 int get2DCode();
359 int getBlackCode();
360 int getWhiteCode();
361 unsigned int get24Bits();
362 void resetByteCounter() { byteCounter = 0; }
363 unsigned int getByteCounter() const { return byteCounter; }
364 void skipTo(unsigned int length);
365
366private:
367 Stream *str;
368 unsigned int buf;
369 unsigned int bufLen;
370 unsigned int nBytesRead;
371 unsigned int byteCounter;
372};
373
374JBIG2MMRDecoder::JBIG2MMRDecoder()
375{
376 str = nullptr;
377 byteCounter = 0;
378 reset();
379}
380
381JBIG2MMRDecoder::~JBIG2MMRDecoder() { }
382
383void JBIG2MMRDecoder::reset()
384{
385 buf = 0;
386 bufLen = 0;
387 nBytesRead = 0;
388}
389
390int JBIG2MMRDecoder::get2DCode()
391{
392 const CCITTCode *p = nullptr;
393
394 if (bufLen == 0) {
395 buf = str->getChar() & 0xff;
396 bufLen = 8;
397 ++nBytesRead;
398 ++byteCounter;
399 p = &twoDimTab1[(buf >> 1) & 0x7f];
400 } else if (bufLen == 8) {
401 p = &twoDimTab1[(buf >> 1) & 0x7f];
402 } else if (bufLen < 8) {
403 p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
404 if (p->bits < 0 || p->bits > (int)bufLen) {
405 buf = (buf << 8) | (str->getChar() & 0xff);
406 bufLen += 8;
407 ++nBytesRead;
408 ++byteCounter;
409 p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
410 }
411 }
412 if (p == nullptr || p->bits < 0) {
413 error(category: errSyntaxError, pos: str->getPos(), msg: "Bad two dim code in JBIG2 MMR stream");
414 return EOF;
415 }
416 bufLen -= p->bits;
417 return p->n;
418}
419
420int JBIG2MMRDecoder::getWhiteCode()
421{
422 const CCITTCode *p;
423 unsigned int code;
424
425 if (bufLen == 0) {
426 buf = str->getChar() & 0xff;
427 bufLen = 8;
428 ++nBytesRead;
429 ++byteCounter;
430 }
431 while (true) {
432 if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
433 if (bufLen <= 12) {
434 code = buf << (12 - bufLen);
435 } else {
436 code = buf >> (bufLen - 12);
437 }
438 p = &whiteTab1[code & 0x1f];
439 } else {
440 if (bufLen <= 9) {
441 code = buf << (9 - bufLen);
442 } else {
443 code = buf >> (bufLen - 9);
444 }
445 p = &whiteTab2[code & 0x1ff];
446 }
447 if (p->bits > 0 && p->bits <= (int)bufLen) {
448 bufLen -= p->bits;
449 return p->n;
450 }
451 if (bufLen >= 12) {
452 break;
453 }
454 buf = (buf << 8) | (str->getChar() & 0xff);
455 bufLen += 8;
456 ++nBytesRead;
457 ++byteCounter;
458 }
459 error(category: errSyntaxError, pos: str->getPos(), msg: "Bad white code in JBIG2 MMR stream");
460 // eat a bit and return a positive number so that the caller doesn't
461 // go into an infinite loop
462 --bufLen;
463 return 1;
464}
465
466int JBIG2MMRDecoder::getBlackCode()
467{
468 const CCITTCode *p;
469 unsigned int code;
470
471 if (bufLen == 0) {
472 buf = str->getChar() & 0xff;
473 bufLen = 8;
474 ++nBytesRead;
475 ++byteCounter;
476 }
477 while (true) {
478 if (bufLen >= 10 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
479 if (bufLen <= 13) {
480 code = buf << (13 - bufLen);
481 } else {
482 code = buf >> (bufLen - 13);
483 }
484 p = &blackTab1[code & 0x7f];
485 } else if (bufLen >= 7 && ((buf >> (bufLen - 4)) & 0x0f) == 0 && ((buf >> (bufLen - 6)) & 0x03) != 0) {
486 if (bufLen <= 12) {
487 code = buf << (12 - bufLen);
488 } else {
489 code = buf >> (bufLen - 12);
490 }
491 if (unlikely((code & 0xff) < 64)) {
492 break;
493 }
494 p = &blackTab2[(code & 0xff) - 64];
495 } else {
496 if (bufLen <= 6) {
497 code = buf << (6 - bufLen);
498 } else {
499 code = buf >> (bufLen - 6);
500 }
501 p = &blackTab3[code & 0x3f];
502 }
503 if (p->bits > 0 && p->bits <= (int)bufLen) {
504 bufLen -= p->bits;
505 return p->n;
506 }
507 if (bufLen >= 13) {
508 break;
509 }
510 buf = (buf << 8) | (str->getChar() & 0xff);
511 bufLen += 8;
512 ++nBytesRead;
513 ++byteCounter;
514 }
515 error(category: errSyntaxError, pos: str->getPos(), msg: "Bad black code in JBIG2 MMR stream");
516 // eat a bit and return a positive number so that the caller doesn't
517 // go into an infinite loop
518 --bufLen;
519 return 1;
520}
521
522unsigned int JBIG2MMRDecoder::get24Bits()
523{
524 while (bufLen < 24) {
525 buf = (buf << 8) | (str->getChar() & 0xff);
526 bufLen += 8;
527 ++nBytesRead;
528 ++byteCounter;
529 }
530 return (buf >> (bufLen - 24)) & 0xffffff;
531}
532
533void JBIG2MMRDecoder::skipTo(unsigned int length)
534{
535 int n = str->discardChars(n: length - nBytesRead);
536 nBytesRead += n;
537 byteCounter += n;
538}
539
540//------------------------------------------------------------------------
541// JBIG2Segment
542//------------------------------------------------------------------------
543
544enum JBIG2SegmentType
545{
546 jbig2SegBitmap,
547 jbig2SegSymbolDict,
548 jbig2SegPatternDict,
549 jbig2SegCodeTable
550};
551
552class JBIG2Segment
553{
554public:
555 explicit JBIG2Segment(unsigned int segNumA) { segNum = segNumA; }
556 virtual ~JBIG2Segment();
557 JBIG2Segment(const JBIG2Segment &) = delete;
558 JBIG2Segment &operator=(const JBIG2Segment &) = delete;
559 void setSegNum(unsigned int segNumA) { segNum = segNumA; }
560 unsigned int getSegNum() { return segNum; }
561 virtual JBIG2SegmentType getType() = 0;
562
563private:
564 unsigned int segNum;
565};
566
567JBIG2Segment::~JBIG2Segment() = default;
568
569//------------------------------------------------------------------------
570// JBIG2Bitmap
571//------------------------------------------------------------------------
572
573struct JBIG2BitmapPtr
574{
575 unsigned char *p;
576 int shift;
577 int x;
578};
579
580class JBIG2Bitmap : public JBIG2Segment
581{
582public:
583 JBIG2Bitmap(unsigned int segNumA, int wA, int hA);
584 explicit JBIG2Bitmap(JBIG2Bitmap *bitmap);
585 ~JBIG2Bitmap() override;
586 JBIG2SegmentType getType() override { return jbig2SegBitmap; }
587 JBIG2Bitmap *getSlice(unsigned int x, unsigned int y, unsigned int wA, unsigned int hA);
588 void expand(int newH, unsigned int pixel);
589 void clearToZero();
590 void clearToOne();
591 int getWidth() const { return w; }
592 int getHeight() const { return h; }
593 int getLineSize() const { return line; }
594 int getPixel(int x, int y) const { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 : (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
595 void setPixel(int x, int y) { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
596 void clearPixel(int x, int y) { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
597 void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
598 int nextPixel(JBIG2BitmapPtr *ptr);
599 void duplicateRow(int yDest, int ySrc);
600 void combine(JBIG2Bitmap *bitmap, int x, int y, unsigned int combOp);
601 unsigned char *getDataPtr() { return data; }
602 int getDataSize() const { return h * line; }
603 bool isOk() const { return data != nullptr; }
604
605private:
606 int w, h, line;
607 unsigned char *data;
608};
609
610JBIG2Bitmap::JBIG2Bitmap(unsigned int segNumA, int wA, int hA) : JBIG2Segment(segNumA)
611{
612 w = wA;
613 h = hA;
614 int auxW;
615 if (unlikely(checkedAdd(wA, 7, &auxW))) {
616 error(category: errSyntaxError, pos: -1, msg: "invalid width");
617 data = nullptr;
618 return;
619 }
620 line = auxW >> 3;
621
622 if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
623 error(category: errSyntaxError, pos: -1, msg: "invalid width/height");
624 data = nullptr;
625 return;
626 }
627 // need to allocate one extra guard byte for use in combine()
628 data = (unsigned char *)gmalloc_checkoverflow(size: h * line + 1);
629 if (data != nullptr) {
630 data[h * line] = 0;
631 }
632}
633
634JBIG2Bitmap::JBIG2Bitmap(JBIG2Bitmap *bitmap) : JBIG2Segment(0)
635{
636 if (unlikely(bitmap == nullptr)) {
637 error(category: errSyntaxError, pos: -1, msg: "NULL bitmap in JBIG2Bitmap");
638 w = h = line = 0;
639 data = nullptr;
640 return;
641 }
642
643 w = bitmap->w;
644 h = bitmap->h;
645 line = bitmap->line;
646
647 if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
648 error(category: errSyntaxError, pos: -1, msg: "invalid width/height");
649 data = nullptr;
650 return;
651 }
652 // need to allocate one extra guard byte for use in combine()
653 data = (unsigned char *)gmalloc(size: h * line + 1);
654 memcpy(dest: data, src: bitmap->data, n: h * line);
655 data[h * line] = 0;
656}
657
658JBIG2Bitmap::~JBIG2Bitmap()
659{
660 gfree(p: data);
661}
662
663//~ optimize this
664JBIG2Bitmap *JBIG2Bitmap::getSlice(unsigned int x, unsigned int y, unsigned int wA, unsigned int hA)
665{
666 JBIG2Bitmap *slice;
667 unsigned int xx, yy;
668
669 if (!data) {
670 return nullptr;
671 }
672
673 slice = new JBIG2Bitmap(0, wA, hA);
674 if (slice->isOk()) {
675 slice->clearToZero();
676 for (yy = 0; yy < hA; ++yy) {
677 for (xx = 0; xx < wA; ++xx) {
678 if (getPixel(x: x + xx, y: y + yy)) {
679 slice->setPixel(x: xx, y: yy);
680 }
681 }
682 }
683 } else {
684 delete slice;
685 slice = nullptr;
686 }
687 return slice;
688}
689
690void JBIG2Bitmap::expand(int newH, unsigned int pixel)
691{
692 if (unlikely(!data)) {
693 return;
694 }
695 if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) {
696 error(category: errSyntaxError, pos: -1, msg: "invalid width/height");
697 gfree(p: data);
698 data = nullptr;
699 return;
700 }
701 // need to allocate one extra guard byte for use in combine()
702 data = (unsigned char *)grealloc(p: data, size: newH * line + 1);
703 if (pixel) {
704 memset(s: data + h * line, c: 0xff, n: (newH - h) * line);
705 } else {
706 memset(s: data + h * line, c: 0x00, n: (newH - h) * line);
707 }
708 h = newH;
709 data[h * line] = 0;
710}
711
712void JBIG2Bitmap::clearToZero()
713{
714 memset(s: data, c: 0, n: h * line);
715}
716
717void JBIG2Bitmap::clearToOne()
718{
719 memset(s: data, c: 0xff, n: h * line);
720}
721
722inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr)
723{
724 if (y < 0 || y >= h || x >= w) {
725 ptr->p = nullptr;
726 ptr->shift = 0; // make gcc happy
727 ptr->x = 0; // make gcc happy
728 } else if (x < 0) {
729 ptr->p = &data[y * line];
730 ptr->shift = 7;
731 ptr->x = x;
732 } else {
733 ptr->p = &data[y * line + (x >> 3)];
734 ptr->shift = 7 - (x & 7);
735 ptr->x = x;
736 }
737}
738
739inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr)
740{
741 int pix;
742
743 if (!ptr->p) {
744 pix = 0;
745 } else if (ptr->x < 0) {
746 ++ptr->x;
747 pix = 0;
748 } else {
749 pix = (*ptr->p >> ptr->shift) & 1;
750 if (++ptr->x == w) {
751 ptr->p = nullptr;
752 } else if (ptr->shift == 0) {
753 ++ptr->p;
754 ptr->shift = 7;
755 } else {
756 --ptr->shift;
757 }
758 }
759 return pix;
760}
761
762void JBIG2Bitmap::duplicateRow(int yDest, int ySrc)
763{
764 memcpy(dest: data + yDest * line, src: data + ySrc * line, n: line);
765}
766
767void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y, unsigned int combOp)
768{
769 int x0, x1, y0, y1, xx, yy;
770 unsigned char *srcPtr, *destPtr;
771 unsigned int src0, src1, src, dest, s1, s2, m1, m2, m3;
772 bool oneByte;
773
774 // check for the pathological case where y = -2^31
775 if (y < -0x7fffffff) {
776 return;
777 }
778 if (y < 0) {
779 y0 = -y;
780 } else {
781 y0 = 0;
782 }
783 if (y + bitmap->h > h) {
784 y1 = h - y;
785 } else {
786 y1 = bitmap->h;
787 }
788 if (y0 >= y1) {
789 return;
790 }
791
792 if (x >= 0) {
793 x0 = x & ~7;
794 } else {
795 x0 = 0;
796 }
797 if (unlikely(checkedAdd(x, bitmap->w, &x1))) {
798 return;
799 }
800 if (x1 > w) {
801 x1 = w;
802 }
803 if (x0 >= x1) {
804 return;
805 }
806
807 s1 = x & 7;
808 s2 = 8 - s1;
809 m1 = 0xff >> (x1 & 7);
810 m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
811 m3 = (0xff >> s1) & m2;
812
813 oneByte = x0 == ((x1 - 1) & ~7);
814
815 for (yy = y0; yy < y1; ++yy) {
816 if (unlikely((y + yy >= h) || (y + yy < 0))) {
817 continue;
818 }
819
820 // one byte per line -- need to mask both left and right side
821 if (oneByte) {
822 if (x >= 0) {
823 destPtr = data + (y + yy) * line + (x >> 3);
824 srcPtr = bitmap->data + yy * bitmap->line;
825 dest = *destPtr;
826 src1 = *srcPtr;
827 switch (combOp) {
828 case 0: // or
829 dest |= (src1 >> s1) & m2;
830 break;
831 case 1: // and
832 dest &= ((0xff00 | src1) >> s1) | m1;
833 break;
834 case 2: // xor
835 dest ^= (src1 >> s1) & m2;
836 break;
837 case 3: // xnor
838 dest ^= ((src1 ^ 0xff) >> s1) & m2;
839 break;
840 case 4: // replace
841 dest = (dest & ~m3) | ((src1 >> s1) & m3);
842 break;
843 }
844 *destPtr = dest;
845 } else {
846 destPtr = data + (y + yy) * line;
847 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
848 dest = *destPtr;
849 src1 = *srcPtr;
850 switch (combOp) {
851 case 0: // or
852 dest |= src1 & m2;
853 break;
854 case 1: // and
855 dest &= src1 | m1;
856 break;
857 case 2: // xor
858 dest ^= src1 & m2;
859 break;
860 case 3: // xnor
861 dest ^= (src1 ^ 0xff) & m2;
862 break;
863 case 4: // replace
864 dest = (src1 & m2) | (dest & m1);
865 break;
866 }
867 *destPtr = dest;
868 }
869
870 // multiple bytes per line -- need to mask left side of left-most
871 // byte and right side of right-most byte
872 } else {
873
874 // left-most byte
875 if (x >= 0) {
876 destPtr = data + (y + yy) * line + (x >> 3);
877 srcPtr = bitmap->data + yy * bitmap->line;
878 src1 = *srcPtr++;
879 dest = *destPtr;
880 switch (combOp) {
881 case 0: // or
882 dest |= src1 >> s1;
883 break;
884 case 1: // and
885 dest &= (0xff00 | src1) >> s1;
886 break;
887 case 2: // xor
888 dest ^= src1 >> s1;
889 break;
890 case 3: // xnor
891 dest ^= (src1 ^ 0xff) >> s1;
892 break;
893 case 4: // replace
894 dest = (dest & (0xff << s2)) | (src1 >> s1);
895 break;
896 }
897 *destPtr++ = dest;
898 xx = x0 + 8;
899 } else {
900 destPtr = data + (y + yy) * line;
901 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
902 src1 = *srcPtr++;
903 xx = x0;
904 }
905
906 // middle bytes
907 for (; xx < x1 - 8; xx += 8) {
908 dest = *destPtr;
909 src0 = src1;
910 src1 = *srcPtr++;
911 src = (((src0 << 8) | src1) >> s1) & 0xff;
912 switch (combOp) {
913 case 0: // or
914 dest |= src;
915 break;
916 case 1: // and
917 dest &= src;
918 break;
919 case 2: // xor
920 dest ^= src;
921 break;
922 case 3: // xnor
923 dest ^= src ^ 0xff;
924 break;
925 case 4: // replace
926 dest = src;
927 break;
928 }
929 *destPtr++ = dest;
930 }
931
932 // right-most byte
933 // note: this last byte (src1) may not actually be used, depending
934 // on the values of s1, m1, and m2 - and in fact, it may be off
935 // the edge of the source bitmap, which means we need to allocate
936 // one extra guard byte at the end of each bitmap
937 dest = *destPtr;
938 src0 = src1;
939 src1 = *srcPtr++;
940 src = (((src0 << 8) | src1) >> s1) & 0xff;
941 switch (combOp) {
942 case 0: // or
943 dest |= src & m2;
944 break;
945 case 1: // and
946 dest &= src | m1;
947 break;
948 case 2: // xor
949 dest ^= src & m2;
950 break;
951 case 3: // xnor
952 dest ^= (src ^ 0xff) & m2;
953 break;
954 case 4: // replace
955 dest = (src & m2) | (dest & m1);
956 break;
957 }
958 *destPtr = dest;
959 }
960 }
961}
962
963//------------------------------------------------------------------------
964// JBIG2SymbolDict
965//------------------------------------------------------------------------
966
967class JBIG2SymbolDict : public JBIG2Segment
968{
969public:
970 JBIG2SymbolDict(unsigned int segNumA, unsigned int sizeA);
971 ~JBIG2SymbolDict() override;
972 JBIG2SegmentType getType() override { return jbig2SegSymbolDict; }
973 unsigned int getSize() { return size; }
974 void setBitmap(unsigned int idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
975 JBIG2Bitmap *getBitmap(unsigned int idx) { return bitmaps[idx]; }
976 bool isOk() const { return ok; }
977 void setGenericRegionStats(JArithmeticDecoderStats *stats) { genericRegionStats = stats; }
978 void setRefinementRegionStats(JArithmeticDecoderStats *stats) { refinementRegionStats = stats; }
979 JArithmeticDecoderStats *getGenericRegionStats() { return genericRegionStats; }
980 JArithmeticDecoderStats *getRefinementRegionStats() { return refinementRegionStats; }
981
982private:
983 bool ok;
984 unsigned int size;
985 JBIG2Bitmap **bitmaps;
986 JArithmeticDecoderStats *genericRegionStats;
987 JArithmeticDecoderStats *refinementRegionStats;
988};
989
990JBIG2SymbolDict::JBIG2SymbolDict(unsigned int segNumA, unsigned int sizeA) : JBIG2Segment(segNumA)
991{
992 ok = true;
993 size = sizeA;
994 if (size != 0) {
995 bitmaps = (JBIG2Bitmap **)gmallocn_checkoverflow(count: size, size: sizeof(JBIG2Bitmap *));
996 if (!bitmaps) {
997 ok = false;
998 size = 0;
999 }
1000 } else {
1001 bitmaps = nullptr;
1002 }
1003 for (unsigned int i = 0; i < size; ++i) {
1004 bitmaps[i] = nullptr;
1005 }
1006 genericRegionStats = nullptr;
1007 refinementRegionStats = nullptr;
1008}
1009
1010JBIG2SymbolDict::~JBIG2SymbolDict()
1011{
1012 unsigned int i;
1013
1014 for (i = 0; i < size; ++i) {
1015 delete bitmaps[i];
1016 }
1017 gfree(p: bitmaps);
1018 if (genericRegionStats) {
1019 delete genericRegionStats;
1020 }
1021 if (refinementRegionStats) {
1022 delete refinementRegionStats;
1023 }
1024}
1025
1026//------------------------------------------------------------------------
1027// JBIG2PatternDict
1028//------------------------------------------------------------------------
1029
1030class JBIG2PatternDict : public JBIG2Segment
1031{
1032public:
1033 JBIG2PatternDict(unsigned int segNumA, unsigned int sizeA);
1034 ~JBIG2PatternDict() override;
1035 JBIG2SegmentType getType() override { return jbig2SegPatternDict; }
1036 unsigned int getSize() { return size; }
1037 void setBitmap(unsigned int idx, JBIG2Bitmap *bitmap)
1038 {
1039 if (likely(idx < size)) {
1040 bitmaps[idx] = bitmap;
1041 }
1042 }
1043 JBIG2Bitmap *getBitmap(unsigned int idx) { return (idx < size) ? bitmaps[idx] : nullptr; }
1044
1045private:
1046 unsigned int size;
1047 JBIG2Bitmap **bitmaps;
1048};
1049
1050JBIG2PatternDict::JBIG2PatternDict(unsigned int segNumA, unsigned int sizeA) : JBIG2Segment(segNumA)
1051{
1052 bitmaps = (JBIG2Bitmap **)gmallocn_checkoverflow(count: sizeA, size: sizeof(JBIG2Bitmap *));
1053 if (bitmaps) {
1054 size = sizeA;
1055 } else {
1056 size = 0;
1057 error(category: errSyntaxError, pos: -1, msg: "JBIG2PatternDict: can't allocate bitmaps");
1058 }
1059}
1060
1061JBIG2PatternDict::~JBIG2PatternDict()
1062{
1063 unsigned int i;
1064
1065 for (i = 0; i < size; ++i) {
1066 delete bitmaps[i];
1067 }
1068 gfree(p: bitmaps);
1069}
1070
1071//------------------------------------------------------------------------
1072// JBIG2CodeTable
1073//------------------------------------------------------------------------
1074
1075class JBIG2CodeTable : public JBIG2Segment
1076{
1077public:
1078 JBIG2CodeTable(unsigned int segNumA, JBIG2HuffmanTable *tableA);
1079 ~JBIG2CodeTable() override;
1080 JBIG2SegmentType getType() override { return jbig2SegCodeTable; }
1081 JBIG2HuffmanTable *getHuffTable() { return table; }
1082
1083private:
1084 JBIG2HuffmanTable *table;
1085};
1086
1087JBIG2CodeTable::JBIG2CodeTable(unsigned int segNumA, JBIG2HuffmanTable *tableA) : JBIG2Segment(segNumA)
1088{
1089 table = tableA;
1090}
1091
1092JBIG2CodeTable::~JBIG2CodeTable()
1093{
1094 gfree(p: table);
1095}
1096
1097//------------------------------------------------------------------------
1098// JBIG2Stream
1099//------------------------------------------------------------------------
1100
1101JBIG2Stream::JBIG2Stream(Stream *strA, Object &&globalsStreamA, Object *globalsStreamRefA) : FilterStream(strA)
1102{
1103 pageBitmap = nullptr;
1104
1105 arithDecoder = new JArithmeticDecoder();
1106 genericRegionStats = new JArithmeticDecoderStats(1 << 1);
1107 refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
1108 iadhStats = new JArithmeticDecoderStats(1 << 9);
1109 iadwStats = new JArithmeticDecoderStats(1 << 9);
1110 iaexStats = new JArithmeticDecoderStats(1 << 9);
1111 iaaiStats = new JArithmeticDecoderStats(1 << 9);
1112 iadtStats = new JArithmeticDecoderStats(1 << 9);
1113 iaitStats = new JArithmeticDecoderStats(1 << 9);
1114 iafsStats = new JArithmeticDecoderStats(1 << 9);
1115 iadsStats = new JArithmeticDecoderStats(1 << 9);
1116 iardxStats = new JArithmeticDecoderStats(1 << 9);
1117 iardyStats = new JArithmeticDecoderStats(1 << 9);
1118 iardwStats = new JArithmeticDecoderStats(1 << 9);
1119 iardhStats = new JArithmeticDecoderStats(1 << 9);
1120 iariStats = new JArithmeticDecoderStats(1 << 9);
1121 iaidStats = new JArithmeticDecoderStats(1 << 1);
1122 huffDecoder = new JBIG2HuffmanDecoder();
1123 mmrDecoder = new JBIG2MMRDecoder();
1124
1125 if (globalsStreamA.isStream()) {
1126 globalsStream = std::move(globalsStreamA);
1127 if (globalsStreamRefA->isRef()) {
1128 globalsStreamRef = globalsStreamRefA->getRef();
1129 }
1130 }
1131
1132 curStr = nullptr;
1133 dataPtr = dataEnd = nullptr;
1134}
1135
1136JBIG2Stream::~JBIG2Stream()
1137{
1138 close();
1139 delete arithDecoder;
1140 delete genericRegionStats;
1141 delete refinementRegionStats;
1142 delete iadhStats;
1143 delete iadwStats;
1144 delete iaexStats;
1145 delete iaaiStats;
1146 delete iadtStats;
1147 delete iaitStats;
1148 delete iafsStats;
1149 delete iadsStats;
1150 delete iardxStats;
1151 delete iardyStats;
1152 delete iardwStats;
1153 delete iardhStats;
1154 delete iariStats;
1155 delete iaidStats;
1156 delete huffDecoder;
1157 delete mmrDecoder;
1158 delete str;
1159}
1160
1161void JBIG2Stream::reset()
1162{
1163 segments.resize(new_size: 0);
1164 globalSegments.resize(new_size: 0);
1165
1166 // read the globals stream
1167 if (globalsStream.isStream()) {
1168 curStr = globalsStream.getStream();
1169 curStr->reset();
1170 arithDecoder->setStream(curStr);
1171 huffDecoder->setStream(curStr);
1172 mmrDecoder->setStream(curStr);
1173 readSegments();
1174 curStr->close();
1175 // swap the newly read segments list into globalSegments
1176 std::swap(x&: segments, y&: globalSegments);
1177 }
1178
1179 // read the main stream
1180 curStr = str;
1181 curStr->reset();
1182 arithDecoder->setStream(curStr);
1183 huffDecoder->setStream(curStr);
1184 mmrDecoder->setStream(curStr);
1185 readSegments();
1186
1187 if (pageBitmap) {
1188 dataPtr = pageBitmap->getDataPtr();
1189 dataEnd = dataPtr + pageBitmap->getDataSize();
1190 } else {
1191 dataPtr = dataEnd = nullptr;
1192 }
1193}
1194
1195void JBIG2Stream::close()
1196{
1197 if (pageBitmap) {
1198 delete pageBitmap;
1199 pageBitmap = nullptr;
1200 }
1201 segments.resize(new_size: 0);
1202 globalSegments.resize(new_size: 0);
1203 dataPtr = dataEnd = nullptr;
1204 FilterStream::close();
1205}
1206
1207int JBIG2Stream::getChar()
1208{
1209 if (dataPtr && dataPtr < dataEnd) {
1210 return (*dataPtr++ ^ 0xff) & 0xff;
1211 }
1212 return EOF;
1213}
1214
1215int JBIG2Stream::lookChar()
1216{
1217 if (dataPtr && dataPtr < dataEnd) {
1218 return (*dataPtr ^ 0xff) & 0xff;
1219 }
1220 return EOF;
1221}
1222
1223Goffset JBIG2Stream::getPos()
1224{
1225 if (pageBitmap == nullptr) {
1226 return 0;
1227 }
1228 return dataPtr - pageBitmap->getDataPtr();
1229}
1230
1231int JBIG2Stream::getChars(int nChars, unsigned char *buffer)
1232{
1233 int n, i;
1234
1235 if (nChars <= 0 || !dataPtr) {
1236 return 0;
1237 }
1238 if (dataEnd - dataPtr < nChars) {
1239 n = (int)(dataEnd - dataPtr);
1240 } else {
1241 n = nChars;
1242 }
1243 for (i = 0; i < n; ++i) {
1244 buffer[i] = *dataPtr++ ^ 0xff;
1245 }
1246 return n;
1247}
1248
1249GooString *JBIG2Stream::getPSFilter(int psLevel, const char *indent)
1250{
1251 return nullptr;
1252}
1253
1254bool JBIG2Stream::isBinary(bool last) const
1255{
1256 return str->isBinary(last: true);
1257}
1258
1259void JBIG2Stream::readSegments()
1260{
1261 unsigned int segNum, segFlags, segType, page, segLength;
1262 unsigned int refFlags, nRefSegs;
1263 unsigned int *refSegs;
1264 int c1, c2, c3;
1265
1266 bool done = false;
1267 while (!done && readULong(x: &segNum)) {
1268
1269 // segment header flags
1270 if (!readUByte(x: &segFlags)) {
1271 goto eofError1;
1272 }
1273 segType = segFlags & 0x3f;
1274
1275 // referred-to segment count and retention flags
1276 if (!readUByte(x: &refFlags)) {
1277 goto eofError1;
1278 }
1279 nRefSegs = refFlags >> 5;
1280 if (nRefSegs == 7) {
1281 if ((c1 = curStr->getChar()) == EOF || (c2 = curStr->getChar()) == EOF || (c3 = curStr->getChar()) == EOF) {
1282 goto eofError1;
1283 }
1284 refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
1285 nRefSegs = refFlags & 0x1fffffff;
1286 const unsigned int nCharsToRead = (nRefSegs + 9) >> 3;
1287 for (unsigned int i = 0; i < nCharsToRead; ++i) {
1288 if ((c1 = curStr->getChar()) == EOF) {
1289 goto eofError1;
1290 }
1291 }
1292 }
1293
1294 // referred-to segment numbers
1295 refSegs = (unsigned int *)gmallocn_checkoverflow(count: nRefSegs, size: sizeof(unsigned int));
1296 if (nRefSegs > 0 && !refSegs) {
1297 return;
1298 }
1299 if (segNum <= 256) {
1300 for (unsigned int i = 0; i < nRefSegs; ++i) {
1301 if (!readUByte(x: &refSegs[i])) {
1302 goto eofError2;
1303 }
1304 }
1305 } else if (segNum <= 65536) {
1306 for (unsigned int i = 0; i < nRefSegs; ++i) {
1307 if (!readUWord(x: &refSegs[i])) {
1308 goto eofError2;
1309 }
1310 }
1311 } else {
1312 for (unsigned int i = 0; i < nRefSegs; ++i) {
1313 if (!readULong(x: &refSegs[i])) {
1314 goto eofError2;
1315 }
1316 }
1317 }
1318
1319 // segment page association
1320 if (segFlags & 0x40) {
1321 if (!readULong(x: &page)) {
1322 goto eofError2;
1323 }
1324 } else {
1325 if (!readUByte(x: &page)) {
1326 goto eofError2;
1327 }
1328 }
1329
1330 // segment data length
1331 if (!readULong(x: &segLength)) {
1332 goto eofError2;
1333 }
1334
1335 // check for missing page information segment
1336 if (!pageBitmap && ((segType >= 4 && segType <= 7) || (segType >= 20 && segType <= 43))) {
1337 error(category: errSyntaxError, pos: curStr->getPos(), msg: "First JBIG2 segment associated with a page must be a page information segment");
1338 goto syntaxError;
1339 }
1340
1341 // read the segment data
1342 arithDecoder->resetByteCounter();
1343 huffDecoder->resetByteCounter();
1344 mmrDecoder->resetByteCounter();
1345 byteCounter = 0;
1346 switch (segType) {
1347 case 0:
1348 if (!readSymbolDictSeg(segNum, length: segLength, refSegs, nRefSegs)) {
1349 error(category: errSyntaxError, pos: curStr->getPos(), msg: "readSymbolDictSeg reports syntax error!");
1350 goto syntaxError;
1351 }
1352 break;
1353 case 4:
1354 readTextRegionSeg(segNum, imm: false, lossless: false, length: segLength, refSegs, nRefSegs);
1355 break;
1356 case 6:
1357 readTextRegionSeg(segNum, imm: true, lossless: false, length: segLength, refSegs, nRefSegs);
1358 break;
1359 case 7:
1360 readTextRegionSeg(segNum, imm: true, lossless: true, length: segLength, refSegs, nRefSegs);
1361 break;
1362 case 16:
1363 readPatternDictSeg(segNum, length: segLength);
1364 break;
1365 case 20:
1366 readHalftoneRegionSeg(segNum, imm: false, lossless: false, length: segLength, refSegs, nRefSegs);
1367 break;
1368 case 22:
1369 readHalftoneRegionSeg(segNum, imm: true, lossless: false, length: segLength, refSegs, nRefSegs);
1370 break;
1371 case 23:
1372 readHalftoneRegionSeg(segNum, imm: true, lossless: true, length: segLength, refSegs, nRefSegs);
1373 break;
1374 case 36:
1375 readGenericRegionSeg(segNum, imm: false, lossless: false, length: segLength);
1376 break;
1377 case 38:
1378 readGenericRegionSeg(segNum, imm: true, lossless: false, length: segLength);
1379 break;
1380 case 39:
1381 readGenericRegionSeg(segNum, imm: true, lossless: true, length: segLength);
1382 break;
1383 case 40:
1384 readGenericRefinementRegionSeg(segNum, imm: false, lossless: false, length: segLength, refSegs, nRefSegs);
1385 break;
1386 case 42:
1387 readGenericRefinementRegionSeg(segNum, imm: true, lossless: false, length: segLength, refSegs, nRefSegs);
1388 break;
1389 case 43:
1390 readGenericRefinementRegionSeg(segNum, imm: true, lossless: true, length: segLength, refSegs, nRefSegs);
1391 break;
1392 case 48:
1393 readPageInfoSeg(length: segLength);
1394 break;
1395 case 50:
1396 readEndOfStripeSeg(length: segLength);
1397 break;
1398 case 51:
1399 // end of file segment
1400 done = true;
1401 break;
1402 case 52:
1403 readProfilesSeg(length: segLength);
1404 break;
1405 case 53:
1406 readCodeTableSeg(segNum, length: segLength);
1407 break;
1408 case 62:
1409 readExtensionSeg(length: segLength);
1410 break;
1411 default:
1412 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unknown segment type in JBIG2 stream");
1413 for (unsigned int i = 0; i < segLength; ++i) {
1414 if ((c1 = curStr->getChar()) == EOF) {
1415 goto eofError2;
1416 }
1417 }
1418 break;
1419 }
1420
1421 // Make sure the segment handler read all of the bytes in the
1422 // segment data, unless this segment is marked as having an
1423 // unknown length (section 7.2.7 of the JBIG2 Final Committee Draft)
1424
1425 if (!(segType == 38 && segLength == 0xffffffff)) {
1426
1427 byteCounter += arithDecoder->getByteCounter();
1428 byteCounter += huffDecoder->getByteCounter();
1429 byteCounter += mmrDecoder->getByteCounter();
1430
1431 if (segLength > byteCounter) {
1432 const unsigned int segExtraBytes = segLength - byteCounter;
1433
1434 // If we didn't read all of the bytes in the segment data,
1435 // indicate an error, and throw away the rest of the data.
1436
1437 // v.3.1.01.13 of the LuraTech PDF Compressor Server will
1438 // sometimes generate an extraneous NULL byte at the end of
1439 // arithmetic-coded symbol dictionary segments when numNewSyms
1440 // == 0. Segments like this often occur for blank pages.
1441
1442 error(category: errSyntaxError, pos: curStr->getPos(), msg: "{0:ud} extraneous byte{1:s} after segment", segExtraBytes, (segExtraBytes > 1) ? "s" : "");
1443 byteCounter += curStr->discardChars(n: segExtraBytes);
1444 } else if (segLength < byteCounter) {
1445
1446 // If we read more bytes than we should have, according to the
1447 // segment length field, note an error.
1448
1449 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Previous segment handler read too many bytes");
1450 goto syntaxError;
1451 }
1452 }
1453
1454 gfree(p: refSegs);
1455 }
1456
1457 return;
1458
1459syntaxError:
1460 gfree(p: refSegs);
1461 return;
1462
1463eofError2:
1464 gfree(p: refSegs);
1465eofError1:
1466 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
1467}
1468
1469bool JBIG2Stream::readSymbolDictSeg(unsigned int segNum, unsigned int length, unsigned int *refSegs, unsigned int nRefSegs)
1470{
1471 std::unique_ptr<JBIG2SymbolDict> symbolDict;
1472 const JBIG2HuffmanTable *huffDHTable, *huffDWTable;
1473 const JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
1474 JBIG2Segment *seg;
1475 std::vector<JBIG2Segment *> codeTables;
1476 JBIG2SymbolDict *inputSymbolDict;
1477 unsigned int flags, sdTemplate, sdrTemplate, huff, refAgg;
1478 unsigned int huffDH, huffDW, huffBMSize, huffAggInst;
1479 unsigned int contextUsed, contextRetained;
1480 int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
1481 unsigned int numExSyms, numNewSyms, numInputSyms, symCodeLen;
1482 JBIG2Bitmap **bitmaps;
1483 JBIG2Bitmap *collBitmap, *refBitmap;
1484 unsigned int *symWidths;
1485 unsigned int symHeight, symWidth, totalWidth, x, symID;
1486 int dh = 0, dw, refAggNum, refDX = 0, refDY = 0, bmSize;
1487 bool ex;
1488 int run, cnt, c;
1489 unsigned int i, j, k;
1490 unsigned char *p;
1491
1492 symWidths = nullptr;
1493
1494 // symbol dictionary flags
1495 if (!readUWord(x: &flags)) {
1496 goto eofError;
1497 }
1498 sdTemplate = (flags >> 10) & 3;
1499 sdrTemplate = (flags >> 12) & 1;
1500 huff = flags & 1;
1501 refAgg = (flags >> 1) & 1;
1502 huffDH = (flags >> 2) & 3;
1503 huffDW = (flags >> 4) & 3;
1504 huffBMSize = (flags >> 6) & 1;
1505 huffAggInst = (flags >> 7) & 1;
1506 contextUsed = (flags >> 8) & 1;
1507 contextRetained = (flags >> 9) & 1;
1508
1509 // symbol dictionary AT flags
1510 if (!huff) {
1511 if (sdTemplate == 0) {
1512 if (!readByte(x: &sdATX[0]) || !readByte(x: &sdATY[0]) || !readByte(x: &sdATX[1]) || !readByte(x: &sdATY[1]) || !readByte(x: &sdATX[2]) || !readByte(x: &sdATY[2]) || !readByte(x: &sdATX[3]) || !readByte(x: &sdATY[3])) {
1513 goto eofError;
1514 }
1515 } else {
1516 if (!readByte(x: &sdATX[0]) || !readByte(x: &sdATY[0])) {
1517 goto eofError;
1518 }
1519 }
1520 }
1521
1522 // symbol dictionary refinement AT flags
1523 if (refAgg && !sdrTemplate) {
1524 if (!readByte(x: &sdrATX[0]) || !readByte(x: &sdrATY[0]) || !readByte(x: &sdrATX[1]) || !readByte(x: &sdrATY[1])) {
1525 goto eofError;
1526 }
1527 }
1528
1529 // SDNUMEXSYMS and SDNUMNEWSYMS
1530 if (!readULong(x: &numExSyms) || !readULong(x: &numNewSyms)) {
1531 goto eofError;
1532 }
1533
1534 // get referenced segments: input symbol dictionaries and code tables
1535 numInputSyms = 0;
1536 for (i = 0; i < nRefSegs; ++i) {
1537 // This is need by bug 12014, returning false makes it not crash
1538 // but we end up with a empty page while acroread is able to render
1539 // part of it
1540 if ((seg = findSegment(segNum: refSegs[i]))) {
1541 if (seg->getType() == jbig2SegSymbolDict) {
1542 j = ((JBIG2SymbolDict *)seg)->getSize();
1543 if (numInputSyms > UINT_MAX - j) {
1544 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Too many input symbols in JBIG2 symbol dictionary");
1545 goto eofError;
1546 }
1547 numInputSyms += j;
1548 } else if (seg->getType() == jbig2SegCodeTable) {
1549 codeTables.push_back(x: seg);
1550 }
1551 } else {
1552 return false;
1553 }
1554 }
1555 if (numInputSyms > UINT_MAX - numNewSyms) {
1556 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Too many input symbols in JBIG2 symbol dictionary");
1557 goto eofError;
1558 }
1559
1560 // compute symbol code length, per 6.5.8.2.3
1561 // symCodeLen = ceil( log2( numInputSyms + numNewSyms ) )
1562 i = numInputSyms + numNewSyms;
1563 if (i <= 1) {
1564 symCodeLen = huff ? 1 : 0;
1565 } else {
1566 --i;
1567 symCodeLen = 0;
1568 // i = floor((numSyms-1) / 2^symCodeLen)
1569 while (i > 0) {
1570 ++symCodeLen;
1571 i >>= 1;
1572 }
1573 }
1574
1575 // get the input symbol bitmaps
1576 bitmaps = (JBIG2Bitmap **)gmallocn_checkoverflow(count: numInputSyms + numNewSyms, size: sizeof(JBIG2Bitmap *));
1577 if (!bitmaps && (numInputSyms + numNewSyms > 0)) {
1578 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Too many input symbols in JBIG2 symbol dictionary");
1579 goto eofError;
1580 }
1581 for (i = 0; i < numInputSyms + numNewSyms; ++i) {
1582 bitmaps[i] = nullptr;
1583 }
1584 k = 0;
1585 inputSymbolDict = nullptr;
1586 for (i = 0; i < nRefSegs; ++i) {
1587 seg = findSegment(segNum: refSegs[i]);
1588 if (seg != nullptr && seg->getType() == jbig2SegSymbolDict) {
1589 inputSymbolDict = (JBIG2SymbolDict *)seg;
1590 for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1591 bitmaps[k++] = inputSymbolDict->getBitmap(idx: j);
1592 }
1593 }
1594 }
1595
1596 // get the Huffman tables
1597 huffDHTable = huffDWTable = nullptr; // make gcc happy
1598 huffBMSizeTable = huffAggInstTable = nullptr; // make gcc happy
1599 i = 0;
1600 if (huff) {
1601 if (huffDH == 0) {
1602 huffDHTable = huffTableD;
1603 } else if (huffDH == 1) {
1604 huffDHTable = huffTableE;
1605 } else {
1606 if (i >= codeTables.size()) {
1607 goto codeTableError;
1608 }
1609 huffDHTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
1610 }
1611 if (huffDW == 0) {
1612 huffDWTable = huffTableB;
1613 } else if (huffDW == 1) {
1614 huffDWTable = huffTableC;
1615 } else {
1616 if (i >= codeTables.size()) {
1617 goto codeTableError;
1618 }
1619 huffDWTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
1620 }
1621 if (huffBMSize == 0) {
1622 huffBMSizeTable = huffTableA;
1623 } else {
1624 if (i >= codeTables.size()) {
1625 goto codeTableError;
1626 }
1627 huffBMSizeTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
1628 }
1629 if (huffAggInst == 0) {
1630 huffAggInstTable = huffTableA;
1631 } else {
1632 if (i >= codeTables.size()) {
1633 goto codeTableError;
1634 }
1635 huffAggInstTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
1636 }
1637 }
1638
1639 // set up the Huffman decoder
1640 if (huff) {
1641 huffDecoder->reset();
1642
1643 // set up the arithmetic decoder
1644 } else {
1645 if (contextUsed && inputSymbolDict) {
1646 resetGenericStats(templ: sdTemplate, prevStats: inputSymbolDict->getGenericRegionStats());
1647 } else {
1648 resetGenericStats(templ: sdTemplate, prevStats: nullptr);
1649 }
1650 if (!resetIntStats(symCodeLen)) {
1651 goto syntaxError;
1652 }
1653 arithDecoder->start();
1654 }
1655
1656 // set up the arithmetic decoder for refinement/aggregation
1657 if (refAgg) {
1658 if (contextUsed && inputSymbolDict) {
1659 resetRefinementStats(templ: sdrTemplate, prevStats: inputSymbolDict->getRefinementRegionStats());
1660 } else {
1661 resetRefinementStats(templ: sdrTemplate, prevStats: nullptr);
1662 }
1663 }
1664
1665 // allocate symbol widths storage
1666 if (huff && !refAgg) {
1667 symWidths = (unsigned int *)gmallocn_checkoverflow(count: numNewSyms, size: sizeof(unsigned int));
1668 if (numNewSyms > 0 && !symWidths) {
1669 goto syntaxError;
1670 }
1671 }
1672
1673 symHeight = 0;
1674 i = 0;
1675 while (i < numNewSyms) {
1676
1677 // read the height class delta height
1678 if (huff) {
1679 huffDecoder->decodeInt(x: &dh, table: huffDHTable);
1680 } else {
1681 arithDecoder->decodeInt(x: &dh, stats: iadhStats);
1682 }
1683 if (dh < 0 && (unsigned int)-dh >= symHeight) {
1684 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad delta-height value in JBIG2 symbol dictionary");
1685 goto syntaxError;
1686 }
1687 symHeight += dh;
1688 if (unlikely(symHeight > 0x40000000)) {
1689 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad height value in JBIG2 symbol dictionary");
1690 goto syntaxError;
1691 }
1692 symWidth = 0;
1693 totalWidth = 0;
1694 j = i;
1695
1696 // read the symbols in this height class
1697 while (true) {
1698
1699 // read the delta width
1700 if (huff) {
1701 if (!huffDecoder->decodeInt(x: &dw, table: huffDWTable)) {
1702 break;
1703 }
1704 } else {
1705 if (!arithDecoder->decodeInt(x: &dw, stats: iadwStats)) {
1706 break;
1707 }
1708 }
1709 if (dw < 0 && (unsigned int)-dw >= symWidth) {
1710 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad delta-height value in JBIG2 symbol dictionary");
1711 goto syntaxError;
1712 }
1713 symWidth += dw;
1714 if (i >= numNewSyms) {
1715 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Too many symbols in JBIG2 symbol dictionary");
1716 goto syntaxError;
1717 }
1718
1719 // using a collective bitmap, so don't read a bitmap here
1720 if (huff && !refAgg) {
1721 symWidths[i] = symWidth;
1722 totalWidth += symWidth;
1723
1724 // refinement/aggregate coding
1725 } else if (refAgg) {
1726 if (huff) {
1727 if (!huffDecoder->decodeInt(x: &refAggNum, table: huffAggInstTable)) {
1728 break;
1729 }
1730 } else {
1731 if (!arithDecoder->decodeInt(x: &refAggNum, stats: iaaiStats)) {
1732 break;
1733 }
1734 }
1735 //~ This special case was added about a year before the final draft
1736 //~ of the JBIG2 spec was released. I have encountered some old
1737 //~ JBIG2 images that predate it.
1738 //~ if (0) {
1739 if (refAggNum == 1) {
1740 if (huff) {
1741 symID = huffDecoder->readBits(n: symCodeLen);
1742 huffDecoder->decodeInt(x: &refDX, table: huffTableO);
1743 huffDecoder->decodeInt(x: &refDY, table: huffTableO);
1744 huffDecoder->decodeInt(x: &bmSize, table: huffTableA);
1745 huffDecoder->reset();
1746 arithDecoder->start();
1747 } else {
1748 if (iaidStats == nullptr) {
1749 goto syntaxError;
1750 }
1751 symID = arithDecoder->decodeIAID(codeLen: symCodeLen, stats: iaidStats);
1752 arithDecoder->decodeInt(x: &refDX, stats: iardxStats);
1753 arithDecoder->decodeInt(x: &refDY, stats: iardyStats);
1754 }
1755 if (symID >= numInputSyms + i) {
1756 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid symbol ID in JBIG2 symbol dictionary");
1757 goto syntaxError;
1758 }
1759 refBitmap = bitmaps[symID];
1760 if (unlikely(refBitmap == nullptr)) {
1761 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid ref bitmap for symbol ID {0:ud} in JBIG2 symbol dictionary", symID);
1762 goto syntaxError;
1763 }
1764 bitmaps[numInputSyms + i] = readGenericRefinementRegion(w: symWidth, h: symHeight, templ: sdrTemplate, tpgrOn: false, refBitmap, refDX, refDY, atx: sdrATX, aty: sdrATY).release();
1765 //~ do we need to use the bmSize value here (in Huffman mode)?
1766 } else {
1767 bitmaps[numInputSyms + i] = readTextRegion(huff, refine: true, w: symWidth, h: symHeight, numInstances: refAggNum, logStrips: 0, numSyms: numInputSyms + i, symCodeTab: nullptr, symCodeLen, syms: bitmaps, defPixel: 0, combOp: 0, transposed: 0, refCorner: 1, sOffset: 0, huffFSTable: huffTableF, huffDSTable: huffTableH, huffDTTable: huffTableK, huffRDWTable: huffTableO, huffRDHTable: huffTableO,
1768 huffRDXTable: huffTableO, huffRDYTable: huffTableO, huffRSizeTable: huffTableA, templ: sdrTemplate, atx: sdrATX, aty: sdrATY)
1769 .release();
1770 if (unlikely(!bitmaps[numInputSyms + i])) {
1771 error(category: errSyntaxError, pos: curStr->getPos(), msg: "NULL bitmap in readTextRegion");
1772 goto syntaxError;
1773 }
1774 }
1775
1776 // non-ref/agg coding
1777 } else {
1778 bitmaps[numInputSyms + i] = readGenericBitmap(mmr: false, w: symWidth, h: symHeight, templ: sdTemplate, tpgdOn: false, useSkip: false, skip: nullptr, atx: sdATX, aty: sdATY, mmrDataLength: 0).release();
1779 if (unlikely(!bitmaps[numInputSyms + i])) {
1780 error(category: errSyntaxError, pos: curStr->getPos(), msg: "NULL bitmap in readGenericBitmap");
1781 goto syntaxError;
1782 }
1783 }
1784
1785 ++i;
1786 }
1787
1788 // read the collective bitmap
1789 if (huff && !refAgg) {
1790 huffDecoder->decodeInt(x: &bmSize, table: huffBMSizeTable);
1791 huffDecoder->reset();
1792 if (bmSize == 0) {
1793 collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
1794 bmSize = symHeight * ((totalWidth + 7) >> 3);
1795 p = collBitmap->getDataPtr();
1796 if (unlikely(p == nullptr)) {
1797 delete collBitmap;
1798 goto syntaxError;
1799 }
1800 for (k = 0; k < (unsigned int)bmSize; ++k) {
1801 if ((c = curStr->getChar()) == EOF) {
1802 memset(s: p, c: 0, n: bmSize - k);
1803 break;
1804 }
1805 *p++ = (unsigned char)c;
1806 }
1807 byteCounter += k;
1808 } else {
1809 collBitmap = readGenericBitmap(mmr: true, w: totalWidth, h: symHeight, templ: 0, tpgdOn: false, useSkip: false, skip: nullptr, atx: nullptr, aty: nullptr, mmrDataLength: bmSize).release();
1810 }
1811 if (likely(collBitmap != nullptr)) {
1812 x = 0;
1813 for (; j < i; ++j) {
1814 bitmaps[numInputSyms + j] = collBitmap->getSlice(x, y: 0, wA: symWidths[j], hA: symHeight);
1815 x += symWidths[j];
1816 }
1817 delete collBitmap;
1818 } else {
1819 error(category: errSyntaxError, pos: curStr->getPos(), msg: "collBitmap was null");
1820 goto syntaxError;
1821 }
1822 }
1823 }
1824
1825 // create the symbol dict object
1826 symbolDict = std::make_unique<JBIG2SymbolDict>(args&: segNum, args&: numExSyms);
1827 if (!symbolDict->isOk()) {
1828 goto syntaxError;
1829 }
1830
1831 // exported symbol list
1832 i = j = 0;
1833 ex = false;
1834 run = 0; // initialize it once in case the first decodeInt fails
1835 // we do not want to use uninitialized memory
1836 while (i < numInputSyms + numNewSyms) {
1837 if (huff) {
1838 huffDecoder->decodeInt(x: &run, table: huffTableA);
1839 } else {
1840 arithDecoder->decodeInt(x: &run, stats: iaexStats);
1841 }
1842 if (i + run > numInputSyms + numNewSyms || (ex && j + run > numExSyms)) {
1843 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Too many exported symbols in JBIG2 symbol dictionary");
1844 for (; j < numExSyms; ++j) {
1845 symbolDict->setBitmap(idx: j, bitmap: nullptr);
1846 }
1847 goto syntaxError;
1848 }
1849 if (ex) {
1850 for (cnt = 0; cnt < run; ++cnt) {
1851 symbolDict->setBitmap(idx: j++, bitmap: new JBIG2Bitmap(bitmaps[i++]));
1852 }
1853 } else {
1854 i += run;
1855 }
1856 ex = !ex;
1857 }
1858 if (j != numExSyms) {
1859 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Too few symbols in JBIG2 symbol dictionary");
1860 for (; j < numExSyms; ++j) {
1861 symbolDict->setBitmap(idx: j, bitmap: nullptr);
1862 }
1863 goto syntaxError;
1864 }
1865
1866 for (i = 0; i < numNewSyms; ++i) {
1867 delete bitmaps[numInputSyms + i];
1868 }
1869 gfree(p: bitmaps);
1870 if (symWidths) {
1871 gfree(p: symWidths);
1872 }
1873
1874 // save the arithmetic decoder stats
1875 if (!huff && contextRetained) {
1876 symbolDict->setGenericRegionStats(genericRegionStats->copy());
1877 if (refAgg) {
1878 symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
1879 }
1880 }
1881
1882 // store the new symbol dict
1883 segments.push_back(x: std::move(symbolDict));
1884
1885 return true;
1886
1887codeTableError:
1888 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Missing code table in JBIG2 symbol dictionary");
1889
1890syntaxError:
1891 for (i = 0; i < numNewSyms; ++i) {
1892 if (bitmaps[numInputSyms + i]) {
1893 delete bitmaps[numInputSyms + i];
1894 }
1895 }
1896 gfree(p: bitmaps);
1897 if (symWidths) {
1898 gfree(p: symWidths);
1899 }
1900 return false;
1901
1902eofError:
1903 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
1904 return false;
1905}
1906
1907void JBIG2Stream::readTextRegionSeg(unsigned int segNum, bool imm, bool lossless, unsigned int length, unsigned int *refSegs, unsigned int nRefSegs)
1908{
1909 std::unique_ptr<JBIG2Bitmap> bitmap;
1910 JBIG2HuffmanTable runLengthTab[36];
1911 JBIG2HuffmanTable *symCodeTab = nullptr;
1912 const JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
1913 const JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
1914 const JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
1915 JBIG2Segment *seg;
1916 std::vector<JBIG2Segment *> codeTables;
1917 JBIG2SymbolDict *symbolDict;
1918 JBIG2Bitmap **syms;
1919 unsigned int w, h, x, y, segInfoFlags, extCombOp;
1920 unsigned int flags, huff, refine, logStrips, refCorner, transposed;
1921 unsigned int combOp, defPixel, templ;
1922 int sOffset;
1923 unsigned int huffFlags, huffFS, huffDS, huffDT;
1924 unsigned int huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
1925 unsigned int numInstances, numSyms, symCodeLen;
1926 int atx[2], aty[2];
1927 unsigned int i, k, kk;
1928 int j = 0;
1929
1930 // region segment info field
1931 if (!readULong(x: &w) || !readULong(x: &h) || !readULong(x: &x) || !readULong(x: &y) || !readUByte(x: &segInfoFlags)) {
1932 goto eofError;
1933 }
1934 extCombOp = segInfoFlags & 7;
1935
1936 // rest of the text region header
1937 if (!readUWord(x: &flags)) {
1938 goto eofError;
1939 }
1940 huff = flags & 1;
1941 refine = (flags >> 1) & 1;
1942 logStrips = (flags >> 2) & 3;
1943 refCorner = (flags >> 4) & 3;
1944 transposed = (flags >> 6) & 1;
1945 combOp = (flags >> 7) & 3;
1946 defPixel = (flags >> 9) & 1;
1947 sOffset = (flags >> 10) & 0x1f;
1948 if (sOffset & 0x10) {
1949 sOffset |= -1 - 0x0f;
1950 }
1951 templ = (flags >> 15) & 1;
1952 huffFS = huffDS = huffDT = 0; // make gcc happy
1953 huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
1954 if (huff) {
1955 if (!readUWord(x: &huffFlags)) {
1956 goto eofError;
1957 }
1958 huffFS = huffFlags & 3;
1959 huffDS = (huffFlags >> 2) & 3;
1960 huffDT = (huffFlags >> 4) & 3;
1961 huffRDW = (huffFlags >> 6) & 3;
1962 huffRDH = (huffFlags >> 8) & 3;
1963 huffRDX = (huffFlags >> 10) & 3;
1964 huffRDY = (huffFlags >> 12) & 3;
1965 huffRSize = (huffFlags >> 14) & 1;
1966 }
1967 if (refine && templ == 0) {
1968 if (!readByte(x: &atx[0]) || !readByte(x: &aty[0]) || !readByte(x: &atx[1]) || !readByte(x: &aty[1])) {
1969 goto eofError;
1970 }
1971 }
1972 if (!readULong(x: &numInstances)) {
1973 goto eofError;
1974 }
1975
1976 // get symbol dictionaries and tables
1977 numSyms = 0;
1978 for (i = 0; i < nRefSegs; ++i) {
1979 if ((seg = findSegment(segNum: refSegs[i]))) {
1980 if (seg->getType() == jbig2SegSymbolDict) {
1981 const unsigned int segSize = ((JBIG2SymbolDict *)seg)->getSize();
1982 if (unlikely(checkedAdd(numSyms, segSize, &numSyms))) {
1983 error(category: errSyntaxError, pos: getPos(), msg: "Too many symbols in JBIG2 text region");
1984 return;
1985 }
1986 } else if (seg->getType() == jbig2SegCodeTable) {
1987 codeTables.push_back(x: seg);
1988 }
1989 } else {
1990 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid segment reference in JBIG2 text region");
1991 return;
1992 }
1993 }
1994 i = numSyms;
1995 if (i <= 1) {
1996 symCodeLen = huff ? 1 : 0;
1997 } else {
1998 --i;
1999 symCodeLen = 0;
2000 // i = floor((numSyms-1) / 2^symCodeLen)
2001 while (i > 0) {
2002 ++symCodeLen;
2003 i >>= 1;
2004 }
2005 }
2006
2007 // get the symbol bitmaps
2008 syms = (JBIG2Bitmap **)gmallocn_checkoverflow(count: numSyms, size: sizeof(JBIG2Bitmap *));
2009 if (numSyms > 0 && !syms) {
2010 return;
2011 }
2012 kk = 0;
2013 for (i = 0; i < nRefSegs; ++i) {
2014 if ((seg = findSegment(segNum: refSegs[i]))) {
2015 if (seg->getType() == jbig2SegSymbolDict) {
2016 symbolDict = (JBIG2SymbolDict *)seg;
2017 for (k = 0; k < symbolDict->getSize(); ++k) {
2018 syms[kk++] = symbolDict->getBitmap(idx: k);
2019 }
2020 }
2021 }
2022 }
2023
2024 // get the Huffman tables
2025 huffFSTable = huffDSTable = huffDTTable = nullptr; // make gcc happy
2026 huffRDWTable = huffRDHTable = nullptr; // make gcc happy
2027 huffRDXTable = huffRDYTable = huffRSizeTable = nullptr; // make gcc happy
2028 i = 0;
2029 if (huff) {
2030 if (huffFS == 0) {
2031 huffFSTable = huffTableF;
2032 } else if (huffFS == 1) {
2033 huffFSTable = huffTableG;
2034 } else {
2035 if (i >= codeTables.size()) {
2036 goto codeTableError;
2037 }
2038 huffFSTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2039 }
2040 if (huffDS == 0) {
2041 huffDSTable = huffTableH;
2042 } else if (huffDS == 1) {
2043 huffDSTable = huffTableI;
2044 } else if (huffDS == 2) {
2045 huffDSTable = huffTableJ;
2046 } else {
2047 if (i >= codeTables.size()) {
2048 goto codeTableError;
2049 }
2050 huffDSTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2051 }
2052 if (huffDT == 0) {
2053 huffDTTable = huffTableK;
2054 } else if (huffDT == 1) {
2055 huffDTTable = huffTableL;
2056 } else if (huffDT == 2) {
2057 huffDTTable = huffTableM;
2058 } else {
2059 if (i >= codeTables.size()) {
2060 goto codeTableError;
2061 }
2062 huffDTTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2063 }
2064 if (huffRDW == 0) {
2065 huffRDWTable = huffTableN;
2066 } else if (huffRDW == 1) {
2067 huffRDWTable = huffTableO;
2068 } else {
2069 if (i >= codeTables.size()) {
2070 goto codeTableError;
2071 }
2072 huffRDWTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2073 }
2074 if (huffRDH == 0) {
2075 huffRDHTable = huffTableN;
2076 } else if (huffRDH == 1) {
2077 huffRDHTable = huffTableO;
2078 } else {
2079 if (i >= codeTables.size()) {
2080 goto codeTableError;
2081 }
2082 huffRDHTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2083 }
2084 if (huffRDX == 0) {
2085 huffRDXTable = huffTableN;
2086 } else if (huffRDX == 1) {
2087 huffRDXTable = huffTableO;
2088 } else {
2089 if (i >= codeTables.size()) {
2090 goto codeTableError;
2091 }
2092 huffRDXTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2093 }
2094 if (huffRDY == 0) {
2095 huffRDYTable = huffTableN;
2096 } else if (huffRDY == 1) {
2097 huffRDYTable = huffTableO;
2098 } else {
2099 if (i >= codeTables.size()) {
2100 goto codeTableError;
2101 }
2102 huffRDYTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2103 }
2104 if (huffRSize == 0) {
2105 huffRSizeTable = huffTableA;
2106 } else {
2107 if (i >= codeTables.size()) {
2108 goto codeTableError;
2109 }
2110 huffRSizeTable = ((JBIG2CodeTable *)codeTables[i++])->getHuffTable();
2111 }
2112 }
2113
2114 // symbol ID Huffman decoding table
2115 if (huff) {
2116 huffDecoder->reset();
2117 for (i = 0; i < 32; ++i) {
2118 runLengthTab[i].val = i;
2119 runLengthTab[i].prefixLen = huffDecoder->readBits(n: 4);
2120 runLengthTab[i].rangeLen = 0;
2121 }
2122 runLengthTab[32].val = 0x103;
2123 runLengthTab[32].prefixLen = huffDecoder->readBits(n: 4);
2124 runLengthTab[32].rangeLen = 2;
2125 runLengthTab[33].val = 0x203;
2126 runLengthTab[33].prefixLen = huffDecoder->readBits(n: 4);
2127 runLengthTab[33].rangeLen = 3;
2128 runLengthTab[34].val = 0x20b;
2129 runLengthTab[34].prefixLen = huffDecoder->readBits(n: 4);
2130 runLengthTab[34].rangeLen = 7;
2131 runLengthTab[35].prefixLen = 0;
2132 runLengthTab[35].rangeLen = jbig2HuffmanEOT;
2133 if (!JBIG2HuffmanDecoder::buildTable(table: runLengthTab, len: 35)) {
2134 huff = false;
2135 }
2136 }
2137
2138 if (huff) {
2139 symCodeTab = (JBIG2HuffmanTable *)gmallocn_checkoverflow(count: numSyms + 1, size: sizeof(JBIG2HuffmanTable));
2140 if (!symCodeTab) {
2141 gfree(p: syms);
2142 return;
2143 }
2144 for (i = 0; i < numSyms; ++i) {
2145 symCodeTab[i].val = i;
2146 symCodeTab[i].rangeLen = 0;
2147 }
2148 i = 0;
2149 while (i < numSyms) {
2150 huffDecoder->decodeInt(x: &j, table: runLengthTab);
2151 if (j > 0x200) {
2152 for (j -= 0x200; j && i < numSyms; --j) {
2153 symCodeTab[i++].prefixLen = 0;
2154 }
2155 } else if (j > 0x100) {
2156 if (unlikely(i == 0)) {
2157 symCodeTab[i].prefixLen = 0;
2158 ++i;
2159 }
2160 for (j -= 0x100; j && i < numSyms; --j) {
2161 symCodeTab[i].prefixLen = symCodeTab[i - 1].prefixLen;
2162 ++i;
2163 }
2164 } else {
2165 symCodeTab[i++].prefixLen = j;
2166 }
2167 }
2168 symCodeTab[numSyms].prefixLen = 0;
2169 symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
2170 if (!JBIG2HuffmanDecoder::buildTable(table: symCodeTab, len: numSyms)) {
2171 huff = false;
2172 gfree(p: symCodeTab);
2173 symCodeTab = nullptr;
2174 }
2175 huffDecoder->reset();
2176
2177 // set up the arithmetic decoder
2178 }
2179
2180 if (!huff) {
2181 if (!resetIntStats(symCodeLen)) {
2182 gfree(p: syms);
2183 return;
2184 }
2185 arithDecoder->start();
2186 }
2187 if (refine) {
2188 resetRefinementStats(templ, prevStats: nullptr);
2189 }
2190
2191 bitmap = readTextRegion(huff, refine, w, h, numInstances, logStrips, numSyms, symCodeTab, symCodeLen, syms, defPixel, combOp, transposed, refCorner, sOffset, huffFSTable, huffDSTable, huffDTTable, huffRDWTable, huffRDHTable,
2192 huffRDXTable, huffRDYTable, huffRSizeTable, templ, atx, aty);
2193
2194 gfree(p: syms);
2195
2196 if (bitmap) {
2197 // combine the region bitmap into the page bitmap
2198 if (imm) {
2199 if (pageH == 0xffffffff && y + h > curPageH) {
2200 pageBitmap->expand(newH: y + h, pixel: pageDefPixel);
2201 }
2202 if (pageBitmap->isOk()) {
2203 pageBitmap->combine(bitmap: bitmap.get(), x, y, combOp: extCombOp);
2204 }
2205
2206 // store the region bitmap
2207 } else {
2208 bitmap->setSegNum(segNum);
2209 segments.push_back(x: std::move(bitmap));
2210 }
2211 }
2212
2213 // clean up the Huffman decoder
2214 if (huff) {
2215 gfree(p: symCodeTab);
2216 }
2217
2218 return;
2219
2220codeTableError:
2221 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Missing code table in JBIG2 text region");
2222 gfree(p: syms);
2223 return;
2224
2225eofError:
2226 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
2227 return;
2228}
2229
2230std::unique_ptr<JBIG2Bitmap> JBIG2Stream::readTextRegion(bool huff, bool refine, int w, int h, unsigned int numInstances, unsigned int logStrips, int numSyms, const JBIG2HuffmanTable *symCodeTab, unsigned int symCodeLen, JBIG2Bitmap **syms,
2231 unsigned int defPixel, unsigned int combOp, unsigned int transposed, unsigned int refCorner, int sOffset, const JBIG2HuffmanTable *huffFSTable, const JBIG2HuffmanTable *huffDSTable,
2232 const JBIG2HuffmanTable *huffDTTable, const JBIG2HuffmanTable *huffRDWTable, const JBIG2HuffmanTable *huffRDHTable, const JBIG2HuffmanTable *huffRDXTable,
2233 const JBIG2HuffmanTable *huffRDYTable, const JBIG2HuffmanTable *huffRSizeTable, unsigned int templ, int *atx, int *aty)
2234{
2235 JBIG2Bitmap *symbolBitmap;
2236 unsigned int strips;
2237 int t = 0, dt = 0, tt, s, ds = 0, sFirst, j = 0;
2238 int rdw, rdh, rdx, rdy, ri = 0, refDX, refDY, bmSize;
2239 unsigned int symID, inst, bw, bh;
2240
2241 strips = 1 << logStrips;
2242
2243 // allocate the bitmap
2244 std::unique_ptr<JBIG2Bitmap> bitmap = std::make_unique<JBIG2Bitmap>(args: 0, args&: w, args&: h);
2245 if (!bitmap->isOk()) {
2246 return nullptr;
2247 }
2248 if (defPixel) {
2249 bitmap->clearToOne();
2250 } else {
2251 bitmap->clearToZero();
2252 }
2253
2254 // decode initial T value
2255 if (huff) {
2256 huffDecoder->decodeInt(x: &t, table: huffDTTable);
2257 } else {
2258 arithDecoder->decodeInt(x: &t, stats: iadtStats);
2259 }
2260
2261 if (checkedMultiply(x: t, y: -(int)strips, z: &t)) {
2262 return {};
2263 }
2264
2265 inst = 0;
2266 sFirst = 0;
2267 while (inst < numInstances) {
2268
2269 // decode delta-T
2270 if (huff) {
2271 huffDecoder->decodeInt(x: &dt, table: huffDTTable);
2272 } else {
2273 arithDecoder->decodeInt(x: &dt, stats: iadtStats);
2274 }
2275 t += dt * strips;
2276
2277 // first S value
2278 if (huff) {
2279 huffDecoder->decodeInt(x: &ds, table: huffFSTable);
2280 } else {
2281 arithDecoder->decodeInt(x: &ds, stats: iafsStats);
2282 }
2283 if (unlikely(checkedAdd(sFirst, ds, &sFirst))) {
2284 return nullptr;
2285 }
2286 s = sFirst;
2287
2288 // read the instances
2289 // (this loop test is here to avoid an infinite loop with damaged
2290 // JBIG2 streams where the normal loop exit doesn't get triggered)
2291 while (inst < numInstances) {
2292
2293 // T value
2294 if (strips == 1) {
2295 dt = 0;
2296 } else if (huff) {
2297 dt = huffDecoder->readBits(n: logStrips);
2298 } else {
2299 arithDecoder->decodeInt(x: &dt, stats: iaitStats);
2300 }
2301 if (unlikely(checkedAdd(t, dt, &tt))) {
2302 return nullptr;
2303 }
2304
2305 // symbol ID
2306 if (huff) {
2307 if (symCodeTab) {
2308 huffDecoder->decodeInt(x: &j, table: symCodeTab);
2309 symID = (unsigned int)j;
2310 } else {
2311 symID = huffDecoder->readBits(n: symCodeLen);
2312 }
2313 } else {
2314 if (iaidStats == nullptr) {
2315 return nullptr;
2316 }
2317 symID = arithDecoder->decodeIAID(codeLen: symCodeLen, stats: iaidStats);
2318 }
2319
2320 if (symID >= (unsigned int)numSyms) {
2321 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid symbol number in JBIG2 text region");
2322 if (unlikely(numInstances - inst > 0x800)) {
2323 // don't loop too often with damaged JBIg2 streams
2324 return nullptr;
2325 }
2326 } else {
2327
2328 // get the symbol bitmap
2329 symbolBitmap = nullptr;
2330 if (refine) {
2331 if (huff) {
2332 ri = (int)huffDecoder->readBit();
2333 } else {
2334 arithDecoder->decodeInt(x: &ri, stats: iariStats);
2335 }
2336 } else {
2337 ri = 0;
2338 }
2339 if (ri) {
2340 bool decodeSuccess;
2341 if (huff) {
2342 decodeSuccess = huffDecoder->decodeInt(x: &rdw, table: huffRDWTable);
2343 decodeSuccess = decodeSuccess && huffDecoder->decodeInt(x: &rdh, table: huffRDHTable);
2344 decodeSuccess = decodeSuccess && huffDecoder->decodeInt(x: &rdx, table: huffRDXTable);
2345 decodeSuccess = decodeSuccess && huffDecoder->decodeInt(x: &rdy, table: huffRDYTable);
2346 decodeSuccess = decodeSuccess && huffDecoder->decodeInt(x: &bmSize, table: huffRSizeTable);
2347 huffDecoder->reset();
2348 arithDecoder->start();
2349 } else {
2350 decodeSuccess = arithDecoder->decodeInt(x: &rdw, stats: iardwStats);
2351 decodeSuccess = decodeSuccess && arithDecoder->decodeInt(x: &rdh, stats: iardhStats);
2352 decodeSuccess = decodeSuccess && arithDecoder->decodeInt(x: &rdx, stats: iardxStats);
2353 decodeSuccess = decodeSuccess && arithDecoder->decodeInt(x: &rdy, stats: iardyStats);
2354 }
2355
2356 if (decodeSuccess && syms[symID]) {
2357 refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
2358 if (checkedAdd(x: ((rdh >= 0) ? rdh : rdh - 1) / 2, y: rdy, z: &refDY)) {
2359 return nullptr;
2360 }
2361
2362 symbolBitmap = readGenericRefinementRegion(w: rdw + syms[symID]->getWidth(), h: rdh + syms[symID]->getHeight(), templ, tpgrOn: false, refBitmap: syms[symID], refDX, refDY, atx, aty).release();
2363 }
2364 //~ do we need to use the bmSize value here (in Huffman mode)?
2365 } else {
2366 symbolBitmap = syms[symID];
2367 }
2368
2369 if (symbolBitmap) {
2370 // combine the symbol bitmap into the region bitmap
2371 //~ something is wrong here - refCorner shouldn't degenerate into
2372 //~ two cases
2373 bw = symbolBitmap->getWidth() - 1;
2374 if (unlikely(symbolBitmap->getHeight() == 0)) {
2375 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid symbol bitmap height");
2376 if (ri) {
2377 delete symbolBitmap;
2378 }
2379 return nullptr;
2380 }
2381 bh = symbolBitmap->getHeight() - 1;
2382 if (transposed) {
2383 if (unlikely(s > 2 * bitmap->getHeight())) {
2384 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid JBIG2 combine");
2385 if (ri) {
2386 delete symbolBitmap;
2387 }
2388 return nullptr;
2389 }
2390 switch (refCorner) {
2391 case 0: // bottom left
2392 bitmap->combine(bitmap: symbolBitmap, x: tt, y: s, combOp);
2393 break;
2394 case 1: // top left
2395 bitmap->combine(bitmap: symbolBitmap, x: tt, y: s, combOp);
2396 break;
2397 case 2: // bottom right
2398 bitmap->combine(bitmap: symbolBitmap, x: tt - bw, y: s, combOp);
2399 break;
2400 case 3: // top right
2401 bitmap->combine(bitmap: symbolBitmap, x: tt - bw, y: s, combOp);
2402 break;
2403 }
2404 s += bh;
2405 } else {
2406 switch (refCorner) {
2407 case 0: // bottom left
2408 if (unlikely(tt - (int)bh > 2 * bitmap->getHeight())) {
2409 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid JBIG2 combine");
2410 if (ri) {
2411 delete symbolBitmap;
2412 }
2413 return nullptr;
2414 }
2415 bitmap->combine(bitmap: symbolBitmap, x: s, y: tt - bh, combOp);
2416 break;
2417 case 1: // top left
2418 if (unlikely(tt > 2 * bitmap->getHeight())) {
2419 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid JBIG2 combine");
2420 if (ri) {
2421 delete symbolBitmap;
2422 }
2423 return nullptr;
2424 }
2425 bitmap->combine(bitmap: symbolBitmap, x: s, y: tt, combOp);
2426 break;
2427 case 2: // bottom right
2428 if (unlikely(tt - (int)bh > 2 * bitmap->getHeight())) {
2429 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid JBIG2 combine");
2430 if (ri) {
2431 delete symbolBitmap;
2432 }
2433 return nullptr;
2434 }
2435 bitmap->combine(bitmap: symbolBitmap, x: s, y: tt - bh, combOp);
2436 break;
2437 case 3: // top right
2438 if (unlikely(tt > 2 * bitmap->getHeight())) {
2439 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid JBIG2 combine");
2440 if (ri) {
2441 delete symbolBitmap;
2442 }
2443 return nullptr;
2444 }
2445 bitmap->combine(bitmap: symbolBitmap, x: s, y: tt, combOp);
2446 break;
2447 }
2448 s += bw;
2449 }
2450 if (ri) {
2451 delete symbolBitmap;
2452 }
2453 } else {
2454 // NULL symbolBitmap only happens on error
2455 return nullptr;
2456 }
2457 }
2458
2459 // next instance
2460 ++inst;
2461
2462 // next S value
2463 if (huff) {
2464 if (!huffDecoder->decodeInt(x: &ds, table: huffDSTable)) {
2465 break;
2466 }
2467 } else {
2468 if (!arithDecoder->decodeInt(x: &ds, stats: iadsStats)) {
2469 break;
2470 }
2471 }
2472 if (checkedAdd(x: s, y: sOffset + ds, z: &s)) {
2473 return nullptr;
2474 }
2475 }
2476 }
2477
2478 return bitmap;
2479}
2480
2481void JBIG2Stream::readPatternDictSeg(unsigned int segNum, unsigned int length)
2482{
2483 std::unique_ptr<JBIG2PatternDict> patternDict;
2484 std::unique_ptr<JBIG2Bitmap> bitmap;
2485 unsigned int flags, patternW, patternH, grayMax, templ, mmr;
2486 int atx[4], aty[4];
2487 unsigned int i, x;
2488
2489 // halftone dictionary flags, pattern width and height, max gray value
2490 if (!readUByte(x: &flags) || !readUByte(x: &patternW) || !readUByte(x: &patternH) || !readULong(x: &grayMax)) {
2491 goto eofError;
2492 }
2493 templ = (flags >> 1) & 3;
2494 mmr = flags & 1;
2495
2496 // set up the arithmetic decoder
2497 if (!mmr) {
2498 resetGenericStats(templ, prevStats: nullptr);
2499 arithDecoder->start();
2500 }
2501
2502 // read the bitmap
2503 atx[0] = -(int)patternW;
2504 aty[0] = 0;
2505 atx[1] = -3;
2506 aty[1] = -1;
2507 atx[2] = 2;
2508 aty[2] = -2;
2509 atx[3] = -2;
2510 aty[3] = -2;
2511
2512 unsigned int grayMaxPlusOne;
2513 if (unlikely(checkedAdd(grayMax, 1u, &grayMaxPlusOne))) {
2514 return;
2515 }
2516 unsigned int bitmapW;
2517 if (unlikely(checkedMultiply(grayMaxPlusOne, patternW, &bitmapW))) {
2518 return;
2519 }
2520 if (bitmapW >= INT_MAX) {
2521 return;
2522 }
2523 bitmap = readGenericBitmap(mmr, w: static_cast<int>(bitmapW), h: patternH, templ, tpgdOn: false, useSkip: false, skip: nullptr, atx, aty, mmrDataLength: length - 7);
2524
2525 if (!bitmap) {
2526 return;
2527 }
2528
2529 // create the pattern dict object
2530 patternDict = std::make_unique<JBIG2PatternDict>(args&: segNum, args: grayMax + 1);
2531
2532 // split up the bitmap
2533 x = 0;
2534 for (i = 0; i <= grayMax && i < patternDict->getSize(); ++i) {
2535 patternDict->setBitmap(idx: i, bitmap: bitmap->getSlice(x, y: 0, wA: patternW, hA: patternH));
2536 x += patternW;
2537 }
2538
2539 // store the new pattern dict
2540 segments.push_back(x: std::move(patternDict));
2541
2542 return;
2543
2544eofError:
2545 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
2546}
2547
2548void JBIG2Stream::readHalftoneRegionSeg(unsigned int segNum, bool imm, bool lossless, unsigned int length, unsigned int *refSegs, unsigned int nRefSegs)
2549{
2550 std::unique_ptr<JBIG2Bitmap> bitmap;
2551 JBIG2Segment *seg;
2552 JBIG2PatternDict *patternDict;
2553 std::unique_ptr<JBIG2Bitmap> skipBitmap;
2554 unsigned int *grayImg;
2555 JBIG2Bitmap *patternBitmap;
2556 unsigned int w, h, x, y, segInfoFlags, extCombOp;
2557 unsigned int flags, mmr, templ, enableSkip, combOp;
2558 unsigned int gridW, gridH, stepX, stepY, patW, patH;
2559 int atx[4], aty[4];
2560 int gridX, gridY, xx, yy, bit, j;
2561 unsigned int bpp, m, n, i;
2562
2563 // region segment info field
2564 if (!readULong(x: &w) || !readULong(x: &h) || !readULong(x: &x) || !readULong(x: &y) || !readUByte(x: &segInfoFlags)) {
2565 goto eofError;
2566 }
2567 extCombOp = segInfoFlags & 7;
2568
2569 // rest of the halftone region header
2570 if (!readUByte(x: &flags)) {
2571 goto eofError;
2572 }
2573 mmr = flags & 1;
2574 templ = (flags >> 1) & 3;
2575 enableSkip = (flags >> 3) & 1;
2576 combOp = (flags >> 4) & 7;
2577 if (!readULong(x: &gridW) || !readULong(x: &gridH) || !readLong(x: &gridX) || !readLong(x: &gridY) || !readUWord(x: &stepX) || !readUWord(x: &stepY)) {
2578 goto eofError;
2579 }
2580 if (w == 0 || h == 0 || w >= INT_MAX / h) {
2581 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad bitmap size in JBIG2 halftone segment");
2582 return;
2583 }
2584 if (gridH == 0 || gridW >= INT_MAX / gridH) {
2585 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad grid size in JBIG2 halftone segment");
2586 return;
2587 }
2588
2589 // get pattern dictionary
2590 if (nRefSegs != 1) {
2591 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad symbol dictionary reference in JBIG2 halftone segment");
2592 return;
2593 }
2594 seg = findSegment(segNum: refSegs[0]);
2595 if (seg == nullptr || seg->getType() != jbig2SegPatternDict) {
2596 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad symbol dictionary reference in JBIG2 halftone segment");
2597 return;
2598 }
2599
2600 patternDict = (JBIG2PatternDict *)seg;
2601 i = patternDict->getSize();
2602 if (i <= 1) {
2603 bpp = 0;
2604 } else {
2605 --i;
2606 bpp = 0;
2607 // i = floor((size-1) / 2^bpp)
2608 while (i > 0) {
2609 ++bpp;
2610 i >>= 1;
2611 }
2612 }
2613 patternBitmap = patternDict->getBitmap(idx: 0);
2614 if (unlikely(patternBitmap == nullptr)) {
2615 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad pattern bitmap");
2616 return;
2617 }
2618 patW = patternBitmap->getWidth();
2619 patH = patternBitmap->getHeight();
2620
2621 // set up the arithmetic decoder
2622 if (!mmr) {
2623 resetGenericStats(templ, prevStats: nullptr);
2624 arithDecoder->start();
2625 }
2626
2627 // allocate the bitmap
2628 bitmap = std::make_unique<JBIG2Bitmap>(args&: segNum, args&: w, args&: h);
2629 if (flags & 0x80) { // HDEFPIXEL
2630 bitmap->clearToOne();
2631 } else {
2632 bitmap->clearToZero();
2633 }
2634
2635 // compute the skip bitmap
2636 if (enableSkip) {
2637 skipBitmap = std::make_unique<JBIG2Bitmap>(args: 0, args&: gridW, args&: gridH);
2638 skipBitmap->clearToZero();
2639 for (m = 0; m < gridH; ++m) {
2640 for (n = 0; n < gridW; ++n) {
2641 xx = gridX + m * stepY + n * stepX;
2642 yy = gridY + m * stepX - n * stepY;
2643 if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w || ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
2644 skipBitmap->setPixel(x: n, y: m);
2645 }
2646 }
2647 }
2648 }
2649
2650 // read the gray-scale image
2651 grayImg = (unsigned int *)gmallocn_checkoverflow(count: gridW * gridH, size: sizeof(unsigned int));
2652 if (!grayImg) {
2653 return;
2654 }
2655 memset(s: grayImg, c: 0, n: gridW * gridH * sizeof(unsigned int));
2656 atx[0] = templ <= 1 ? 3 : 2;
2657 aty[0] = -1;
2658 atx[1] = -3;
2659 aty[1] = -1;
2660 atx[2] = 2;
2661 aty[2] = -2;
2662 atx[3] = -2;
2663 aty[3] = -2;
2664 for (j = bpp - 1; j >= 0; --j) {
2665 std::unique_ptr<JBIG2Bitmap> grayBitmap = readGenericBitmap(mmr, w: gridW, h: gridH, templ, tpgdOn: false, useSkip: enableSkip, skip: skipBitmap.get(), atx, aty, mmrDataLength: -1);
2666 i = 0;
2667 for (m = 0; m < gridH; ++m) {
2668 for (n = 0; n < gridW; ++n) {
2669 bit = grayBitmap->getPixel(x: n, y: m) ^ (grayImg[i] & 1);
2670 grayImg[i] = (grayImg[i] << 1) | bit;
2671 ++i;
2672 }
2673 }
2674 }
2675
2676 // decode the image
2677 i = 0;
2678 for (m = 0; m < gridH; ++m) {
2679 xx = gridX + m * stepY;
2680 yy = gridY + m * stepX;
2681 for (n = 0; n < gridW; ++n) {
2682 if (!(enableSkip && skipBitmap->getPixel(x: n, y: m))) {
2683 patternBitmap = patternDict->getBitmap(idx: grayImg[i]);
2684 if (unlikely(patternBitmap == nullptr)) {
2685 gfree(p: grayImg);
2686 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad pattern bitmap");
2687 return;
2688 }
2689 bitmap->combine(bitmap: patternBitmap, x: xx >> 8, y: yy >> 8, combOp);
2690 }
2691 xx += stepX;
2692 yy -= stepY;
2693 ++i;
2694 }
2695 }
2696
2697 gfree(p: grayImg);
2698
2699 // combine the region bitmap into the page bitmap
2700 if (imm) {
2701 if (pageH == 0xffffffff && y + h > curPageH) {
2702 pageBitmap->expand(newH: y + h, pixel: pageDefPixel);
2703 }
2704 pageBitmap->combine(bitmap: bitmap.get(), x, y, combOp: extCombOp);
2705
2706 // store the region bitmap
2707 } else {
2708 segments.push_back(x: std::move(bitmap));
2709 }
2710
2711 return;
2712
2713eofError:
2714 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
2715}
2716
2717void JBIG2Stream::readGenericRegionSeg(unsigned int segNum, bool imm, bool lossless, unsigned int length)
2718{
2719 std::unique_ptr<JBIG2Bitmap> bitmap;
2720 unsigned int w, h, x, y, segInfoFlags, extCombOp, rowCount;
2721 unsigned int flags, mmr, templ, tpgdOn;
2722 int atx[4], aty[4];
2723
2724 // region segment info field
2725 if (!readULong(x: &w) || !readULong(x: &h) || !readULong(x: &x) || !readULong(x: &y) || !readUByte(x: &segInfoFlags)) {
2726 goto eofError;
2727 }
2728 extCombOp = segInfoFlags & 7;
2729
2730 // rest of the generic region segment header
2731 if (!readUByte(x: &flags)) {
2732 goto eofError;
2733 }
2734 mmr = flags & 1;
2735 templ = (flags >> 1) & 3;
2736 tpgdOn = (flags >> 3) & 1;
2737
2738 // AT flags
2739 if (!mmr) {
2740 if (templ == 0) {
2741 if (!readByte(x: &atx[0]) || !readByte(x: &aty[0]) || !readByte(x: &atx[1]) || !readByte(x: &aty[1]) || !readByte(x: &atx[2]) || !readByte(x: &aty[2]) || !readByte(x: &atx[3]) || !readByte(x: &aty[3])) {
2742 goto eofError;
2743 }
2744 } else {
2745 if (!readByte(x: &atx[0]) || !readByte(x: &aty[0])) {
2746 goto eofError;
2747 }
2748 }
2749 }
2750
2751 // set up the arithmetic decoder
2752 if (!mmr) {
2753 resetGenericStats(templ, prevStats: nullptr);
2754 arithDecoder->start();
2755 }
2756
2757 // read the bitmap
2758 bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, useSkip: false, skip: nullptr, atx, aty, mmrDataLength: mmr ? length - 18 : 0);
2759 if (!bitmap) {
2760 return;
2761 }
2762
2763 // combine the region bitmap into the page bitmap
2764 if (imm) {
2765 if (pageH == 0xffffffff && y + h > curPageH) {
2766 pageBitmap->expand(newH: y + h, pixel: pageDefPixel);
2767 if (!pageBitmap->isOk()) {
2768 error(category: errSyntaxError, pos: curStr->getPos(), msg: "JBIG2Stream::readGenericRegionSeg: expand failed");
2769 return;
2770 }
2771 }
2772 pageBitmap->combine(bitmap: bitmap.get(), x, y, combOp: extCombOp);
2773
2774 // store the region bitmap
2775 } else {
2776 bitmap->setSegNum(segNum);
2777 segments.push_back(x: std::move(bitmap));
2778 }
2779
2780 // immediate generic segments can have an unspecified length, in
2781 // which case, a row count is stored at the end of the segment
2782 if (imm && length == 0xffffffff) {
2783 readULong(x: &rowCount);
2784 }
2785
2786 return;
2787
2788eofError:
2789 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
2790}
2791
2792inline void JBIG2Stream::mmrAddPixels(int a1, int blackPixels, int *codingLine, int *a0i, int w)
2793{
2794 if (a1 > codingLine[*a0i]) {
2795 if (a1 > w) {
2796 error(category: errSyntaxError, pos: curStr->getPos(), msg: "JBIG2 MMR row is wrong length ({0:d})", a1);
2797 a1 = w;
2798 }
2799 if ((*a0i & 1) ^ blackPixels) {
2800 ++*a0i;
2801 }
2802 codingLine[*a0i] = a1;
2803 }
2804}
2805
2806inline void JBIG2Stream::mmrAddPixelsNeg(int a1, int blackPixels, int *codingLine, int *a0i, int w)
2807{
2808 if (a1 > codingLine[*a0i]) {
2809 if (a1 > w) {
2810 error(category: errSyntaxError, pos: curStr->getPos(), msg: "JBIG2 MMR row is wrong length ({0:d})", a1);
2811 a1 = w;
2812 }
2813 if ((*a0i & 1) ^ blackPixels) {
2814 ++*a0i;
2815 }
2816 codingLine[*a0i] = a1;
2817 } else if (a1 < codingLine[*a0i]) {
2818 if (a1 < 0) {
2819 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Invalid JBIG2 MMR code");
2820 a1 = 0;
2821 }
2822 while (*a0i > 0 && a1 <= codingLine[*a0i - 1]) {
2823 --*a0i;
2824 }
2825 codingLine[*a0i] = a1;
2826 }
2827}
2828
2829std::unique_ptr<JBIG2Bitmap> JBIG2Stream::readGenericBitmap(bool mmr, int w, int h, int templ, bool tpgdOn, bool useSkip, JBIG2Bitmap *skip, int *atx, int *aty, int mmrDataLength)
2830{
2831 bool ltp;
2832 unsigned int ltpCX, cx, cx0, cx1, cx2;
2833 int *refLine, *codingLine;
2834 int code1, code2, code3;
2835 unsigned char *p0, *p1, *p2, *pp;
2836 unsigned char *atP0, *atP1, *atP2, *atP3;
2837 unsigned int buf0, buf1, buf2;
2838 unsigned int atBuf0, atBuf1, atBuf2, atBuf3;
2839 int atShift0, atShift1, atShift2, atShift3;
2840 unsigned char mask;
2841 int x, y, x0, x1, a0i, b1i, blackPixels, pix, i;
2842
2843 auto bitmap = std::make_unique<JBIG2Bitmap>(args: 0, args&: w, args&: h);
2844 if (!bitmap->isOk()) {
2845 return nullptr;
2846 }
2847 bitmap->clearToZero();
2848
2849 //----- MMR decode
2850
2851 if (mmr) {
2852
2853 mmrDecoder->reset();
2854 // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = w
2855 // ---> max codingLine size = w + 1
2856 // refLine has one extra guard entry at the end
2857 // ---> max refLine size = w + 2
2858 codingLine = (int *)gmallocn_checkoverflow(count: w + 1, size: sizeof(int));
2859 refLine = (int *)gmallocn_checkoverflow(count: w + 2, size: sizeof(int));
2860
2861 if (unlikely(!codingLine || !refLine)) {
2862 gfree(p: codingLine);
2863 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad width in JBIG2 generic bitmap");
2864 return nullptr;
2865 }
2866
2867 memset(s: refLine, c: 0, n: (w + 2) * sizeof(int));
2868 for (i = 0; i < w + 1; ++i) {
2869 codingLine[i] = w;
2870 }
2871
2872 for (y = 0; y < h; ++y) {
2873
2874 // copy coding line to ref line
2875 for (i = 0; codingLine[i] < w; ++i) {
2876 refLine[i] = codingLine[i];
2877 }
2878 refLine[i++] = w;
2879 refLine[i] = w;
2880
2881 // decode a line
2882 codingLine[0] = 0;
2883 a0i = 0;
2884 b1i = 0;
2885 blackPixels = 0;
2886 // invariant:
2887 // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1] <= w
2888 // exception at left edge:
2889 // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
2890 // exception at right edge:
2891 // refLine[b1i] = refLine[b1i+1] = w is possible
2892 while (codingLine[a0i] < w) {
2893 code1 = mmrDecoder->get2DCode();
2894 switch (code1) {
2895 case twoDimPass:
2896 if (unlikely(b1i + 1 >= w + 2)) {
2897 break;
2898 }
2899 mmrAddPixels(a1: refLine[b1i + 1], blackPixels, codingLine, a0i: &a0i, w);
2900 if (refLine[b1i + 1] < w) {
2901 b1i += 2;
2902 }
2903 break;
2904 case twoDimHoriz:
2905 code1 = code2 = 0;
2906 if (blackPixels) {
2907 do {
2908 code1 += code3 = mmrDecoder->getBlackCode();
2909 } while (code3 >= 64);
2910 do {
2911 code2 += code3 = mmrDecoder->getWhiteCode();
2912 } while (code3 >= 64);
2913 } else {
2914 do {
2915 code1 += code3 = mmrDecoder->getWhiteCode();
2916 } while (code3 >= 64);
2917 do {
2918 code2 += code3 = mmrDecoder->getBlackCode();
2919 } while (code3 >= 64);
2920 }
2921 mmrAddPixels(a1: codingLine[a0i] + code1, blackPixels, codingLine, a0i: &a0i, w);
2922 if (codingLine[a0i] < w) {
2923 mmrAddPixels(a1: codingLine[a0i] + code2, blackPixels: blackPixels ^ 1, codingLine, a0i: &a0i, w);
2924 }
2925 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2926 b1i += 2;
2927 }
2928 break;
2929 case twoDimVertR3:
2930 if (unlikely(b1i >= w + 2)) {
2931 break;
2932 }
2933 mmrAddPixels(a1: refLine[b1i] + 3, blackPixels, codingLine, a0i: &a0i, w);
2934 blackPixels ^= 1;
2935 if (codingLine[a0i] < w) {
2936 ++b1i;
2937 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2938 b1i += 2;
2939 }
2940 }
2941 break;
2942 case twoDimVertR2:
2943 if (unlikely(b1i >= w + 2)) {
2944 break;
2945 }
2946 mmrAddPixels(a1: refLine[b1i] + 2, blackPixels, codingLine, a0i: &a0i, w);
2947 blackPixels ^= 1;
2948 if (codingLine[a0i] < w) {
2949 ++b1i;
2950 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2951 b1i += 2;
2952 }
2953 }
2954 break;
2955 case twoDimVertR1:
2956 if (unlikely(b1i >= w + 2)) {
2957 break;
2958 }
2959 mmrAddPixels(a1: refLine[b1i] + 1, blackPixels, codingLine, a0i: &a0i, w);
2960 blackPixels ^= 1;
2961 if (codingLine[a0i] < w) {
2962 ++b1i;
2963 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2964 b1i += 2;
2965 }
2966 }
2967 break;
2968 case twoDimVert0:
2969 if (unlikely(b1i >= w + 2)) {
2970 break;
2971 }
2972 mmrAddPixels(a1: refLine[b1i], blackPixels, codingLine, a0i: &a0i, w);
2973 blackPixels ^= 1;
2974 if (codingLine[a0i] < w) {
2975 ++b1i;
2976 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2977 b1i += 2;
2978 }
2979 }
2980 break;
2981 case twoDimVertL3:
2982 if (unlikely(b1i >= w + 2)) {
2983 break;
2984 }
2985 mmrAddPixelsNeg(a1: refLine[b1i] - 3, blackPixels, codingLine, a0i: &a0i, w);
2986 blackPixels ^= 1;
2987 if (codingLine[a0i] < w) {
2988 if (b1i > 0) {
2989 --b1i;
2990 } else {
2991 ++b1i;
2992 }
2993 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2994 b1i += 2;
2995 }
2996 }
2997 break;
2998 case twoDimVertL2:
2999 if (unlikely(b1i >= w + 2)) {
3000 break;
3001 }
3002 mmrAddPixelsNeg(a1: refLine[b1i] - 2, blackPixels, codingLine, a0i: &a0i, w);
3003 blackPixels ^= 1;
3004 if (codingLine[a0i] < w) {
3005 if (b1i > 0) {
3006 --b1i;
3007 } else {
3008 ++b1i;
3009 }
3010 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3011 b1i += 2;
3012 }
3013 }
3014 break;
3015 case twoDimVertL1:
3016 if (unlikely(b1i >= w + 2)) {
3017 break;
3018 }
3019 mmrAddPixelsNeg(a1: refLine[b1i] - 1, blackPixels, codingLine, a0i: &a0i, w);
3020 blackPixels ^= 1;
3021 if (codingLine[a0i] < w) {
3022 if (b1i > 0) {
3023 --b1i;
3024 } else {
3025 ++b1i;
3026 }
3027 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3028 b1i += 2;
3029 }
3030 }
3031 break;
3032 case EOF:
3033 mmrAddPixels(a1: w, blackPixels: 0, codingLine, a0i: &a0i, w);
3034 break;
3035 default:
3036 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Illegal code in JBIG2 MMR bitmap data");
3037 mmrAddPixels(a1: w, blackPixels: 0, codingLine, a0i: &a0i, w);
3038 break;
3039 }
3040 }
3041
3042 // convert the run lengths to a bitmap line
3043 i = 0;
3044 while (true) {
3045 for (x = codingLine[i]; x < codingLine[i + 1]; ++x) {
3046 bitmap->setPixel(x, y);
3047 }
3048 if (codingLine[i + 1] >= w || codingLine[i + 2] >= w) {
3049 break;
3050 }
3051 i += 2;
3052 }
3053 }
3054
3055 if (mmrDataLength >= 0) {
3056 mmrDecoder->skipTo(length: mmrDataLength);
3057 } else {
3058 if (mmrDecoder->get24Bits() != 0x001001) {
3059 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Missing EOFB in JBIG2 MMR bitmap data");
3060 }
3061 }
3062
3063 gfree(p: refLine);
3064 gfree(p: codingLine);
3065
3066 //----- arithmetic decode
3067
3068 } else {
3069 // set up the typical row context
3070 ltpCX = 0; // make gcc happy
3071 if (tpgdOn) {
3072 switch (templ) {
3073 case 0:
3074 ltpCX = 0x3953; // 001 11001 0101 0011
3075 break;
3076 case 1:
3077 ltpCX = 0x079a; // 0011 11001 101 0
3078 break;
3079 case 2:
3080 ltpCX = 0x0e3; // 001 1100 01 1
3081 break;
3082 case 3:
3083 ltpCX = 0x18b; // 01100 0101 1
3084 break;
3085 }
3086 }
3087
3088 ltp = false;
3089 cx = cx0 = cx1 = cx2 = 0; // make gcc happy
3090 for (y = 0; y < h; ++y) {
3091
3092 // check for a "typical" (duplicate) row
3093 if (tpgdOn) {
3094 if (arithDecoder->decodeBit(context: ltpCX, stats: genericRegionStats)) {
3095 ltp = !ltp;
3096 }
3097 if (ltp) {
3098 if (y > 0) {
3099 bitmap->duplicateRow(yDest: y, ySrc: y - 1);
3100 }
3101 continue;
3102 }
3103 }
3104
3105 switch (templ) {
3106 case 0:
3107
3108 // set up the context
3109 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3110 buf2 = *p2++ << 8;
3111 if (y >= 1) {
3112 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3113 buf1 = *p1++ << 8;
3114 if (y >= 2) {
3115 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3116 buf0 = *p0++ << 8;
3117 } else {
3118 p0 = nullptr;
3119 buf0 = 0;
3120 }
3121 } else {
3122 p1 = p0 = nullptr;
3123 buf1 = buf0 = 0;
3124 }
3125
3126 if (atx[0] >= -8 && atx[0] <= 8 && atx[1] >= -8 && atx[1] <= 8 && atx[2] >= -8 && atx[2] <= 8 && atx[3] >= -8 && atx[3] <= 8) {
3127 // set up the adaptive context
3128 if (y + aty[0] >= 0 && y + aty[0] < bitmap->getHeight()) {
3129 atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3130 atBuf0 = *atP0++ << 8;
3131 } else {
3132 atP0 = nullptr;
3133 atBuf0 = 0;
3134 }
3135 atShift0 = 15 - atx[0];
3136 if (y + aty[1] >= 0 && y + aty[1] < bitmap->getHeight()) {
3137 atP1 = bitmap->getDataPtr() + (y + aty[1]) * bitmap->getLineSize();
3138 atBuf1 = *atP1++ << 8;
3139 } else {
3140 atP1 = nullptr;
3141 atBuf1 = 0;
3142 }
3143 atShift1 = 15 - atx[1];
3144 if (y + aty[2] >= 0 && y + aty[2] < bitmap->getHeight()) {
3145 atP2 = bitmap->getDataPtr() + (y + aty[2]) * bitmap->getLineSize();
3146 atBuf2 = *atP2++ << 8;
3147 } else {
3148 atP2 = nullptr;
3149 atBuf2 = 0;
3150 }
3151 atShift2 = 15 - atx[2];
3152 if (y + aty[3] >= 0 && y + aty[3] < bitmap->getHeight()) {
3153 atP3 = bitmap->getDataPtr() + (y + aty[3]) * bitmap->getLineSize();
3154 atBuf3 = *atP3++ << 8;
3155 } else {
3156 atP3 = nullptr;
3157 atBuf3 = 0;
3158 }
3159 atShift3 = 15 - atx[3];
3160
3161 // decode the row
3162 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3163 if (x0 + 8 < w) {
3164 if (p0) {
3165 buf0 |= *p0++;
3166 }
3167 if (p1) {
3168 buf1 |= *p1++;
3169 }
3170 buf2 |= *p2++;
3171 if (atP0) {
3172 atBuf0 |= *atP0++;
3173 }
3174 if (atP1) {
3175 atBuf1 |= *atP1++;
3176 }
3177 if (atP2) {
3178 atBuf2 |= *atP2++;
3179 }
3180 if (atP3) {
3181 atBuf3 |= *atP3++;
3182 }
3183 }
3184 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3185
3186 // build the context
3187 cx0 = (buf0 >> 14) & 0x07;
3188 cx1 = (buf1 >> 13) & 0x1f;
3189 cx2 = (buf2 >> 16) & 0x0f;
3190 cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) | (((atBuf0 >> atShift0) & 1) << 3) | (((atBuf1 >> atShift1) & 1) << 2) | (((atBuf2 >> atShift2) & 1) << 1) | ((atBuf3 >> atShift3) & 1);
3191
3192 // check for a skipped pixel
3193 if (!(useSkip && skip->getPixel(x, y))) {
3194
3195 // decode the pixel
3196 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3197 *pp |= mask;
3198 buf2 |= 0x8000;
3199 if (aty[0] == 0) {
3200 atBuf0 |= 0x8000;
3201 }
3202 if (aty[1] == 0) {
3203 atBuf1 |= 0x8000;
3204 }
3205 if (aty[2] == 0) {
3206 atBuf2 |= 0x8000;
3207 }
3208 if (aty[3] == 0) {
3209 atBuf3 |= 0x8000;
3210 }
3211 }
3212 }
3213
3214 // update the context
3215 buf0 <<= 1;
3216 buf1 <<= 1;
3217 buf2 <<= 1;
3218 atBuf0 <<= 1;
3219 atBuf1 <<= 1;
3220 atBuf2 <<= 1;
3221 atBuf3 <<= 1;
3222 }
3223 }
3224
3225 } else {
3226 // decode the row
3227 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3228 if (x0 + 8 < w) {
3229 if (p0) {
3230 buf0 |= *p0++;
3231 }
3232 if (p1) {
3233 buf1 |= *p1++;
3234 }
3235 buf2 |= *p2++;
3236 }
3237 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3238
3239 // build the context
3240 cx0 = (buf0 >> 14) & 0x07;
3241 cx1 = (buf1 >> 13) & 0x1f;
3242 cx2 = (buf2 >> 16) & 0x0f;
3243 cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) | (bitmap->getPixel(x: x + atx[0], y: y + aty[0]) << 3) | (bitmap->getPixel(x: x + atx[1], y: y + aty[1]) << 2) | (bitmap->getPixel(x: x + atx[2], y: y + aty[2]) << 1)
3244 | bitmap->getPixel(x: x + atx[3], y: y + aty[3]);
3245
3246 // check for a skipped pixel
3247 if (!(useSkip && skip->getPixel(x, y))) {
3248
3249 // decode the pixel
3250 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3251 *pp |= mask;
3252 buf2 |= 0x8000;
3253 }
3254 }
3255
3256 // update the context
3257 buf0 <<= 1;
3258 buf1 <<= 1;
3259 buf2 <<= 1;
3260 }
3261 }
3262 }
3263 break;
3264
3265 case 1:
3266
3267 // set up the context
3268 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3269 buf2 = *p2++ << 8;
3270 if (y >= 1) {
3271 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3272 buf1 = *p1++ << 8;
3273 if (y >= 2) {
3274 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3275 buf0 = *p0++ << 8;
3276 } else {
3277 p0 = nullptr;
3278 buf0 = 0;
3279 }
3280 } else {
3281 p1 = p0 = nullptr;
3282 buf1 = buf0 = 0;
3283 }
3284
3285 if (atx[0] >= -8 && atx[0] <= 8) {
3286 // set up the adaptive context
3287 const int atY = y + aty[0];
3288 if ((atY >= 0) && (atY < bitmap->getHeight())) {
3289 atP0 = bitmap->getDataPtr() + atY * bitmap->getLineSize();
3290 atBuf0 = *atP0++ << 8;
3291 } else {
3292 atP0 = nullptr;
3293 atBuf0 = 0;
3294 }
3295 atShift0 = 15 - atx[0];
3296
3297 // decode the row
3298 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3299 if (x0 + 8 < w) {
3300 if (p0) {
3301 buf0 |= *p0++;
3302 }
3303 if (p1) {
3304 buf1 |= *p1++;
3305 }
3306 buf2 |= *p2++;
3307 if (atP0) {
3308 atBuf0 |= *atP0++;
3309 }
3310 }
3311 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3312
3313 // build the context
3314 cx0 = (buf0 >> 13) & 0x0f;
3315 cx1 = (buf1 >> 13) & 0x1f;
3316 cx2 = (buf2 >> 16) & 0x07;
3317 cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) | ((atBuf0 >> atShift0) & 1);
3318
3319 // check for a skipped pixel
3320 if (!(useSkip && skip->getPixel(x, y))) {
3321
3322 // decode the pixel
3323 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3324 *pp |= mask;
3325 buf2 |= 0x8000;
3326 if (aty[0] == 0) {
3327 atBuf0 |= 0x8000;
3328 }
3329 }
3330 }
3331
3332 // update the context
3333 buf0 <<= 1;
3334 buf1 <<= 1;
3335 buf2 <<= 1;
3336 atBuf0 <<= 1;
3337 }
3338 }
3339
3340 } else {
3341 // decode the row
3342 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3343 if (x0 + 8 < w) {
3344 if (p0) {
3345 buf0 |= *p0++;
3346 }
3347 if (p1) {
3348 buf1 |= *p1++;
3349 }
3350 buf2 |= *p2++;
3351 }
3352 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3353
3354 // build the context
3355 cx0 = (buf0 >> 13) & 0x0f;
3356 cx1 = (buf1 >> 13) & 0x1f;
3357 cx2 = (buf2 >> 16) & 0x07;
3358 cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) | bitmap->getPixel(x: x + atx[0], y: y + aty[0]);
3359
3360 // check for a skipped pixel
3361 if (!(useSkip && skip->getPixel(x, y))) {
3362
3363 // decode the pixel
3364 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3365 *pp |= mask;
3366 buf2 |= 0x8000;
3367 }
3368 }
3369
3370 // update the context
3371 buf0 <<= 1;
3372 buf1 <<= 1;
3373 buf2 <<= 1;
3374 }
3375 }
3376 }
3377 break;
3378
3379 case 2:
3380
3381 // set up the context
3382 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3383 buf2 = *p2++ << 8;
3384 if (y >= 1) {
3385 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3386 buf1 = *p1++ << 8;
3387 if (y >= 2) {
3388 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3389 buf0 = *p0++ << 8;
3390 } else {
3391 p0 = nullptr;
3392 buf0 = 0;
3393 }
3394 } else {
3395 p1 = p0 = nullptr;
3396 buf1 = buf0 = 0;
3397 }
3398
3399 if (atx[0] >= -8 && atx[0] <= 8) {
3400 // set up the adaptive context
3401 const int atY = y + aty[0];
3402 if ((atY >= 0) && (atY < bitmap->getHeight())) {
3403 atP0 = bitmap->getDataPtr() + atY * bitmap->getLineSize();
3404 atBuf0 = *atP0++ << 8;
3405 } else {
3406 atP0 = nullptr;
3407 atBuf0 = 0;
3408 }
3409 atShift0 = 15 - atx[0];
3410
3411 // decode the row
3412 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3413 if (x0 + 8 < w) {
3414 if (p0) {
3415 buf0 |= *p0++;
3416 }
3417 if (p1) {
3418 buf1 |= *p1++;
3419 }
3420 buf2 |= *p2++;
3421 if (atP0) {
3422 atBuf0 |= *atP0++;
3423 }
3424 }
3425 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3426
3427 // build the context
3428 cx0 = (buf0 >> 14) & 0x07;
3429 cx1 = (buf1 >> 14) & 0x0f;
3430 cx2 = (buf2 >> 16) & 0x03;
3431 cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) | ((atBuf0 >> atShift0) & 1);
3432
3433 // check for a skipped pixel
3434 if (!(useSkip && skip->getPixel(x, y))) {
3435
3436 // decode the pixel
3437 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3438 *pp |= mask;
3439 buf2 |= 0x8000;
3440 if (aty[0] == 0) {
3441 atBuf0 |= 0x8000;
3442 }
3443 }
3444 }
3445
3446 // update the context
3447 buf0 <<= 1;
3448 buf1 <<= 1;
3449 buf2 <<= 1;
3450 atBuf0 <<= 1;
3451 }
3452 }
3453
3454 } else {
3455 // decode the row
3456 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3457 if (x0 + 8 < w) {
3458 if (p0) {
3459 buf0 |= *p0++;
3460 }
3461 if (p1) {
3462 buf1 |= *p1++;
3463 }
3464 buf2 |= *p2++;
3465 }
3466 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3467
3468 // build the context
3469 cx0 = (buf0 >> 14) & 0x07;
3470 cx1 = (buf1 >> 14) & 0x0f;
3471 cx2 = (buf2 >> 16) & 0x03;
3472 cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) | bitmap->getPixel(x: x + atx[0], y: y + aty[0]);
3473
3474 // check for a skipped pixel
3475 if (!(useSkip && skip->getPixel(x, y))) {
3476
3477 // decode the pixel
3478 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3479 *pp |= mask;
3480 buf2 |= 0x8000;
3481 }
3482 }
3483
3484 // update the context
3485 buf0 <<= 1;
3486 buf1 <<= 1;
3487 buf2 <<= 1;
3488 }
3489 }
3490 }
3491 break;
3492
3493 case 3:
3494
3495 // set up the context
3496 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3497 buf2 = *p2++ << 8;
3498 if (y >= 1) {
3499 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3500 buf1 = *p1++ << 8;
3501 } else {
3502 p1 = nullptr;
3503 buf1 = 0;
3504 }
3505
3506 if (atx[0] >= -8 && atx[0] <= 8) {
3507 // set up the adaptive context
3508 const int atY = y + aty[0];
3509 if ((atY >= 0) && (atY < bitmap->getHeight())) {
3510 atP0 = bitmap->getDataPtr() + atY * bitmap->getLineSize();
3511 atBuf0 = *atP0++ << 8;
3512 } else {
3513 atP0 = nullptr;
3514 atBuf0 = 0;
3515 }
3516 atShift0 = 15 - atx[0];
3517
3518 // decode the row
3519 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3520 if (x0 + 8 < w) {
3521 if (p1) {
3522 buf1 |= *p1++;
3523 }
3524 buf2 |= *p2++;
3525 if (atP0) {
3526 atBuf0 |= *atP0++;
3527 }
3528 }
3529 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3530
3531 // build the context
3532 cx1 = (buf1 >> 14) & 0x1f;
3533 cx2 = (buf2 >> 16) & 0x0f;
3534 cx = (cx1 << 5) | (cx2 << 1) | ((atBuf0 >> atShift0) & 1);
3535
3536 // check for a skipped pixel
3537 if (!(useSkip && skip->getPixel(x, y))) {
3538
3539 // decode the pixel
3540 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3541 *pp |= mask;
3542 buf2 |= 0x8000;
3543 if (aty[0] == 0) {
3544 atBuf0 |= 0x8000;
3545 }
3546 }
3547 }
3548
3549 // update the context
3550 buf1 <<= 1;
3551 buf2 <<= 1;
3552 atBuf0 <<= 1;
3553 }
3554 }
3555
3556 } else {
3557 // decode the row
3558 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3559 if (x0 + 8 < w) {
3560 if (p1) {
3561 buf1 |= *p1++;
3562 }
3563 buf2 |= *p2++;
3564 }
3565 for (x1 = 0, mask = 0x80; x1 < 8 && x < w; ++x1, ++x, mask >>= 1) {
3566
3567 // build the context
3568 cx1 = (buf1 >> 14) & 0x1f;
3569 cx2 = (buf2 >> 16) & 0x0f;
3570 cx = (cx1 << 5) | (cx2 << 1) | bitmap->getPixel(x: x + atx[0], y: y + aty[0]);
3571
3572 // check for a skipped pixel
3573 if (!(useSkip && skip->getPixel(x, y))) {
3574
3575 // decode the pixel
3576 if ((pix = arithDecoder->decodeBit(context: cx, stats: genericRegionStats))) {
3577 *pp |= mask;
3578 buf2 |= 0x8000;
3579 }
3580 }
3581
3582 // update the context
3583 buf1 <<= 1;
3584 buf2 <<= 1;
3585 }
3586 }
3587 }
3588 break;
3589 }
3590 }
3591 }
3592
3593 return bitmap;
3594}
3595
3596void JBIG2Stream::readGenericRefinementRegionSeg(unsigned int segNum, bool imm, bool lossless, unsigned int length, unsigned int *refSegs, unsigned int nRefSegs)
3597{
3598 std::unique_ptr<JBIG2Bitmap> bitmap;
3599 JBIG2Bitmap *refBitmap;
3600 unsigned int w, h, x, y, segInfoFlags, extCombOp;
3601 unsigned int flags, templ, tpgrOn;
3602 int atx[2], aty[2];
3603 JBIG2Segment *seg;
3604
3605 // region segment info field
3606 if (!readULong(x: &w) || !readULong(x: &h) || !readULong(x: &x) || !readULong(x: &y) || !readUByte(x: &segInfoFlags)) {
3607 goto eofError;
3608 }
3609 extCombOp = segInfoFlags & 7;
3610
3611 // rest of the generic refinement region segment header
3612 if (!readUByte(x: &flags)) {
3613 goto eofError;
3614 }
3615 templ = flags & 1;
3616 tpgrOn = (flags >> 1) & 1;
3617
3618 // AT flags
3619 if (!templ) {
3620 if (!readByte(x: &atx[0]) || !readByte(x: &aty[0]) || !readByte(x: &atx[1]) || !readByte(x: &aty[1])) {
3621 goto eofError;
3622 }
3623 }
3624
3625 // resize the page bitmap if needed
3626 if (nRefSegs == 0 || imm) {
3627 if (pageH == 0xffffffff && y + h > curPageH) {
3628 pageBitmap->expand(newH: y + h, pixel: pageDefPixel);
3629 }
3630 }
3631
3632 // get referenced bitmap
3633 if (nRefSegs > 1) {
3634 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad reference in JBIG2 generic refinement segment");
3635 return;
3636 }
3637 if (nRefSegs == 1) {
3638 seg = findSegment(segNum: refSegs[0]);
3639 if (seg == nullptr || seg->getType() != jbig2SegBitmap) {
3640 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Bad bitmap reference in JBIG2 generic refinement segment");
3641 return;
3642 }
3643 refBitmap = (JBIG2Bitmap *)seg;
3644 } else {
3645 refBitmap = pageBitmap->getSlice(x, y, wA: w, hA: h);
3646 }
3647
3648 // set up the arithmetic decoder
3649 resetRefinementStats(templ, prevStats: nullptr);
3650 arithDecoder->start();
3651
3652 // read
3653 bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn, refBitmap, refDX: 0, refDY: 0, atx, aty);
3654
3655 // combine the region bitmap into the page bitmap
3656 if (imm && bitmap) {
3657 pageBitmap->combine(bitmap: bitmap.get(), x, y, combOp: extCombOp);
3658
3659 // store the region bitmap
3660 } else {
3661 if (bitmap) {
3662 bitmap->setSegNum(segNum);
3663 segments.push_back(x: std::move(bitmap));
3664 } else {
3665 error(category: errSyntaxError, pos: curStr->getPos(), msg: "readGenericRefinementRegionSeg with null bitmap");
3666 }
3667 }
3668
3669 // delete the referenced bitmap
3670 if (nRefSegs == 1) {
3671 discardSegment(segNum: refSegs[0]);
3672 } else {
3673 delete refBitmap;
3674 }
3675
3676 return;
3677
3678eofError:
3679 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
3680}
3681
3682std::unique_ptr<JBIG2Bitmap> JBIG2Stream::readGenericRefinementRegion(int w, int h, int templ, bool tpgrOn, JBIG2Bitmap *refBitmap, int refDX, int refDY, int *atx, int *aty)
3683{
3684 bool ltp;
3685 unsigned int ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
3686 JBIG2BitmapPtr cxPtr0 = { .p: nullptr, .shift: 0, .x: 0 };
3687 JBIG2BitmapPtr cxPtr1 = { .p: nullptr, .shift: 0, .x: 0 };
3688 JBIG2BitmapPtr cxPtr2 = { .p: nullptr, .shift: 0, .x: 0 };
3689 JBIG2BitmapPtr cxPtr3 = { .p: nullptr, .shift: 0, .x: 0 };
3690 JBIG2BitmapPtr cxPtr4 = { .p: nullptr, .shift: 0, .x: 0 };
3691 JBIG2BitmapPtr cxPtr5 = { .p: nullptr, .shift: 0, .x: 0 };
3692 JBIG2BitmapPtr cxPtr6 = { .p: nullptr, .shift: 0, .x: 0 };
3693 JBIG2BitmapPtr tpgrCXPtr0 = { .p: nullptr, .shift: 0, .x: 0 };
3694 JBIG2BitmapPtr tpgrCXPtr1 = { .p: nullptr, .shift: 0, .x: 0 };
3695 JBIG2BitmapPtr tpgrCXPtr2 = { .p: nullptr, .shift: 0, .x: 0 };
3696 int x, y, pix;
3697
3698 if (!refBitmap) {
3699 return nullptr;
3700 }
3701
3702 auto bitmap = std::make_unique<JBIG2Bitmap>(args: 0, args&: w, args&: h);
3703 if (!bitmap->isOk()) {
3704 return nullptr;
3705 }
3706 bitmap->clearToZero();
3707
3708 // set up the typical row context
3709 if (templ) {
3710 ltpCX = 0x008;
3711 } else {
3712 ltpCX = 0x0010;
3713 }
3714
3715 ltp = false;
3716 for (y = 0; y < h; ++y) {
3717
3718 if (templ) {
3719
3720 // set up the context
3721 bitmap->getPixelPtr(x: 0, y: y - 1, ptr: &cxPtr0);
3722 cx0 = bitmap->nextPixel(ptr: &cxPtr0);
3723 bitmap->getPixelPtr(x: -1, y, ptr: &cxPtr1);
3724 refBitmap->getPixelPtr(x: -refDX, y: y - 1 - refDY, ptr: &cxPtr2);
3725 refBitmap->getPixelPtr(x: -1 - refDX, y: y - refDY, ptr: &cxPtr3);
3726 cx3 = refBitmap->nextPixel(ptr: &cxPtr3);
3727 cx3 = (cx3 << 1) | refBitmap->nextPixel(ptr: &cxPtr3);
3728 refBitmap->getPixelPtr(x: -refDX, y: y + 1 - refDY, ptr: &cxPtr4);
3729 cx4 = refBitmap->nextPixel(ptr: &cxPtr4);
3730
3731 // set up the typical prediction context
3732 tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3733 if (tpgrOn) {
3734 refBitmap->getPixelPtr(x: -1 - refDX, y: y - 1 - refDY, ptr: &tpgrCXPtr0);
3735 tpgrCX0 = refBitmap->nextPixel(ptr: &tpgrCXPtr0);
3736 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr0);
3737 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr0);
3738 refBitmap->getPixelPtr(x: -1 - refDX, y: y - refDY, ptr: &tpgrCXPtr1);
3739 tpgrCX1 = refBitmap->nextPixel(ptr: &tpgrCXPtr1);
3740 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr1);
3741 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr1);
3742 refBitmap->getPixelPtr(x: -1 - refDX, y: y + 1 - refDY, ptr: &tpgrCXPtr2);
3743 tpgrCX2 = refBitmap->nextPixel(ptr: &tpgrCXPtr2);
3744 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr2);
3745 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr2);
3746 } else {
3747 tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = nullptr; // make gcc happy
3748 tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
3749 tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
3750 }
3751
3752 for (x = 0; x < w; ++x) {
3753
3754 // update the context
3755 cx0 = ((cx0 << 1) | bitmap->nextPixel(ptr: &cxPtr0)) & 7;
3756 cx3 = ((cx3 << 1) | refBitmap->nextPixel(ptr: &cxPtr3)) & 7;
3757 cx4 = ((cx4 << 1) | refBitmap->nextPixel(ptr: &cxPtr4)) & 3;
3758
3759 if (tpgrOn) {
3760 // update the typical predictor context
3761 tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr0)) & 7;
3762 tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr1)) & 7;
3763 tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr2)) & 7;
3764
3765 // check for a "typical" pixel
3766 if (arithDecoder->decodeBit(context: ltpCX, stats: refinementRegionStats)) {
3767 ltp = !ltp;
3768 }
3769 if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3770 bitmap->clearPixel(x, y);
3771 continue;
3772 } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3773 bitmap->setPixel(x, y);
3774 continue;
3775 }
3776 }
3777
3778 // build the context
3779 cx = (cx0 << 7) | (bitmap->nextPixel(ptr: &cxPtr1) << 6) | (refBitmap->nextPixel(ptr: &cxPtr2) << 5) | (cx3 << 2) | cx4;
3780
3781 // decode the pixel
3782 if ((pix = arithDecoder->decodeBit(context: cx, stats: refinementRegionStats))) {
3783 bitmap->setPixel(x, y);
3784 }
3785 }
3786
3787 } else {
3788
3789 // set up the context
3790 bitmap->getPixelPtr(x: 0, y: y - 1, ptr: &cxPtr0);
3791 cx0 = bitmap->nextPixel(ptr: &cxPtr0);
3792 bitmap->getPixelPtr(x: -1, y, ptr: &cxPtr1);
3793 refBitmap->getPixelPtr(x: -refDX, y: y - 1 - refDY, ptr: &cxPtr2);
3794 cx2 = refBitmap->nextPixel(ptr: &cxPtr2);
3795 refBitmap->getPixelPtr(x: -1 - refDX, y: y - refDY, ptr: &cxPtr3);
3796 cx3 = refBitmap->nextPixel(ptr: &cxPtr3);
3797 cx3 = (cx3 << 1) | refBitmap->nextPixel(ptr: &cxPtr3);
3798 refBitmap->getPixelPtr(x: -1 - refDX, y: y + 1 - refDY, ptr: &cxPtr4);
3799 cx4 = refBitmap->nextPixel(ptr: &cxPtr4);
3800 cx4 = (cx4 << 1) | refBitmap->nextPixel(ptr: &cxPtr4);
3801 bitmap->getPixelPtr(x: atx[0], y: y + aty[0], ptr: &cxPtr5);
3802 refBitmap->getPixelPtr(x: atx[1] - refDX, y: y + aty[1] - refDY, ptr: &cxPtr6);
3803
3804 // set up the typical prediction context
3805 tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3806 if (tpgrOn) {
3807 refBitmap->getPixelPtr(x: -1 - refDX, y: y - 1 - refDY, ptr: &tpgrCXPtr0);
3808 tpgrCX0 = refBitmap->nextPixel(ptr: &tpgrCXPtr0);
3809 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr0);
3810 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr0);
3811 refBitmap->getPixelPtr(x: -1 - refDX, y: y - refDY, ptr: &tpgrCXPtr1);
3812 tpgrCX1 = refBitmap->nextPixel(ptr: &tpgrCXPtr1);
3813 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr1);
3814 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr1);
3815 refBitmap->getPixelPtr(x: -1 - refDX, y: y + 1 - refDY, ptr: &tpgrCXPtr2);
3816 tpgrCX2 = refBitmap->nextPixel(ptr: &tpgrCXPtr2);
3817 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr2);
3818 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr2);
3819 } else {
3820 tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = nullptr; // make gcc happy
3821 tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
3822 tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
3823 }
3824
3825 for (x = 0; x < w; ++x) {
3826
3827 // update the context
3828 cx0 = ((cx0 << 1) | bitmap->nextPixel(ptr: &cxPtr0)) & 3;
3829 cx2 = ((cx2 << 1) | refBitmap->nextPixel(ptr: &cxPtr2)) & 3;
3830 cx3 = ((cx3 << 1) | refBitmap->nextPixel(ptr: &cxPtr3)) & 7;
3831 cx4 = ((cx4 << 1) | refBitmap->nextPixel(ptr: &cxPtr4)) & 7;
3832
3833 if (tpgrOn) {
3834 // update the typical predictor context
3835 tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr0)) & 7;
3836 tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr1)) & 7;
3837 tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(ptr: &tpgrCXPtr2)) & 7;
3838
3839 // check for a "typical" pixel
3840 if (arithDecoder->decodeBit(context: ltpCX, stats: refinementRegionStats)) {
3841 ltp = !ltp;
3842 }
3843 if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3844 bitmap->clearPixel(x, y);
3845 continue;
3846 } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3847 bitmap->setPixel(x, y);
3848 continue;
3849 }
3850 }
3851
3852 // build the context
3853 cx = (cx0 << 11) | (bitmap->nextPixel(ptr: &cxPtr1) << 10) | (cx2 << 8) | (cx3 << 5) | (cx4 << 2) | (bitmap->nextPixel(ptr: &cxPtr5) << 1) | refBitmap->nextPixel(ptr: &cxPtr6);
3854
3855 // decode the pixel
3856 if ((pix = arithDecoder->decodeBit(context: cx, stats: refinementRegionStats))) {
3857 bitmap->setPixel(x, y);
3858 }
3859 }
3860 }
3861 }
3862
3863 return bitmap;
3864}
3865
3866void JBIG2Stream::readPageInfoSeg(unsigned int length)
3867{
3868 unsigned int xRes, yRes, flags, striping;
3869
3870 if (!readULong(x: &pageW) || !readULong(x: &pageH) || !readULong(x: &xRes) || !readULong(x: &yRes) || !readUByte(x: &flags) || !readUWord(x: &striping)) {
3871 goto eofError;
3872 }
3873 pageDefPixel = (flags >> 2) & 1;
3874 defCombOp = (flags >> 3) & 3;
3875
3876 // allocate the page bitmap
3877 if (pageH == 0xffffffff) {
3878 curPageH = striping & 0x7fff;
3879 } else {
3880 curPageH = pageH;
3881 }
3882 delete pageBitmap;
3883 pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
3884
3885 if (!pageBitmap->isOk()) {
3886 delete pageBitmap;
3887 pageBitmap = nullptr;
3888 return;
3889 }
3890
3891 // default pixel value
3892 if (pageDefPixel) {
3893 pageBitmap->clearToOne();
3894 } else {
3895 pageBitmap->clearToZero();
3896 }
3897
3898 return;
3899
3900eofError:
3901 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
3902}
3903
3904void JBIG2Stream::readEndOfStripeSeg(unsigned int length)
3905{
3906 // skip the segment
3907 byteCounter += curStr->discardChars(n: length);
3908}
3909
3910void JBIG2Stream::readProfilesSeg(unsigned int length)
3911{
3912 // skip the segment
3913 byteCounter += curStr->discardChars(n: length);
3914}
3915
3916void JBIG2Stream::readCodeTableSeg(unsigned int segNum, unsigned int length)
3917{
3918 JBIG2HuffmanTable *huffTab;
3919 unsigned int flags, oob, prefixBits, rangeBits;
3920 int lowVal, highVal, val;
3921 unsigned int huffTabSize, i;
3922
3923 if (!readUByte(x: &flags) || !readLong(x: &lowVal) || !readLong(x: &highVal)) {
3924 goto eofError;
3925 }
3926 oob = flags & 1;
3927 prefixBits = ((flags >> 1) & 7) + 1;
3928 rangeBits = ((flags >> 4) & 7) + 1;
3929
3930 huffDecoder->reset();
3931 huffTabSize = 8;
3932 huffTab = (JBIG2HuffmanTable *)gmallocn_checkoverflow(count: huffTabSize, size: sizeof(JBIG2HuffmanTable));
3933 if (unlikely(!huffTab)) {
3934 goto oomError;
3935 }
3936
3937 i = 0;
3938 val = lowVal;
3939 while (val < highVal) {
3940 if (i == huffTabSize) {
3941 huffTabSize *= 2;
3942 huffTab = (JBIG2HuffmanTable *)greallocn_checkoverflow(p: huffTab, count: huffTabSize, size: sizeof(JBIG2HuffmanTable));
3943 if (unlikely(!huffTab)) {
3944 goto oomError;
3945 }
3946 }
3947 huffTab[i].val = val;
3948 huffTab[i].prefixLen = huffDecoder->readBits(n: prefixBits);
3949 huffTab[i].rangeLen = huffDecoder->readBits(n: rangeBits);
3950 if (unlikely(checkedAdd(val, 1 << huffTab[i].rangeLen, &val))) {
3951 free(ptr: huffTab);
3952 return;
3953 }
3954 ++i;
3955 }
3956 if (i + oob + 3 > huffTabSize) {
3957 huffTabSize = i + oob + 3;
3958 huffTab = (JBIG2HuffmanTable *)greallocn_checkoverflow(p: huffTab, count: huffTabSize, size: sizeof(JBIG2HuffmanTable));
3959 if (unlikely(!huffTab)) {
3960 goto oomError;
3961 }
3962 }
3963 huffTab[i].val = lowVal - 1;
3964 huffTab[i].prefixLen = huffDecoder->readBits(n: prefixBits);
3965 huffTab[i].rangeLen = jbig2HuffmanLOW;
3966 ++i;
3967 huffTab[i].val = highVal;
3968 huffTab[i].prefixLen = huffDecoder->readBits(n: prefixBits);
3969 huffTab[i].rangeLen = 32;
3970 ++i;
3971 if (oob) {
3972 huffTab[i].val = 0;
3973 huffTab[i].prefixLen = huffDecoder->readBits(n: prefixBits);
3974 huffTab[i].rangeLen = jbig2HuffmanOOB;
3975 ++i;
3976 }
3977 huffTab[i].val = 0;
3978 huffTab[i].prefixLen = 0;
3979 huffTab[i].rangeLen = jbig2HuffmanEOT;
3980 if (JBIG2HuffmanDecoder::buildTable(table: huffTab, len: i)) {
3981 // create and store the new table segment
3982 segments.push_back(x: std::make_unique<JBIG2CodeTable>(args&: segNum, args&: huffTab));
3983 } else {
3984 free(ptr: huffTab);
3985 }
3986
3987 return;
3988
3989eofError:
3990 error(category: errSyntaxError, pos: curStr->getPos(), msg: "Unexpected EOF in JBIG2 stream");
3991oomError:
3992 error(category: errInternal, pos: curStr->getPos(), msg: "Failed allocation when processing JBIG2 stream");
3993}
3994
3995void JBIG2Stream::readExtensionSeg(unsigned int length)
3996{
3997 // skip the segment
3998 byteCounter += curStr->discardChars(n: length);
3999}
4000
4001JBIG2Segment *JBIG2Stream::findSegment(unsigned int segNum)
4002{
4003 for (std::unique_ptr<JBIG2Segment> &seg : globalSegments) {
4004 if (seg->getSegNum() == segNum) {
4005 return seg.get();
4006 }
4007 }
4008 for (std::unique_ptr<JBIG2Segment> &seg : segments) {
4009 if (seg->getSegNum() == segNum) {
4010 return seg.get();
4011 }
4012 }
4013 return nullptr;
4014}
4015
4016void JBIG2Stream::discardSegment(unsigned int segNum)
4017{
4018 for (auto it = globalSegments.begin(); it != globalSegments.end(); ++it) {
4019 if ((*it)->getSegNum() == segNum) {
4020 globalSegments.erase(position: it);
4021 return;
4022 }
4023 }
4024 for (auto it = segments.begin(); it != segments.end(); ++it) {
4025 if ((*it)->getSegNum() == segNum) {
4026 segments.erase(position: it);
4027 return;
4028 }
4029 }
4030}
4031
4032void JBIG2Stream::resetGenericStats(unsigned int templ, JArithmeticDecoderStats *prevStats)
4033{
4034 int size;
4035
4036 size = contextSize[templ];
4037 if (prevStats && prevStats->getContextSize() == size) {
4038 if (genericRegionStats->getContextSize() == size) {
4039 genericRegionStats->copyFrom(stats: prevStats);
4040 } else {
4041 delete genericRegionStats;
4042 genericRegionStats = prevStats->copy();
4043 }
4044 } else {
4045 if (genericRegionStats->getContextSize() == size) {
4046 genericRegionStats->reset();
4047 } else {
4048 delete genericRegionStats;
4049 genericRegionStats = new JArithmeticDecoderStats(1 << size);
4050 }
4051 }
4052}
4053
4054void JBIG2Stream::resetRefinementStats(unsigned int templ, JArithmeticDecoderStats *prevStats)
4055{
4056 int size;
4057
4058 size = refContextSize[templ];
4059 if (prevStats && prevStats->getContextSize() == size) {
4060 if (refinementRegionStats->getContextSize() == size) {
4061 refinementRegionStats->copyFrom(stats: prevStats);
4062 } else {
4063 delete refinementRegionStats;
4064 refinementRegionStats = prevStats->copy();
4065 }
4066 } else {
4067 if (refinementRegionStats->getContextSize() == size) {
4068 refinementRegionStats->reset();
4069 } else {
4070 delete refinementRegionStats;
4071 refinementRegionStats = new JArithmeticDecoderStats(1 << size);
4072 }
4073 }
4074}
4075
4076bool JBIG2Stream::resetIntStats(int symCodeLen)
4077{
4078 iadhStats->reset();
4079 iadwStats->reset();
4080 iaexStats->reset();
4081 iaaiStats->reset();
4082 iadtStats->reset();
4083 iaitStats->reset();
4084 iafsStats->reset();
4085 iadsStats->reset();
4086 iardxStats->reset();
4087 iardyStats->reset();
4088 iardwStats->reset();
4089 iardhStats->reset();
4090 iariStats->reset();
4091 if (symCodeLen + 1 >= 31) {
4092 return false;
4093 }
4094 if (iaidStats != nullptr && iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
4095 iaidStats->reset();
4096 } else {
4097 delete iaidStats;
4098 iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
4099 if (!iaidStats->isValid()) {
4100 delete iaidStats;
4101 iaidStats = nullptr;
4102 return false;
4103 }
4104 }
4105 return true;
4106}
4107
4108bool JBIG2Stream::readUByte(unsigned int *x)
4109{
4110 int c0;
4111
4112 if ((c0 = curStr->getChar()) == EOF) {
4113 return false;
4114 }
4115 ++byteCounter;
4116 *x = (unsigned int)c0;
4117 return true;
4118}
4119
4120bool JBIG2Stream::readByte(int *x)
4121{
4122 int c0;
4123
4124 if ((c0 = curStr->getChar()) == EOF) {
4125 return false;
4126 }
4127 ++byteCounter;
4128 *x = c0;
4129 if (c0 & 0x80) {
4130 *x |= -1 - 0xff;
4131 }
4132 return true;
4133}
4134
4135bool JBIG2Stream::readUWord(unsigned int *x)
4136{
4137 int c0, c1;
4138
4139 if ((c0 = curStr->getChar()) == EOF || (c1 = curStr->getChar()) == EOF) {
4140 return false;
4141 }
4142 byteCounter += 2;
4143 *x = (unsigned int)((c0 << 8) | c1);
4144 return true;
4145}
4146
4147bool JBIG2Stream::readULong(unsigned int *x)
4148{
4149 int c0, c1, c2, c3;
4150
4151 if ((c0 = curStr->getChar()) == EOF || (c1 = curStr->getChar()) == EOF || (c2 = curStr->getChar()) == EOF || (c3 = curStr->getChar()) == EOF) {
4152 return false;
4153 }
4154 byteCounter += 4;
4155 *x = (unsigned int)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4156 return true;
4157}
4158
4159bool JBIG2Stream::readLong(int *x)
4160{
4161 int c0, c1, c2, c3;
4162
4163 if ((c0 = curStr->getChar()) == EOF || (c1 = curStr->getChar()) == EOF || (c2 = curStr->getChar()) == EOF || (c3 = curStr->getChar()) == EOF) {
4164 return false;
4165 }
4166 byteCounter += 4;
4167 *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4168 if (c0 & 0x80) {
4169 *x |= -1 - (int)0xffffffff;
4170 }
4171 return true;
4172}
4173

source code of poppler/poppler/JBIG2Stream.cc