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

source code of poppler/poppler/Stream.cc