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