Coverage Report

Created: 2025-12-31 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/poppler/Stream.cc
Line
Count
Source
1
//========================================================================
2
//
3
// Stream.cc
4
//
5
// Copyright 1996-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) 2005 Jeff Muizelaar <jeff@infidigm.net>
17
// Copyright (C) 2006-2010, 2012-2014, 2016-2021, 2023-2025 Albert Astals Cid <aacid@kde.org>
18
// Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
19
// Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
20
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
21
// Copyright (C) 2009 Glenn Ganz <glenn.ganz@uptime.ch>
22
// Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
23
// Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
24
// Copyright (C) 2010 Tomas Hoger <thoger@redhat.com>
25
// Copyright (C) 2011, 2012, 2016, 2020 William Bader <williambader@hotmail.com>
26
// Copyright (C) 2012, 2013, 2020 Thomas Freitag <Thomas.Freitag@alfa.de>
27
// Copyright (C) 2012, 2021 Oliver Sander <oliver.sander@tu-dresden.de>
28
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
29
// Copyright (C) 2012, 2024 Even Rouault <even.rouault@spatialys.com>
30
// Copyright (C) 2013, 2017, 2018 Adrian Johnson <ajohnson@redneon.com>
31
// Copyright (C) 2013, 2018 Adam Reichold <adamreichold@myopera.com>
32
// Copyright (C) 2013 Pino Toscano <pino@kde.org>
33
// Copyright (C) 2015 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
34
// Copyright (C) 2015 Jason Crain <jason@aquaticape.us>
35
// Copyright (C) 2017 Jose Aliste <jaliste@src.gnome.org>
36
// Copyright (C) 2017 Kay Dohmann <k.dohmann@gmx.net>
37
// Copyright (C) 2019 Christian Persch <chpe@src.gnome.org>
38
// Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com>
39
// Copyright (C) 2019 Volker Krause <vkrause@kde.org>
40
// Copyright (C) 2019 Alexander Volkov <a.volkov@rusbitech.ru>
41
// Copyright (C) 2020 Philipp Knechtges <philipp-dev@knechtges.com>
42
// Copyright (C) 2021 Hubert Figuiere <hub@figuiere.net>
43
// Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
44
// Copyright (C) 2024, 2025 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
45
// Copyright (C) 2025 Nelson Benítez León <nbenitezl@gmail.com>
46
// Copyright (C) 2025 Martin Emrich <dev@martinemrich.me>
47
// Copyright (C) 2025 Arnav V <arnav0872@gmail.com>
48
//
49
// To see a description of the changes please see the Changelog file that
50
// came with your tarball or type make ChangeLog if you are building from git
51
//
52
//========================================================================
53
54
#include <config.h>
55
56
#include <cstdio>
57
#include <cstdlib>
58
#include <cstddef>
59
#include <climits>
60
#include <cstring>
61
#include <cctype>
62
#include "goo/gmem.h"
63
#include "goo/gfile.h"
64
#include "poppler-config.h"
65
#include "Error.h"
66
#include "Object.h"
67
#include "Lexer.h"
68
#include "GfxState.h"
69
#include "Stream.h"
70
#include "XRef.h"
71
#include "JBIG2Stream.h"
72
#include "Stream-CCITT.h"
73
#include "CachedFile.h"
74
75
#include "splash/SplashBitmap.h"
76
77
#if ENABLE_LIBJPEG
78
#    include "DCTStream.h"
79
#endif
80
81
#if ENABLE_ZLIB_UNCOMPRESS
82
#    include "FlateStream.h"
83
#endif
84
85
#if ENABLE_LIBOPENJPEG
86
#    include "JPEG2000Stream.h"
87
#else
88
#    include "JPXStream.h"
89
#endif
90
91
//------------------------------------------------------------------------
92
// Stream (base class)
93
//------------------------------------------------------------------------
94
95
Stream::Stream()
96
33.3M
{
97
33.3M
    ref = 1;
98
33.3M
}
99
100
33.3M
Stream::~Stream() = default;
101
102
1.07M
void Stream::close() { }
103
104
int Stream::getRawChar()
105
0
{
106
0
    error(errInternal, -1, "Internal: called getRawChar() on non-predictor stream");
107
0
    return EOF;
108
0
}
109
110
int Stream::getChars(int /*nChars*/, unsigned char * /*buffer*/)
111
0
{
112
0
    error(errInternal, -1, "Internal: called getChars() on non-predictor stream");
113
0
    return 0;
114
0
}
115
116
void Stream::getRawChars(int /*nChars*/, int * /*buffer*/)
117
0
{
118
0
    error(errInternal, -1, "Internal: called getRawChars() on non-predictor stream");
119
0
}
120
121
char *Stream::getLine(char *buf, int size)
122
321M
{
123
321M
    int i;
124
321M
    int c;
125
126
321M
    if (lookChar() == EOF || size < 0) {
127
365k
        return nullptr;
128
365k
    }
129
18.2G
    for (i = 0; i < size - 1; ++i) {
130
18.2G
        c = getChar();
131
18.2G
        if (c == EOF || c == '\n') {
132
218M
            break;
133
218M
        }
134
17.9G
        if (c == '\r') {
135
76.8M
            if ((c = lookChar()) == '\n') {
136
16.6M
                getChar();
137
16.6M
            }
138
76.8M
            break;
139
76.8M
        }
140
17.9G
        buf[i] = c;
141
17.9G
    }
142
320M
    buf[i] = '\0';
143
320M
    return buf;
144
321M
}
145
146
unsigned int Stream::discardChars(unsigned int n)
147
3.00M
{
148
3.00M
    unsigned char buf[4096];
149
3.00M
    unsigned int count, i, j;
150
151
3.00M
    count = 0;
152
5.38M
    while (count < n) {
153
3.03M
        if ((i = n - count) > sizeof(buf)) {
154
660k
            i = (unsigned int)sizeof(buf);
155
660k
        }
156
3.03M
        j = (unsigned int)doGetChars((int)i, buf);
157
3.03M
        count += j;
158
3.03M
        if (j != i) {
159
659k
            break;
160
659k
        }
161
3.03M
    }
162
3.00M
    return count;
163
3.00M
}
164
165
std::optional<std::string> Stream::getPSFilter(int /*psLevel*/, const char * /*indent*/)
166
40.0k
{
167
40.0k
    return std::string {};
168
40.0k
}
169
170
static Stream *wrapEOFStream(Stream *str)
171
4.86M
{
172
4.86M
    if (dynamic_cast<EOFStream *>(str)) {
173
        // str is already a EOFStream, no need to wrap it in another EOFStream
174
4.67M
        return str;
175
4.67M
    } else {
176
193k
        return new EOFStream(str);
177
193k
    }
178
4.86M
}
179
180
Stream *Stream::addFilters(Dict *dict, int recursion)
181
6.47M
{
182
6.47M
    Object obj, obj2;
183
6.47M
    Object params, params2;
184
6.47M
    Stream *str;
185
6.47M
    int i;
186
187
6.47M
    str = this;
188
6.47M
    obj = dict->lookup("Filter", recursion);
189
6.47M
    if (obj.isNull()) {
190
1.75M
        obj = dict->lookup("F", recursion);
191
1.75M
    }
192
6.47M
    params = dict->lookup("DecodeParms", recursion);
193
6.47M
    if (params.isNull()) {
194
5.41M
        params = dict->lookup("DP", recursion);
195
5.41M
    }
196
6.47M
    if (obj.isName()) {
197
4.31M
        str = makeFilter(obj.getName(), str, &params, recursion, dict);
198
4.31M
    } else if (obj.isArray()) {
199
5.87M
        for (i = 0; i < obj.arrayGetLength(); ++i) {
200
5.40M
            obj2 = obj.arrayGet(i, recursion);
201
5.40M
            if (params.isArray()) {
202
36.3k
                params2 = params.arrayGet(i, recursion);
203
5.36M
            } else {
204
5.36M
                params2.setToNull();
205
5.36M
            }
206
5.40M
            if (obj2.isName()) {
207
1.73M
                str = makeFilter(obj2.getName(), str, &params2, recursion);
208
3.66M
            } else {
209
3.66M
                error(errSyntaxError, getPos(), "Bad filter name");
210
3.66M
                str = wrapEOFStream(str);
211
3.66M
            }
212
5.40M
        }
213
1.68M
    } else if (!obj.isNull()) {
214
14.1k
        error(errSyntaxError, getPos(), "Bad 'Filter' attribute in stream");
215
14.1k
    }
216
217
6.47M
    return str;
218
6.47M
}
219
220
bool Stream::isEncrypted() const
221
0
{
222
0
    for (const Stream *str = this; str != nullptr; str = str->getNextStream()) {
223
0
        if (str->getKind() == strCrypt) {
224
0
            return true;
225
0
        }
226
0
    }
227
0
    return false;
228
0
}
229
230
class BaseStreamStream : public Stream
231
{
232
public:
233
965
    explicit BaseStreamStream(Stream *strA) : str(strA) { }
234
    ~BaseStreamStream() override;
235
236
110
    StreamKind getKind() const override { return str->getBaseStream()->getKind(); }
237
179
    [[nodiscard]] bool rewind() override { return str->getBaseStream()->rewind(); }
238
186k
    int getChar() override { return str->getBaseStream()->getChar(); }
239
0
    int lookChar() override { return str->getBaseStream()->lookChar(); }
240
0
    bool isBinary(bool /*last*/ = true) const override { return str->getBaseStream()->isBinary(); }
241
0
    int getUnfilteredChar() override { return str->getBaseStream()->getUnfilteredChar(); }
242
0
    [[nodiscard]] bool unfilteredRewind() override { return str->getBaseStream()->unfilteredRewind(); }
243
958
    Goffset getPos() override { return str->getBaseStream()->getPos(); }
244
0
    void setPos(Goffset pos, int dir) override { str->getBaseStream()->setPos(pos, dir); }
245
0
    BaseStream *getBaseStream() override { return str->getBaseStream()->getBaseStream(); }
246
0
    Stream *getUndecodedStream() override { return str->getBaseStream()->getUndecodedStream(); }
247
439
    Dict *getDict() override { return str->getBaseStream()->getDict(); }
248
0
    Object *getDictObject() override { return str->getBaseStream()->getDictObject(); }
249
250
private:
251
    std::unique_ptr<Stream> str;
252
};
253
254
965
BaseStreamStream::~BaseStreamStream() = default;
255
256
Stream *Stream::makeFilter(const char *name, Stream *str, Object *params, int recursion, Dict *dict)
257
6.05M
{
258
6.05M
    int pred; // parameters
259
6.05M
    int colors;
260
6.05M
    int bits;
261
6.05M
    int early;
262
6.05M
    int encoding;
263
6.05M
    bool endOfLine, byteAlign, endOfBlock, black, damagedRowsBeforeError;
264
6.05M
    int columns, rows;
265
6.05M
    Object obj;
266
267
6.05M
    if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
268
40.7k
        str = new ASCIIHexStream(str);
269
6.01M
    } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
270
70.6k
        str = new ASCII85Stream(str);
271
5.94M
    } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
272
53.9k
        pred = 1;
273
53.9k
        columns = 1;
274
53.9k
        colors = 1;
275
53.9k
        bits = 8;
276
53.9k
        early = 1;
277
53.9k
        if (params->isDict()) {
278
25.1k
            obj = params->dictLookup("Predictor", recursion);
279
25.1k
            if (obj.isInt()) {
280
15.3k
                pred = obj.getInt();
281
15.3k
            }
282
25.1k
            obj = params->dictLookup("Columns", recursion);
283
25.1k
            if (obj.isInt()) {
284
8.77k
                columns = obj.getInt();
285
8.77k
            }
286
25.1k
            obj = params->dictLookup("Colors", recursion);
287
25.1k
            if (obj.isInt()) {
288
9.12k
                colors = obj.getInt();
289
9.12k
            }
290
25.1k
            obj = params->dictLookup("BitsPerComponent", recursion);
291
25.1k
            if (obj.isInt()) {
292
2.60k
                bits = obj.getInt();
293
2.60k
            }
294
25.1k
            obj = params->dictLookup("EarlyChange", recursion);
295
25.1k
            if (obj.isInt()) {
296
289
                early = obj.getInt();
297
289
            }
298
25.1k
        }
299
53.9k
        str = new LZWStream(str, pred, columns, colors, bits, early);
300
5.88M
    } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
301
58.1k
        str = new RunLengthStream(str);
302
5.83M
    } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
303
126k
        encoding = 0;
304
126k
        endOfLine = false;
305
126k
        byteAlign = false;
306
126k
        columns = 1728;
307
126k
        rows = 0;
308
126k
        endOfBlock = true;
309
126k
        black = false;
310
126k
        damagedRowsBeforeError = false;
311
126k
        if (params->isDict()) {
312
110k
            obj = params->dictLookup("K", recursion);
313
110k
            if (obj.isInt()) {
314
87.1k
                encoding = obj.getInt();
315
87.1k
            }
316
110k
            obj = params->dictLookup("EndOfLine", recursion);
317
110k
            if (obj.isBool()) {
318
162
                endOfLine = obj.getBool();
319
162
            }
320
110k
            obj = params->dictLookup("EncodedByteAlign", recursion);
321
110k
            if (obj.isBool()) {
322
299
                byteAlign = obj.getBool();
323
299
            }
324
110k
            obj = params->dictLookup("Columns", recursion);
325
110k
            if (obj.isInt()) {
326
68.6k
                columns = obj.getInt();
327
68.6k
            }
328
110k
            obj = params->dictLookup("Rows", recursion);
329
110k
            if (obj.isInt()) {
330
17.5k
                rows = obj.getInt();
331
17.5k
            }
332
110k
            obj = params->dictLookup("EndOfBlock", recursion);
333
110k
            if (obj.isBool()) {
334
25.2k
                endOfBlock = obj.getBool();
335
25.2k
            }
336
110k
            obj = params->dictLookup("BlackIs1", recursion);
337
110k
            if (obj.isBool()) {
338
1.16k
                black = obj.getBool();
339
1.16k
            }
340
110k
            obj = params->dictLookup("DamagedRowsBeforeError", recursion);
341
110k
            if (obj.isInt()) {
342
922
                damagedRowsBeforeError = obj.getInt();
343
922
            }
344
110k
        }
345
126k
        str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign, columns, rows, endOfBlock, black, damagedRowsBeforeError);
346
5.70M
    } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
347
#if HAVE_DCT_DECODER
348
        int colorXform = -1;
349
        if (params->isDict()) {
350
            obj = params->dictLookup("ColorTransform", recursion);
351
            if (obj.isInt()) {
352
                colorXform = obj.getInt();
353
            }
354
        }
355
        str = new DCTStream(str, colorXform, dict, recursion);
356
#else
357
38.2k
        error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
358
38.2k
        str = wrapEOFStream(str);
359
38.2k
#endif
360
5.66M
    } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
361
2.79M
        pred = 1;
362
2.79M
        columns = 1;
363
2.79M
        colors = 1;
364
2.79M
        bits = 8;
365
2.79M
        if (params->isDict()) {
366
183k
            obj = params->dictLookup("Predictor", recursion);
367
183k
            if (obj.isInt()) {
368
170k
                pred = obj.getInt();
369
170k
            }
370
183k
            obj = params->dictLookup("Columns", recursion);
371
183k
            if (obj.isInt()) {
372
167k
                columns = obj.getInt();
373
167k
            }
374
183k
            obj = params->dictLookup("Colors", recursion);
375
183k
            if (obj.isInt()) {
376
74.1k
                colors = obj.getInt();
377
74.1k
            }
378
183k
            obj = params->dictLookup("BitsPerComponent", recursion);
379
183k
            if (obj.isInt()) {
380
72.0k
                bits = obj.getInt();
381
72.0k
            }
382
183k
        }
383
2.79M
        str = new FlateStream(str, pred, columns, colors, bits);
384
2.87M
    } else if (!strcmp(name, "JBIG2Decode")) {
385
1.25M
        Object globals;
386
1.25M
        if (params->isDict()) {
387
573k
            XRef *xref = params->getDict()->getXRef();
388
573k
            obj = params->dictLookupNF("JBIG2Globals").copy();
389
573k
            globals = obj.fetch(xref, recursion);
390
573k
        }
391
1.25M
        str = new JBIG2Stream(str, std::move(globals), &obj);
392
1.62M
    } else if (!strcmp(name, "JPXDecode")) {
393
436k
#if HAVE_JPX_DECODER
394
436k
        str = new JPXStream(str);
395
#else
396
        error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
397
        str = wrapEOFStream(str);
398
#endif
399
1.18M
    } else if (!strcmp(name, "Crypt")) {
400
23.4k
        if (str->getKind() == strCrypt) {
401
965
            str = new BaseStreamStream(str);
402
22.4k
        } else {
403
22.4k
            error(errSyntaxError, getPos(), "Can't revert non decrypt streams");
404
22.4k
        }
405
1.16M
    } else {
406
1.16M
        error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
407
1.16M
        str = wrapEOFStream(str);
408
1.16M
    }
409
6.05M
    return str;
410
6.05M
}
411
412
//------------------------------------------------------------------------
413
// OutStream
414
//------------------------------------------------------------------------
415
8.62k
OutStream::OutStream() = default;
416
417
8.62k
OutStream::~OutStream() = default;
418
419
//------------------------------------------------------------------------
420
// FileOutStream
421
//------------------------------------------------------------------------
422
FileOutStream::FileOutStream(FILE *fa, Goffset startA)
423
0
{
424
0
    f = fa;
425
0
    start = startA;
426
0
}
427
428
FileOutStream::~FileOutStream()
429
0
{
430
0
    close();
431
0
}
432
433
0
void FileOutStream::close() { }
434
435
Goffset FileOutStream::getPos()
436
0
{
437
0
    return Gftell(f);
438
0
}
439
440
void FileOutStream::put(char c)
441
0
{
442
0
    fputc(c, f);
443
0
}
444
445
size_t FileOutStream::write(std::span<const unsigned char> data)
446
0
{
447
0
    return fwrite(data.data(), sizeof(decltype(data)::element_type), data.size(), f);
448
0
}
449
450
void FileOutStream::printf(const char *format, ...)
451
0
{
452
0
    va_list argptr;
453
0
    va_start(argptr, format);
454
0
    vfprintf(f, format, argptr);
455
0
    va_end(argptr);
456
0
}
457
458
//------------------------------------------------------------------------
459
// BaseStream
460
//------------------------------------------------------------------------
461
462
BaseStream::BaseStream(Object &&dictA, Goffset lengthA)
463
27.6M
{
464
27.6M
    dict = std::move(dictA);
465
27.6M
    length = lengthA;
466
27.6M
}
467
468
27.6M
BaseStream::~BaseStream() = default;
469
470
//------------------------------------------------------------------------
471
// BaseStream
472
//------------------------------------------------------------------------
473
474
BaseSeekInputStream::BaseSeekInputStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA)
475
0
    : BaseStream(std::move(dictA), lengthA), start(startA), limited(limitedA), bufPtr(buf), bufEnd(buf), bufPos(start), savePos(0), saved(false)
476
0
{
477
0
}
478
479
BaseSeekInputStream::~BaseSeekInputStream() = default;
480
481
bool BaseSeekInputStream::rewind()
482
0
{
483
0
    savePos = currentPos();
484
0
    setCurrentPos(start);
485
0
    saved = true;
486
0
    bufPtr = bufEnd = buf;
487
0
    bufPos = start;
488
489
0
    return true;
490
0
}
491
492
void BaseSeekInputStream::close()
493
0
{
494
0
    if (!saved) {
495
0
        return;
496
0
    }
497
0
    setCurrentPos(savePos);
498
0
    saved = false;
499
0
}
500
501
void BaseSeekInputStream::setPos(Goffset pos, int dir)
502
0
{
503
0
    if (dir >= 0) {
504
0
        setCurrentPos(pos);
505
0
        bufPos = pos;
506
0
    } else {
507
0
        if (pos > length) {
508
0
            pos = length;
509
0
        }
510
511
0
        bufPos = length - pos;
512
0
        setCurrentPos(bufPos);
513
0
    }
514
0
    bufPtr = bufEnd = buf;
515
0
}
516
517
void BaseSeekInputStream::moveStart(Goffset delta)
518
0
{
519
0
    start += delta;
520
0
    bufPtr = bufEnd = buf;
521
0
    bufPos = start;
522
0
}
523
524
bool BaseSeekInputStream::fillBuf()
525
0
{
526
0
    Goffset n;
527
528
0
    bufPos += bufEnd - buf;
529
0
    bufPtr = bufEnd = buf;
530
0
    if (limited && bufPos >= start + length) {
531
0
        return false;
532
0
    }
533
534
0
    if (limited && bufPos + seekInputStreamBufSize > start + length) {
535
0
        n = start + length - bufPos;
536
0
    } else {
537
0
        n = seekInputStreamBufSize - (bufPos % seekInputStreamBufSize);
538
0
    }
539
540
0
    n = read(buf, n);
541
0
    bufEnd = buf + n;
542
0
    if (bufPtr >= bufEnd) {
543
0
        return false;
544
0
    }
545
546
0
    return true;
547
0
}
548
549
int BaseSeekInputStream::getChars(int nChars, unsigned char *buffer)
550
0
{
551
0
    int n, m;
552
553
0
    n = 0;
554
0
    while (n < nChars) {
555
0
        if (bufPtr >= bufEnd) {
556
0
            if (!fillBuf()) {
557
0
                break;
558
0
            }
559
0
        }
560
0
        m = (int)(bufEnd - bufPtr);
561
0
        if (m > nChars - n) {
562
0
            m = nChars - n;
563
0
        }
564
0
        memcpy(buffer + n, bufPtr, m);
565
0
        bufPtr += m;
566
0
        n += m;
567
0
    }
568
0
    return n;
569
0
}
570
571
//------------------------------------------------------------------------
572
// FilterStream
573
//------------------------------------------------------------------------
574
575
FilterStream::FilterStream(Stream *strA)
576
5.69M
{
577
5.69M
    str = strA;
578
5.69M
}
579
580
FilterStream::~FilterStream() = default;
581
582
void FilterStream::close()
583
3.09M
{
584
3.09M
    str->close();
585
3.09M
}
586
587
void FilterStream::setPos(Goffset /*pos*/, int /*dir*/)
588
0
{
589
0
    error(errInternal, -1, "Internal: called setPos() on FilterStream");
590
0
}
591
592
//------------------------------------------------------------------------
593
// ImageStream
594
//------------------------------------------------------------------------
595
596
ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA)
597
389k
{
598
389k
    int imgLineSize;
599
600
389k
    str = strA;
601
389k
    width = widthA;
602
389k
    nComps = nCompsA;
603
389k
    nBits = nBitsA;
604
605
389k
    nVals = width * nComps;
606
389k
    inputLineSize = (nVals * nBits + 7) >> 3;
607
389k
    if (nComps <= 0 || nBits <= 0 || nVals > INT_MAX / nBits - 7 || width > INT_MAX / nComps) {
608
0
        inputLineSize = -1;
609
0
    }
610
389k
    inputLine = (unsigned char *)gmallocn_checkoverflow(inputLineSize, sizeof(char));
611
389k
    if (nBits == 8) {
612
127k
        imgLine = (unsigned char *)inputLine;
613
261k
    } else {
614
261k
        if (nBits == 1) {
615
260k
            imgLineSize = (nVals + 7) & ~7;
616
260k
        } else {
617
885
            imgLineSize = nVals;
618
885
        }
619
261k
        if (nComps <= 0 || width > INT_MAX / nComps) {
620
0
            imgLineSize = -1;
621
0
        }
622
261k
        imgLine = (unsigned char *)gmallocn_checkoverflow(imgLineSize, sizeof(unsigned char));
623
261k
    }
624
389k
    imgIdx = nVals;
625
389k
}
626
627
ImageStream::~ImageStream()
628
389k
{
629
389k
    if (imgLine != (unsigned char *)inputLine) {
630
261k
        gfree(imgLine);
631
261k
    }
632
389k
    gfree(inputLine);
633
389k
}
634
635
bool ImageStream::rewind()
636
389k
{
637
389k
    return str->rewind();
638
389k
}
639
640
void ImageStream::close()
641
7.30k
{
642
7.30k
    str->close();
643
7.30k
}
644
645
bool ImageStream::getPixel(unsigned char *pix)
646
1.31M
{
647
1.31M
    int i;
648
649
1.31M
    if (imgIdx >= nVals) {
650
5.12k
        if (!getLine()) {
651
0
            return false;
652
0
        }
653
5.12k
        imgIdx = 0;
654
5.12k
    }
655
5.24M
    for (i = 0; i < nComps; ++i) {
656
3.93M
        pix[i] = imgLine[imgIdx++];
657
3.93M
    }
658
1.31M
    return true;
659
1.31M
}
660
661
unsigned char *ImageStream::getLine()
662
20.2M
{
663
20.2M
    if (unlikely(inputLine == nullptr || imgLine == nullptr)) {
664
0
        return nullptr;
665
0
    }
666
667
20.2M
    int readChars = str->doGetChars(inputLineSize, inputLine);
668
20.2M
    if (unlikely(readChars == -1)) {
669
0
        readChars = 0;
670
0
    }
671
6.11G
    for (; readChars < inputLineSize; readChars++) {
672
6.09G
        inputLine[readChars] = EOF;
673
6.09G
    }
674
20.2M
    if (nBits == 1) {
675
6.55M
        unsigned char *p = inputLine;
676
153M
        for (int i = 0; i < nVals; i += 8) {
677
147M
            const int c = *p++;
678
147M
            imgLine[i + 0] = (unsigned char)((c >> 7) & 1);
679
147M
            imgLine[i + 1] = (unsigned char)((c >> 6) & 1);
680
147M
            imgLine[i + 2] = (unsigned char)((c >> 5) & 1);
681
147M
            imgLine[i + 3] = (unsigned char)((c >> 4) & 1);
682
147M
            imgLine[i + 4] = (unsigned char)((c >> 3) & 1);
683
147M
            imgLine[i + 5] = (unsigned char)((c >> 2) & 1);
684
147M
            imgLine[i + 6] = (unsigned char)((c >> 1) & 1);
685
147M
            imgLine[i + 7] = (unsigned char)(c & 1);
686
147M
        }
687
13.6M
    } else if (nBits == 8) {
688
        // special case: imgLine == inputLine
689
13.6M
    } else if (nBits == 16) {
690
        // this is a hack to support 16 bits images, everywhere
691
        // we assume a component fits in 8 bits, with this hack
692
        // we treat 16 bit images as 8 bit ones until it's fixed correctly.
693
        // The hack has another part on GfxImageColorMap::GfxImageColorMap
694
0
        unsigned char *p = inputLine;
695
0
        for (int i = 0; i < nVals; ++i) {
696
0
            imgLine[i] = *p++;
697
0
            p++;
698
0
        }
699
36.6k
    } else {
700
36.6k
        const unsigned long bitMask = (1 << nBits) - 1;
701
36.6k
        unsigned long buf = 0;
702
36.6k
        int bits = 0;
703
36.6k
        unsigned char *p = inputLine;
704
13.6M
        for (int i = 0; i < nVals; ++i) {
705
21.2M
            while (bits < nBits) {
706
7.69M
                buf = (buf << 8) | (*p++ & 0xff);
707
7.69M
                bits += 8;
708
7.69M
            }
709
13.5M
            imgLine[i] = (unsigned char)((buf >> (bits - nBits)) & bitMask);
710
13.5M
            bits -= nBits;
711
13.5M
        }
712
36.6k
    }
713
20.2M
    return imgLine;
714
20.2M
}
715
716
void ImageStream::skipLine()
717
0
{
718
0
    str->doGetChars(inputLineSize, inputLine);
719
0
}
720
721
//------------------------------------------------------------------------
722
// StreamPredictor
723
//------------------------------------------------------------------------
724
725
StreamPredictor::StreamPredictor(Stream *strA, int predictorA, int widthA, int nCompsA, int nBitsA)
726
181k
{
727
181k
    str = strA;
728
181k
    predictor = predictorA;
729
181k
    width = widthA;
730
181k
    nComps = nCompsA;
731
181k
    nBits = nBitsA;
732
181k
    predLine = nullptr;
733
181k
    ok = false;
734
735
181k
    if (checkedMultiply(width, nComps, &nVals)) {
736
7
        return;
737
7
    }
738
181k
    if (width <= 0 || nComps <= 0 || nBits <= 0 || nComps > gfxColorMaxComps || nBits > 16 || nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes
739
11.0k
        return;
740
11.0k
    }
741
170k
    pixBytes = (nComps * nBits + 7) >> 3;
742
170k
    rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
743
170k
    predLine = (unsigned char *)gmalloc(rowBytes);
744
170k
    memset(predLine, 0, rowBytes);
745
170k
    predIdx = rowBytes;
746
747
170k
    ok = true;
748
170k
}
749
750
StreamPredictor::~StreamPredictor()
751
181k
{
752
181k
    gfree(predLine);
753
181k
}
754
755
int StreamPredictor::lookChar()
756
1.92k
{
757
1.92k
    if (predIdx >= rowBytes) {
758
1.00k
        if (!getNextLine()) {
759
24
            return EOF;
760
24
        }
761
1.00k
    }
762
1.89k
    return predLine[predIdx];
763
1.92k
}
764
765
int StreamPredictor::getChar()
766
16.3M
{
767
16.3M
    if (predIdx >= rowBytes) {
768
4.32M
        if (!getNextLine()) {
769
1.65M
            return EOF;
770
1.65M
        }
771
4.32M
    }
772
14.6M
    return predLine[predIdx++];
773
16.3M
}
774
775
int StreamPredictor::getChars(int nChars, unsigned char *buffer)
776
4.36M
{
777
4.36M
    int n, m;
778
779
4.36M
    n = 0;
780
11.0M
    while (n < nChars) {
781
7.93M
        if (predIdx >= rowBytes) {
782
6.27M
            if (!getNextLine()) {
783
1.23M
                break;
784
1.23M
            }
785
6.27M
        }
786
6.69M
        m = rowBytes - predIdx;
787
6.69M
        if (m > nChars - n) {
788
1.65M
            m = nChars - n;
789
1.65M
        }
790
6.69M
        memcpy(buffer + n, predLine + predIdx, m);
791
6.69M
        predIdx += m;
792
6.69M
        n += m;
793
6.69M
    }
794
4.36M
    return n;
795
4.36M
}
796
797
bool StreamPredictor::getNextLine()
798
10.6M
{
799
10.6M
    int curPred;
800
10.6M
    unsigned char upLeftBuf[gfxColorMaxComps * 2 + 1];
801
10.6M
    int left, up, upLeft, p, pa, pb, pc;
802
10.6M
    int c;
803
10.6M
    unsigned long inBuf, outBuf;
804
10.6M
    int inBits, outBits;
805
10.6M
    int i, j, k, kk;
806
807
    // get PNG optimum predictor number
808
10.6M
    if (predictor >= 10) {
809
10.5M
        if ((curPred = str->getRawChar()) == EOF) {
810
2.88M
            return false;
811
2.88M
        }
812
7.62M
        curPred += 10;
813
7.62M
    } else {
814
90.8k
        curPred = predictor;
815
90.8k
    }
816
817
    // read the raw line, apply PNG (byte) predictor
818
7.71M
    int *rawCharLine = new int[rowBytes - pixBytes];
819
7.71M
    str->getRawChars(rowBytes - pixBytes, rawCharLine);
820
7.71M
    memset(upLeftBuf, 0, pixBytes + 1);
821
565M
    for (i = pixBytes; i < rowBytes; ++i) {
822
2.03G
        for (j = pixBytes; j > 0; --j) {
823
1.47G
            upLeftBuf[j] = upLeftBuf[j - 1];
824
1.47G
        }
825
558M
        upLeftBuf[0] = predLine[i];
826
558M
        if ((c = rawCharLine[i - pixBytes]) == EOF) {
827
34.4k
            if (i > pixBytes) {
828
                // this ought to return false, but some (broken) PDF files
829
                // contain truncated image data, and Adobe apparently reads the
830
                // last partial line
831
22.2k
                break;
832
22.2k
            }
833
12.2k
            delete[] rawCharLine;
834
12.2k
            return false;
835
34.4k
        }
836
558M
        switch (curPred) {
837
152M
        case 11: // PNG sub
838
152M
            predLine[i] = predLine[i - pixBytes] + (unsigned char)c;
839
152M
            break;
840
30.6M
        case 12: // PNG up
841
30.6M
            predLine[i] = predLine[i] + (unsigned char)c;
842
30.6M
            break;
843
17.5M
        case 13: // PNG average
844
17.5M
            predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) + (unsigned char)c;
845
17.5M
            break;
846
44.3M
        case 14: // PNG Paeth
847
44.3M
            left = predLine[i - pixBytes];
848
44.3M
            up = predLine[i];
849
44.3M
            upLeft = upLeftBuf[pixBytes];
850
44.3M
            p = left + up - upLeft;
851
44.3M
            if ((pa = p - left) < 0) {
852
18.0M
                pa = -pa;
853
18.0M
            }
854
44.3M
            if ((pb = p - up) < 0) {
855
19.7M
                pb = -pb;
856
19.7M
            }
857
44.3M
            if ((pc = p - upLeft) < 0) {
858
20.7M
                pc = -pc;
859
20.7M
            }
860
44.3M
            if (pa <= pb && pa <= pc) {
861
24.8M
                predLine[i] = left + (unsigned char)c;
862
24.8M
            } else if (pb <= pc) {
863
15.4M
                predLine[i] = up + (unsigned char)c;
864
15.4M
            } else {
865
4.05M
                predLine[i] = upLeft + (unsigned char)c;
866
4.05M
            }
867
44.3M
            break;
868
150M
        case 10: // PNG none
869
313M
        default: // no predictor or TIFF predictor
870
313M
            predLine[i] = (unsigned char)c;
871
313M
            break;
872
558M
        }
873
558M
    }
874
7.70M
    delete[] rawCharLine;
875
876
    // apply TIFF (component) predictor
877
7.70M
    if (predictor == 2) {
878
34.2k
        if (nBits == 1 && nComps == 1) {
879
1.63k
            inBuf = predLine[pixBytes - 1];
880
4.04k
            for (i = pixBytes; i < rowBytes; ++i) {
881
2.40k
                c = predLine[i] ^ inBuf;
882
2.40k
                c ^= c >> 1;
883
2.40k
                c ^= c >> 2;
884
2.40k
                c ^= c >> 4;
885
2.40k
                inBuf = (c & 1) << 7;
886
2.40k
                predLine[i] = c;
887
2.40k
            }
888
32.6k
        } else if (nBits == 8) {
889
113M
            for (i = pixBytes; i < rowBytes; ++i) {
890
113M
                predLine[i] += predLine[i - nComps];
891
113M
            }
892
29.1k
        } else {
893
3.53k
            memset(upLeftBuf, 0, nComps + 1);
894
3.53k
            const unsigned long bitMask = (1 << nBits) - 1;
895
3.53k
            inBuf = outBuf = 0;
896
3.53k
            inBits = outBits = 0;
897
3.53k
            j = k = pixBytes;
898
13.2k
            for (i = 0; i < width; ++i) {
899
33.0k
                for (kk = 0; kk < nComps; ++kk) {
900
30.4k
                    while (inBits < nBits) {
901
7.14k
                        inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
902
7.14k
                        inBits += 8;
903
7.14k
                    }
904
23.2k
                    upLeftBuf[kk] = (unsigned char)((upLeftBuf[kk] + (inBuf >> (inBits - nBits))) & bitMask);
905
23.2k
                    inBits -= nBits;
906
23.2k
                    outBuf = (outBuf << nBits) | upLeftBuf[kk];
907
23.2k
                    outBits += nBits;
908
23.2k
                    if (outBits >= 8) {
909
5.22k
                        predLine[k++] = (unsigned char)(outBuf >> (outBits - 8));
910
5.22k
                        outBits -= 8;
911
5.22k
                    }
912
23.2k
                }
913
9.73k
            }
914
3.53k
            if (outBits > 0) {
915
1.92k
                predLine[k++] = (unsigned char)((outBuf << (8 - outBits)) + (inBuf & ((1 << (8 - outBits)) - 1)));
916
1.92k
            }
917
3.53k
        }
918
34.2k
    }
919
920
    // rewind to start of line
921
7.70M
    predIdx = pixBytes;
922
923
7.70M
    return true;
924
7.71M
}
925
926
//------------------------------------------------------------------------
927
// FileStream
928
//------------------------------------------------------------------------
929
930
1.78M
FileStream::FileStream(GooFile *fileA, Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA) : BaseStream(std::move(dictA), lengthA)
931
1.78M
{
932
1.78M
    file = fileA;
933
1.78M
    offset = start = startA;
934
1.78M
    limited = limitedA;
935
1.78M
    length = lengthA;
936
1.78M
    bufPtr = bufEnd = buf;
937
1.78M
    bufPos = start;
938
1.78M
    savePos = 0;
939
1.78M
    saved = false;
940
1.78M
    needsEncryptionOnSave = false;
941
1.78M
}
942
943
FileStream::~FileStream()
944
1.78M
{
945
1.78M
    close();
946
1.78M
}
947
948
BaseStream *FileStream::copy()
949
14.6k
{
950
14.6k
    return new FileStream(file, start, limited, length, dict.copy());
951
14.6k
}
952
953
std::unique_ptr<Stream> FileStream::makeSubStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA)
954
1.76M
{
955
1.76M
    return std::make_unique<FileStream>(file, startA, limitedA, lengthA, std::move(dictA));
956
1.76M
}
957
958
bool FileStream::rewind()
959
1.66M
{
960
1.66M
    savePos = offset;
961
1.66M
    offset = start;
962
1.66M
    saved = true;
963
1.66M
    bufPtr = bufEnd = buf;
964
1.66M
    bufPos = start;
965
966
1.66M
    return true;
967
1.66M
}
968
969
void FileStream::close()
970
3.38M
{
971
3.38M
    if (saved) {
972
1.64M
        offset = savePos;
973
1.64M
        saved = false;
974
1.64M
    }
975
3.38M
}
976
977
bool FileStream::fillBuf()
978
3.07M
{
979
3.07M
    int n;
980
981
3.07M
    bufPos += bufEnd - buf;
982
3.07M
    bufPtr = bufEnd = buf;
983
3.07M
    if (limited && bufPos >= start + length) {
984
539k
        return false;
985
539k
    }
986
2.53M
    if (limited && bufPos + fileStreamBufSize > start + length) {
987
296k
        n = start + length - bufPos;
988
2.23M
    } else {
989
2.23M
        n = fileStreamBufSize;
990
2.23M
    }
991
2.53M
    n = file->read(buf, n, offset);
992
2.53M
    if (n == -1) {
993
0
        return false;
994
0
    }
995
2.53M
    offset += n;
996
2.53M
    bufEnd = buf + n;
997
2.53M
    if (bufPtr >= bufEnd) {
998
173k
        return false;
999
173k
    }
1000
2.35M
    return true;
1001
2.53M
}
1002
1003
void FileStream::setPos(Goffset pos, int dir)
1004
540k
{
1005
540k
    Goffset size;
1006
1007
540k
    if (dir >= 0) {
1008
474k
        offset = bufPos = pos;
1009
474k
    } else {
1010
66.6k
        size = file->size();
1011
66.6k
        if (pos > size) {
1012
1.28k
            pos = size;
1013
1.28k
        }
1014
66.6k
        offset = size - pos;
1015
66.6k
        bufPos = offset;
1016
66.6k
    }
1017
540k
    bufPtr = bufEnd = buf;
1018
540k
}
1019
1020
void FileStream::moveStart(Goffset delta)
1021
6.29k
{
1022
6.29k
    start += delta;
1023
6.29k
    bufPtr = bufEnd = buf;
1024
6.29k
    bufPos = start;
1025
6.29k
}
1026
1027
//------------------------------------------------------------------------
1028
// CachedFileStream
1029
//------------------------------------------------------------------------
1030
1031
0
CachedFileStream::CachedFileStream(std::shared_ptr<CachedFile> ccA, Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA) : BaseStream(std::move(dictA), lengthA)
1032
0
{
1033
0
    cc = std::move(ccA);
1034
0
    start = startA;
1035
0
    limited = limitedA;
1036
0
    length = lengthA;
1037
0
    bufPtr = bufEnd = buf;
1038
0
    bufPos = start;
1039
0
    savePos = 0;
1040
0
    saved = false;
1041
0
}
1042
1043
CachedFileStream::~CachedFileStream()
1044
0
{
1045
0
    close();
1046
0
}
1047
1048
BaseStream *CachedFileStream::copy()
1049
0
{
1050
0
    return new CachedFileStream(cc, start, limited, length, dict.copy());
1051
0
}
1052
1053
std::unique_ptr<Stream> CachedFileStream::makeSubStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA)
1054
0
{
1055
0
    return std::make_unique<CachedFileStream>(cc, startA, limitedA, lengthA, std::move(dictA));
1056
0
}
1057
1058
bool CachedFileStream::rewind()
1059
0
{
1060
0
    savePos = (unsigned int)cc->tell();
1061
0
    cc->seek(start, SEEK_SET);
1062
1063
0
    saved = true;
1064
0
    bufPtr = bufEnd = buf;
1065
0
    bufPos = start;
1066
1067
0
    return true;
1068
0
}
1069
1070
void CachedFileStream::close()
1071
0
{
1072
0
    if (saved) {
1073
0
        cc->seek(savePos, SEEK_SET);
1074
0
        saved = false;
1075
0
    }
1076
0
}
1077
1078
bool CachedFileStream::fillBuf()
1079
0
{
1080
0
    int n;
1081
1082
0
    bufPos += bufEnd - buf;
1083
0
    bufPtr = bufEnd = buf;
1084
0
    if (limited && bufPos >= start + length) {
1085
0
        return false;
1086
0
    }
1087
0
    if (limited && bufPos + cachedStreamBufSize > start + length) {
1088
0
        n = start + length - bufPos;
1089
0
    } else {
1090
0
        n = cachedStreamBufSize - (bufPos % cachedStreamBufSize);
1091
0
    }
1092
0
    n = cc->read(buf, 1, n);
1093
0
    bufEnd = buf + n;
1094
0
    if (bufPtr >= bufEnd) {
1095
0
        return false;
1096
0
    }
1097
0
    return true;
1098
0
}
1099
1100
void CachedFileStream::setPos(Goffset pos, int dir)
1101
0
{
1102
0
    unsigned int size;
1103
1104
0
    if (dir >= 0) {
1105
0
        if (cc->seek(pos, SEEK_SET) == 0) {
1106
0
            bufPos = pos;
1107
0
        } else {
1108
0
            cc->seek(0, SEEK_END);
1109
0
            bufPos = pos = (unsigned int)cc->tell();
1110
0
            error(errInternal, pos, "CachedFileStream: Seek beyond end attempted, capped to file size");
1111
0
        }
1112
0
    } else {
1113
0
        cc->seek(0, SEEK_END);
1114
0
        size = (unsigned int)cc->tell();
1115
1116
0
        if (pos > size) {
1117
0
            pos = (unsigned int)size;
1118
0
        }
1119
1120
0
        cc->seek(-(int)pos, SEEK_END);
1121
0
        bufPos = (unsigned int)cc->tell();
1122
0
    }
1123
1124
0
    bufPtr = bufEnd = buf;
1125
0
}
1126
1127
void CachedFileStream::moveStart(Goffset delta)
1128
0
{
1129
0
    start += delta;
1130
0
    bufPtr = bufEnd = buf;
1131
0
    bufPos = start;
1132
0
}
1133
1134
564k
MemStream::~MemStream() = default;
1135
1136
102k
AutoFreeMemStream::~AutoFreeMemStream() = default;
1137
1138
bool AutoFreeMemStream::isFilterRemovalForbidden() const
1139
0
{
1140
0
    return filterRemovalForbidden;
1141
0
}
1142
1143
void AutoFreeMemStream::setFilterRemovalForbidden(bool forbidden)
1144
5.97k
{
1145
5.97k
    filterRemovalForbidden = forbidden;
1146
5.97k
}
1147
1148
//------------------------------------------------------------------------
1149
// EmbedStream
1150
//------------------------------------------------------------------------
1151
1152
1.09M
EmbedStream::EmbedStream(Stream *strA, Object &&dictA, bool limitedA, Goffset lengthA, bool reusableA) : BaseStream(std::move(dictA), lengthA), limited(limitedA), reusable(reusableA), initialLength(length)
1153
1.09M
{
1154
1.09M
    str = strA;
1155
1.09M
    length = lengthA;
1156
1.09M
    replay = false;
1157
1.09M
    if (reusable) {
1158
457k
        bufData = (unsigned char *)gmalloc(16384);
1159
457k
        bufMax = 16384;
1160
457k
        bufLen = 0;
1161
457k
    }
1162
1.09M
}
1163
1164
EmbedStream::~EmbedStream()
1165
1.09M
{
1166
1.09M
    if (reusable) {
1167
457k
        gfree(bufData);
1168
457k
    }
1169
1.09M
}
1170
1171
bool EmbedStream::rewind()
1172
1.06M
{
1173
1.06M
    if (length == initialLength) {
1174
        // In general one can't rewind EmbedStream
1175
        // but if we have not read anything yet, that's fine
1176
1.06M
        return true;
1177
1.06M
    }
1178
1179
0
    if (reusable) {
1180
        // If the EmbedStream is reusable, rewinding switches back to reading the recorded data
1181
0
        replay = true;
1182
0
        bufPos = 0;
1183
0
        return true;
1184
0
    }
1185
1186
0
    return false;
1187
0
}
1188
1189
BaseStream *EmbedStream::copy()
1190
0
{
1191
0
    error(errInternal, -1, "Called copy() on EmbedStream");
1192
0
    return nullptr;
1193
0
}
1194
1195
std::unique_ptr<Stream> EmbedStream::makeSubStream(Goffset /*startA*/, bool /*limitedA*/, Goffset /*lengthA*/, Object && /*dictA*/)
1196
0
{
1197
0
    error(errInternal, -1, "Called makeSubStream() on EmbedStream");
1198
0
    return nullptr;
1199
0
}
1200
1201
Goffset EmbedStream::getPos()
1202
1.19M
{
1203
1.19M
    if (replay) {
1204
0
        return bufPos;
1205
1.19M
    } else {
1206
1.19M
        return str->getPos();
1207
1.19M
    }
1208
1.19M
}
1209
1210
int EmbedStream::getChar()
1211
131M
{
1212
131M
    if (replay) {
1213
0
        if (bufPos < bufLen) {
1214
0
            return bufData[bufPos++];
1215
0
        } else {
1216
0
            replay = false;
1217
0
            return EOF;
1218
0
        }
1219
131M
    } else {
1220
131M
        if (limited && !length) {
1221
355k
            return EOF;
1222
355k
        }
1223
131M
        int c = str->getChar();
1224
131M
        --length;
1225
131M
        if (reusable) {
1226
53.9M
            bufData[bufLen] = c;
1227
53.9M
            bufLen++;
1228
53.9M
            if (bufLen >= bufMax) {
1229
192
                bufMax *= 2;
1230
192
                bufData = (unsigned char *)grealloc(bufData, bufMax);
1231
192
            }
1232
53.9M
        }
1233
131M
        return c;
1234
131M
    }
1235
131M
}
1236
1237
int EmbedStream::lookChar()
1238
180
{
1239
180
    if (replay) {
1240
0
        if (bufPos < bufLen) {
1241
0
            return bufData[bufPos];
1242
0
        } else {
1243
0
            return EOF;
1244
0
        }
1245
180
    } else {
1246
180
        if (limited && !length) {
1247
0
            return EOF;
1248
0
        }
1249
180
        return str->lookChar();
1250
180
    }
1251
180
}
1252
1253
int EmbedStream::getChars(int nChars, unsigned char *buffer)
1254
3.53M
{
1255
3.53M
    if (nChars <= 0) {
1256
0
        return 0;
1257
0
    }
1258
3.53M
    if (replay) {
1259
0
        if (bufPos >= bufLen) {
1260
0
            replay = false;
1261
0
            return EOF;
1262
0
        }
1263
0
        const long len = bufLen - bufPos;
1264
0
        if (nChars > len) {
1265
0
            nChars = len;
1266
0
        }
1267
0
        memcpy(buffer, &bufData[bufPos], nChars);
1268
0
        bufPos += nChars;
1269
0
        return nChars;
1270
3.53M
    } else {
1271
3.53M
        if (limited && length < nChars) {
1272
0
            nChars = length;
1273
0
        }
1274
3.53M
        const int len = str->doGetChars(nChars, buffer);
1275
3.53M
        length -= len;
1276
3.53M
        if (reusable) {
1277
3.53M
            if (bufLen + len >= bufMax) {
1278
68
                while (bufLen + len >= bufMax) {
1279
34
                    bufMax *= 2;
1280
34
                }
1281
34
                bufData = (unsigned char *)grealloc(bufData, bufMax);
1282
34
            }
1283
3.53M
            memcpy(bufData + bufLen, buffer, len);
1284
3.53M
            bufLen += len;
1285
3.53M
        }
1286
3.53M
        return len;
1287
3.53M
    }
1288
3.53M
}
1289
1290
void EmbedStream::setPos(Goffset /*pos*/, int /*dir*/)
1291
0
{
1292
0
    error(errInternal, -1, "Internal: called setPos() on EmbedStream");
1293
0
}
1294
1295
Goffset EmbedStream::getStart()
1296
0
{
1297
0
    error(errInternal, -1, "Internal: called getStart() on EmbedStream");
1298
0
    return 0;
1299
0
}
1300
1301
void EmbedStream::moveStart(Goffset /*delta*/)
1302
0
{
1303
0
    error(errInternal, -1, "Internal: called moveStart() on EmbedStream");
1304
0
}
1305
1306
//------------------------------------------------------------------------
1307
// ASCIIHexStream
1308
//------------------------------------------------------------------------
1309
1310
40.7k
ASCIIHexStream::ASCIIHexStream(Stream *strA) : FilterStream(strA)
1311
40.7k
{
1312
40.7k
    buf = EOF;
1313
40.7k
    eof = false;
1314
40.7k
}
1315
1316
ASCIIHexStream::~ASCIIHexStream()
1317
40.7k
{
1318
40.7k
    delete str;
1319
40.7k
}
1320
1321
bool ASCIIHexStream::rewind()
1322
21.9k
{
1323
21.9k
    buf = EOF;
1324
21.9k
    eof = false;
1325
1326
21.9k
    return str->rewind();
1327
21.9k
}
1328
1329
int ASCIIHexStream::lookChar()
1330
13.2M
{
1331
13.2M
    int c1, c2, x;
1332
1333
13.2M
    if (buf != EOF) {
1334
171
        return buf;
1335
171
    }
1336
13.2M
    if (eof) {
1337
6.61M
        buf = EOF;
1338
6.61M
        return EOF;
1339
6.61M
    }
1340
7.10M
    do {
1341
7.10M
        c1 = str->getChar();
1342
7.10M
    } while (isspace(c1));
1343
6.64M
    if (c1 == '>') {
1344
2.49k
        eof = true;
1345
2.49k
        buf = EOF;
1346
2.49k
        return buf;
1347
2.49k
    }
1348
6.87M
    do {
1349
6.87M
        c2 = str->getChar();
1350
6.87M
    } while (isspace(c2));
1351
6.64M
    if (c2 == '>') {
1352
5.72k
        eof = true;
1353
5.72k
        c2 = '0';
1354
5.72k
    }
1355
6.64M
    if (c1 >= '0' && c1 <= '9') {
1356
2.82M
        x = (c1 - '0') << 4;
1357
3.81M
    } else if (c1 >= 'A' && c1 <= 'F') {
1358
53.5k
        x = (c1 - 'A' + 10) << 4;
1359
3.76M
    } else if (c1 >= 'a' && c1 <= 'f') {
1360
2.69M
        x = (c1 - 'a' + 10) << 4;
1361
2.69M
    } else if (c1 == EOF) {
1362
5.43k
        eof = true;
1363
5.43k
        x = 0;
1364
1.06M
    } else {
1365
1.06M
        error(errSyntaxError, getPos(), "Illegal character <{0:02x}> in ASCIIHex stream", c1);
1366
1.06M
        x = 0;
1367
1.06M
    }
1368
6.64M
    if (c2 >= '0' && c2 <= '9') {
1369
2.81M
        x += c2 - '0';
1370
3.83M
    } else if (c2 >= 'A' && c2 <= 'F') {
1371
72.1k
        x += c2 - 'A' + 10;
1372
3.76M
    } else if (c2 >= 'a' && c2 <= 'f') {
1373
2.71M
        x += c2 - 'a' + 10;
1374
2.71M
    } else if (c2 == EOF) {
1375
5.77k
        eof = true;
1376
5.77k
        x = 0;
1377
1.03M
    } else {
1378
1.03M
        error(errSyntaxError, getPos(), "Illegal character <{0:02x}> in ASCIIHex stream", c2);
1379
1.03M
    }
1380
6.64M
    buf = x & 0xff;
1381
6.64M
    return buf;
1382
6.64M
}
1383
1384
std::optional<std::string> ASCIIHexStream::getPSFilter(int psLevel, const char *indent)
1385
241
{
1386
241
    std::optional<std::string> s;
1387
1388
241
    if (psLevel < 2) {
1389
0
        return {};
1390
0
    }
1391
241
    if (!(s = str->getPSFilter(psLevel, indent))) {
1392
0
        return {};
1393
0
    }
1394
241
    s->append(indent).append("/ASCIIHexDecode filter\n");
1395
241
    return s;
1396
241
}
1397
1398
bool ASCIIHexStream::isBinary(bool /*last*/) const
1399
25
{
1400
25
    return str->isBinary(false);
1401
25
}
1402
1403
//------------------------------------------------------------------------
1404
// ASCII85Stream
1405
//------------------------------------------------------------------------
1406
1407
70.6k
ASCII85Stream::ASCII85Stream(Stream *strA) : FilterStream(strA)
1408
70.6k
{
1409
70.6k
    index = n = 0;
1410
70.6k
    eof = false;
1411
70.6k
}
1412
1413
ASCII85Stream::~ASCII85Stream()
1414
70.6k
{
1415
70.6k
    delete str;
1416
70.6k
}
1417
1418
bool ASCII85Stream::rewind()
1419
43.3k
{
1420
43.3k
    index = n = 0;
1421
43.3k
    eof = false;
1422
1423
43.3k
    return str->rewind();
1424
43.3k
}
1425
1426
int ASCII85Stream::lookChar()
1427
26.8M
{
1428
26.8M
    int k;
1429
26.8M
    unsigned long t;
1430
1431
26.8M
    if (index >= n) {
1432
6.90M
        if (eof) {
1433
242k
            return EOF;
1434
242k
        }
1435
6.66M
        index = 0;
1436
7.37M
        do {
1437
7.37M
            c[0] = str->getChar();
1438
7.37M
        } while (Lexer::isSpace(c[0]));
1439
6.66M
        if (c[0] == '~' || c[0] == EOF) {
1440
10.6k
            eof = true;
1441
10.6k
            n = 0;
1442
10.6k
            return EOF;
1443
6.65M
        } else if (c[0] == 'z') {
1444
7.15k
            b[0] = b[1] = b[2] = b[3] = 0;
1445
7.15k
            n = 4;
1446
6.64M
        } else {
1447
33.1M
            for (k = 1; k < 5; ++k) {
1448
30.4M
                do {
1449
30.4M
                    c[k] = str->getChar();
1450
30.4M
                } while (Lexer::isSpace(c[k]));
1451
26.5M
                if (c[k] == '~' || c[k] == EOF) {
1452
20.4k
                    break;
1453
20.4k
                }
1454
26.5M
            }
1455
6.64M
            n = k - 1;
1456
6.64M
            if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
1457
47.9k
                for (++k; k < 5; ++k) {
1458
27.4k
                    c[k] = 0x21 + 84;
1459
27.4k
                }
1460
20.4k
                eof = true;
1461
20.4k
            }
1462
6.64M
            t = 0;
1463
39.8M
            for (k = 0; k < 5; ++k) {
1464
33.2M
                t = t * 85 + (c[k] - 0x21);
1465
33.2M
            }
1466
33.2M
            for (k = 3; k >= 0; --k) {
1467
26.5M
                b[k] = (int)(t & 0xff);
1468
26.5M
                t >>= 8;
1469
26.5M
            }
1470
6.64M
        }
1471
6.66M
    }
1472
26.5M
    return b[index];
1473
26.8M
}
1474
1475
std::optional<std::string> ASCII85Stream::getPSFilter(int psLevel, const char *indent)
1476
11
{
1477
11
    std::optional<std::string> s;
1478
1479
11
    if (psLevel < 2) {
1480
0
        return {};
1481
0
    }
1482
11
    if (!(s = str->getPSFilter(psLevel, indent))) {
1483
0
        return {};
1484
0
    }
1485
11
    s->append(indent).append("/ASCII85Decode filter\n");
1486
11
    return s;
1487
11
}
1488
1489
bool ASCII85Stream::isBinary(bool /*last*/) const
1490
0
{
1491
0
    return str->isBinary(false);
1492
0
}
1493
1494
//------------------------------------------------------------------------
1495
// LZWStream
1496
//------------------------------------------------------------------------
1497
1498
53.9k
LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors, int bits, int earlyA) : FilterStream(strA)
1499
53.9k
{
1500
53.9k
    if (predictor != 1) {
1501
15.3k
        pred = new StreamPredictor(this, predictor, columns, colors, bits);
1502
15.3k
        if (!pred->isOk()) {
1503
6.48k
            delete pred;
1504
6.48k
            pred = nullptr;
1505
6.48k
        }
1506
38.6k
    } else {
1507
38.6k
        pred = nullptr;
1508
38.6k
    }
1509
53.9k
    early = earlyA;
1510
53.9k
    eof = false;
1511
53.9k
    inputBits = 0;
1512
53.9k
    clearTable();
1513
53.9k
}
1514
1515
LZWStream::~LZWStream()
1516
53.9k
{
1517
53.9k
    delete pred;
1518
53.9k
    delete str;
1519
53.9k
}
1520
1521
int LZWStream::getChar()
1522
201k
{
1523
201k
    if (pred) {
1524
41.0k
        return pred->getChar();
1525
41.0k
    }
1526
160k
    if (eof) {
1527
21.0k
        return EOF;
1528
21.0k
    }
1529
139k
    if (seqIndex >= seqLength) {
1530
133k
        if (!processNextCode()) {
1531
6.24k
            return EOF;
1532
6.24k
        }
1533
133k
    }
1534
133k
    return seqBuf[seqIndex++];
1535
139k
}
1536
1537
int LZWStream::lookChar()
1538
2.93k
{
1539
2.93k
    if (pred) {
1540
0
        return pred->lookChar();
1541
0
    }
1542
2.93k
    if (eof) {
1543
0
        return EOF;
1544
0
    }
1545
2.93k
    if (seqIndex >= seqLength) {
1546
2.93k
        if (!processNextCode()) {
1547
6
            return EOF;
1548
6
        }
1549
2.93k
    }
1550
2.93k
    return seqBuf[seqIndex];
1551
2.93k
}
1552
1553
void LZWStream::getRawChars(int nChars, int *buffer)
1554
50.5k
{
1555
158M
    for (int i = 0; i < nChars; ++i) {
1556
158M
        buffer[i] = doGetRawChar();
1557
158M
    }
1558
50.5k
}
1559
1560
int LZWStream::getRawChar()
1561
51.6k
{
1562
51.6k
    return doGetRawChar();
1563
51.6k
}
1564
1565
int LZWStream::getChars(int nChars, unsigned char *buffer)
1566
6.75k
{
1567
6.75k
    int n, m;
1568
1569
6.75k
    if (pred) {
1570
128
        return pred->getChars(nChars, buffer);
1571
128
    }
1572
6.63k
    if (eof) {
1573
1.52k
        return 0;
1574
1.52k
    }
1575
5.10k
    n = 0;
1576
12.1M
    while (n < nChars) {
1577
12.1M
        if (seqIndex >= seqLength) {
1578
12.1M
            if (!processNextCode()) {
1579
2.14k
                break;
1580
2.14k
            }
1581
12.1M
        }
1582
12.1M
        m = seqLength - seqIndex;
1583
12.1M
        if (m > nChars - n) {
1584
15
            m = nChars - n;
1585
15
        }
1586
12.1M
        memcpy(buffer + n, seqBuf + seqIndex, m);
1587
12.1M
        seqIndex += m;
1588
12.1M
        n += m;
1589
12.1M
    }
1590
5.10k
    return n;
1591
6.63k
}
1592
1593
bool LZWStream::rewind()
1594
21.0k
{
1595
21.0k
    bool success = str->rewind();
1596
21.0k
    eof = false;
1597
21.0k
    inputBits = 0;
1598
21.0k
    clearTable();
1599
1600
21.0k
    return success;
1601
21.0k
}
1602
1603
bool LZWStream::processNextCode()
1604
12.3M
{
1605
12.3M
    int code;
1606
12.3M
    int nextLength;
1607
12.3M
    int i, j;
1608
1609
    // check for EOF
1610
12.3M
    if (eof) {
1611
0
        return false;
1612
0
    }
1613
1614
    // check for eod and clear-table codes
1615
12.3M
start:
1616
12.3M
    code = getCode();
1617
12.3M
    if (code == EOF || code == 257) {
1618
2.58k
        eof = true;
1619
2.58k
        return false;
1620
2.58k
    }
1621
12.3M
    if (code == 256) {
1622
5.10k
        clearTable();
1623
5.10k
        goto start;
1624
5.10k
    }
1625
1626
    // process the next code
1627
12.3M
    nextLength = seqLength + 1;
1628
12.3M
    if (code < 256) {
1629
12.3M
        seqBuf[0] = code;
1630
12.3M
        seqLength = 1;
1631
12.3M
    } else if (code < nextCode) {
1632
20.7k
        seqLength = table[code].length;
1633
44.2k
        for (i = seqLength - 1, j = code; i > 0; --i) {
1634
23.5k
            seqBuf[i] = table[j].tail;
1635
23.5k
            j = table[j].head;
1636
23.5k
        }
1637
20.7k
        seqBuf[0] = j;
1638
20.7k
    } else if (code == nextCode) {
1639
2.53k
        seqBuf[seqLength] = newChar;
1640
2.53k
        ++seqLength;
1641
9.36k
    } else {
1642
9.36k
        error(errSyntaxError, getPos(), "Bad LZW stream - unexpected code");
1643
9.36k
        eof = true;
1644
9.36k
        return false;
1645
9.36k
    }
1646
12.3M
    newChar = seqBuf[0];
1647
12.3M
    if (first) {
1648
13.3k
        first = false;
1649
12.3M
    } else {
1650
12.3M
        if (nextCode < 4097) {
1651
438k
            table[nextCode].length = nextLength;
1652
438k
            table[nextCode].head = prevCode;
1653
438k
            table[nextCode].tail = newChar;
1654
438k
            ++nextCode;
1655
438k
        }
1656
12.3M
        if (nextCode + early == 512) {
1657
160
            nextBits = 10;
1658
12.3M
        } else if (nextCode + early == 1024) {
1659
78
            nextBits = 11;
1660
12.3M
        } else if (nextCode + early == 2048) {
1661
34
            nextBits = 12;
1662
34
        }
1663
12.3M
    }
1664
12.3M
    prevCode = code;
1665
1666
    // rewind buffer
1667
12.3M
    seqIndex = 0;
1668
1669
12.3M
    return true;
1670
12.3M
}
1671
1672
void LZWStream::clearTable()
1673
80.1k
{
1674
80.1k
    nextCode = 258;
1675
80.1k
    nextBits = 9;
1676
80.1k
    seqIndex = seqLength = 0;
1677
80.1k
    first = true;
1678
80.1k
    newChar = 0;
1679
80.1k
}
1680
1681
int LZWStream::getCode()
1682
12.3M
{
1683
12.3M
    int c;
1684
12.3M
    int code;
1685
1686
30.7M
    while (inputBits < nextBits) {
1687
18.4M
        if ((c = str->getChar()) == EOF) {
1688
1.58k
            return EOF;
1689
1.58k
        }
1690
18.3M
        inputBuf = (inputBuf << 8) | static_cast<unsigned>(c & 0xff);
1691
18.3M
        inputBits += 8;
1692
18.3M
    }
1693
12.3M
    code = static_cast<signed>((inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1));
1694
12.3M
    inputBits -= nextBits;
1695
12.3M
    return code;
1696
12.3M
}
1697
1698
std::optional<std::string> LZWStream::getPSFilter(int psLevel, const char *indent)
1699
0
{
1700
0
    std::optional<std::string> s;
1701
1702
0
    if (psLevel < 2 || pred) {
1703
0
        return {};
1704
0
    }
1705
0
    if (!(s = str->getPSFilter(psLevel, indent))) {
1706
0
        return {};
1707
0
    }
1708
0
    s->append(indent).append("<< ");
1709
0
    if (!early) {
1710
0
        s->append("/EarlyChange 0 ");
1711
0
    }
1712
0
    s->append(">> /LZWDecode filter\n");
1713
0
    return s;
1714
0
}
1715
1716
bool LZWStream::isBinary(bool /*last*/) const
1717
0
{
1718
0
    return str->isBinary(true);
1719
0
}
1720
1721
//------------------------------------------------------------------------
1722
// RunLengthStream
1723
//------------------------------------------------------------------------
1724
1725
58.1k
RunLengthStream::RunLengthStream(Stream *strA) : FilterStream(strA)
1726
58.1k
{
1727
58.1k
    bufPtr = bufEnd = buf;
1728
58.1k
    eof = false;
1729
58.1k
}
1730
1731
RunLengthStream::~RunLengthStream()
1732
58.1k
{
1733
58.1k
    delete str;
1734
58.1k
}
1735
1736
bool RunLengthStream::rewind()
1737
33.7k
{
1738
33.7k
    bufPtr = bufEnd = buf;
1739
33.7k
    eof = false;
1740
1741
33.7k
    return str->rewind();
1742
33.7k
}
1743
1744
int RunLengthStream::getChars(int nChars, unsigned char *buffer)
1745
352k
{
1746
352k
    int n, m;
1747
1748
352k
    n = 0;
1749
41.0M
    while (n < nChars) {
1750
40.7M
        if (bufPtr >= bufEnd) {
1751
40.4M
            if (!fillBuf()) {
1752
47.8k
                break;
1753
47.8k
            }
1754
40.4M
        }
1755
40.6M
        m = (int)(bufEnd - bufPtr);
1756
40.6M
        if (m > nChars - n) {
1757
289k
            m = nChars - n;
1758
289k
        }
1759
40.6M
        memcpy(buffer + n, bufPtr, m);
1760
40.6M
        bufPtr += m;
1761
40.6M
        n += m;
1762
40.6M
    }
1763
352k
    return n;
1764
352k
}
1765
1766
std::optional<std::string> RunLengthStream::getPSFilter(int psLevel, const char *indent)
1767
12
{
1768
12
    std::optional<std::string> s;
1769
1770
12
    if (psLevel < 2) {
1771
0
        return {};
1772
0
    }
1773
12
    if (!(s = str->getPSFilter(psLevel, indent))) {
1774
0
        return {};
1775
0
    }
1776
12
    s->append(indent).append("/RunLengthDecode filter\n");
1777
12
    return s;
1778
12
}
1779
1780
bool RunLengthStream::isBinary(bool /*last*/) const
1781
12
{
1782
12
    return str->isBinary(true);
1783
12
}
1784
1785
bool RunLengthStream::fillBuf()
1786
41.9M
{
1787
41.9M
    int c;
1788
41.9M
    int n, i;
1789
1790
41.9M
    if (eof) {
1791
209k
        return false;
1792
209k
    }
1793
41.7M
    c = str->getChar();
1794
41.7M
    if (c == 0x80 || c == EOF) {
1795
24.0k
        eof = true;
1796
24.0k
        return false;
1797
24.0k
    }
1798
41.7M
    if (c < 0x80) {
1799
24.0M
        n = c + 1;
1800
77.6M
        for (i = 0; i < n; ++i) {
1801
53.5M
            buf[i] = (char)str->getChar();
1802
53.5M
        }
1803
24.0M
    } else {
1804
17.6M
        n = 0x101 - c;
1805
17.6M
        c = str->getChar();
1806
476M
        for (i = 0; i < n; ++i) {
1807
458M
            buf[i] = (char)c;
1808
458M
        }
1809
17.6M
    }
1810
41.7M
    bufPtr = buf;
1811
41.7M
    bufEnd = buf + n;
1812
41.7M
    return true;
1813
41.7M
}
1814
1815
//------------------------------------------------------------------------
1816
// CCITTFaxStream
1817
//------------------------------------------------------------------------
1818
1819
126k
CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, bool endOfLineA, bool byteAlignA, int columnsA, int rowsA, bool endOfBlockA, bool blackA, int damagedRowsBeforeErrorA) : FilterStream(strA)
1820
126k
{
1821
126k
    encoding = encodingA;
1822
126k
    endOfLine = endOfLineA;
1823
126k
    byteAlign = byteAlignA;
1824
126k
    columns = columnsA;
1825
126k
    damagedRowsBeforeError = damagedRowsBeforeErrorA;
1826
126k
    if (columns < 1) {
1827
3.40k
        columns = 1;
1828
122k
    } else if (columns > INT_MAX - 2) {
1829
1.16k
        columns = INT_MAX - 2;
1830
1.16k
    }
1831
126k
    rows = rowsA;
1832
126k
    endOfBlock = endOfBlockA;
1833
126k
    black = blackA;
1834
    // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
1835
    // ---> max codingLine size = columns + 1
1836
    // refLine has one extra guard entry at the end
1837
    // ---> max refLine size = columns + 2
1838
126k
    codingLine = (int *)gmallocn_checkoverflow(columns + 1, sizeof(int));
1839
126k
    refLine = (int *)gmallocn_checkoverflow(columns + 2, sizeof(int));
1840
1841
126k
    if (codingLine != nullptr && refLine != nullptr) {
1842
124k
        eof = false;
1843
124k
        codingLine[0] = columns;
1844
124k
    } else {
1845
1.50k
        eof = true;
1846
1.50k
    }
1847
126k
    row = 0;
1848
126k
    nextLine2D = encoding < 0;
1849
126k
    inputBits = 0;
1850
126k
    a0i = 0;
1851
126k
    outputBits = 0;
1852
1853
126k
    buf = EOF;
1854
126k
}
1855
1856
CCITTFaxStream::~CCITTFaxStream()
1857
126k
{
1858
126k
    delete str;
1859
126k
    gfree(refLine);
1860
126k
    gfree(codingLine);
1861
126k
}
1862
1863
bool CCITTFaxStream::ccittRewind(bool unfiltered)
1864
100k
{
1865
100k
    row = 0;
1866
100k
    nextLine2D = encoding < 0;
1867
100k
    inputBits = 0;
1868
100k
    a0i = 0;
1869
100k
    outputBits = 0;
1870
100k
    buf = EOF;
1871
1872
100k
    if (unfiltered) {
1873
199
        return str->unfilteredRewind();
1874
100k
    } else {
1875
100k
        return str->rewind();
1876
100k
    }
1877
100k
}
1878
1879
bool CCITTFaxStream::unfilteredRewind()
1880
199
{
1881
199
    return ccittRewind(true);
1882
199
}
1883
1884
bool CCITTFaxStream::rewind()
1885
100k
{
1886
100k
    int code1;
1887
1888
100k
    bool rewindSuccess = ccittRewind(false);
1889
1890
100k
    if (codingLine != nullptr && refLine != nullptr) {
1891
100k
        eof = false;
1892
100k
        codingLine[0] = columns;
1893
100k
    } else {
1894
527
        eof = true;
1895
527
    }
1896
1897
    // skip any initial zero bits and end-of-line marker, and get the 2D
1898
    // encoding tag
1899
2.15M
    while ((code1 = lookBits(12)) == 0) {
1900
2.05M
        eatBits(1);
1901
2.05M
    }
1902
100k
    if (code1 == 0x001) {
1903
7.40k
        eatBits(12);
1904
7.40k
        endOfLine = true;
1905
7.40k
    }
1906
100k
    if (encoding > 0) {
1907
37.2k
        nextLine2D = !lookBits(1);
1908
37.2k
        eatBits(1);
1909
37.2k
    }
1910
1911
100k
    return rewindSuccess;
1912
100k
}
1913
1914
inline void CCITTFaxStream::addPixels(int a1, int blackPixels)
1915
88.3M
{
1916
88.3M
    if (a1 > codingLine[a0i]) {
1917
86.9M
        if (a1 > columns) {
1918
2.22M
            error(errSyntaxError, getPos(), "CCITTFax row is wrong length ({0:d})", a1);
1919
2.22M
            err = true;
1920
2.22M
            a1 = columns;
1921
2.22M
        }
1922
86.9M
        if ((a0i & 1) ^ blackPixels) {
1923
82.3M
            ++a0i;
1924
82.3M
        }
1925
86.9M
        codingLine[a0i] = a1;
1926
86.9M
    }
1927
88.3M
}
1928
1929
inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels)
1930
1.96M
{
1931
1.96M
    if (a1 > codingLine[a0i]) {
1932
1.69M
        if (a1 > columns) {
1933
0
            error(errSyntaxError, getPos(), "CCITTFax row is wrong length ({0:d})", a1);
1934
0
            err = true;
1935
0
            a1 = columns;
1936
0
        }
1937
1.69M
        if ((a0i & 1) ^ blackPixels) {
1938
1.47M
            ++a0i;
1939
1.47M
        }
1940
1.69M
        codingLine[a0i] = a1;
1941
1.69M
    } else if (a1 < codingLine[a0i]) {
1942
51.4k
        if (a1 < 0) {
1943
34.6k
            error(errSyntaxError, getPos(), "Invalid CCITTFax code");
1944
34.6k
            err = true;
1945
34.6k
            a1 = columns;
1946
34.6k
        }
1947
58.9k
        while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
1948
7.43k
            --a0i;
1949
7.43k
        }
1950
51.4k
        codingLine[a0i] = a1;
1951
51.4k
    }
1952
1.96M
}
1953
1954
int CCITTFaxStream::lookChar()
1955
173M
{
1956
173M
    int code1, code2, code3;
1957
173M
    int b1i, blackPixels, i, bits;
1958
173M
    bool gotEOL;
1959
1960
173M
    if (buf != EOF) {
1961
16.3k
        return buf;
1962
16.3k
    }
1963
1964
    // read the next row
1965
173M
    if (outputBits == 0) {
1966
1967
        // if at eof just return EOF
1968
15.1M
        if (eof) {
1969
9.45M
            return EOF;
1970
9.45M
        }
1971
1972
5.68M
        err = false;
1973
1974
        // 2-D encoding
1975
5.68M
        if (nextLine2D) {
1976
14.2M
            for (i = 0; i < columns && codingLine[i] < columns; ++i) {
1977
10.4M
                refLine[i] = codingLine[i];
1978
10.4M
            }
1979
526M
            for (; i < columns + 2; ++i) {
1980
522M
                refLine[i] = columns;
1981
522M
            }
1982
3.81M
            codingLine[0] = 0;
1983
3.81M
            a0i = 0;
1984
3.81M
            b1i = 0;
1985
3.81M
            blackPixels = 0;
1986
            // invariant:
1987
            // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
1988
            //                                                             <= columns
1989
            // exception at left edge:
1990
            //   codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
1991
            // exception at right edge:
1992
            //   refLine[b1i] = refLine[b1i+1] = columns is possible
1993
17.7M
            while (codingLine[a0i] < columns && !err) {
1994
13.9M
                code1 = getTwoDimCode();
1995
13.9M
                switch (code1) {
1996
625k
                case twoDimPass:
1997
625k
                    if (likely(b1i + 1 < columns + 2)) {
1998
623k
                        addPixels(refLine[b1i + 1], blackPixels);
1999
623k
                        if (refLine[b1i + 1] < columns) {
2000
454k
                            b1i += 2;
2001
454k
                        }
2002
623k
                    }
2003
625k
                    break;
2004
918k
                case twoDimHoriz:
2005
918k
                    code1 = code2 = 0;
2006
918k
                    if (blackPixels) {
2007
407k
                        do {
2008
407k
                            code1 += code3 = getBlackCode();
2009
407k
                        } while (code3 >= 64);
2010
431k
                        do {
2011
431k
                            code2 += code3 = getWhiteCode();
2012
431k
                        } while (code3 >= 64);
2013
522k
                    } else {
2014
551k
                        do {
2015
551k
                            code1 += code3 = getWhiteCode();
2016
551k
                        } while (code3 >= 64);
2017
536k
                        do {
2018
536k
                            code2 += code3 = getBlackCode();
2019
536k
                        } while (code3 >= 64);
2020
522k
                    }
2021
918k
                    addPixels(codingLine[a0i] + code1, blackPixels);
2022
918k
                    if (codingLine[a0i] < columns) {
2023
733k
                        addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
2024
733k
                    }
2025
1.19M
                    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2026
280k
                        b1i += 2;
2027
280k
                        if (unlikely(b1i > columns + 1)) {
2028
0
                            error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2029
0
                            err = true;
2030
0
                            break;
2031
0
                        }
2032
280k
                    }
2033
918k
                    break;
2034
146k
                case twoDimVertR3:
2035
146k
                    if (unlikely(b1i > columns + 1)) {
2036
0
                        error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2037
0
                        err = true;
2038
0
                        break;
2039
0
                    }
2040
146k
                    addPixels(refLine[b1i] + 3, blackPixels);
2041
146k
                    blackPixels ^= 1;
2042
146k
                    if (codingLine[a0i] < columns) {
2043
76.5k
                        ++b1i;
2044
80.2k
                        while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2045
3.73k
                            b1i += 2;
2046
3.73k
                            if (unlikely(b1i > columns + 1)) {
2047
0
                                error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2048
0
                                err = true;
2049
0
                                break;
2050
0
                            }
2051
3.73k
                        }
2052
76.5k
                    }
2053
146k
                    break;
2054
252k
                case twoDimVertR2:
2055
252k
                    if (unlikely(b1i > columns + 1)) {
2056
0
                        error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2057
0
                        err = true;
2058
0
                        break;
2059
0
                    }
2060
252k
                    addPixels(refLine[b1i] + 2, blackPixels);
2061
252k
                    blackPixels ^= 1;
2062
252k
                    if (codingLine[a0i] < columns) {
2063
198k
                        ++b1i;
2064
215k
                        while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2065
17.2k
                            b1i += 2;
2066
17.2k
                            if (unlikely(b1i > columns + 1)) {
2067
0
                                error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2068
0
                                err = true;
2069
0
                                break;
2070
0
                            }
2071
17.2k
                        }
2072
198k
                    }
2073
252k
                    break;
2074
1.06M
                case twoDimVertR1:
2075
1.06M
                    if (unlikely(b1i > columns + 1)) {
2076
0
                        error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2077
0
                        err = true;
2078
0
                        break;
2079
0
                    }
2080
1.06M
                    addPixels(refLine[b1i] + 1, blackPixels);
2081
1.06M
                    blackPixels ^= 1;
2082
1.06M
                    if (codingLine[a0i] < columns) {
2083
835k
                        ++b1i;
2084
903k
                        while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2085
67.8k
                            b1i += 2;
2086
67.8k
                            if (unlikely(b1i > columns + 1)) {
2087
0
                                error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2088
0
                                err = true;
2089
0
                                break;
2090
0
                            }
2091
67.8k
                        }
2092
835k
                    }
2093
1.06M
                    break;
2094
8.99M
                case twoDimVert0:
2095
8.99M
                    if (unlikely(b1i > columns + 1)) {
2096
0
                        error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2097
0
                        err = true;
2098
0
                        break;
2099
0
                    }
2100
8.99M
                    addPixels(refLine[b1i], blackPixels);
2101
8.99M
                    blackPixels ^= 1;
2102
8.99M
                    if (codingLine[a0i] < columns) {
2103
6.03M
                        ++b1i;
2104
6.03M
                        while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2105
0
                            b1i += 2;
2106
0
                            if (unlikely(b1i > columns + 1)) {
2107
0
                                error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2108
0
                                err = true;
2109
0
                                break;
2110
0
                            }
2111
0
                        }
2112
6.03M
                    }
2113
8.99M
                    break;
2114
167k
                case twoDimVertL3:
2115
167k
                    if (unlikely(b1i > columns + 1)) {
2116
0
                        error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2117
0
                        err = true;
2118
0
                        break;
2119
0
                    }
2120
167k
                    addPixelsNeg(refLine[b1i] - 3, blackPixels);
2121
167k
                    blackPixels ^= 1;
2122
167k
                    if (codingLine[a0i] < columns) {
2123
164k
                        if (b1i > 0) {
2124
149k
                            --b1i;
2125
149k
                        } else {
2126
15.4k
                            ++b1i;
2127
15.4k
                        }
2128
266k
                        while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2129
101k
                            b1i += 2;
2130
101k
                            if (unlikely(b1i > columns + 1)) {
2131
0
                                error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2132
0
                                err = true;
2133
0
                                break;
2134
0
                            }
2135
101k
                        }
2136
164k
                    }
2137
167k
                    break;
2138
358k
                case twoDimVertL2:
2139
358k
                    if (unlikely(b1i > columns + 1)) {
2140
0
                        error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2141
0
                        err = true;
2142
0
                        break;
2143
0
                    }
2144
358k
                    addPixelsNeg(refLine[b1i] - 2, blackPixels);
2145
358k
                    blackPixels ^= 1;
2146
358k
                    if (codingLine[a0i] < columns) {
2147
339k
                        if (b1i > 0) {
2148
321k
                            --b1i;
2149
321k
                        } else {
2150
18.3k
                            ++b1i;
2151
18.3k
                        }
2152
626k
                        while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2153
287k
                            b1i += 2;
2154
287k
                            if (unlikely(b1i > columns + 1)) {
2155
0
                                error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2156
0
                                err = true;
2157
0
                                break;
2158
0
                            }
2159
287k
                        }
2160
339k
                    }
2161
358k
                    break;
2162
1.43M
                case twoDimVertL1:
2163
1.43M
                    if (unlikely(b1i > columns + 1)) {
2164
0
                        error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2165
0
                        err = true;
2166
0
                        break;
2167
0
                    }
2168
1.43M
                    addPixelsNeg(refLine[b1i] - 1, blackPixels);
2169
1.43M
                    blackPixels ^= 1;
2170
1.43M
                    if (codingLine[a0i] < columns) {
2171
1.42M
                        if (b1i > 0) {
2172
1.17M
                            --b1i;
2173
1.17M
                        } else {
2174
250k
                            ++b1i;
2175
250k
                        }
2176
2.55M
                        while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2177
1.12M
                            b1i += 2;
2178
1.12M
                            if (unlikely(b1i > columns + 1)) {
2179
0
                                error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2180
0
                                err = true;
2181
0
                                break;
2182
0
                            }
2183
1.12M
                        }
2184
1.42M
                    }
2185
1.43M
                    break;
2186
13.8k
                case EOF:
2187
13.8k
                    addPixels(columns, 0);
2188
13.8k
                    eof = true;
2189
13.8k
                    break;
2190
0
                default:
2191
0
                    error(errSyntaxError, getPos(), "Bad 2D code {0:04x} in CCITTFax stream", code1);
2192
0
                    addPixels(columns, 0);
2193
0
                    err = true;
2194
0
                    break;
2195
13.9M
                }
2196
13.9M
            }
2197
2198
            // 1-D encoding
2199
3.81M
        } else {
2200
1.87M
            codingLine[0] = 0;
2201
1.87M
            a0i = 0;
2202
1.87M
            blackPixels = 0;
2203
77.4M
            while (codingLine[a0i] < columns) {
2204
75.6M
                code1 = 0;
2205
75.6M
                if (blackPixels) {
2206
37.0M
                    do {
2207
37.0M
                        code1 += code3 = getBlackCode();
2208
37.0M
                    } while (code3 >= 64);
2209
38.5M
                } else {
2210
44.6M
                    do {
2211
44.6M
                        code1 += code3 = getWhiteCode();
2212
44.6M
                    } while (code3 >= 64);
2213
38.5M
                }
2214
75.6M
                addPixels(codingLine[a0i] + code1, blackPixels);
2215
75.6M
                blackPixels ^= 1;
2216
75.6M
            }
2217
1.87M
        }
2218
2219
        // check for end-of-line marker, skipping over any extra zero bits
2220
        // (if EncodedByteAlign is true and EndOfLine is false, there can
2221
        // be "false" EOL markers -- i.e., if the last n unused bits in
2222
        // row i are set to zero, and the first 11-n bits in row i+1
2223
        // happen to be zero -- so we don't look for EOL markers in this
2224
        // case)
2225
5.68M
        gotEOL = false;
2226
5.68M
        if (!endOfBlock && row == rows - 1) {
2227
3.41k
            eof = true;
2228
5.67M
        } else if (endOfLine || !byteAlign) {
2229
5.67M
            code1 = lookBits(12);
2230
5.67M
            if (endOfLine) {
2231
19.6M
                while (code1 != EOF && code1 != 0x001) {
2232
19.5M
                    eatBits(1);
2233
19.5M
                    code1 = lookBits(12);
2234
19.5M
                }
2235
5.64M
            } else {
2236
11.8M
                while (code1 == 0) {
2237
6.22M
                    eatBits(1);
2238
6.22M
                    code1 = lookBits(12);
2239
6.22M
                }
2240
5.64M
            }
2241
5.67M
            if (code1 == 0x001) {
2242
107k
                eatBits(12);
2243
107k
                gotEOL = true;
2244
107k
            }
2245
5.67M
        }
2246
2247
        // byte-align the row
2248
        // (Adobe apparently doesn't do byte alignment after EOL markers
2249
        // -- I've seen CCITT image data streams in two different formats,
2250
        // both with the byteAlign flag set:
2251
        //   1. xx:x0:01:yy:yy
2252
        //   2. xx:00:1y:yy:yy
2253
        // where xx is the previous line, yy is the next line, and colons
2254
        // separate bytes.)
2255
5.68M
        if (byteAlign && !gotEOL) {
2256
0
            inputBits &= ~7;
2257
0
        }
2258
2259
        // check for end of stream
2260
5.68M
        if (lookBits(1) == EOF) {
2261
19.3k
            eof = true;
2262
19.3k
        }
2263
2264
        // get 2D encoding tag
2265
5.68M
        if (!eof && encoding > 0) {
2266
618k
            nextLine2D = !lookBits(1);
2267
618k
            eatBits(1);
2268
618k
        }
2269
2270
        // check for end-of-block marker
2271
5.68M
        if (endOfBlock && !endOfLine && byteAlign) {
2272
            // in this case, we didn't check for an EOL code above, so we
2273
            // need to check here
2274
0
            code1 = lookBits(24);
2275
0
            if (code1 == 0x001001) {
2276
0
                eatBits(12);
2277
0
                gotEOL = true;
2278
0
            }
2279
0
        }
2280
5.68M
        if (endOfBlock && gotEOL) {
2281
97.1k
            code1 = lookBits(12);
2282
97.1k
            if (code1 == 0x001) {
2283
33.2k
                eatBits(12);
2284
33.2k
                if (encoding > 0) {
2285
1.70k
                    lookBits(1);
2286
1.70k
                    eatBits(1);
2287
1.70k
                }
2288
33.2k
                if (encoding >= 0) {
2289
31.9k
                    for (i = 0; i < 4; ++i) {
2290
25.5k
                        code1 = lookBits(12);
2291
25.5k
                        if (code1 != 0x001) {
2292
24.4k
                            error(errSyntaxError, getPos(), "Bad RTC code in CCITTFax stream");
2293
24.4k
                        }
2294
25.5k
                        eatBits(12);
2295
25.5k
                        if (encoding > 0) {
2296
6.81k
                            lookBits(1);
2297
6.81k
                            eatBits(1);
2298
6.81k
                        }
2299
25.5k
                    }
2300
6.39k
                }
2301
33.2k
                eof = true;
2302
33.2k
            }
2303
2304
            // look for an end-of-line marker after an error -- we only do
2305
            // this if we know the stream contains end-of-line markers because
2306
            // the "just plow on" technique tends to work better otherwise
2307
5.58M
        } else if (err && endOfLine) {
2308
3.04M
            while (true) {
2309
3.04M
                code1 = lookBits(13);
2310
3.04M
                if (code1 == EOF) {
2311
2.70k
                    eof = true;
2312
2.70k
                    return EOF;
2313
2.70k
                }
2314
3.04M
                if ((code1 >> 1) == 0x001) {
2315
4.05k
                    break;
2316
4.05k
                }
2317
3.03M
                eatBits(1);
2318
3.03M
            }
2319
4.05k
            eatBits(12);
2320
4.05k
            if (encoding > 0) {
2321
1.09k
                eatBits(1);
2322
1.09k
                nextLine2D = !(code1 & 1);
2323
1.09k
            }
2324
4.05k
        }
2325
2326
        // set up for output
2327
5.67M
        if (codingLine[0] > 0) {
2328
4.23M
            outputBits = codingLine[a0i = 0];
2329
4.23M
        } else {
2330
1.44M
            outputBits = codingLine[a0i = 1];
2331
1.44M
        }
2332
2333
5.67M
        ++row;
2334
5.67M
    }
2335
2336
    // get a byte
2337
164M
    if (outputBits >= 8) {
2338
138M
        buf = (a0i & 1) ? 0x00 : 0xff;
2339
138M
        outputBits -= 8;
2340
138M
        if (outputBits == 0 && codingLine[a0i] < columns) {
2341
1.24M
            ++a0i;
2342
1.24M
            outputBits = codingLine[a0i] - codingLine[a0i - 1];
2343
1.24M
        }
2344
138M
    } else {
2345
25.9M
        bits = 8;
2346
25.9M
        buf = 0;
2347
63.2M
        do {
2348
63.2M
            if (outputBits > bits) {
2349
15.6M
                buf <<= bits;
2350
15.6M
                if (!(a0i & 1)) {
2351
9.10M
                    buf |= 0xff >> (8 - bits);
2352
9.10M
                }
2353
15.6M
                outputBits -= bits;
2354
15.6M
                bits = 0;
2355
47.6M
            } else {
2356
47.6M
                buf <<= outputBits;
2357
47.6M
                if (!(a0i & 1)) {
2358
24.0M
                    buf |= 0xff >> (8 - outputBits);
2359
24.0M
                }
2360
47.6M
                bits -= outputBits;
2361
47.6M
                outputBits = 0;
2362
47.6M
                if (codingLine[a0i] < columns) {
2363
43.0M
                    ++a0i;
2364
43.0M
                    if (unlikely(a0i > columns)) {
2365
0
                        error(errSyntaxError, getPos(), "Bad bits {0:04x} in CCITTFax stream", bits);
2366
0
                        err = true;
2367
0
                        break;
2368
0
                    }
2369
43.0M
                    outputBits = codingLine[a0i] - codingLine[a0i - 1];
2370
43.0M
                } else if (bits > 0) {
2371
3.94M
                    buf <<= bits;
2372
3.94M
                    bits = 0;
2373
3.94M
                }
2374
47.6M
            }
2375
63.2M
        } while (bits);
2376
25.9M
    }
2377
164M
    if (black) {
2378
163k
        buf ^= 0xff;
2379
163k
    }
2380
164M
    return buf;
2381
173M
}
2382
2383
short CCITTFaxStream::getTwoDimCode()
2384
13.9M
{
2385
13.9M
    int code;
2386
13.9M
    const CCITTCode *p;
2387
13.9M
    int n;
2388
2389
13.9M
    code = 0; // make gcc happy
2390
13.9M
    if (endOfBlock) {
2391
13.6M
        if ((code = lookBits(7)) != EOF) {
2392
13.6M
            p = &twoDimTab1[code];
2393
13.6M
            if (p->bits > 0) {
2394
13.6M
                eatBits(p->bits);
2395
13.6M
                return p->n;
2396
13.6M
            }
2397
13.6M
        }
2398
13.6M
    } else {
2399
689k
        for (n = 1; n <= 7; ++n) {
2400
687k
            if ((code = lookBits(n)) == EOF) {
2401
956
                break;
2402
956
            }
2403
686k
            if (n < 7) {
2404
666k
                code <<= 7 - n;
2405
666k
            }
2406
686k
            p = &twoDimTab1[code];
2407
686k
            if (p->bits == n) {
2408
285k
                eatBits(n);
2409
285k
                return p->n;
2410
285k
            }
2411
686k
        }
2412
288k
    }
2413
13.8k
    error(errSyntaxError, getPos(), "Bad two dim code ({0:04x}) in CCITTFax stream", code);
2414
13.8k
    return EOF;
2415
13.9M
}
2416
2417
short CCITTFaxStream::getWhiteCode()
2418
45.6M
{
2419
45.6M
    short code;
2420
45.6M
    const CCITTCode *p;
2421
45.6M
    int n;
2422
2423
45.6M
    code = 0; // make gcc happy
2424
45.6M
    if (endOfBlock) {
2425
31.7M
        code = lookBits(12);
2426
31.7M
        if (code == EOF) {
2427
10.3M
            return 1;
2428
10.3M
        }
2429
21.4M
        if ((code >> 5) == 0) {
2430
1.20M
            p = &whiteTab1[code];
2431
20.1M
        } else {
2432
20.1M
            p = &whiteTab2[code >> 3];
2433
20.1M
        }
2434
21.4M
        if (p->bits > 0) {
2435
20.2M
            eatBits(p->bits);
2436
20.2M
            return p->n;
2437
20.2M
        }
2438
21.4M
    } else {
2439
21.5M
        for (n = 1; n <= 9; ++n) {
2440
21.3M
            code = lookBits(n);
2441
21.3M
            if (code == EOF) {
2442
12.4M
                return 1;
2443
12.4M
            }
2444
8.91M
            if (n < 9) {
2445
8.71M
                code <<= 9 - n;
2446
8.71M
            }
2447
8.91M
            p = &whiteTab2[code];
2448
8.91M
            if (p->bits == n) {
2449
1.27M
                eatBits(n);
2450
1.27M
                return p->n;
2451
1.27M
            }
2452
8.91M
        }
2453
470k
        for (n = 11; n <= 12; ++n) {
2454
321k
            code = lookBits(n);
2455
321k
            if (code == EOF) {
2456
0
                return 1;
2457
0
            }
2458
321k
            if (n < 12) {
2459
163k
                code <<= 12 - n;
2460
163k
            }
2461
321k
            p = &whiteTab1[code];
2462
321k
            if (p->bits == n) {
2463
14.7k
                eatBits(n);
2464
14.7k
                return p->n;
2465
14.7k
            }
2466
321k
        }
2467
163k
    }
2468
1.31M
    error(errSyntaxError, getPos(), "Bad white code ({0:04x}) in CCITTFax stream", code);
2469
    // eat a bit and return a positive number so that the caller doesn't
2470
    // go into an infinite loop
2471
1.31M
    eatBits(1);
2472
1.31M
    return 1;
2473
45.6M
}
2474
2475
short CCITTFaxStream::getBlackCode()
2476
38.0M
{
2477
38.0M
    short code;
2478
38.0M
    const CCITTCode *p;
2479
38.0M
    int n;
2480
2481
38.0M
    code = 0; // make gcc happy
2482
38.0M
    if (endOfBlock) {
2483
24.7M
        code = lookBits(13);
2484
24.7M
        if (code == EOF) {
2485
10.3M
            return 1;
2486
10.3M
        }
2487
14.3M
        if ((code >> 7) == 0) {
2488
1.27M
            p = &blackTab1[code];
2489
13.0M
        } else if ((code >> 9) == 0 && (code >> 7) != 0) {
2490
422k
            p = &blackTab2[(code >> 1) - 64];
2491
12.6M
        } else {
2492
12.6M
            p = &blackTab3[code >> 7];
2493
12.6M
        }
2494
14.3M
        if (p->bits > 0) {
2495
13.2M
            eatBits(p->bits);
2496
13.2M
            return p->n;
2497
13.2M
        }
2498
14.3M
    } else {
2499
14.7M
        for (n = 2; n <= 6; ++n) {
2500
14.5M
            code = lookBits(n);
2501
14.5M
            if (code == EOF) {
2502
12.4M
                return 1;
2503
12.4M
            }
2504
2.12M
            if (n < 6) {
2505
1.90M
                code <<= 6 - n;
2506
1.90M
            }
2507
2.12M
            p = &blackTab3[code];
2508
2.12M
            if (p->bits == n) {
2509
659k
                eatBits(n);
2510
659k
                return p->n;
2511
659k
            }
2512
2.12M
        }
2513
1.25M
        for (n = 7; n <= 12; ++n) {
2514
1.09M
            code = lookBits(n);
2515
1.09M
            if (code == EOF) {
2516
0
                return 1;
2517
0
            }
2518
1.09M
            if (n < 12) {
2519
919k
                code <<= 12 - n;
2520
919k
            }
2521
1.09M
            if (code >= 64) {
2522
105k
                p = &blackTab2[code - 64];
2523
105k
                if (p->bits == n) {
2524
38.3k
                    eatBits(n);
2525
38.3k
                    return p->n;
2526
38.3k
                }
2527
105k
            }
2528
1.09M
        }
2529
765k
        for (n = 10; n <= 13; ++n) {
2530
623k
            code = lookBits(n);
2531
623k
            if (code == EOF) {
2532
0
                return 1;
2533
0
            }
2534
623k
            if (n < 13) {
2535
479k
                code <<= 13 - n;
2536
479k
            }
2537
623k
            p = &blackTab1[code];
2538
623k
            if (p->bits == n) {
2539
21.4k
                eatBits(n);
2540
21.4k
                return p->n;
2541
21.4k
            }
2542
623k
        }
2543
164k
    }
2544
1.28M
    error(errSyntaxError, getPos(), "Bad black code ({0:04x}) in CCITTFax stream", code);
2545
    // eat a bit and return a positive number so that the caller doesn't
2546
    // go into an infinite loop
2547
1.28M
    eatBits(1);
2548
1.28M
    return 1;
2549
38.0M
}
2550
2551
short CCITTFaxStream::lookBits(int n)
2552
152M
{
2553
152M
    int c;
2554
2555
178M
    while (inputBits < n) {
2556
72.7M
        if ((c = str->getChar()) == EOF) {
2557
45.8M
            if (inputBits == 0) {
2558
45.7M
                return EOF;
2559
45.7M
            }
2560
            // near the end of the stream, the caller may ask for more bits
2561
            // than are available, but there may still be a valid code in
2562
            // however many bits are available -- we need to return correct
2563
            // data in this case
2564
147k
            return (inputBuf << (n - inputBits)) & (0xffffffff >> (32 - n));
2565
45.8M
        }
2566
26.8M
        inputBuf = (inputBuf << 8) + c;
2567
26.8M
        inputBits += 8;
2568
26.8M
    }
2569
106M
    return (inputBuf >> (inputBits - n)) & (0xffffffff >> (32 - n));
2570
152M
}
2571
2572
std::optional<std::string> CCITTFaxStream::getPSFilter(int psLevel, const char *indent)
2573
5.73k
{
2574
5.73k
    std::optional<std::string> s;
2575
5.73k
    char s1[50];
2576
2577
5.73k
    if (psLevel < 2) {
2578
0
        return {};
2579
0
    }
2580
5.73k
    if (!(s = str->getPSFilter(psLevel, indent))) {
2581
0
        return {};
2582
0
    }
2583
5.73k
    s->append(indent).append("<< ");
2584
5.73k
    if (encoding != 0) {
2585
5.66k
        sprintf(s1, "/K %d ", encoding);
2586
5.66k
        s->append(s1);
2587
5.66k
    }
2588
5.73k
    if (endOfLine) {
2589
3
        s->append("/EndOfLine true ");
2590
3
    }
2591
5.73k
    if (byteAlign) {
2592
0
        s->append("/EncodedByteAlign true ");
2593
0
    }
2594
5.73k
    sprintf(s1, "/Columns %d ", columns);
2595
5.73k
    s->append(s1);
2596
5.73k
    if (rows != 0) {
2597
33
        sprintf(s1, "/Rows %d ", rows);
2598
33
        s->append(s1);
2599
33
    }
2600
5.73k
    if (!endOfBlock) {
2601
0
        s->append("/EndOfBlock false ");
2602
0
    }
2603
5.73k
    if (black) {
2604
12
        s->append("/BlackIs1 true ");
2605
12
    }
2606
5.73k
    s->append(">> /CCITTFaxDecode filter\n");
2607
5.73k
    return s;
2608
5.73k
}
2609
2610
bool CCITTFaxStream::isBinary(bool /*last*/) const
2611
69
{
2612
69
    return str->isBinary(true);
2613
69
}
2614
2615
#if !ENABLE_LIBJPEG
2616
2617
//------------------------------------------------------------------------
2618
// DCTStream
2619
//------------------------------------------------------------------------
2620
2621
// IDCT constants (20.12 fixed point format)
2622
0
#    define dctCos1 4017 // cos(pi/16)
2623
0
#    define dctSin1 799 // sin(pi/16)
2624
0
#    define dctCos3 3406 // cos(3*pi/16)
2625
0
#    define dctSin3 2276 // sin(3*pi/16)
2626
0
#    define dctCos6 1567 // cos(6*pi/16)
2627
0
#    define dctSin6 3784 // sin(6*pi/16)
2628
0
#    define dctSqrt2 5793 // sqrt(2)
2629
0
#    define dctSqrt1d2 2896 // sqrt(2) / 2
2630
2631
// color conversion parameters (16.16 fixed point format)
2632
0
#    define dctCrToR 91881 //  1.4020
2633
0
#    define dctCbToG -22553 // -0.3441363
2634
0
#    define dctCrToG -46802 // -0.71413636
2635
0
#    define dctCbToB 116130 //  1.772
2636
2637
// clip [-256,511] --> [0,255]
2638
0
#    define dctClipOffset 256
2639
#    define dctClipLength 768
2640
static unsigned char dctClip[dctClipLength];
2641
static int dctClipInit = 0;
2642
2643
// zig zag decode map
2644
static const int dctZigZag[64] = { 0,  1,  8,  16, 9,  2,  3,  10, 17, 24, 32, 25, 18, 11, 4,  5,  12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6,  7,  14, 21, 28,
2645
                                   35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 };
2646
2647
0
DCTStream::DCTStream(Stream *strA, int colorXformA, Dict * /*dict*/, int /*recursion*/) : FilterStream(strA)
2648
0
{
2649
0
    int i, j;
2650
2651
0
    colorXform = colorXformA;
2652
0
    progressive = interleaved = false;
2653
0
    width = height = 0;
2654
0
    mcuWidth = mcuHeight = 0;
2655
0
    numComps = 0;
2656
0
    comp = 0;
2657
0
    x = y = dy = 0;
2658
0
    for (i = 0; i < 4; ++i) {
2659
0
        for (j = 0; j < 32; ++j) {
2660
0
            rowBuf[i][j] = nullptr;
2661
0
        }
2662
0
        frameBuf[i] = nullptr;
2663
0
    }
2664
2665
0
    if (!dctClipInit) {
2666
0
        for (i = -256; i < 0; ++i)
2667
0
            dctClip[dctClipOffset + i] = 0;
2668
0
        for (i = 0; i < 256; ++i)
2669
0
            dctClip[dctClipOffset + i] = i;
2670
0
        for (i = 256; i < 512; ++i)
2671
0
            dctClip[dctClipOffset + i] = 255;
2672
0
        dctClipInit = 1;
2673
0
    }
2674
0
}
2675
2676
DCTStream::~DCTStream()
2677
0
{
2678
0
    close();
2679
0
    delete str;
2680
0
}
2681
2682
bool DCTStream::dctRewind(bool unfiltered)
2683
0
{
2684
0
    progressive = interleaved = false;
2685
0
    width = height = 0;
2686
0
    numComps = 0;
2687
0
    numQuantTables = 0;
2688
0
    numDCHuffTables = 0;
2689
0
    numACHuffTables = 0;
2690
0
    gotJFIFMarker = false;
2691
0
    gotAdobeMarker = false;
2692
0
    restartInterval = 0;
2693
0
    if (unfiltered)
2694
0
        return str->unfilteredRewind();
2695
0
    else
2696
0
        return str->rewind();
2697
0
}
2698
2699
bool DCTStream::unfilteredRewind()
2700
0
{
2701
0
    return dctRewind(true);
2702
0
}
2703
2704
bool DCTStream::rewind()
2705
0
{
2706
0
    int i, j;
2707
2708
0
    bool resetResult = dctRewind(false);
2709
2710
0
    if (!readHeader()) {
2711
0
        y = height;
2712
0
        return false;
2713
0
    }
2714
2715
    // compute MCU size
2716
0
    if (numComps == 1) {
2717
0
        compInfo[0].hSample = compInfo[0].vSample = 1;
2718
0
    }
2719
0
    mcuWidth = compInfo[0].hSample;
2720
0
    mcuHeight = compInfo[0].vSample;
2721
0
    for (i = 1; i < numComps; ++i) {
2722
0
        if (compInfo[i].hSample > mcuWidth) {
2723
0
            mcuWidth = compInfo[i].hSample;
2724
0
        }
2725
0
        if (compInfo[i].vSample > mcuHeight) {
2726
0
            mcuHeight = compInfo[i].vSample;
2727
0
        }
2728
0
    }
2729
0
    mcuWidth *= 8;
2730
0
    mcuHeight *= 8;
2731
2732
    // figure out color transform
2733
0
    if (colorXform == -1) {
2734
0
        if (numComps == 3) {
2735
0
            if (gotJFIFMarker) {
2736
0
                colorXform = 1;
2737
0
            } else if (compInfo[0].id == 82 && compInfo[1].id == 71 && compInfo[2].id == 66) { // ASCII "RGB"
2738
0
                colorXform = 0;
2739
0
            } else {
2740
0
                colorXform = 1;
2741
0
            }
2742
0
        } else {
2743
0
            colorXform = 0;
2744
0
        }
2745
0
    }
2746
2747
0
    if (progressive || !interleaved) {
2748
2749
        // allocate a buffer for the whole image
2750
0
        bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2751
0
        bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
2752
0
        if (bufWidth <= 0 || bufHeight <= 0 || bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
2753
0
            error(errSyntaxError, getPos(), "Invalid image size in DCT stream");
2754
0
            y = height;
2755
0
            return false;
2756
0
        }
2757
0
        for (i = 0; i < numComps; ++i) {
2758
0
            frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
2759
0
            memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
2760
0
        }
2761
2762
        // read the image data
2763
0
        do {
2764
0
            restartMarker = 0xd0;
2765
0
            restart();
2766
0
            readScan();
2767
0
        } while (readHeader());
2768
2769
        // decode
2770
0
        decodeImage();
2771
2772
        // initialize counters
2773
0
        comp = 0;
2774
0
        x = 0;
2775
0
        y = 0;
2776
2777
0
    } else {
2778
2779
        // allocate a buffer for one row of MCUs
2780
0
        bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2781
0
        for (i = 0; i < numComps; ++i) {
2782
0
            for (j = 0; j < mcuHeight; ++j) {
2783
0
                rowBuf[i][j] = (unsigned char *)gmallocn(bufWidth, sizeof(unsigned char));
2784
0
            }
2785
0
        }
2786
2787
        // initialize counters
2788
0
        comp = 0;
2789
0
        x = 0;
2790
0
        y = 0;
2791
0
        dy = mcuHeight;
2792
2793
0
        restartMarker = 0xd0;
2794
0
        restart();
2795
0
    }
2796
2797
0
    return resetResult;
2798
0
}
2799
2800
void DCTStream::close()
2801
0
{
2802
0
    int i, j;
2803
2804
0
    for (i = 0; i < 4; ++i) {
2805
0
        for (j = 0; j < 32; ++j) {
2806
0
            gfree(rowBuf[i][j]);
2807
0
            rowBuf[i][j] = nullptr;
2808
0
        }
2809
0
        gfree(frameBuf[i]);
2810
0
        frameBuf[i] = nullptr;
2811
0
    }
2812
0
    FilterStream::close();
2813
0
}
2814
2815
int DCTStream::getChar()
2816
0
{
2817
0
    int c;
2818
2819
0
    if (y >= height) {
2820
0
        return EOF;
2821
0
    }
2822
0
    if (progressive || !interleaved) {
2823
0
        c = frameBuf[comp][y * bufWidth + x];
2824
0
        if (++comp == numComps) {
2825
0
            comp = 0;
2826
0
            if (++x == width) {
2827
0
                x = 0;
2828
0
                ++y;
2829
0
            }
2830
0
        }
2831
0
    } else {
2832
0
        if (dy >= mcuHeight) {
2833
0
            if (!readMCURow()) {
2834
0
                y = height;
2835
0
                return EOF;
2836
0
            }
2837
0
            comp = 0;
2838
0
            x = 0;
2839
0
            dy = 0;
2840
0
        }
2841
0
        c = rowBuf[comp][dy][x];
2842
0
        if (++comp == numComps) {
2843
0
            comp = 0;
2844
0
            if (++x == width) {
2845
0
                x = 0;
2846
0
                ++y;
2847
0
                ++dy;
2848
0
                if (y == height) {
2849
0
                    readTrailer();
2850
0
                }
2851
0
            }
2852
0
        }
2853
0
    }
2854
0
    return c;
2855
0
}
2856
2857
int DCTStream::lookChar()
2858
0
{
2859
0
    if (y >= height) {
2860
0
        return EOF;
2861
0
    }
2862
0
    if (progressive || !interleaved) {
2863
0
        return frameBuf[comp][y * bufWidth + x];
2864
0
    } else {
2865
0
        if (dy >= mcuHeight) {
2866
0
            if (!readMCURow()) {
2867
0
                y = height;
2868
0
                return EOF;
2869
0
            }
2870
0
            comp = 0;
2871
0
            x = 0;
2872
0
            dy = 0;
2873
0
        }
2874
0
        return rowBuf[comp][dy][x];
2875
0
    }
2876
0
}
2877
2878
void DCTStream::restart()
2879
0
{
2880
0
    int i;
2881
2882
0
    inputBits = 0;
2883
0
    restartCtr = restartInterval;
2884
0
    for (i = 0; i < numComps; ++i) {
2885
0
        compInfo[i].prevDC = 0;
2886
0
    }
2887
0
    eobRun = 0;
2888
0
}
2889
2890
// Read one row of MCUs from a sequential JPEG stream.
2891
bool DCTStream::readMCURow()
2892
0
{
2893
0
    int data1[64];
2894
0
    unsigned char data2[64];
2895
0
    unsigned char *p1, *p2;
2896
0
    int pY, pCb, pCr, pR, pG, pB;
2897
0
    int h, v, horiz, vert, hSub, vSub;
2898
0
    int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2899
0
    int c;
2900
2901
0
    for (x1 = 0; x1 < width; x1 += mcuWidth) {
2902
2903
        // deal with restart marker
2904
0
        if (restartInterval > 0 && restartCtr == 0) {
2905
0
            c = readMarker();
2906
0
            if (c != restartMarker) {
2907
0
                error(errSyntaxError, getPos(), "Bad DCT data: incorrect restart marker");
2908
0
                return false;
2909
0
            }
2910
0
            if (++restartMarker == 0xd8)
2911
0
                restartMarker = 0xd0;
2912
0
            restart();
2913
0
        }
2914
2915
        // read one MCU
2916
0
        for (cc = 0; cc < numComps; ++cc) {
2917
0
            h = compInfo[cc].hSample;
2918
0
            v = compInfo[cc].vSample;
2919
0
            horiz = mcuWidth / h;
2920
0
            vert = mcuHeight / v;
2921
0
            hSub = horiz / 8;
2922
0
            vSub = vert / 8;
2923
0
            for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2924
0
                for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2925
0
                    if (unlikely(scanInfo.dcHuffTable[cc] >= 4) || unlikely(scanInfo.acHuffTable[cc] >= 4)) {
2926
0
                        return false;
2927
0
                    }
2928
0
                    if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], &acHuffTables[scanInfo.acHuffTable[cc]], &compInfo[cc].prevDC, data1)) {
2929
0
                        return false;
2930
0
                    }
2931
0
                    transformDataUnit(quantTables[compInfo[cc].quantTable], data1, data2);
2932
0
                    if (hSub == 1 && vSub == 1) {
2933
0
                        for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2934
0
                            p1 = &rowBuf[cc][y2 + y3][x1 + x2];
2935
0
                            p1[0] = data2[i];
2936
0
                            p1[1] = data2[i + 1];
2937
0
                            p1[2] = data2[i + 2];
2938
0
                            p1[3] = data2[i + 3];
2939
0
                            p1[4] = data2[i + 4];
2940
0
                            p1[5] = data2[i + 5];
2941
0
                            p1[6] = data2[i + 6];
2942
0
                            p1[7] = data2[i + 7];
2943
0
                        }
2944
0
                    } else if (hSub == 2 && vSub == 2) {
2945
0
                        for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2946
0
                            p1 = &rowBuf[cc][y2 + y3][x1 + x2];
2947
0
                            p2 = &rowBuf[cc][y2 + y3 + 1][x1 + x2];
2948
0
                            p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2949
0
                            p1[2] = p1[3] = p2[2] = p2[3] = data2[i + 1];
2950
0
                            p1[4] = p1[5] = p2[4] = p2[5] = data2[i + 2];
2951
0
                            p1[6] = p1[7] = p2[6] = p2[7] = data2[i + 3];
2952
0
                            p1[8] = p1[9] = p2[8] = p2[9] = data2[i + 4];
2953
0
                            p1[10] = p1[11] = p2[10] = p2[11] = data2[i + 5];
2954
0
                            p1[12] = p1[13] = p2[12] = p2[13] = data2[i + 6];
2955
0
                            p1[14] = p1[15] = p2[14] = p2[15] = data2[i + 7];
2956
0
                        }
2957
0
                    } else {
2958
0
                        i = 0;
2959
0
                        for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2960
0
                            for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2961
0
                                for (y5 = 0; y5 < vSub; ++y5)
2962
0
                                    for (x5 = 0; x5 < hSub; ++x5)
2963
0
                                        rowBuf[cc][y2 + y4 + y5][x1 + x2 + x4 + x5] = data2[i];
2964
0
                                ++i;
2965
0
                            }
2966
0
                        }
2967
0
                    }
2968
0
                }
2969
0
            }
2970
0
        }
2971
0
        --restartCtr;
2972
2973
        // color space conversion
2974
0
        if (colorXform) {
2975
            // convert YCbCr to RGB
2976
0
            if (numComps == 3) {
2977
0
                for (y2 = 0; y2 < mcuHeight; ++y2) {
2978
0
                    for (x2 = 0; x2 < mcuWidth; ++x2) {
2979
0
                        pY = rowBuf[0][y2][x1 + x2];
2980
0
                        pCb = rowBuf[1][y2][x1 + x2] - 128;
2981
0
                        pCr = rowBuf[2][y2][x1 + x2] - 128;
2982
0
                        pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2983
0
                        rowBuf[0][y2][x1 + x2] = dctClip[dctClipOffset + pR];
2984
0
                        pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2985
0
                        rowBuf[1][y2][x1 + x2] = dctClip[dctClipOffset + pG];
2986
0
                        pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2987
0
                        rowBuf[2][y2][x1 + x2] = dctClip[dctClipOffset + pB];
2988
0
                    }
2989
0
                }
2990
                // convert YCbCrK to CMYK (K is passed through unchanged)
2991
0
            } else if (numComps == 4) {
2992
0
                for (y2 = 0; y2 < mcuHeight; ++y2) {
2993
0
                    for (x2 = 0; x2 < mcuWidth; ++x2) {
2994
0
                        pY = rowBuf[0][y2][x1 + x2];
2995
0
                        pCb = rowBuf[1][y2][x1 + x2] - 128;
2996
0
                        pCr = rowBuf[2][y2][x1 + x2] - 128;
2997
0
                        pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2998
0
                        rowBuf[0][y2][x1 + x2] = 255 - dctClip[dctClipOffset + pR];
2999
0
                        pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
3000
0
                        rowBuf[1][y2][x1 + x2] = 255 - dctClip[dctClipOffset + pG];
3001
0
                        pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3002
0
                        rowBuf[2][y2][x1 + x2] = 255 - dctClip[dctClipOffset + pB];
3003
0
                    }
3004
0
                }
3005
0
            }
3006
0
        }
3007
0
    }
3008
0
    return true;
3009
0
}
3010
3011
// Read one scan from a progressive or non-interleaved JPEG stream.
3012
void DCTStream::readScan()
3013
0
{
3014
0
    int data[64];
3015
0
    int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
3016
0
    int h, v, horiz, vert, vSub;
3017
0
    int *p1;
3018
0
    int c;
3019
3020
0
    if (scanInfo.numComps == 1) {
3021
0
        for (cc = 0; cc < numComps; ++cc) {
3022
0
            if (scanInfo.comp[cc]) {
3023
0
                break;
3024
0
            }
3025
0
        }
3026
0
        dx1 = mcuWidth / compInfo[cc].hSample;
3027
0
        dy1 = mcuHeight / compInfo[cc].vSample;
3028
0
    } else {
3029
0
        dx1 = mcuWidth;
3030
0
        dy1 = mcuHeight;
3031
0
    }
3032
3033
0
    for (y1 = 0; y1 < height; y1 += dy1) {
3034
0
        for (x1 = 0; x1 < width; x1 += dx1) {
3035
3036
            // deal with restart marker
3037
0
            if (restartInterval > 0 && restartCtr == 0) {
3038
0
                c = readMarker();
3039
0
                if (c != restartMarker) {
3040
0
                    error(errSyntaxError, getPos(), "Bad DCT data: incorrect restart marker");
3041
0
                    return;
3042
0
                }
3043
0
                if (++restartMarker == 0xd8) {
3044
0
                    restartMarker = 0xd0;
3045
0
                }
3046
0
                restart();
3047
0
            }
3048
3049
            // read one MCU
3050
0
            for (cc = 0; cc < numComps; ++cc) {
3051
0
                if (!scanInfo.comp[cc]) {
3052
0
                    continue;
3053
0
                }
3054
3055
0
                h = compInfo[cc].hSample;
3056
0
                v = compInfo[cc].vSample;
3057
0
                horiz = mcuWidth / h;
3058
0
                vert = mcuHeight / v;
3059
0
                vSub = vert / 8;
3060
0
                for (y2 = 0; y2 < dy1; y2 += vert) {
3061
0
                    for (x2 = 0; x2 < dx1; x2 += horiz) {
3062
3063
                        // pull out the current values
3064
0
                        p1 = &frameBuf[cc][(y1 + y2) * bufWidth + (x1 + x2)];
3065
0
                        for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3066
0
                            data[i] = p1[0];
3067
0
                            data[i + 1] = p1[1];
3068
0
                            data[i + 2] = p1[2];
3069
0
                            data[i + 3] = p1[3];
3070
0
                            data[i + 4] = p1[4];
3071
0
                            data[i + 5] = p1[5];
3072
0
                            data[i + 6] = p1[6];
3073
0
                            data[i + 7] = p1[7];
3074
0
                            p1 += bufWidth * vSub;
3075
0
                        }
3076
3077
                        // read one data unit
3078
0
                        if (progressive) {
3079
0
                            if (!readProgressiveDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], &acHuffTables[scanInfo.acHuffTable[cc]], &compInfo[cc].prevDC, data)) {
3080
0
                                return;
3081
0
                            }
3082
0
                        } else {
3083
0
                            if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], &acHuffTables[scanInfo.acHuffTable[cc]], &compInfo[cc].prevDC, data)) {
3084
0
                                return;
3085
0
                            }
3086
0
                        }
3087
3088
                        // add the data unit into frameBuf
3089
0
                        p1 = &frameBuf[cc][(y1 + y2) * bufWidth + (x1 + x2)];
3090
0
                        for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3091
0
                            p1[0] = data[i];
3092
0
                            p1[1] = data[i + 1];
3093
0
                            p1[2] = data[i + 2];
3094
0
                            p1[3] = data[i + 3];
3095
0
                            p1[4] = data[i + 4];
3096
0
                            p1[5] = data[i + 5];
3097
0
                            p1[6] = data[i + 6];
3098
0
                            p1[7] = data[i + 7];
3099
0
                            p1 += bufWidth * vSub;
3100
0
                        }
3101
0
                    }
3102
0
                }
3103
0
            }
3104
0
            --restartCtr;
3105
0
        }
3106
0
    }
3107
0
}
3108
3109
// Read one data unit from a sequential JPEG stream.
3110
bool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, int *prevDC, int data[64])
3111
0
{
3112
0
    int run, size, amp;
3113
0
    int c;
3114
0
    int i, j;
3115
3116
0
    if ((size = readHuffSym(dcHuffTable)) == 9999) {
3117
0
        return false;
3118
0
    }
3119
0
    if (size > 0) {
3120
0
        if ((amp = readAmp(size)) == 9999) {
3121
0
            return false;
3122
0
        }
3123
0
    } else {
3124
0
        amp = 0;
3125
0
    }
3126
0
    data[0] = *prevDC += amp;
3127
0
    for (i = 1; i < 64; ++i) {
3128
0
        data[i] = 0;
3129
0
    }
3130
0
    i = 1;
3131
0
    while (i < 64) {
3132
0
        run = 0;
3133
0
        while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
3134
0
            run += 0x10;
3135
0
        }
3136
0
        if (c == 9999) {
3137
0
            return false;
3138
0
        }
3139
0
        if (c == 0x00) {
3140
0
            break;
3141
0
        } else {
3142
0
            run += (c >> 4) & 0x0f;
3143
0
            size = c & 0x0f;
3144
0
            amp = readAmp(size);
3145
0
            if (amp == 9999) {
3146
0
                return false;
3147
0
            }
3148
0
            i += run;
3149
0
            if (i < 64) {
3150
0
                j = dctZigZag[i++];
3151
0
                data[j] = amp;
3152
0
            }
3153
0
        }
3154
0
    }
3155
0
    return true;
3156
0
}
3157
3158
// Read one data unit from a sequential JPEG stream.
3159
bool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, int *prevDC, int data[64])
3160
0
{
3161
0
    int run, size, amp, bit, c;
3162
0
    int i, j, k;
3163
3164
    // get the DC coefficient
3165
0
    i = scanInfo.firstCoeff;
3166
0
    if (i == 0) {
3167
0
        if (scanInfo.ah == 0) {
3168
0
            if ((size = readHuffSym(dcHuffTable)) == 9999) {
3169
0
                return false;
3170
0
            }
3171
0
            if (size > 0) {
3172
0
                if ((amp = readAmp(size)) == 9999) {
3173
0
                    return false;
3174
0
                }
3175
0
            } else {
3176
0
                amp = 0;
3177
0
            }
3178
0
            data[0] += (*prevDC += amp) << scanInfo.al;
3179
0
        } else {
3180
0
            if ((bit = readBit()) == 9999) {
3181
0
                return false;
3182
0
            }
3183
0
            data[0] += bit << scanInfo.al;
3184
0
        }
3185
0
        ++i;
3186
0
    }
3187
0
    if (scanInfo.lastCoeff == 0) {
3188
0
        return true;
3189
0
    }
3190
3191
    // check for an EOB run
3192
0
    if (eobRun > 0) {
3193
0
        while (i <= scanInfo.lastCoeff) {
3194
0
            j = dctZigZag[i++];
3195
0
            if (data[j] != 0) {
3196
0
                if ((bit = readBit()) == EOF) {
3197
0
                    return false;
3198
0
                }
3199
0
                if (bit) {
3200
0
                    data[j] += 1 << scanInfo.al;
3201
0
                }
3202
0
            }
3203
0
        }
3204
0
        --eobRun;
3205
0
        return true;
3206
0
    }
3207
3208
    // read the AC coefficients
3209
0
    while (i <= scanInfo.lastCoeff) {
3210
0
        if ((c = readHuffSym(acHuffTable)) == 9999) {
3211
0
            return false;
3212
0
        }
3213
3214
        // ZRL
3215
0
        if (c == 0xf0) {
3216
0
            k = 0;
3217
0
            while (k < 16 && i <= scanInfo.lastCoeff) {
3218
0
                j = dctZigZag[i++];
3219
0
                if (data[j] == 0) {
3220
0
                    ++k;
3221
0
                } else {
3222
0
                    if ((bit = readBit()) == EOF) {
3223
0
                        return false;
3224
0
                    }
3225
0
                    if (bit) {
3226
0
                        data[j] += 1 << scanInfo.al;
3227
0
                    }
3228
0
                }
3229
0
            }
3230
3231
            // EOB run
3232
0
        } else if ((c & 0x0f) == 0x00) {
3233
0
            j = c >> 4;
3234
0
            eobRun = 0;
3235
0
            for (k = 0; k < j; ++k) {
3236
0
                if ((bit = readBit()) == EOF) {
3237
0
                    return false;
3238
0
                }
3239
0
                eobRun = (eobRun << 1) | bit;
3240
0
            }
3241
0
            eobRun += 1 << j;
3242
0
            while (i <= scanInfo.lastCoeff) {
3243
0
                j = dctZigZag[i++];
3244
0
                if (data[j] != 0) {
3245
0
                    if ((bit = readBit()) == EOF) {
3246
0
                        return false;
3247
0
                    }
3248
0
                    if (bit) {
3249
0
                        data[j] += 1 << scanInfo.al;
3250
0
                    }
3251
0
                }
3252
0
            }
3253
0
            --eobRun;
3254
0
            break;
3255
3256
            // zero run and one AC coefficient
3257
0
        } else {
3258
0
            run = (c >> 4) & 0x0f;
3259
0
            size = c & 0x0f;
3260
0
            if ((amp = readAmp(size)) == 9999) {
3261
0
                return false;
3262
0
            }
3263
0
            j = 0; // make gcc happy
3264
0
            for (k = 0; k <= run && i <= scanInfo.lastCoeff; ++k) {
3265
0
                j = dctZigZag[i++];
3266
0
                while (data[j] != 0 && i <= scanInfo.lastCoeff) {
3267
0
                    if ((bit = readBit()) == EOF) {
3268
0
                        return false;
3269
0
                    }
3270
0
                    if (bit) {
3271
0
                        data[j] += 1 << scanInfo.al;
3272
0
                    }
3273
0
                    j = dctZigZag[i++];
3274
0
                }
3275
0
            }
3276
0
            data[j] = amp << scanInfo.al;
3277
0
        }
3278
0
    }
3279
3280
0
    return true;
3281
0
}
3282
3283
// Decode a progressive JPEG image.
3284
void DCTStream::decodeImage()
3285
0
{
3286
0
    int dataIn[64];
3287
0
    unsigned char dataOut[64];
3288
0
    unsigned short *quantTable;
3289
0
    int pY, pCb, pCr, pR, pG, pB;
3290
0
    int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
3291
0
    int h, v, horiz, vert, hSub, vSub;
3292
0
    int *p0, *p1, *p2;
3293
3294
0
    for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
3295
0
        for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
3296
0
            for (cc = 0; cc < numComps; ++cc) {
3297
0
                quantTable = quantTables[compInfo[cc].quantTable];
3298
0
                h = compInfo[cc].hSample;
3299
0
                v = compInfo[cc].vSample;
3300
0
                horiz = mcuWidth / h;
3301
0
                vert = mcuHeight / v;
3302
0
                hSub = horiz / 8;
3303
0
                vSub = vert / 8;
3304
0
                for (y2 = 0; y2 < mcuHeight; y2 += vert) {
3305
0
                    for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
3306
3307
                        // pull out the coded data unit
3308
0
                        p1 = &frameBuf[cc][(y1 + y2) * bufWidth + (x1 + x2)];
3309
0
                        for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3310
0
                            dataIn[i] = p1[0];
3311
0
                            dataIn[i + 1] = p1[1];
3312
0
                            dataIn[i + 2] = p1[2];
3313
0
                            dataIn[i + 3] = p1[3];
3314
0
                            dataIn[i + 4] = p1[4];
3315
0
                            dataIn[i + 5] = p1[5];
3316
0
                            dataIn[i + 6] = p1[6];
3317
0
                            dataIn[i + 7] = p1[7];
3318
0
                            p1 += bufWidth * vSub;
3319
0
                        }
3320
3321
                        // transform
3322
0
                        transformDataUnit(quantTable, dataIn, dataOut);
3323
3324
                        // store back into frameBuf, doing replication for
3325
                        // subsampled components
3326
0
                        p1 = &frameBuf[cc][(y1 + y2) * bufWidth + (x1 + x2)];
3327
0
                        if (hSub == 1 && vSub == 1) {
3328
0
                            for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3329
0
                                p1[0] = dataOut[i] & 0xff;
3330
0
                                p1[1] = dataOut[i + 1] & 0xff;
3331
0
                                p1[2] = dataOut[i + 2] & 0xff;
3332
0
                                p1[3] = dataOut[i + 3] & 0xff;
3333
0
                                p1[4] = dataOut[i + 4] & 0xff;
3334
0
                                p1[5] = dataOut[i + 5] & 0xff;
3335
0
                                p1[6] = dataOut[i + 6] & 0xff;
3336
0
                                p1[7] = dataOut[i + 7] & 0xff;
3337
0
                                p1 += bufWidth;
3338
0
                            }
3339
0
                        } else if (hSub == 2 && vSub == 2) {
3340
0
                            p2 = p1 + bufWidth;
3341
0
                            for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
3342
0
                                p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
3343
0
                                p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i + 1] & 0xff;
3344
0
                                p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i + 2] & 0xff;
3345
0
                                p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i + 3] & 0xff;
3346
0
                                p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i + 4] & 0xff;
3347
0
                                p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i + 5] & 0xff;
3348
0
                                p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i + 6] & 0xff;
3349
0
                                p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i + 7] & 0xff;
3350
0
                                p1 += bufWidth * 2;
3351
0
                                p2 += bufWidth * 2;
3352
0
                            }
3353
0
                        } else {
3354
0
                            i = 0;
3355
0
                            for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
3356
0
                                for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
3357
0
                                    p2 = p1 + x4;
3358
0
                                    for (y5 = 0; y5 < vSub; ++y5) {
3359
0
                                        for (x5 = 0; x5 < hSub; ++x5) {
3360
0
                                            p2[x5] = dataOut[i] & 0xff;
3361
0
                                        }
3362
0
                                        p2 += bufWidth;
3363
0
                                    }
3364
0
                                    ++i;
3365
0
                                }
3366
0
                                p1 += bufWidth * vSub;
3367
0
                            }
3368
0
                        }
3369
0
                    }
3370
0
                }
3371
0
            }
3372
3373
            // color space conversion
3374
0
            if (colorXform) {
3375
                // convert YCbCr to RGB
3376
0
                if (numComps == 3) {
3377
0
                    for (y2 = 0; y2 < mcuHeight; ++y2) {
3378
0
                        p0 = &frameBuf[0][(y1 + y2) * bufWidth + x1];
3379
0
                        p1 = &frameBuf[1][(y1 + y2) * bufWidth + x1];
3380
0
                        p2 = &frameBuf[2][(y1 + y2) * bufWidth + x1];
3381
0
                        for (x2 = 0; x2 < mcuWidth; ++x2) {
3382
0
                            pY = *p0;
3383
0
                            pCb = *p1 - 128;
3384
0
                            pCr = *p2 - 128;
3385
0
                            pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3386
0
                            *p0++ = dctClip[dctClipOffset + pR];
3387
0
                            pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
3388
0
                            *p1++ = dctClip[dctClipOffset + pG];
3389
0
                            pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3390
0
                            *p2++ = dctClip[dctClipOffset + pB];
3391
0
                        }
3392
0
                    }
3393
                    // convert YCbCrK to CMYK (K is passed through unchanged)
3394
0
                } else if (numComps == 4) {
3395
0
                    for (y2 = 0; y2 < mcuHeight; ++y2) {
3396
0
                        p0 = &frameBuf[0][(y1 + y2) * bufWidth + x1];
3397
0
                        p1 = &frameBuf[1][(y1 + y2) * bufWidth + x1];
3398
0
                        p2 = &frameBuf[2][(y1 + y2) * bufWidth + x1];
3399
0
                        for (x2 = 0; x2 < mcuWidth; ++x2) {
3400
0
                            pY = *p0;
3401
0
                            pCb = *p1 - 128;
3402
0
                            pCr = *p2 - 128;
3403
0
                            pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3404
0
                            *p0++ = 255 - dctClip[dctClipOffset + pR];
3405
0
                            pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
3406
0
                            *p1++ = 255 - dctClip[dctClipOffset + pG];
3407
0
                            pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3408
0
                            *p2++ = 255 - dctClip[dctClipOffset + pB];
3409
0
                        }
3410
0
                    }
3411
0
                }
3412
0
            }
3413
0
        }
3414
0
    }
3415
0
}
3416
3417
// Transform one data unit -- this performs the dequantization and
3418
// IDCT steps.  This IDCT algorithm is taken from:
3419
//   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
3420
//   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
3421
//   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
3422
//   988-991.
3423
// The stage numbers mentioned in the comments refer to Figure 1 in this
3424
// paper.
3425
void DCTStream::transformDataUnit(unsigned short *quantTable, int dataIn[64], unsigned char dataOut[64])
3426
0
{
3427
0
    int v0, v1, v2, v3, v4, v5, v6, v7, t;
3428
0
    int *p;
3429
0
    int i;
3430
3431
    // dequant
3432
0
    for (i = 0; i < 64; ++i) {
3433
0
        dataIn[i] *= quantTable[i];
3434
0
    }
3435
3436
    // inverse DCT on rows
3437
0
    for (i = 0; i < 64; i += 8) {
3438
0
        p = dataIn + i;
3439
3440
        // check for all-zero AC coefficients
3441
0
        if (p[1] == 0 && p[2] == 0 && p[3] == 0 && p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
3442
0
            t = (dctSqrt2 * p[0] + 512) >> 10;
3443
0
            p[0] = t;
3444
0
            p[1] = t;
3445
0
            p[2] = t;
3446
0
            p[3] = t;
3447
0
            p[4] = t;
3448
0
            p[5] = t;
3449
0
            p[6] = t;
3450
0
            p[7] = t;
3451
0
            continue;
3452
0
        }
3453
3454
        // stage 4
3455
0
        v0 = (dctSqrt2 * p[0] + 128) >> 8;
3456
0
        v1 = (dctSqrt2 * p[4] + 128) >> 8;
3457
0
        v2 = p[2];
3458
0
        v3 = p[6];
3459
0
        v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
3460
0
        v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
3461
0
        v5 = p[3] << 4;
3462
0
        v6 = p[5] << 4;
3463
3464
        // stage 3
3465
0
        t = (v0 - v1 + 1) >> 1;
3466
0
        v0 = (v0 + v1 + 1) >> 1;
3467
0
        v1 = t;
3468
0
        t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
3469
0
        v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
3470
0
        v3 = t;
3471
0
        t = (v4 - v6 + 1) >> 1;
3472
0
        v4 = (v4 + v6 + 1) >> 1;
3473
0
        v6 = t;
3474
0
        t = (v7 + v5 + 1) >> 1;
3475
0
        v5 = (v7 - v5 + 1) >> 1;
3476
0
        v7 = t;
3477
3478
        // stage 2
3479
0
        t = (v0 - v3 + 1) >> 1;
3480
0
        v0 = (v0 + v3 + 1) >> 1;
3481
0
        v3 = t;
3482
0
        t = (v1 - v2 + 1) >> 1;
3483
0
        v1 = (v1 + v2 + 1) >> 1;
3484
0
        v2 = t;
3485
0
        t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
3486
0
        v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
3487
0
        v7 = t;
3488
0
        t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
3489
0
        v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
3490
0
        v6 = t;
3491
3492
        // stage 1
3493
0
        p[0] = v0 + v7;
3494
0
        p[7] = v0 - v7;
3495
0
        p[1] = v1 + v6;
3496
0
        p[6] = v1 - v6;
3497
0
        p[2] = v2 + v5;
3498
0
        p[5] = v2 - v5;
3499
0
        p[3] = v3 + v4;
3500
0
        p[4] = v3 - v4;
3501
0
    }
3502
3503
    // inverse DCT on columns
3504
0
    for (i = 0; i < 8; ++i) {
3505
0
        p = dataIn + i;
3506
3507
        // check for all-zero AC coefficients
3508
0
        if (p[1 * 8] == 0 && p[2 * 8] == 0 && p[3 * 8] == 0 && p[4 * 8] == 0 && p[5 * 8] == 0 && p[6 * 8] == 0 && p[7 * 8] == 0) {
3509
0
            t = (dctSqrt2 * dataIn[i + 0] + 8192) >> 14;
3510
0
            p[0 * 8] = t;
3511
0
            p[1 * 8] = t;
3512
0
            p[2 * 8] = t;
3513
0
            p[3 * 8] = t;
3514
0
            p[4 * 8] = t;
3515
0
            p[5 * 8] = t;
3516
0
            p[6 * 8] = t;
3517
0
            p[7 * 8] = t;
3518
0
            continue;
3519
0
        }
3520
3521
        // stage 4
3522
0
        v0 = (dctSqrt2 * p[0 * 8] + 2048) >> 12;
3523
0
        v1 = (dctSqrt2 * p[4 * 8] + 2048) >> 12;
3524
0
        v2 = p[2 * 8];
3525
0
        v3 = p[6 * 8];
3526
0
        v4 = (dctSqrt1d2 * (p[1 * 8] - p[7 * 8]) + 2048) >> 12;
3527
0
        v7 = (dctSqrt1d2 * (p[1 * 8] + p[7 * 8]) + 2048) >> 12;
3528
0
        v5 = p[3 * 8];
3529
0
        v6 = p[5 * 8];
3530
3531
        // stage 3
3532
0
        t = (v0 - v1 + 1) >> 1;
3533
0
        v0 = (v0 + v1 + 1) >> 1;
3534
0
        v1 = t;
3535
0
        t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
3536
0
        v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
3537
0
        v3 = t;
3538
0
        t = (v4 - v6 + 1) >> 1;
3539
0
        v4 = (v4 + v6 + 1) >> 1;
3540
0
        v6 = t;
3541
0
        t = (v7 + v5 + 1) >> 1;
3542
0
        v5 = (v7 - v5 + 1) >> 1;
3543
0
        v7 = t;
3544
3545
        // stage 2
3546
0
        t = (v0 - v3 + 1) >> 1;
3547
0
        v0 = (v0 + v3 + 1) >> 1;
3548
0
        v3 = t;
3549
0
        t = (v1 - v2 + 1) >> 1;
3550
0
        v1 = (v1 + v2 + 1) >> 1;
3551
0
        v2 = t;
3552
0
        t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
3553
0
        v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
3554
0
        v7 = t;
3555
0
        t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
3556
0
        v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
3557
0
        v6 = t;
3558
3559
        // stage 1
3560
0
        p[0 * 8] = v0 + v7;
3561
0
        p[7 * 8] = v0 - v7;
3562
0
        p[1 * 8] = v1 + v6;
3563
0
        p[6 * 8] = v1 - v6;
3564
0
        p[2 * 8] = v2 + v5;
3565
0
        p[5 * 8] = v2 - v5;
3566
0
        p[3 * 8] = v3 + v4;
3567
0
        p[4 * 8] = v3 - v4;
3568
0
    }
3569
3570
    // convert to 8-bit integers
3571
0
    for (i = 0; i < 64; ++i) {
3572
0
        const int ix = dctClipOffset + 128 + ((dataIn[i] + 8) >> 4);
3573
0
        if (unlikely(ix < 0 || ix >= dctClipLength)) {
3574
0
            dataOut[i] = 0;
3575
0
        } else {
3576
0
            dataOut[i] = dctClip[ix];
3577
0
        }
3578
0
    }
3579
0
}
3580
3581
int DCTStream::readHuffSym(DCTHuffTable *table)
3582
0
{
3583
0
    unsigned short code;
3584
0
    int bit;
3585
0
    int codeBits;
3586
3587
0
    code = 0;
3588
0
    codeBits = 0;
3589
0
    do {
3590
        // add a bit to the code
3591
0
        if ((bit = readBit()) == EOF) {
3592
0
            return 9999;
3593
0
        }
3594
0
        code = (code << 1) + bit;
3595
0
        ++codeBits;
3596
3597
        // look up code
3598
0
        if (code < table->firstCode[codeBits]) {
3599
0
            break;
3600
0
        }
3601
0
        if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
3602
0
            code -= table->firstCode[codeBits];
3603
0
            return table->sym[table->firstSym[codeBits] + code];
3604
0
        }
3605
0
    } while (codeBits < 16);
3606
3607
0
    error(errSyntaxError, getPos(), "Bad Huffman code in DCT stream");
3608
0
    return 9999;
3609
0
}
3610
3611
int DCTStream::readAmp(int size)
3612
0
{
3613
0
    int amp, bit;
3614
0
    int bits;
3615
3616
0
    amp = 0;
3617
0
    for (bits = 0; bits < size; ++bits) {
3618
0
        if ((bit = readBit()) == EOF)
3619
0
            return 9999;
3620
0
        amp = (amp << 1) + bit;
3621
0
    }
3622
0
    if (amp < (1 << (size - 1)))
3623
0
        amp -= (1 << size) - 1;
3624
0
    return amp;
3625
0
}
3626
3627
int DCTStream::readBit()
3628
0
{
3629
0
    int bit;
3630
0
    int c, c2;
3631
3632
0
    if (inputBits == 0) {
3633
0
        if ((c = str->getChar()) == EOF)
3634
0
            return EOF;
3635
0
        if (c == 0xff) {
3636
0
            do {
3637
0
                c2 = str->getChar();
3638
0
            } while (c2 == 0xff);
3639
0
            if (c2 != 0x00) {
3640
0
                error(errSyntaxError, getPos(), "Bad DCT data: missing 00 after ff");
3641
0
                return EOF;
3642
0
            }
3643
0
        }
3644
0
        inputBuf = c;
3645
0
        inputBits = 8;
3646
0
    }
3647
0
    bit = (inputBuf >> (inputBits - 1)) & 1;
3648
0
    --inputBits;
3649
0
    return bit;
3650
0
}
3651
3652
bool DCTStream::readHeader()
3653
0
{
3654
0
    bool doScan;
3655
0
    int n;
3656
0
    int c = 0;
3657
0
    int i;
3658
3659
    // read headers
3660
0
    doScan = false;
3661
0
    while (!doScan) {
3662
0
        c = readMarker();
3663
0
        switch (c) {
3664
0
        case 0xc0: // SOF0 (sequential)
3665
0
        case 0xc1: // SOF1 (extended sequential)
3666
0
            if (!readBaselineSOF()) {
3667
0
                return false;
3668
0
            }
3669
0
            break;
3670
0
        case 0xc2: // SOF2 (progressive)
3671
0
            if (!readProgressiveSOF()) {
3672
0
                return false;
3673
0
            }
3674
0
            break;
3675
0
        case 0xc4: // DHT
3676
0
            if (!readHuffmanTables()) {
3677
0
                return false;
3678
0
            }
3679
0
            break;
3680
0
        case 0xd8: // SOI
3681
0
            break;
3682
0
        case 0xd9: // EOI
3683
0
            return false;
3684
0
        case 0xda: // SOS
3685
0
            if (!readScanInfo()) {
3686
0
                return false;
3687
0
            }
3688
0
            doScan = true;
3689
0
            break;
3690
0
        case 0xdb: // DQT
3691
0
            if (!readQuantTables()) {
3692
0
                return false;
3693
0
            }
3694
0
            break;
3695
0
        case 0xdd: // DRI
3696
0
            if (!readRestartInterval()) {
3697
0
                return false;
3698
0
            }
3699
0
            break;
3700
0
        case 0xe0: // APP0
3701
0
            if (!readJFIFMarker()) {
3702
0
                return false;
3703
0
            }
3704
0
            break;
3705
0
        case 0xee: // APP14
3706
0
            if (!readAdobeMarker()) {
3707
0
                return false;
3708
0
            }
3709
0
            break;
3710
0
        case EOF:
3711
0
            error(errSyntaxError, getPos(), "Bad DCT header");
3712
0
            return false;
3713
0
        default:
3714
            // skip APPn / COM / etc.
3715
0
            if (c >= 0xe0) {
3716
0
                n = read16() - 2;
3717
0
                for (i = 0; i < n; ++i) {
3718
0
                    str->getChar();
3719
0
                }
3720
0
            } else {
3721
0
                error(errSyntaxError, getPos(), "Unknown DCT marker <{0:02x}>", c);
3722
0
                return false;
3723
0
            }
3724
0
            break;
3725
0
        }
3726
0
    }
3727
3728
0
    return true;
3729
0
}
3730
3731
bool DCTStream::readBaselineSOF()
3732
0
{
3733
0
    int prec;
3734
0
    int i;
3735
0
    int c;
3736
3737
    // read the length
3738
0
    (void)read16();
3739
0
    prec = str->getChar();
3740
0
    height = read16();
3741
0
    width = read16();
3742
0
    numComps = str->getChar();
3743
0
    if (numComps <= 0 || numComps > 4) {
3744
0
        error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
3745
0
        numComps = 0;
3746
0
        return false;
3747
0
    }
3748
0
    if (prec != 8) {
3749
0
        error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
3750
0
        return false;
3751
0
    }
3752
0
    for (i = 0; i < numComps; ++i) {
3753
0
        compInfo[i].id = str->getChar();
3754
0
        c = str->getChar();
3755
0
        compInfo[i].hSample = (c >> 4) & 0x0f;
3756
0
        compInfo[i].vSample = c & 0x0f;
3757
0
        compInfo[i].quantTable = str->getChar();
3758
0
        if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 || compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
3759
0
            error(errSyntaxError, getPos(), "Bad DCT sampling factor");
3760
0
            return false;
3761
0
        }
3762
0
        if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
3763
0
            error(errSyntaxError, getPos(), "Bad DCT quant table selector");
3764
0
            return false;
3765
0
        }
3766
0
    }
3767
0
    progressive = false;
3768
0
    return true;
3769
0
}
3770
3771
bool DCTStream::readProgressiveSOF()
3772
0
{
3773
0
    int prec;
3774
0
    int i;
3775
0
    int c;
3776
3777
    // read the length
3778
0
    (void)read16();
3779
0
    prec = str->getChar();
3780
0
    height = read16();
3781
0
    width = read16();
3782
0
    numComps = str->getChar();
3783
3784
0
    if (numComps <= 0 || numComps > 4) {
3785
0
        error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
3786
0
        numComps = 0;
3787
0
        return false;
3788
0
    }
3789
0
    if (prec != 8) {
3790
0
        error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
3791
0
        return false;
3792
0
    }
3793
0
    for (i = 0; i < numComps; ++i) {
3794
0
        compInfo[i].id = str->getChar();
3795
0
        c = str->getChar();
3796
0
        compInfo[i].hSample = (c >> 4) & 0x0f;
3797
0
        compInfo[i].vSample = c & 0x0f;
3798
0
        compInfo[i].quantTable = str->getChar();
3799
0
        if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 || compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
3800
0
            error(errSyntaxError, getPos(), "Bad DCT sampling factor");
3801
0
            return false;
3802
0
        }
3803
0
        if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
3804
0
            error(errSyntaxError, getPos(), "Bad DCT quant table selector");
3805
0
            return false;
3806
0
        }
3807
0
    }
3808
0
    progressive = true;
3809
0
    return true;
3810
0
}
3811
3812
bool DCTStream::readScanInfo()
3813
0
{
3814
0
    int length;
3815
0
    int id, c;
3816
0
    int i, j;
3817
3818
0
    length = read16() - 2;
3819
0
    scanInfo.numComps = str->getChar();
3820
0
    if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
3821
0
        error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
3822
0
        scanInfo.numComps = 0;
3823
0
        return false;
3824
0
    }
3825
0
    --length;
3826
0
    if (length != 2 * scanInfo.numComps + 3) {
3827
0
        error(errSyntaxError, getPos(), "Bad DCT scan info block");
3828
0
        return false;
3829
0
    }
3830
0
    interleaved = scanInfo.numComps == numComps;
3831
0
    for (j = 0; j < numComps; ++j) {
3832
0
        scanInfo.comp[j] = false;
3833
0
        scanInfo.dcHuffTable[j] = 0;
3834
0
        scanInfo.acHuffTable[j] = 0;
3835
0
    }
3836
0
    for (i = 0; i < scanInfo.numComps; ++i) {
3837
0
        id = str->getChar();
3838
        // some (broken) DCT streams reuse ID numbers, but at least they
3839
        // keep the components in order, so we check compInfo[i] first to
3840
        // work around the problem
3841
0
        if (id == compInfo[i].id) {
3842
0
            j = i;
3843
0
        } else {
3844
0
            for (j = 0; j < numComps; ++j) {
3845
0
                if (id == compInfo[j].id) {
3846
0
                    break;
3847
0
                }
3848
0
            }
3849
0
            if (j == numComps) {
3850
0
                error(errSyntaxError, getPos(), "Bad DCT component ID in scan info block");
3851
0
                return false;
3852
0
            }
3853
0
        }
3854
0
        scanInfo.comp[j] = true;
3855
0
        c = str->getChar();
3856
0
        scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
3857
0
        scanInfo.acHuffTable[j] = c & 0x0f;
3858
0
    }
3859
0
    scanInfo.firstCoeff = str->getChar();
3860
0
    scanInfo.lastCoeff = str->getChar();
3861
0
    if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 || scanInfo.firstCoeff > scanInfo.lastCoeff) {
3862
0
        error(errSyntaxError, getPos(), "Bad DCT coefficient numbers in scan info block");
3863
0
        return false;
3864
0
    }
3865
0
    c = str->getChar();
3866
0
    scanInfo.ah = (c >> 4) & 0x0f;
3867
0
    scanInfo.al = c & 0x0f;
3868
0
    return true;
3869
0
}
3870
3871
bool DCTStream::readQuantTables()
3872
0
{
3873
0
    int length, prec, i, index;
3874
3875
0
    length = read16() - 2;
3876
0
    while (length > 0) {
3877
0
        index = str->getChar();
3878
0
        prec = (index >> 4) & 0x0f;
3879
0
        index &= 0x0f;
3880
0
        if (prec > 1 || index >= 4) {
3881
0
            error(errSyntaxError, getPos(), "Bad DCT quantization table");
3882
0
            return false;
3883
0
        }
3884
0
        if (index == numQuantTables) {
3885
0
            numQuantTables = index + 1;
3886
0
        }
3887
0
        for (i = 0; i < 64; ++i) {
3888
0
            if (prec) {
3889
0
                quantTables[index][dctZigZag[i]] = read16();
3890
0
            } else {
3891
0
                quantTables[index][dctZigZag[i]] = str->getChar();
3892
0
            }
3893
0
        }
3894
0
        if (prec) {
3895
0
            length -= 129;
3896
0
        } else {
3897
0
            length -= 65;
3898
0
        }
3899
0
    }
3900
0
    return true;
3901
0
}
3902
3903
bool DCTStream::readHuffmanTables()
3904
0
{
3905
0
    DCTHuffTable *tbl;
3906
0
    int length;
3907
0
    int index;
3908
0
    unsigned short code;
3909
0
    unsigned char sym;
3910
0
    int i;
3911
0
    int c;
3912
3913
0
    length = read16() - 2;
3914
0
    while (length > 0) {
3915
0
        index = str->getChar();
3916
0
        --length;
3917
0
        if ((index & 0x0f) >= 4) {
3918
0
            error(errSyntaxError, getPos(), "Bad DCT Huffman table");
3919
0
            return false;
3920
0
        }
3921
0
        if (index & 0x10) {
3922
0
            index &= 0x0f;
3923
0
            if (index >= numACHuffTables)
3924
0
                numACHuffTables = index + 1;
3925
0
            tbl = &acHuffTables[index];
3926
0
        } else {
3927
0
            index &= 0x0f;
3928
0
            if (index >= numDCHuffTables)
3929
0
                numDCHuffTables = index + 1;
3930
0
            tbl = &dcHuffTables[index];
3931
0
        }
3932
0
        sym = 0;
3933
0
        code = 0;
3934
0
        for (i = 1; i <= 16; ++i) {
3935
0
            c = str->getChar();
3936
0
            tbl->firstSym[i] = sym;
3937
0
            tbl->firstCode[i] = code;
3938
0
            tbl->numCodes[i] = c;
3939
0
            sym += c;
3940
0
            code = (code + c) << 1;
3941
0
        }
3942
0
        length -= 16;
3943
0
        for (i = 0; i < sym; ++i)
3944
0
            tbl->sym[i] = str->getChar();
3945
0
        length -= sym;
3946
0
    }
3947
0
    return true;
3948
0
}
3949
3950
bool DCTStream::readRestartInterval()
3951
0
{
3952
0
    int length;
3953
3954
0
    length = read16();
3955
0
    if (length != 4) {
3956
0
        error(errSyntaxError, getPos(), "Bad DCT restart interval");
3957
0
        return false;
3958
0
    }
3959
0
    restartInterval = read16();
3960
0
    return true;
3961
0
}
3962
3963
bool DCTStream::readJFIFMarker()
3964
0
{
3965
0
    int length, i;
3966
0
    char buf[5];
3967
0
    int c;
3968
3969
0
    length = read16();
3970
0
    length -= 2;
3971
0
    if (length >= 5) {
3972
0
        for (i = 0; i < 5; ++i) {
3973
0
            if ((c = str->getChar()) == EOF) {
3974
0
                error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
3975
0
                return false;
3976
0
            }
3977
0
            buf[i] = c;
3978
0
        }
3979
0
        length -= 5;
3980
0
        if (!memcmp(buf, "JFIF\0", 5)) {
3981
0
            gotJFIFMarker = true;
3982
0
        }
3983
0
    }
3984
0
    while (length > 0) {
3985
0
        if (str->getChar() == EOF) {
3986
0
            error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
3987
0
            return false;
3988
0
        }
3989
0
        --length;
3990
0
    }
3991
0
    return true;
3992
0
}
3993
3994
bool DCTStream::readAdobeMarker()
3995
0
{
3996
0
    int length, i;
3997
0
    char buf[12];
3998
0
    int c;
3999
4000
0
    length = read16();
4001
0
    if (length < 14) {
4002
0
        goto err;
4003
0
    }
4004
0
    for (i = 0; i < 12; ++i) {
4005
0
        if ((c = str->getChar()) == EOF) {
4006
0
            goto err;
4007
0
        }
4008
0
        buf[i] = c;
4009
0
    }
4010
0
    if (strncmp(buf, "Adobe", 5)) {
4011
0
        goto err;
4012
0
    }
4013
0
    colorXform = buf[11];
4014
0
    gotAdobeMarker = true;
4015
0
    for (i = 14; i < length; ++i) {
4016
0
        if (str->getChar() == EOF) {
4017
0
            goto err;
4018
0
        }
4019
0
    }
4020
0
    return true;
4021
4022
0
err:
4023
0
    error(errSyntaxError, getPos(), "Bad DCT Adobe APP14 marker");
4024
0
    return false;
4025
0
}
4026
4027
bool DCTStream::readTrailer()
4028
0
{
4029
0
    int c;
4030
4031
0
    c = readMarker();
4032
0
    if (c != 0xd9) { // EOI
4033
0
        error(errSyntaxError, getPos(), "Bad DCT trailer");
4034
0
        return false;
4035
0
    }
4036
0
    return true;
4037
0
}
4038
4039
int DCTStream::readMarker()
4040
0
{
4041
0
    int c;
4042
4043
0
    do {
4044
0
        do {
4045
0
            c = str->getChar();
4046
0
        } while (c != 0xff && c != EOF);
4047
0
        while (c == 0xff) {
4048
0
            c = str->getChar();
4049
0
        }
4050
0
    } while (c == 0x00);
4051
0
    return c;
4052
0
}
4053
4054
int DCTStream::read16()
4055
0
{
4056
0
    int c1, c2;
4057
4058
0
    if ((c1 = str->getChar()) == EOF)
4059
0
        return EOF;
4060
0
    if ((c2 = str->getChar()) == EOF)
4061
0
        return EOF;
4062
0
    return (c1 << 8) + c2;
4063
0
}
4064
4065
std::optional<std::string> DCTStream::getPSFilter(int psLevel, const char *indent)
4066
0
{
4067
0
    std::optional<std::string> s;
4068
4069
0
    if (psLevel < 2) {
4070
0
        return {};
4071
0
    }
4072
0
    if (!(s = str->getPSFilter(psLevel, indent))) {
4073
0
        return {};
4074
0
    }
4075
0
    s->append(indent).append("<< >> /DCTDecode filter\n");
4076
0
    return s;
4077
0
}
4078
4079
bool DCTStream::isBinary(bool /*last*/) const
4080
0
{
4081
0
    return str->isBinary(true);
4082
0
}
4083
4084
#endif
4085
4086
#if !ENABLE_ZLIB_UNCOMPRESS
4087
//------------------------------------------------------------------------
4088
// FlateStream
4089
//------------------------------------------------------------------------
4090
4091
const int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
4092
4093
const FlateDecode FlateStream::lengthDecode[flateMaxLitCodes - 257] = { { 0, 3 },  { 0, 4 },   { 0, 5 },   { 0, 6 },   { 0, 7 },   { 0, 8 },   { 0, 9 },   { 0, 10 },  { 1, 11 }, { 1, 13 }, { 1, 15 },
4094
                                                                        { 1, 17 }, { 2, 19 },  { 2, 23 },  { 2, 27 },  { 2, 31 },  { 3, 35 },  { 3, 43 },  { 3, 51 },  { 3, 59 }, { 4, 67 }, { 4, 83 },
4095
                                                                        { 4, 99 }, { 4, 115 }, { 5, 131 }, { 5, 163 }, { 5, 195 }, { 5, 227 }, { 0, 258 }, { 0, 258 }, { 0, 258 } };
4096
4097
const FlateDecode FlateStream::distDecode[flateMaxDistCodes] = { { 0, 1 },    { 0, 2 },    { 0, 3 },     { 0, 4 },     { 1, 5 },     { 1, 7 },     { 2, 9 },     { 2, 13 },     { 3, 17 },     { 3, 25 },
4098
                                                                 { 4, 33 },   { 4, 49 },   { 5, 65 },    { 5, 97 },    { 6, 129 },   { 6, 193 },   { 7, 257 },   { 7, 385 },    { 8, 513 },    { 8, 769 },
4099
                                                                 { 9, 1025 }, { 9, 1537 }, { 10, 2049 }, { 10, 3073 }, { 11, 4097 }, { 11, 6145 }, { 12, 8193 }, { 12, 12289 }, { 13, 16385 }, { 13, 24577 } };
4100
4101
static const FlateCode flateFixedLitCodeTabCodes[512] = {
4102
    { 7, 0x0100 }, { 8, 0x0050 }, { 8, 0x0010 }, { 8, 0x0118 }, { 7, 0x0110 }, { 8, 0x0070 }, { 8, 0x0030 }, { 9, 0x00c0 }, { 7, 0x0108 }, { 8, 0x0060 }, { 8, 0x0020 }, { 9, 0x00a0 }, { 8, 0x0000 }, { 8, 0x0080 }, { 8, 0x0040 },
4103
    { 9, 0x00e0 }, { 7, 0x0104 }, { 8, 0x0058 }, { 8, 0x0018 }, { 9, 0x0090 }, { 7, 0x0114 }, { 8, 0x0078 }, { 8, 0x0038 }, { 9, 0x00d0 }, { 7, 0x010c }, { 8, 0x0068 }, { 8, 0x0028 }, { 9, 0x00b0 }, { 8, 0x0008 }, { 8, 0x0088 },
4104
    { 8, 0x0048 }, { 9, 0x00f0 }, { 7, 0x0102 }, { 8, 0x0054 }, { 8, 0x0014 }, { 8, 0x011c }, { 7, 0x0112 }, { 8, 0x0074 }, { 8, 0x0034 }, { 9, 0x00c8 }, { 7, 0x010a }, { 8, 0x0064 }, { 8, 0x0024 }, { 9, 0x00a8 }, { 8, 0x0004 },
4105
    { 8, 0x0084 }, { 8, 0x0044 }, { 9, 0x00e8 }, { 7, 0x0106 }, { 8, 0x005c }, { 8, 0x001c }, { 9, 0x0098 }, { 7, 0x0116 }, { 8, 0x007c }, { 8, 0x003c }, { 9, 0x00d8 }, { 7, 0x010e }, { 8, 0x006c }, { 8, 0x002c }, { 9, 0x00b8 },
4106
    { 8, 0x000c }, { 8, 0x008c }, { 8, 0x004c }, { 9, 0x00f8 }, { 7, 0x0101 }, { 8, 0x0052 }, { 8, 0x0012 }, { 8, 0x011a }, { 7, 0x0111 }, { 8, 0x0072 }, { 8, 0x0032 }, { 9, 0x00c4 }, { 7, 0x0109 }, { 8, 0x0062 }, { 8, 0x0022 },
4107
    { 9, 0x00a4 }, { 8, 0x0002 }, { 8, 0x0082 }, { 8, 0x0042 }, { 9, 0x00e4 }, { 7, 0x0105 }, { 8, 0x005a }, { 8, 0x001a }, { 9, 0x0094 }, { 7, 0x0115 }, { 8, 0x007a }, { 8, 0x003a }, { 9, 0x00d4 }, { 7, 0x010d }, { 8, 0x006a },
4108
    { 8, 0x002a }, { 9, 0x00b4 }, { 8, 0x000a }, { 8, 0x008a }, { 8, 0x004a }, { 9, 0x00f4 }, { 7, 0x0103 }, { 8, 0x0056 }, { 8, 0x0016 }, { 8, 0x011e }, { 7, 0x0113 }, { 8, 0x0076 }, { 8, 0x0036 }, { 9, 0x00cc }, { 7, 0x010b },
4109
    { 8, 0x0066 }, { 8, 0x0026 }, { 9, 0x00ac }, { 8, 0x0006 }, { 8, 0x0086 }, { 8, 0x0046 }, { 9, 0x00ec }, { 7, 0x0107 }, { 8, 0x005e }, { 8, 0x001e }, { 9, 0x009c }, { 7, 0x0117 }, { 8, 0x007e }, { 8, 0x003e }, { 9, 0x00dc },
4110
    { 7, 0x010f }, { 8, 0x006e }, { 8, 0x002e }, { 9, 0x00bc }, { 8, 0x000e }, { 8, 0x008e }, { 8, 0x004e }, { 9, 0x00fc }, { 7, 0x0100 }, { 8, 0x0051 }, { 8, 0x0011 }, { 8, 0x0119 }, { 7, 0x0110 }, { 8, 0x0071 }, { 8, 0x0031 },
4111
    { 9, 0x00c2 }, { 7, 0x0108 }, { 8, 0x0061 }, { 8, 0x0021 }, { 9, 0x00a2 }, { 8, 0x0001 }, { 8, 0x0081 }, { 8, 0x0041 }, { 9, 0x00e2 }, { 7, 0x0104 }, { 8, 0x0059 }, { 8, 0x0019 }, { 9, 0x0092 }, { 7, 0x0114 }, { 8, 0x0079 },
4112
    { 8, 0x0039 }, { 9, 0x00d2 }, { 7, 0x010c }, { 8, 0x0069 }, { 8, 0x0029 }, { 9, 0x00b2 }, { 8, 0x0009 }, { 8, 0x0089 }, { 8, 0x0049 }, { 9, 0x00f2 }, { 7, 0x0102 }, { 8, 0x0055 }, { 8, 0x0015 }, { 8, 0x011d }, { 7, 0x0112 },
4113
    { 8, 0x0075 }, { 8, 0x0035 }, { 9, 0x00ca }, { 7, 0x010a }, { 8, 0x0065 }, { 8, 0x0025 }, { 9, 0x00aa }, { 8, 0x0005 }, { 8, 0x0085 }, { 8, 0x0045 }, { 9, 0x00ea }, { 7, 0x0106 }, { 8, 0x005d }, { 8, 0x001d }, { 9, 0x009a },
4114
    { 7, 0x0116 }, { 8, 0x007d }, { 8, 0x003d }, { 9, 0x00da }, { 7, 0x010e }, { 8, 0x006d }, { 8, 0x002d }, { 9, 0x00ba }, { 8, 0x000d }, { 8, 0x008d }, { 8, 0x004d }, { 9, 0x00fa }, { 7, 0x0101 }, { 8, 0x0053 }, { 8, 0x0013 },
4115
    { 8, 0x011b }, { 7, 0x0111 }, { 8, 0x0073 }, { 8, 0x0033 }, { 9, 0x00c6 }, { 7, 0x0109 }, { 8, 0x0063 }, { 8, 0x0023 }, { 9, 0x00a6 }, { 8, 0x0003 }, { 8, 0x0083 }, { 8, 0x0043 }, { 9, 0x00e6 }, { 7, 0x0105 }, { 8, 0x005b },
4116
    { 8, 0x001b }, { 9, 0x0096 }, { 7, 0x0115 }, { 8, 0x007b }, { 8, 0x003b }, { 9, 0x00d6 }, { 7, 0x010d }, { 8, 0x006b }, { 8, 0x002b }, { 9, 0x00b6 }, { 8, 0x000b }, { 8, 0x008b }, { 8, 0x004b }, { 9, 0x00f6 }, { 7, 0x0103 },
4117
    { 8, 0x0057 }, { 8, 0x0017 }, { 8, 0x011f }, { 7, 0x0113 }, { 8, 0x0077 }, { 8, 0x0037 }, { 9, 0x00ce }, { 7, 0x010b }, { 8, 0x0067 }, { 8, 0x0027 }, { 9, 0x00ae }, { 8, 0x0007 }, { 8, 0x0087 }, { 8, 0x0047 }, { 9, 0x00ee },
4118
    { 7, 0x0107 }, { 8, 0x005f }, { 8, 0x001f }, { 9, 0x009e }, { 7, 0x0117 }, { 8, 0x007f }, { 8, 0x003f }, { 9, 0x00de }, { 7, 0x010f }, { 8, 0x006f }, { 8, 0x002f }, { 9, 0x00be }, { 8, 0x000f }, { 8, 0x008f }, { 8, 0x004f },
4119
    { 9, 0x00fe }, { 7, 0x0100 }, { 8, 0x0050 }, { 8, 0x0010 }, { 8, 0x0118 }, { 7, 0x0110 }, { 8, 0x0070 }, { 8, 0x0030 }, { 9, 0x00c1 }, { 7, 0x0108 }, { 8, 0x0060 }, { 8, 0x0020 }, { 9, 0x00a1 }, { 8, 0x0000 }, { 8, 0x0080 },
4120
    { 8, 0x0040 }, { 9, 0x00e1 }, { 7, 0x0104 }, { 8, 0x0058 }, { 8, 0x0018 }, { 9, 0x0091 }, { 7, 0x0114 }, { 8, 0x0078 }, { 8, 0x0038 }, { 9, 0x00d1 }, { 7, 0x010c }, { 8, 0x0068 }, { 8, 0x0028 }, { 9, 0x00b1 }, { 8, 0x0008 },
4121
    { 8, 0x0088 }, { 8, 0x0048 }, { 9, 0x00f1 }, { 7, 0x0102 }, { 8, 0x0054 }, { 8, 0x0014 }, { 8, 0x011c }, { 7, 0x0112 }, { 8, 0x0074 }, { 8, 0x0034 }, { 9, 0x00c9 }, { 7, 0x010a }, { 8, 0x0064 }, { 8, 0x0024 }, { 9, 0x00a9 },
4122
    { 8, 0x0004 }, { 8, 0x0084 }, { 8, 0x0044 }, { 9, 0x00e9 }, { 7, 0x0106 }, { 8, 0x005c }, { 8, 0x001c }, { 9, 0x0099 }, { 7, 0x0116 }, { 8, 0x007c }, { 8, 0x003c }, { 9, 0x00d9 }, { 7, 0x010e }, { 8, 0x006c }, { 8, 0x002c },
4123
    { 9, 0x00b9 }, { 8, 0x000c }, { 8, 0x008c }, { 8, 0x004c }, { 9, 0x00f9 }, { 7, 0x0101 }, { 8, 0x0052 }, { 8, 0x0012 }, { 8, 0x011a }, { 7, 0x0111 }, { 8, 0x0072 }, { 8, 0x0032 }, { 9, 0x00c5 }, { 7, 0x0109 }, { 8, 0x0062 },
4124
    { 8, 0x0022 }, { 9, 0x00a5 }, { 8, 0x0002 }, { 8, 0x0082 }, { 8, 0x0042 }, { 9, 0x00e5 }, { 7, 0x0105 }, { 8, 0x005a }, { 8, 0x001a }, { 9, 0x0095 }, { 7, 0x0115 }, { 8, 0x007a }, { 8, 0x003a }, { 9, 0x00d5 }, { 7, 0x010d },
4125
    { 8, 0x006a }, { 8, 0x002a }, { 9, 0x00b5 }, { 8, 0x000a }, { 8, 0x008a }, { 8, 0x004a }, { 9, 0x00f5 }, { 7, 0x0103 }, { 8, 0x0056 }, { 8, 0x0016 }, { 8, 0x011e }, { 7, 0x0113 }, { 8, 0x0076 }, { 8, 0x0036 }, { 9, 0x00cd },
4126
    { 7, 0x010b }, { 8, 0x0066 }, { 8, 0x0026 }, { 9, 0x00ad }, { 8, 0x0006 }, { 8, 0x0086 }, { 8, 0x0046 }, { 9, 0x00ed }, { 7, 0x0107 }, { 8, 0x005e }, { 8, 0x001e }, { 9, 0x009d }, { 7, 0x0117 }, { 8, 0x007e }, { 8, 0x003e },
4127
    { 9, 0x00dd }, { 7, 0x010f }, { 8, 0x006e }, { 8, 0x002e }, { 9, 0x00bd }, { 8, 0x000e }, { 8, 0x008e }, { 8, 0x004e }, { 9, 0x00fd }, { 7, 0x0100 }, { 8, 0x0051 }, { 8, 0x0011 }, { 8, 0x0119 }, { 7, 0x0110 }, { 8, 0x0071 },
4128
    { 8, 0x0031 }, { 9, 0x00c3 }, { 7, 0x0108 }, { 8, 0x0061 }, { 8, 0x0021 }, { 9, 0x00a3 }, { 8, 0x0001 }, { 8, 0x0081 }, { 8, 0x0041 }, { 9, 0x00e3 }, { 7, 0x0104 }, { 8, 0x0059 }, { 8, 0x0019 }, { 9, 0x0093 }, { 7, 0x0114 },
4129
    { 8, 0x0079 }, { 8, 0x0039 }, { 9, 0x00d3 }, { 7, 0x010c }, { 8, 0x0069 }, { 8, 0x0029 }, { 9, 0x00b3 }, { 8, 0x0009 }, { 8, 0x0089 }, { 8, 0x0049 }, { 9, 0x00f3 }, { 7, 0x0102 }, { 8, 0x0055 }, { 8, 0x0015 }, { 8, 0x011d },
4130
    { 7, 0x0112 }, { 8, 0x0075 }, { 8, 0x0035 }, { 9, 0x00cb }, { 7, 0x010a }, { 8, 0x0065 }, { 8, 0x0025 }, { 9, 0x00ab }, { 8, 0x0005 }, { 8, 0x0085 }, { 8, 0x0045 }, { 9, 0x00eb }, { 7, 0x0106 }, { 8, 0x005d }, { 8, 0x001d },
4131
    { 9, 0x009b }, { 7, 0x0116 }, { 8, 0x007d }, { 8, 0x003d }, { 9, 0x00db }, { 7, 0x010e }, { 8, 0x006d }, { 8, 0x002d }, { 9, 0x00bb }, { 8, 0x000d }, { 8, 0x008d }, { 8, 0x004d }, { 9, 0x00fb }, { 7, 0x0101 }, { 8, 0x0053 },
4132
    { 8, 0x0013 }, { 8, 0x011b }, { 7, 0x0111 }, { 8, 0x0073 }, { 8, 0x0033 }, { 9, 0x00c7 }, { 7, 0x0109 }, { 8, 0x0063 }, { 8, 0x0023 }, { 9, 0x00a7 }, { 8, 0x0003 }, { 8, 0x0083 }, { 8, 0x0043 }, { 9, 0x00e7 }, { 7, 0x0105 },
4133
    { 8, 0x005b }, { 8, 0x001b }, { 9, 0x0097 }, { 7, 0x0115 }, { 8, 0x007b }, { 8, 0x003b }, { 9, 0x00d7 }, { 7, 0x010d }, { 8, 0x006b }, { 8, 0x002b }, { 9, 0x00b7 }, { 8, 0x000b }, { 8, 0x008b }, { 8, 0x004b }, { 9, 0x00f7 },
4134
    { 7, 0x0103 }, { 8, 0x0057 }, { 8, 0x0017 }, { 8, 0x011f }, { 7, 0x0113 }, { 8, 0x0077 }, { 8, 0x0037 }, { 9, 0x00cf }, { 7, 0x010b }, { 8, 0x0067 }, { 8, 0x0027 }, { 9, 0x00af }, { 8, 0x0007 }, { 8, 0x0087 }, { 8, 0x0047 },
4135
    { 9, 0x00ef }, { 7, 0x0107 }, { 8, 0x005f }, { 8, 0x001f }, { 9, 0x009f }, { 7, 0x0117 }, { 8, 0x007f }, { 8, 0x003f }, { 9, 0x00df }, { 7, 0x010f }, { 8, 0x006f }, { 8, 0x002f }, { 9, 0x00bf }, { 8, 0x000f }, { 8, 0x008f },
4136
    { 8, 0x004f }, { 9, 0x00ff }
4137
};
4138
4139
FlateHuffmanTab FlateStream::fixedLitCodeTab = { flateFixedLitCodeTabCodes, 9 };
4140
4141
static const FlateCode flateFixedDistCodeTabCodes[32] = { { 5, 0x0000 }, { 5, 0x0010 }, { 5, 0x0008 }, { 5, 0x0018 }, { 5, 0x0004 }, { 5, 0x0014 }, { 5, 0x000c }, { 5, 0x001c }, { 5, 0x0002 }, { 5, 0x0012 }, { 5, 0x000a },
4142
                                                          { 5, 0x001a }, { 5, 0x0006 }, { 5, 0x0016 }, { 5, 0x000e }, { 0, 0x0000 }, { 5, 0x0001 }, { 5, 0x0011 }, { 5, 0x0009 }, { 5, 0x0019 }, { 5, 0x0005 }, { 5, 0x0015 },
4143
                                                          { 5, 0x000d }, { 5, 0x001d }, { 5, 0x0003 }, { 5, 0x0013 }, { 5, 0x000b }, { 5, 0x001b }, { 5, 0x0007 }, { 5, 0x0017 }, { 5, 0x000f }, { 0, 0x0000 } };
4144
4145
FlateHuffmanTab FlateStream::fixedDistCodeTab = { flateFixedDistCodeTabCodes, 5 };
4146
4147
2.79M
FlateStream::FlateStream(Stream *strA, int predictor, int columns, int colors, int bits) : FilterStream(strA)
4148
2.79M
{
4149
2.79M
    if (predictor != 1) {
4150
165k
        pred = new StreamPredictor(this, predictor, columns, colors, bits);
4151
165k
        if (!pred->isOk()) {
4152
4.57k
            delete pred;
4153
4.57k
            pred = nullptr;
4154
4.57k
        }
4155
2.62M
    } else {
4156
2.62M
        pred = nullptr;
4157
2.62M
    }
4158
2.79M
    litCodeTab.codes = nullptr;
4159
2.79M
    distCodeTab.codes = nullptr;
4160
2.79M
    memset(buf, 0, flateWindow);
4161
2.79M
}
4162
4163
FlateStream::~FlateStream()
4164
2.79M
{
4165
2.79M
    if (litCodeTab.codes != fixedLitCodeTab.codes) {
4166
2.32M
        gfree(const_cast<FlateCode *>(litCodeTab.codes));
4167
2.32M
    }
4168
2.79M
    if (distCodeTab.codes != fixedDistCodeTab.codes) {
4169
2.32M
        gfree(const_cast<FlateCode *>(distCodeTab.codes));
4170
2.32M
    }
4171
2.79M
    delete pred;
4172
2.79M
    delete str;
4173
2.79M
}
4174
4175
bool FlateStream::flateRewind(bool unfiltered)
4176
1.70M
{
4177
1.70M
    index = 0;
4178
1.70M
    remain = 0;
4179
1.70M
    codeBuf = 0;
4180
1.70M
    codeSize = 0;
4181
1.70M
    compressedBlock = false;
4182
1.70M
    endOfBlock = true;
4183
1.70M
    eof = true;
4184
1.70M
    if (unfiltered) {
4185
4.28k
        return str->unfilteredRewind();
4186
1.70M
    } else {
4187
1.70M
        return str->rewind();
4188
1.70M
    }
4189
1.70M
}
4190
4191
bool FlateStream::unfilteredRewind()
4192
4.28k
{
4193
4.28k
    return flateRewind(true);
4194
4.28k
}
4195
4196
bool FlateStream::rewind()
4197
1.70M
{
4198
1.70M
    int cmf, flg;
4199
4200
1.70M
    bool internalResetResult = flateRewind(false);
4201
4202
    // read header
4203
    //~ need to look at window size?
4204
1.70M
    endOfBlock = eof = true;
4205
1.70M
    cmf = str->getChar();
4206
1.70M
    flg = str->getChar();
4207
1.70M
    if (cmf == EOF || flg == EOF) {
4208
3.49k
        return false;
4209
3.49k
    }
4210
1.70M
    if ((cmf & 0x0f) != 0x08) {
4211
17.1k
        error(errSyntaxError, getPos(), "Unknown compression method in flate stream");
4212
17.1k
        return false;
4213
17.1k
    }
4214
1.68M
    if ((((cmf << 8) + flg) % 31) != 0) {
4215
4.68k
        error(errSyntaxError, getPos(), "Bad FCHECK in flate stream");
4216
4.68k
        return false;
4217
4.68k
    }
4218
1.67M
    if (flg & 0x20) {
4219
402
        error(errSyntaxError, getPos(), "FDICT bit set in flate stream");
4220
402
        return false;
4221
402
    }
4222
4223
1.67M
    eof = false;
4224
4225
1.67M
    return internalResetResult;
4226
1.67M
}
4227
4228
int FlateStream::getChar()
4229
2.20G
{
4230
2.20G
    if (pred) {
4231
16.2M
        return pred->getChar();
4232
16.2M
    }
4233
2.18G
    return doGetRawChar();
4234
2.20G
}
4235
4236
int FlateStream::getChars(int nChars, unsigned char *buffer)
4237
20.2M
{
4238
20.2M
    if (pred) {
4239
4.36M
        return pred->getChars(nChars, buffer);
4240
15.8M
    } else {
4241
7.26G
        for (int i = 0; i < nChars; ++i) {
4242
7.25G
            const int c = doGetRawChar();
4243
7.25G
            if (likely(c != EOF)) {
4244
7.24G
                buffer[i] = c;
4245
7.24G
            } else {
4246
1.37M
                return i;
4247
1.37M
            }
4248
7.25G
        }
4249
14.4M
        return nChars;
4250
15.8M
    }
4251
20.2M
}
4252
4253
int FlateStream::lookChar()
4254
5.30M
{
4255
5.30M
    int c;
4256
4257
5.30M
    if (pred) {
4258
1.92k
        return pred->lookChar();
4259
1.92k
    }
4260
6.76M
    while (remain == 0) {
4261
1.46M
        if (endOfBlock && eof) {
4262
773
            return EOF;
4263
773
        }
4264
1.46M
        readSome();
4265
1.46M
    }
4266
5.30M
    c = buf[index];
4267
5.30M
    return c;
4268
5.30M
}
4269
4270
void FlateStream::getRawChars(int nChars, int *buffer)
4271
7.66M
{
4272
1.00G
    for (int i = 0; i < nChars; ++i) {
4273
997M
        buffer[i] = doGetRawChar();
4274
997M
    }
4275
7.66M
}
4276
4277
int FlateStream::getRawChar()
4278
10.4M
{
4279
10.4M
    return doGetRawChar();
4280
10.4M
}
4281
4282
std::optional<std::string> FlateStream::getPSFilter(int psLevel, const char *indent)
4283
3.97k
{
4284
3.97k
    std::optional<std::string> s;
4285
4286
3.97k
    if (psLevel < 3 || pred) {
4287
3.97k
        return {};
4288
3.97k
    }
4289
0
    if (!(s = str->getPSFilter(psLevel, indent))) {
4290
0
        return {};
4291
0
    }
4292
0
    s->append(indent).append("<< >> /FlateDecode filter\n");
4293
0
    return s;
4294
0
}
4295
4296
bool FlateStream::isBinary(bool /*last*/) const
4297
0
{
4298
0
    return str->isBinary(true);
4299
0
}
4300
4301
void FlateStream::readSome()
4302
3.08G
{
4303
3.08G
    int code1, code2;
4304
3.08G
    int len, dist;
4305
3.08G
    int i, j, k;
4306
3.08G
    int c;
4307
4308
3.08G
    if (endOfBlock) {
4309
2.53M
        if (!startBlock()) {
4310
65.0k
            return;
4311
65.0k
        }
4312
2.53M
    }
4313
4314
3.08G
    if (compressedBlock) {
4315
3.08G
        if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF) {
4316
83.6k
            goto err;
4317
83.6k
        }
4318
3.08G
        if (code1 < 256) {
4319
2.56G
            buf[index] = code1;
4320
2.56G
            remain = 1;
4321
2.56G
        } else if (code1 == 256) {
4322
1.43M
            endOfBlock = true;
4323
1.43M
            remain = 0;
4324
516M
        } else {
4325
516M
            code1 -= 257;
4326
516M
            code2 = lengthDecode[code1].bits;
4327
516M
            if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) {
4328
1.40k
                goto err;
4329
1.40k
            }
4330
516M
            len = lengthDecode[code1].first + code2;
4331
516M
            if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF) {
4332
47.1k
                goto err;
4333
47.1k
            }
4334
516M
            code2 = distDecode[code1].bits;
4335
516M
            if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF) {
4336
20.2k
                goto err;
4337
20.2k
            }
4338
516M
            dist = distDecode[code1].first + code2;
4339
516M
            i = index;
4340
516M
            j = (index - dist) & flateMask;
4341
7.76G
            for (k = 0; k < len; ++k) {
4342
7.25G
                buf[i] = buf[j];
4343
7.25G
                i = (i + 1) & flateMask;
4344
7.25G
                j = (j + 1) & flateMask;
4345
7.25G
            }
4346
516M
            remain = len;
4347
516M
        }
4348
4349
3.08G
    } else {
4350
322k
        len = (blockLen < flateWindow) ? blockLen : flateWindow;
4351
186M
        for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
4352
186M
            if ((c = str->getChar()) == EOF) {
4353
23.8k
                endOfBlock = eof = true;
4354
23.8k
                break;
4355
23.8k
            }
4356
186M
            buf[j] = c & 0xff;
4357
186M
        }
4358
322k
        remain = i;
4359
322k
        blockLen -= len;
4360
322k
        if (blockLen == 0) {
4361
309k
            endOfBlock = true;
4362
309k
        }
4363
322k
    }
4364
4365
3.08G
    return;
4366
4367
3.08G
err:
4368
152k
    error(errSyntaxError, getPos(), "Unexpected end of file in flate stream");
4369
152k
    endOfBlock = eof = true;
4370
152k
    remain = 0;
4371
152k
}
4372
4373
bool FlateStream::startBlock()
4374
2.53M
{
4375
2.53M
    int blockHdr;
4376
2.53M
    int c;
4377
2.53M
    int check;
4378
4379
    // free the code tables from the previous block
4380
2.53M
    if (litCodeTab.codes != fixedLitCodeTab.codes) {
4381
2.21M
        gfree(const_cast<FlateCode *>(litCodeTab.codes));
4382
2.21M
    }
4383
2.53M
    litCodeTab.codes = nullptr;
4384
2.53M
    if (distCodeTab.codes != fixedDistCodeTab.codes) {
4385
2.21M
        gfree(const_cast<FlateCode *>(distCodeTab.codes));
4386
2.21M
    }
4387
2.53M
    distCodeTab.codes = nullptr;
4388
4389
    // read block header
4390
2.53M
    blockHdr = getCodeWord(3);
4391
2.53M
    if (blockHdr & 1) {
4392
1.25M
        eof = true;
4393
1.25M
    }
4394
2.53M
    blockHdr >>= 1;
4395
4396
    // uncompressed block
4397
2.53M
    if (blockHdr == 0) {
4398
327k
        compressedBlock = false;
4399
327k
        if ((c = str->getChar()) == EOF) {
4400
918
            goto err;
4401
918
        }
4402
326k
        blockLen = c & 0xff;
4403
326k
        if ((c = str->getChar()) == EOF) {
4404
231
            goto err;
4405
231
        }
4406
326k
        blockLen |= (c & 0xff) << 8;
4407
326k
        if ((c = str->getChar()) == EOF) {
4408
3.50k
            goto err;
4409
3.50k
        }
4410
322k
        check = c & 0xff;
4411
322k
        if ((c = str->getChar()) == EOF) {
4412
506
            goto err;
4413
506
        }
4414
322k
        check |= (c & 0xff) << 8;
4415
322k
        if (check != (~blockLen & 0xffff)) {
4416
270k
            error(errSyntaxError, getPos(), "Bad uncompressed block length in flate stream");
4417
270k
        }
4418
322k
        codeBuf = 0;
4419
322k
        codeSize = 0;
4420
4421
        // compressed block with fixed codes
4422
2.20M
    } else if (blockHdr == 1) {
4423
787k
        compressedBlock = true;
4424
787k
        loadFixedCodes();
4425
4426
        // compressed block with dynamic codes
4427
1.42M
    } else if (blockHdr == 2) {
4428
1.40M
        compressedBlock = true;
4429
1.40M
        if (!readDynamicCodes()) {
4430
44.7k
            goto err;
4431
44.7k
        }
4432
4433
        // unknown block type
4434
1.40M
    } else {
4435
15.0k
        goto err;
4436
15.0k
    }
4437
4438
2.47M
    endOfBlock = false;
4439
2.47M
    return true;
4440
4441
65.0k
err:
4442
65.0k
    error(errSyntaxError, getPos(), "Bad block header in flate stream");
4443
65.0k
    endOfBlock = eof = true;
4444
65.0k
    return false;
4445
2.53M
}
4446
4447
void FlateStream::loadFixedCodes()
4448
787k
{
4449
787k
    litCodeTab.codes = fixedLitCodeTab.codes;
4450
787k
    litCodeTab.maxLen = fixedLitCodeTab.maxLen;
4451
787k
    distCodeTab.codes = fixedDistCodeTab.codes;
4452
787k
    distCodeTab.maxLen = fixedDistCodeTab.maxLen;
4453
787k
}
4454
4455
bool FlateStream::readDynamicCodes()
4456
1.40M
{
4457
1.40M
    int numCodeLenCodes;
4458
1.40M
    int numLitCodes;
4459
1.40M
    int numDistCodes;
4460
1.40M
    int codeLenCodeLengths[flateMaxCodeLenCodes];
4461
1.40M
    FlateHuffmanTab codeLenCodeTab;
4462
1.40M
    int len, repeat, code;
4463
1.40M
    int i;
4464
4465
1.40M
    codeLenCodeTab.codes = nullptr;
4466
4467
    // read lengths
4468
1.40M
    if ((numLitCodes = getCodeWord(5)) == EOF) {
4469
206
        goto err;
4470
206
    }
4471
1.40M
    numLitCodes += 257;
4472
1.40M
    if ((numDistCodes = getCodeWord(5)) == EOF) {
4473
613
        goto err;
4474
613
    }
4475
1.40M
    numDistCodes += 1;
4476
1.40M
    if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
4477
896
        goto err;
4478
896
    }
4479
1.40M
    numCodeLenCodes += 4;
4480
1.40M
    if (numLitCodes > flateMaxLitCodes || numDistCodes > flateMaxDistCodes || numCodeLenCodes > flateMaxCodeLenCodes) {
4481
2.24k
        goto err;
4482
2.24k
    }
4483
4484
    // build the code length code table
4485
28.0M
    for (i = 0; i < flateMaxCodeLenCodes; ++i) {
4486
26.6M
        codeLenCodeLengths[i] = 0;
4487
26.6M
    }
4488
23.4M
    for (i = 0; i < numCodeLenCodes; ++i) {
4489
22.0M
        if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
4490
2.36k
            goto err;
4491
2.36k
        }
4492
22.0M
    }
4493
1.39M
    codeLenCodeTab.codes = compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab.maxLen);
4494
4495
    // build the literal and distance code tables
4496
1.39M
    len = 0;
4497
1.39M
    repeat = 0;
4498
1.39M
    i = 0;
4499
234M
    while (i < numLitCodes + numDistCodes) {
4500
232M
        if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
4501
10.4k
            goto err;
4502
10.4k
        }
4503
232M
        if (code == 16) {
4504
15.3M
            if ((repeat = getCodeWord(2)) == EOF) {
4505
791
                goto err;
4506
791
            }
4507
15.3M
            repeat += 3;
4508
15.3M
            if (i + repeat > numLitCodes + numDistCodes) {
4509
6.10k
                goto err;
4510
6.10k
            }
4511
87.3M
            for (; repeat > 0; --repeat) {
4512
72.0M
                codeLengths[i++] = len;
4513
72.0M
            }
4514
217M
        } else if (code == 17) {
4515
5.68M
            if ((repeat = getCodeWord(3)) == EOF) {
4516
1.05k
                goto err;
4517
1.05k
            }
4518
5.68M
            repeat += 3;
4519
5.68M
            if (i + repeat > numLitCodes + numDistCodes) {
4520
6.52k
                goto err;
4521
6.52k
            }
4522
5.67M
            len = 0;
4523
33.4M
            for (; repeat > 0; --repeat) {
4524
27.7M
                codeLengths[i++] = 0;
4525
27.7M
            }
4526
211M
        } else if (code == 18) {
4527
1.85M
            if ((repeat = getCodeWord(7)) == EOF) {
4528
653
                goto err;
4529
653
            }
4530
1.85M
            repeat += 11;
4531
1.85M
            if (i + repeat > numLitCodes + numDistCodes) {
4532
12.8k
                goto err;
4533
12.8k
            }
4534
1.84M
            len = 0;
4535
107M
            for (; repeat > 0; --repeat) {
4536
105M
                codeLengths[i++] = 0;
4537
105M
            }
4538
209M
        } else {
4539
209M
            codeLengths[i++] = len = code;
4540
209M
        }
4541
232M
    }
4542
1.36M
    litCodeTab.codes = compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab.maxLen);
4543
1.36M
    distCodeTab.codes = compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab.maxLen);
4544
4545
1.36M
    gfree(const_cast<FlateCode *>(codeLenCodeTab.codes));
4546
1.36M
    return true;
4547
4548
44.7k
err:
4549
44.7k
    error(errSyntaxError, getPos(), "Bad dynamic code table in flate stream");
4550
44.7k
    gfree(const_cast<FlateCode *>(codeLenCodeTab.codes));
4551
44.7k
    return false;
4552
1.39M
}
4553
4554
// Convert an array <lengths> of <n> lengths, in value order, into a
4555
// Huffman code lookup table.
4556
FlateCode *FlateStream::compHuffmanCodes(const int *lengths, int n, int *maxLen)
4557
4.12M
{
4558
4.12M
    int len, code, code2, skip, val, i, t;
4559
4560
    // find max code length
4561
4.12M
    *maxLen = 0;
4562
438M
    for (val = 0; val < n; ++val) {
4563
434M
        if (lengths[val] > *maxLen) {
4564
10.3M
            *maxLen = lengths[val];
4565
10.3M
        }
4566
434M
    }
4567
4568
    // allocate the table
4569
4.12M
    const int tabSize = 1 << *maxLen;
4570
4.12M
    FlateCode *codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
4571
4572
    // clear the table
4573
6.93G
    for (i = 0; i < tabSize; ++i) {
4574
6.92G
        codes[i].len = 0;
4575
6.92G
        codes[i].val = 0;
4576
6.92G
    }
4577
4578
    // build the table
4579
36.2M
    for (len = 1, code = 0, skip = 2; len <= *maxLen; ++len, code <<= 1, skip <<= 1) {
4580
4.36G
        for (val = 0; val < n; ++val) {
4581
4.33G
            if (lengths[val] == len) {
4582
4583
                // bit-reverse the code
4584
276M
                code2 = 0;
4585
276M
                t = code;
4586
2.49G
                for (i = 0; i < len; ++i) {
4587
2.21G
                    code2 = (code2 << 1) | (t & 1);
4588
2.21G
                    t >>= 1;
4589
2.21G
                }
4590
4591
                // fill in the table entries
4592
7.61G
                for (i = code2; i < tabSize; i += skip) {
4593
7.33G
                    codes[i].len = (unsigned short)len;
4594
7.33G
                    codes[i].val = (unsigned short)val;
4595
7.33G
                }
4596
4597
276M
                ++code;
4598
276M
            }
4599
4.33G
        }
4600
32.1M
    }
4601
4602
4.12M
    return codes;
4603
4.12M
}
4604
4605
int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab)
4606
3.83G
{
4607
3.83G
    const FlateCode *code;
4608
3.83G
    int c;
4609
4610
7.14G
    while (codeSize < tab->maxLen) {
4611
3.30G
        if ((c = str->getChar()) == EOF) {
4612
198k
            break;
4613
198k
        }
4614
3.30G
        codeBuf |= (c & 0xff) << codeSize;
4615
3.30G
        codeSize += 8;
4616
3.30G
    }
4617
3.83G
    code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
4618
3.83G
    if (codeSize == 0 || codeSize < code->len || code->len == 0) {
4619
141k
        return EOF;
4620
141k
    }
4621
3.83G
    codeBuf >>= code->len;
4622
3.83G
    codeSize -= code->len;
4623
3.83G
    return (int)code->val;
4624
3.83G
}
4625
4626
int FlateStream::getCodeWord(int bits)
4627
604M
{
4628
604M
    int c;
4629
4630
748M
    while (codeSize < bits) {
4631
144M
        if ((c = str->getChar()) == EOF) {
4632
29.1k
            return EOF;
4633
29.1k
        }
4634
144M
        codeBuf |= (c & 0xff) << codeSize;
4635
144M
        codeSize += 8;
4636
144M
    }
4637
604M
    c = codeBuf & ((1 << bits) - 1);
4638
604M
    codeBuf >>= bits;
4639
604M
    codeSize -= bits;
4640
604M
    return c;
4641
604M
}
4642
#endif
4643
4644
//------------------------------------------------------------------------
4645
// EOFStream
4646
//------------------------------------------------------------------------
4647
4648
193k
EOFStream::EOFStream(Stream *strA) : FilterStream(strA) { }
4649
4650
EOFStream::~EOFStream()
4651
193k
{
4652
193k
    delete str;
4653
193k
}
4654
4655
//------------------------------------------------------------------------
4656
// BufStream
4657
//------------------------------------------------------------------------
4658
4659
0
BufStream::BufStream(Stream *strA, int bufSizeA) : FilterStream(strA)
4660
0
{
4661
0
    bufSize = bufSizeA;
4662
0
    buf = (int *)gmallocn(bufSize, sizeof(int));
4663
0
}
4664
4665
BufStream::~BufStream()
4666
0
{
4667
0
    gfree(buf);
4668
0
    delete str;
4669
0
}
4670
4671
bool BufStream::rewind()
4672
0
{
4673
0
    int i;
4674
4675
0
    bool success = str->rewind();
4676
0
    for (i = 0; i < bufSize; ++i) {
4677
0
        buf[i] = str->getChar();
4678
0
    }
4679
4680
0
    return success;
4681
0
}
4682
4683
int BufStream::getChar()
4684
0
{
4685
0
    int c, i;
4686
4687
0
    c = buf[0];
4688
0
    for (i = 1; i < bufSize; ++i) {
4689
0
        buf[i - 1] = buf[i];
4690
0
    }
4691
0
    buf[bufSize - 1] = str->getChar();
4692
0
    return c;
4693
0
}
4694
4695
int BufStream::lookChar()
4696
0
{
4697
0
    return buf[0];
4698
0
}
4699
4700
int BufStream::lookChar(int idx)
4701
0
{
4702
0
    return buf[idx];
4703
0
}
4704
4705
bool BufStream::isBinary(bool /*last*/) const
4706
0
{
4707
0
    return str->isBinary(true);
4708
0
}
4709
4710
//------------------------------------------------------------------------
4711
// FixedLengthEncoder
4712
//------------------------------------------------------------------------
4713
4714
39.6k
FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA) : FilterStream(strA)
4715
39.6k
{
4716
39.6k
    length = lengthA;
4717
39.6k
    count = 0;
4718
39.6k
}
4719
4720
FixedLengthEncoder::~FixedLengthEncoder()
4721
39.6k
{
4722
39.6k
    if (str->isEncoder()) {
4723
0
        delete str;
4724
0
    }
4725
39.6k
}
4726
4727
bool FixedLengthEncoder::rewind()
4728
39.6k
{
4729
39.6k
    count = 0;
4730
4731
39.6k
    return str->rewind();
4732
39.6k
}
4733
4734
int FixedLengthEncoder::getChar()
4735
8.39M
{
4736
8.39M
    if (length >= 0 && count >= length) {
4737
2.19M
        return EOF;
4738
2.19M
    }
4739
6.20M
    ++count;
4740
6.20M
    return str->getChar();
4741
8.39M
}
4742
4743
int FixedLengthEncoder::lookChar()
4744
0
{
4745
0
    if (length >= 0 && count >= length) {
4746
0
        return EOF;
4747
0
    }
4748
0
    return str->getChar();
4749
0
}
4750
4751
bool FixedLengthEncoder::isBinary(bool /*last*/) const
4752
0
{
4753
0
    return str->isBinary(true);
4754
0
}
4755
4756
//------------------------------------------------------------------------
4757
// ASCIIHexEncoder
4758
//------------------------------------------------------------------------
4759
4760
0
ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA) : FilterStream(strA)
4761
0
{
4762
0
    bufPtr = bufEnd = buf;
4763
0
    lineLen = 0;
4764
0
    eof = false;
4765
0
}
4766
4767
ASCIIHexEncoder::~ASCIIHexEncoder()
4768
0
{
4769
0
    if (str->isEncoder()) {
4770
0
        delete str;
4771
0
    }
4772
0
}
4773
4774
bool ASCIIHexEncoder::rewind()
4775
0
{
4776
0
    bufPtr = bufEnd = buf;
4777
0
    lineLen = 0;
4778
0
    eof = false;
4779
4780
0
    return str->rewind();
4781
0
}
4782
4783
bool ASCIIHexEncoder::fillBuf()
4784
0
{
4785
0
    static const char *hex = "0123456789abcdef";
4786
0
    int c;
4787
4788
0
    if (eof) {
4789
0
        return false;
4790
0
    }
4791
0
    bufPtr = bufEnd = buf;
4792
0
    if ((c = str->getChar()) == EOF) {
4793
0
        *bufEnd++ = '>';
4794
0
        eof = true;
4795
0
    } else {
4796
0
        if (lineLen >= 64) {
4797
0
            *bufEnd++ = '\n';
4798
0
            lineLen = 0;
4799
0
        }
4800
0
        *bufEnd++ = hex[(c >> 4) & 0x0f];
4801
0
        *bufEnd++ = hex[c & 0x0f];
4802
0
        lineLen += 2;
4803
0
    }
4804
0
    return true;
4805
0
}
4806
4807
//------------------------------------------------------------------------
4808
// ASCII85Encoder
4809
//------------------------------------------------------------------------
4810
4811
44.8k
ASCII85Encoder::ASCII85Encoder(Stream *strA) : FilterStream(strA)
4812
44.8k
{
4813
44.8k
    bufPtr = bufEnd = buf;
4814
44.8k
    lineLen = 0;
4815
44.8k
    eof = false;
4816
44.8k
}
4817
4818
ASCII85Encoder::~ASCII85Encoder()
4819
44.8k
{
4820
44.8k
    if (str->isEncoder()) {
4821
44.4k
        delete str;
4822
44.4k
    }
4823
44.8k
}
4824
4825
bool ASCII85Encoder::rewind()
4826
46.5k
{
4827
46.5k
    bufPtr = bufEnd = buf;
4828
46.5k
    lineLen = 0;
4829
46.5k
    eof = false;
4830
4831
46.5k
    return str->rewind();
4832
46.5k
}
4833
4834
bool ASCII85Encoder::fillBuf()
4835
49.3M
{
4836
49.3M
    unsigned int t;
4837
49.3M
    char buf1[5];
4838
49.3M
    int c0, c1, c2, c3;
4839
49.3M
    int n, i;
4840
4841
49.3M
    if (eof) {
4842
32.6k
        return false;
4843
32.6k
    }
4844
49.3M
    c0 = str->getChar();
4845
49.3M
    c1 = str->getChar();
4846
49.3M
    c2 = str->getChar();
4847
49.3M
    c3 = str->getChar();
4848
49.3M
    bufPtr = bufEnd = buf;
4849
49.3M
    if (c3 == EOF) {
4850
46.5k
        if (c0 == EOF) {
4851
9.96k
            n = 0;
4852
9.96k
            t = 0;
4853
36.5k
        } else {
4854
36.5k
            if (c1 == EOF) {
4855
17.2k
                n = 1;
4856
17.2k
                t = c0 << 24;
4857
19.3k
            } else if (c2 == EOF) {
4858
14.6k
                n = 2;
4859
14.6k
                t = (c0 << 24) | (c1 << 16);
4860
14.6k
            } else {
4861
4.71k
                n = 3;
4862
4.71k
                t = (c0 << 24) | (c1 << 16) | (c2 << 8);
4863
4.71k
            }
4864
219k
            for (i = 4; i >= 0; --i) {
4865
182k
                buf1[i] = (char)(t % 85 + 0x21);
4866
182k
                t /= 85;
4867
182k
            }
4868
133k
            for (i = 0; i <= n; ++i) {
4869
97.2k
                *bufEnd++ = buf1[i];
4870
97.2k
                if (++lineLen == 65) {
4871
8
                    *bufEnd++ = '\n';
4872
8
                    lineLen = 0;
4873
8
                }
4874
97.2k
            }
4875
36.5k
        }
4876
46.5k
        *bufEnd++ = '~';
4877
46.5k
        *bufEnd++ = '>';
4878
46.5k
        eof = true;
4879
49.2M
    } else {
4880
49.2M
        t = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
4881
49.2M
        if (t == 0) {
4882
14.5k
            *bufEnd++ = 'z';
4883
14.5k
            if (++lineLen == 65) {
4884
212
                *bufEnd++ = '\n';
4885
212
                lineLen = 0;
4886
212
            }
4887
49.2M
        } else {
4888
295M
            for (i = 4; i >= 0; --i) {
4889
246M
                buf1[i] = (char)(t % 85 + 0x21);
4890
246M
                t /= 85;
4891
246M
            }
4892
295M
            for (i = 0; i <= 4; ++i) {
4893
246M
                *bufEnd++ = buf1[i];
4894
246M
                if (++lineLen == 65) {
4895
3.77M
                    *bufEnd++ = '\n';
4896
3.77M
                    lineLen = 0;
4897
3.77M
                }
4898
246M
            }
4899
49.2M
        }
4900
49.2M
    }
4901
49.3M
    return true;
4902
49.3M
}
4903
4904
//------------------------------------------------------------------------
4905
// RunLengthEncoder
4906
//------------------------------------------------------------------------
4907
4908
0
RunLengthEncoder::RunLengthEncoder(Stream *strA) : FilterStream(strA)
4909
0
{
4910
0
    bufPtr = bufEnd = nextEnd = buf;
4911
0
    eof = false;
4912
0
}
4913
4914
RunLengthEncoder::~RunLengthEncoder()
4915
0
{
4916
0
    if (str->isEncoder()) {
4917
0
        delete str;
4918
0
    }
4919
0
}
4920
4921
bool RunLengthEncoder::rewind()
4922
0
{
4923
0
    bufPtr = bufEnd = nextEnd = buf;
4924
0
    eof = false;
4925
4926
0
    return str->rewind();
4927
0
}
4928
4929
//
4930
// When fillBuf finishes, buf[] looks like this:
4931
//   +-----+--------------+-----------------+--
4932
//   + tag | ... data ... | next 0, 1, or 2 |
4933
//   +-----+--------------+-----------------+--
4934
//    ^                    ^                 ^
4935
//    bufPtr               bufEnd            nextEnd
4936
//
4937
bool RunLengthEncoder::fillBuf()
4938
0
{
4939
0
    int c, c1, c2;
4940
0
    int n;
4941
4942
    // already hit EOF?
4943
0
    if (eof) {
4944
0
        return false;
4945
0
    }
4946
4947
    // grab two bytes
4948
0
    if (nextEnd < bufEnd + 1) {
4949
0
        if ((c1 = str->getChar()) == EOF) {
4950
0
            eof = true;
4951
0
            return false;
4952
0
        }
4953
0
    } else {
4954
0
        c1 = bufEnd[0] & 0xff;
4955
0
    }
4956
0
    if (nextEnd < bufEnd + 2) {
4957
0
        if ((c2 = str->getChar()) == EOF) {
4958
0
            eof = true;
4959
0
            buf[0] = 0;
4960
0
            buf[1] = c1;
4961
0
            bufPtr = buf;
4962
0
            bufEnd = &buf[2];
4963
0
            return true;
4964
0
        }
4965
0
    } else {
4966
0
        c2 = bufEnd[1] & 0xff;
4967
0
    }
4968
4969
    // check for repeat
4970
0
    c = 0; // make gcc happy
4971
0
    if (c1 == c2) {
4972
0
        n = 2;
4973
0
        while (n < 128 && (c = str->getChar()) == c1) {
4974
0
            ++n;
4975
0
        }
4976
0
        buf[0] = (char)(257 - n);
4977
0
        buf[1] = c1;
4978
0
        bufEnd = &buf[2];
4979
0
        if (c == EOF) {
4980
0
            eof = true;
4981
0
        } else if (n < 128) {
4982
0
            buf[2] = c;
4983
0
            nextEnd = &buf[3];
4984
0
        } else {
4985
0
            nextEnd = bufEnd;
4986
0
        }
4987
4988
        // get up to 128 chars
4989
0
    } else {
4990
0
        buf[1] = c1;
4991
0
        buf[2] = c2;
4992
0
        n = 2;
4993
0
        while (n < 128) {
4994
0
            if ((c = str->getChar()) == EOF) {
4995
0
                eof = true;
4996
0
                break;
4997
0
            }
4998
0
            ++n;
4999
0
            buf[n] = c;
5000
0
            if (buf[n] == buf[n - 1]) {
5001
0
                break;
5002
0
            }
5003
0
        }
5004
0
        if (buf[n] == buf[n - 1]) {
5005
0
            buf[0] = (char)(n - 2 - 1);
5006
0
            bufEnd = &buf[n - 1];
5007
0
            nextEnd = &buf[n + 1];
5008
0
        } else {
5009
0
            buf[0] = (char)(n - 1);
5010
0
            bufEnd = nextEnd = &buf[n + 1];
5011
0
        }
5012
0
    }
5013
0
    bufPtr = buf;
5014
0
    return true;
5015
0
}
5016
5017
//------------------------------------------------------------------------
5018
// LZWEncoder
5019
//------------------------------------------------------------------------
5020
5021
44.4k
LZWEncoder::LZWEncoder(Stream *strA) : FilterStream(strA)
5022
44.4k
{
5023
44.4k
    inBufLen = 0;
5024
44.4k
    outBufLen = 0;
5025
44.4k
}
5026
5027
LZWEncoder::~LZWEncoder()
5028
44.4k
{
5029
44.4k
    if (str->isEncoder()) {
5030
39.6k
        delete str;
5031
39.6k
    }
5032
44.4k
}
5033
5034
bool LZWEncoder::rewind()
5035
45.8k
{
5036
45.8k
    int i;
5037
5038
45.8k
    bool success = str->rewind();
5039
5040
    // initialize code table
5041
11.7M
    for (i = 0; i < 256; ++i) {
5042
11.7M
        table[i].byte = i;
5043
11.7M
        table[i].next = nullptr;
5044
11.7M
        table[i].children = nullptr;
5045
11.7M
    }
5046
45.8k
    nextSeq = 258;
5047
45.8k
    codeLen = 9;
5048
5049
    // initialize input buffer
5050
45.8k
    inBufLen = str->doGetChars(sizeof(inBuf), inBuf);
5051
5052
    // initialize output buffer with a clear-table code
5053
45.8k
    outBuf = 256;
5054
45.8k
    outBufLen = 9;
5055
45.8k
    needEOD = false;
5056
5057
45.8k
    return success;
5058
45.8k
}
5059
5060
int LZWEncoder::getChar()
5061
154M
{
5062
154M
    int ret;
5063
5064
154M
    if (inBufLen == 0 && !needEOD && outBufLen == 0) {
5065
123k
        return EOF;
5066
123k
    }
5067
154M
    if (outBufLen < 8 && (inBufLen > 0 || needEOD)) {
5068
110M
        fillBuf();
5069
110M
    }
5070
154M
    if (outBufLen >= 8) {
5071
154M
        ret = (outBuf >> (outBufLen - 8)) & 0xff;
5072
154M
        outBufLen -= 8;
5073
154M
    } else {
5074
44.3k
        ret = (outBuf << (8 - outBufLen)) & 0xff;
5075
44.3k
        outBufLen = 0;
5076
44.3k
    }
5077
154M
    return ret;
5078
154M
}
5079
5080
int LZWEncoder::lookChar()
5081
0
{
5082
0
    if (inBufLen == 0 && !needEOD && outBufLen == 0) {
5083
0
        return EOF;
5084
0
    }
5085
0
    if (outBufLen < 8 && (inBufLen > 0 || needEOD)) {
5086
0
        fillBuf();
5087
0
    }
5088
0
    if (outBufLen >= 8) {
5089
0
        return (outBuf >> (outBufLen - 8)) & 0xff;
5090
0
    } else {
5091
0
        return (outBuf << (8 - outBufLen)) & 0xff;
5092
0
    }
5093
0
}
5094
5095
// On input, outBufLen < 8.
5096
// This function generates, at most, 2 12-bit codes
5097
//   --> outBufLen < 8 + 12 + 12 = 32
5098
void LZWEncoder::fillBuf()
5099
110M
{
5100
110M
    LZWEncoderNode *p0, *p1;
5101
110M
    int seqLen, code, i;
5102
5103
110M
    if (needEOD) {
5104
45.0k
        outBuf = (outBuf << codeLen) | 257;
5105
45.0k
        outBufLen += codeLen;
5106
45.0k
        needEOD = false;
5107
45.0k
        return;
5108
45.0k
    }
5109
5110
    // find longest matching sequence (if any)
5111
109M
    p0 = table + inBuf[0];
5112
109M
    seqLen = 1;
5113
15.0G
    while (inBufLen > seqLen) {
5114
16.7G
        for (p1 = p0->children; p1; p1 = p1->next) {
5115
16.6G
            if (p1->byte == inBuf[seqLen]) {
5116
14.8G
                break;
5117
14.8G
            }
5118
16.6G
        }
5119
15.0G
        if (!p1) {
5120
109M
            break;
5121
109M
        }
5122
14.8G
        p0 = p1;
5123
14.8G
        ++seqLen;
5124
14.8G
    }
5125
109M
    code = (int)(p0 - table);
5126
5127
    // generate an output code
5128
109M
    outBuf = (outBuf << codeLen) | code;
5129
109M
    outBufLen += codeLen;
5130
5131
    // update the table
5132
109M
    table[nextSeq].byte = seqLen < inBufLen ? inBuf[seqLen] : 0;
5133
109M
    table[nextSeq].children = nullptr;
5134
109M
    if (table[code].children) {
5135
49.2M
        table[nextSeq].next = table[code].children;
5136
60.7M
    } else {
5137
60.7M
        table[nextSeq].next = nullptr;
5138
60.7M
    }
5139
109M
    table[code].children = table + nextSeq;
5140
109M
    ++nextSeq;
5141
5142
    // update the input buffer
5143
109M
    memmove(inBuf, inBuf + seqLen, inBufLen - seqLen);
5144
109M
    inBufLen -= seqLen;
5145
109M
    inBufLen += str->doGetChars(sizeof(inBuf) - inBufLen, inBuf + inBufLen);
5146
5147
    // increment codeLen; generate clear-table code
5148
109M
    if (nextSeq == (1 << codeLen)) {
5149
116k
        ++codeLen;
5150
116k
        if (codeLen == 13) {
5151
27.1k
            outBuf = (outBuf << 12) | 256;
5152
27.1k
            outBufLen += 12;
5153
6.98M
            for (i = 0; i < 256; ++i) {
5154
6.96M
                table[i].next = nullptr;
5155
6.96M
                table[i].children = nullptr;
5156
6.96M
            }
5157
27.1k
            nextSeq = 258;
5158
27.1k
            codeLen = 9;
5159
27.1k
        }
5160
116k
    }
5161
5162
    // generate EOD next time
5163
109M
    if (inBufLen == 0) {
5164
45.0k
        needEOD = true;
5165
45.0k
    }
5166
109M
}
5167
5168
//------------------------------------------------------------------------
5169
// CMYKGrayEncoder
5170
//------------------------------------------------------------------------
5171
5172
0
CMYKGrayEncoder::CMYKGrayEncoder(Stream *strA) : FilterStream(strA)
5173
0
{
5174
0
    bufPtr = bufEnd = buf;
5175
0
    eof = false;
5176
0
}
5177
5178
CMYKGrayEncoder::~CMYKGrayEncoder()
5179
0
{
5180
0
    if (str->isEncoder()) {
5181
0
        delete str;
5182
0
    }
5183
0
}
5184
5185
bool CMYKGrayEncoder::rewind()
5186
0
{
5187
0
    bufPtr = bufEnd = buf;
5188
0
    eof = false;
5189
5190
0
    return str->rewind();
5191
0
}
5192
5193
bool CMYKGrayEncoder::fillBuf()
5194
0
{
5195
0
    int c0, c1, c2, c3;
5196
0
    int i;
5197
5198
0
    if (eof) {
5199
0
        return false;
5200
0
    }
5201
0
    c0 = str->getChar();
5202
0
    c1 = str->getChar();
5203
0
    c2 = str->getChar();
5204
0
    c3 = str->getChar();
5205
0
    if (c3 == EOF) {
5206
0
        eof = true;
5207
0
        return false;
5208
0
    }
5209
0
    i = (3 * c0 + 6 * c1 + c2) / 10 + c3;
5210
0
    if (i > 255) {
5211
0
        i = 255;
5212
0
    }
5213
0
    bufPtr = bufEnd = buf;
5214
0
    *bufEnd++ = (char)i;
5215
0
    return true;
5216
0
}
5217
5218
//------------------------------------------------------------------------
5219
// RGBGrayEncoder
5220
//------------------------------------------------------------------------
5221
5222
0
RGBGrayEncoder::RGBGrayEncoder(Stream *strA) : FilterStream(strA)
5223
0
{
5224
0
    bufPtr = bufEnd = buf;
5225
0
    eof = false;
5226
0
}
5227
5228
RGBGrayEncoder::~RGBGrayEncoder()
5229
0
{
5230
0
    if (str->isEncoder()) {
5231
0
        delete str;
5232
0
    }
5233
0
}
5234
5235
bool RGBGrayEncoder::rewind()
5236
0
{
5237
0
    bufPtr = bufEnd = buf;
5238
0
    eof = false;
5239
5240
0
    return str->rewind();
5241
0
}
5242
5243
bool RGBGrayEncoder::fillBuf()
5244
0
{
5245
0
    int c0, c1, c2;
5246
0
    int i;
5247
5248
0
    if (eof) {
5249
0
        return false;
5250
0
    }
5251
0
    c0 = str->getChar();
5252
0
    c1 = str->getChar();
5253
0
    c2 = str->getChar();
5254
0
    if (c2 == EOF) {
5255
0
        eof = true;
5256
0
        return false;
5257
0
    }
5258
0
    i = 255 - (3 * c0 + 6 * c1 + c2) / 10;
5259
0
    if (i < 0) {
5260
0
        i = 0;
5261
0
    }
5262
0
    bufPtr = bufEnd = buf;
5263
0
    *bufEnd++ = (char)i;
5264
0
    return true;
5265
0
}
5266
5267
//------------------------------------------------------------------------
5268
// SplashBitmapCMYKEncoder
5269
//------------------------------------------------------------------------
5270
5271
0
SplashBitmapCMYKEncoder::SplashBitmapCMYKEncoder(SplashBitmap *bitmapA) : bitmap(bitmapA)
5272
0
{
5273
0
    width = (size_t)4 * bitmap->getWidth();
5274
0
    height = bitmap->getHeight();
5275
0
    buf.resize(width);
5276
0
    bufPtr = width;
5277
0
    curLine = height - 1;
5278
0
}
5279
5280
0
SplashBitmapCMYKEncoder::~SplashBitmapCMYKEncoder() = default;
5281
5282
bool SplashBitmapCMYKEncoder::rewind()
5283
0
{
5284
0
    bufPtr = width;
5285
0
    curLine = height - 1;
5286
5287
0
    return true;
5288
0
}
5289
5290
int SplashBitmapCMYKEncoder::lookChar()
5291
0
{
5292
0
    if (bufPtr >= width && !fillBuf()) {
5293
0
        return EOF;
5294
0
    }
5295
0
    return buf[bufPtr];
5296
0
}
5297
5298
int SplashBitmapCMYKEncoder::getChar()
5299
0
{
5300
0
    int ret = lookChar();
5301
0
    bufPtr++;
5302
0
    return ret;
5303
0
}
5304
5305
bool SplashBitmapCMYKEncoder::fillBuf()
5306
0
{
5307
0
    if (curLine < 0) {
5308
0
        return false;
5309
0
    }
5310
5311
0
    if (bufPtr < width) {
5312
0
        return true;
5313
0
    }
5314
5315
0
    bitmap->getCMYKLine(curLine, &buf[0]);
5316
0
    bufPtr = 0;
5317
0
    curLine--;
5318
0
    return true;
5319
0
}
5320
5321
Goffset SplashBitmapCMYKEncoder::getPos()
5322
0
{
5323
0
    return (height - 1 - curLine) * width + bufPtr;
5324
0
}
5325
5326
void SplashBitmapCMYKEncoder::setPos(Goffset pos, int dir)
5327
0
{
5328
    // This code is mostly untested!
5329
0
    if (dir < 0) {
5330
0
        curLine = pos / width;
5331
0
    } else {
5332
0
        curLine = height - 1 - pos / width;
5333
0
    }
5334
5335
0
    bufPtr = width;
5336
0
    fillBuf();
5337
5338
0
    if (dir < 0) {
5339
0
        bufPtr = width - 1 - pos % width;
5340
0
    } else {
5341
0
        bufPtr = pos % width;
5342
0
    }
5343
0
}