beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / poppler / Stream.cc
blob961767896c2b6da08716660ca59bcf567bc05ec8
1 //========================================================================
2 //
3 // Stream.cc
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
17 // Copyright (C) 2006-2010, 2012-2014 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 William Bader <williambader@hotmail.com>
26 // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
27 // Copyright (C) 2012 Oliver Sander <sander@mi.fu-berlin.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 Adrian Johnson <ajohnson@redneon.com>
31 // Copyright (C) 2013 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>
36 // To see a description of the changes please see the Changelog file that
37 // came with your tarball or type make ChangeLog if you are building from git
39 //========================================================================
41 #include <config.h>
43 #ifdef USE_GCC_PRAGMAS
44 #pragma implementation
45 #endif
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <stddef.h>
50 #include <limits.h>
51 #ifdef HAVE_UNISTD_H
52 #include <unistd.h>
53 #endif
54 #include <string.h>
55 #include <ctype.h>
56 #include "goo/gmem.h"
57 #include "goo/gfile.h"
58 #include "poppler-config.h"
59 #include "Error.h"
60 #include "Object.h"
61 #include "Lexer.h"
62 #include "GfxState.h"
63 #include "Stream.h"
64 #include "XRef.h"
65 #include "JBIG2Stream.h"
66 #include "Stream-CCITT.h"
67 #include "CachedFile.h"
69 #ifdef ENABLE_LIBJPEG
70 #include "DCTStream.h"
71 #endif
73 #ifdef ENABLE_ZLIB
74 #include "FlateStream.h"
75 #endif
77 #ifdef ENABLE_LIBOPENJPEG
78 #include "JPEG2000Stream.h"
79 #else
80 #include "JPXStream.h"
81 #endif
83 #ifdef __DJGPP__
84 static GBool setDJSYSFLAGS = gFalse;
85 #endif
87 #ifdef VMS
88 #ifdef __GNUC__
89 #define SEEK_SET 0
90 #define SEEK_CUR 1
91 #define SEEK_END 2
92 #endif
93 #endif
95 #if MULTITHREADED
96 # define streamLocker() MutexLocker locker(&mutex)
97 #else
98 # define streamLocker()
99 #endif
100 //------------------------------------------------------------------------
101 // Stream (base class)
102 //------------------------------------------------------------------------
104 Stream::Stream() {
105 ref = 1;
106 #if MULTITHREADED
107 gInitMutex(&mutex);
108 #endif
111 Stream::~Stream() {
112 #if MULTITHREADED
113 gDestroyMutex(&mutex);
114 #endif
117 int Stream::incRef() {
118 streamLocker();
119 ++ref;
120 return ref;
123 int Stream::decRef() {
124 streamLocker();
125 --ref;
126 return ref;
129 void Stream::close() {
132 int Stream::getRawChar() {
133 error(errInternal, -1, "Internal: called getRawChar() on non-predictor stream");
134 return EOF;
137 int Stream::getChars(int nChars, Guchar *buffer) {
138 error(errInternal, -1, "Internal: called getChars() on non-predictor stream");
139 return 0;
142 void Stream::getRawChars(int nChars, int *buffer) {
143 error(errInternal, -1, "Internal: called getRawChars() on non-predictor stream");
146 char *Stream::getLine(char *buf, int size) {
147 int i;
148 int c;
150 if (lookChar() == EOF || size < 0)
151 return NULL;
152 for (i = 0; i < size - 1; ++i) {
153 c = getChar();
154 if (c == EOF || c == '\n')
155 break;
156 if (c == '\r') {
157 if ((c = lookChar()) == '\n')
158 getChar();
159 break;
161 buf[i] = c;
163 buf[i] = '\0';
164 return buf;
167 GooString *Stream::getPSFilter(int psLevel, const char *indent) {
168 return new GooString();
171 Stream *Stream::addFilters(Object *dict, int recursion) {
172 Object obj, obj2;
173 Object params, params2;
174 Stream *str;
175 int i;
177 str = this;
178 dict->dictLookup("Filter", &obj, recursion);
179 if (obj.isNull()) {
180 obj.free();
181 dict->dictLookup("F", &obj);
183 dict->dictLookup("DecodeParms", &params, recursion);
184 if (params.isNull()) {
185 params.free();
186 dict->dictLookup("DP", &params);
188 if (obj.isName()) {
189 str = makeFilter(obj.getName(), str, &params, recursion, dict);
190 } else if (obj.isArray()) {
191 for (i = 0; i < obj.arrayGetLength(); ++i) {
192 obj.arrayGet(i, &obj2, recursion);
193 if (params.isArray())
194 params.arrayGet(i, &params2, recursion);
195 else
196 params2.initNull();
197 if (obj2.isName()) {
198 str = makeFilter(obj2.getName(), str, &params2, recursion);
199 } else {
200 error(errSyntaxError, getPos(), "Bad filter name");
201 str = new EOFStream(str);
203 obj2.free();
204 params2.free();
206 } else if (!obj.isNull()) {
207 error(errSyntaxError, getPos(), "Bad 'Filter' attribute in stream");
209 obj.free();
210 params.free();
212 return str;
215 Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursion, Object *dict) {
216 int pred; // parameters
217 int colors;
218 int bits;
219 int early;
220 int encoding;
221 GBool endOfLine, byteAlign, endOfBlock, black;
222 int columns, rows;
223 int colorXform;
224 Object globals, obj;
226 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
227 str = new ASCIIHexStream(str);
228 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
229 str = new ASCII85Stream(str);
230 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
231 pred = 1;
232 columns = 1;
233 colors = 1;
234 bits = 8;
235 early = 1;
236 if (params->isDict()) {
237 params->dictLookup("Predictor", &obj, recursion);
238 if (obj.isInt())
239 pred = obj.getInt();
240 obj.free();
241 params->dictLookup("Columns", &obj, recursion);
242 if (obj.isInt())
243 columns = obj.getInt();
244 obj.free();
245 params->dictLookup("Colors", &obj, recursion);
246 if (obj.isInt())
247 colors = obj.getInt();
248 obj.free();
249 params->dictLookup("BitsPerComponent", &obj, recursion);
250 if (obj.isInt())
251 bits = obj.getInt();
252 obj.free();
253 params->dictLookup("EarlyChange", &obj, recursion);
254 if (obj.isInt())
255 early = obj.getInt();
256 obj.free();
258 str = new LZWStream(str, pred, columns, colors, bits, early);
259 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
260 str = new RunLengthStream(str);
261 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
262 encoding = 0;
263 endOfLine = gFalse;
264 byteAlign = gFalse;
265 columns = 1728;
266 rows = 0;
267 endOfBlock = gTrue;
268 black = gFalse;
269 if (params->isDict()) {
270 params->dictLookup("K", &obj, recursion);
271 if (obj.isInt()) {
272 encoding = obj.getInt();
274 obj.free();
275 params->dictLookup("EndOfLine", &obj, recursion);
276 if (obj.isBool()) {
277 endOfLine = obj.getBool();
279 obj.free();
280 params->dictLookup("EncodedByteAlign", &obj, recursion);
281 if (obj.isBool()) {
282 byteAlign = obj.getBool();
284 obj.free();
285 params->dictLookup("Columns", &obj, recursion);
286 if (obj.isInt()) {
287 columns = obj.getInt();
289 obj.free();
290 params->dictLookup("Rows", &obj, recursion);
291 if (obj.isInt()) {
292 rows = obj.getInt();
294 obj.free();
295 params->dictLookup("EndOfBlock", &obj, recursion);
296 if (obj.isBool()) {
297 endOfBlock = obj.getBool();
299 obj.free();
300 params->dictLookup("BlackIs1", &obj, recursion);
301 if (obj.isBool()) {
302 black = obj.getBool();
304 obj.free();
306 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
307 columns, rows, endOfBlock, black);
308 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
309 colorXform = -1;
310 if (params->isDict()) {
311 if (params->dictLookup("ColorTransform", &obj, recursion)->isInt()) {
312 colorXform = obj.getInt();
314 obj.free();
316 str = new DCTStream(str, colorXform, dict, recursion);
317 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
318 pred = 1;
319 columns = 1;
320 colors = 1;
321 bits = 8;
322 if (params->isDict()) {
323 params->dictLookup("Predictor", &obj, recursion);
324 if (obj.isInt())
325 pred = obj.getInt();
326 obj.free();
327 params->dictLookup("Columns", &obj, recursion);
328 if (obj.isInt())
329 columns = obj.getInt();
330 obj.free();
331 params->dictLookup("Colors", &obj, recursion);
332 if (obj.isInt())
333 colors = obj.getInt();
334 obj.free();
335 params->dictLookup("BitsPerComponent", &obj, recursion);
336 if (obj.isInt())
337 bits = obj.getInt();
338 obj.free();
340 str = new FlateStream(str, pred, columns, colors, bits);
341 } else if (!strcmp(name, "JBIG2Decode")) {
342 if (params->isDict()) {
343 XRef *xref = params->getDict()->getXRef();
344 params->dictLookupNF("JBIG2Globals", &obj);
345 obj.fetch(xref, &globals, recursion);
347 str = new JBIG2Stream(str, &globals, &obj);
348 globals.free();
349 obj.free();
350 } else if (!strcmp(name, "JPXDecode")) {
351 str = new JPXStream(str);
352 } else if (!strcmp(name, "Crypt")) {
353 if (str->getKind() == strCrypt) {
354 str = str->getBaseStream();
355 } else {
356 error(errSyntaxError, getPos(), "Can't revert non decrypt streams");
358 } else {
359 error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
360 str = new EOFStream(str);
362 return str;
365 //------------------------------------------------------------------------
366 // OutStream
367 //------------------------------------------------------------------------
368 OutStream::OutStream ()
370 ref = 1;
373 OutStream::~OutStream ()
377 //------------------------------------------------------------------------
378 // FileOutStream
379 //------------------------------------------------------------------------
380 FileOutStream::FileOutStream (FILE* fa, Goffset startA)
382 f = fa;
383 start = startA;
386 FileOutStream::~FileOutStream ()
388 close ();
391 void FileOutStream::close ()
396 Goffset FileOutStream::getPos ()
398 return Gftell(f);
401 void FileOutStream::put (char c)
403 fputc(c,f);
406 void FileOutStream::printf(const char *format, ...)
408 va_list argptr;
409 va_start (argptr, format);
410 vfprintf(f, format, argptr);
411 va_end (argptr);
415 //------------------------------------------------------------------------
416 // BaseStream
417 //------------------------------------------------------------------------
419 BaseStream::BaseStream(Object *dictA, Goffset lengthA) {
420 dict = *dictA;
421 length = lengthA;
424 BaseStream::~BaseStream() {
425 dict.free();
428 //------------------------------------------------------------------------
429 // FilterStream
430 //------------------------------------------------------------------------
432 FilterStream::FilterStream(Stream *strA) {
433 str = strA;
436 FilterStream::~FilterStream() {
439 void FilterStream::close() {
440 str->close();
443 void FilterStream::setPos(Goffset pos, int dir) {
444 error(errInternal, -1, "Internal: called setPos() on FilterStream");
447 //------------------------------------------------------------------------
448 // ImageStream
449 //------------------------------------------------------------------------
451 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
452 int imgLineSize;
454 str = strA;
455 width = widthA;
456 nComps = nCompsA;
457 nBits = nBitsA;
459 nVals = width * nComps;
460 inputLineSize = (nVals * nBits + 7) >> 3;
461 if (nBits <= 0 || nVals > INT_MAX / nBits - 7 || width > INT_MAX / nComps) {
462 inputLineSize = -1;
464 inputLine = (Guchar *)gmallocn_checkoverflow(inputLineSize, sizeof(char));
465 if (nBits == 8) {
466 imgLine = (Guchar *)inputLine;
467 } else {
468 if (nBits == 1) {
469 imgLineSize = (nVals + 7) & ~7;
470 } else {
471 imgLineSize = nVals;
473 if (width > INT_MAX / nComps) {
474 // force a call to gmallocn(-1,...), which will throw an exception
475 imgLineSize = -1;
477 imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
479 imgIdx = nVals;
482 ImageStream::~ImageStream() {
483 if (imgLine != (Guchar *)inputLine) {
484 gfree(imgLine);
486 gfree(inputLine);
489 void ImageStream::reset() {
490 str->reset();
493 void ImageStream::close() {
494 str->close();
497 GBool ImageStream::getPixel(Guchar *pix) {
498 int i;
500 if (imgIdx >= nVals) {
501 if (!getLine()) {
502 return gFalse;
504 imgIdx = 0;
506 for (i = 0; i < nComps; ++i) {
507 pix[i] = imgLine[imgIdx++];
509 return gTrue;
512 Guchar *ImageStream::getLine() {
513 Gulong buf, bitMask;
514 int bits;
515 int c;
516 int i;
517 Guchar *p;
519 if (unlikely(inputLine == NULL)) {
520 return NULL;
523 int readChars = str->doGetChars(inputLineSize, inputLine);
524 for ( ; readChars < inputLineSize; readChars++) inputLine[readChars] = EOF;
525 if (nBits == 1) {
526 p = inputLine;
527 for (i = 0; i < nVals; i += 8) {
528 c = *p++;
529 imgLine[i+0] = (Guchar)((c >> 7) & 1);
530 imgLine[i+1] = (Guchar)((c >> 6) & 1);
531 imgLine[i+2] = (Guchar)((c >> 5) & 1);
532 imgLine[i+3] = (Guchar)((c >> 4) & 1);
533 imgLine[i+4] = (Guchar)((c >> 3) & 1);
534 imgLine[i+5] = (Guchar)((c >> 2) & 1);
535 imgLine[i+6] = (Guchar)((c >> 1) & 1);
536 imgLine[i+7] = (Guchar)(c & 1);
538 } else if (nBits == 8) {
539 // special case: imgLine == inputLine
540 } else if (nBits == 16) {
541 // this is a hack to support 16 bits images, everywhere
542 // we assume a component fits in 8 bits, with this hack
543 // we treat 16 bit images as 8 bit ones until it's fixed correctly.
544 // The hack has another part on GfxImageColorMap::GfxImageColorMap
545 p = inputLine;
546 for (i = 0; i < nVals; ++i) {
547 imgLine[i] = *p++;
548 p++;
550 } else {
551 bitMask = (1 << nBits) - 1;
552 buf = 0;
553 bits = 0;
554 p = inputLine;
555 for (i = 0; i < nVals; ++i) {
556 if (bits < nBits) {
557 buf = (buf << 8) | (*p++ & 0xff);
558 bits += 8;
560 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
561 bits -= nBits;
564 return imgLine;
567 void ImageStream::skipLine() {
568 str->doGetChars(inputLineSize, inputLine);
571 //------------------------------------------------------------------------
572 // StreamPredictor
573 //------------------------------------------------------------------------
575 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
576 int widthA, int nCompsA, int nBitsA) {
577 str = strA;
578 predictor = predictorA;
579 width = widthA;
580 nComps = nCompsA;
581 nBits = nBitsA;
582 predLine = NULL;
583 ok = gFalse;
585 nVals = width * nComps;
586 pixBytes = (nComps * nBits + 7) >> 3;
587 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
588 if (width <= 0 || nComps <= 0 || nBits <= 0 ||
589 nComps > gfxColorMaxComps ||
590 nBits > 16 ||
591 width >= INT_MAX / nComps || // check for overflow in nVals
592 nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes
593 return;
595 predLine = (Guchar *)gmalloc(rowBytes);
596 memset(predLine, 0, rowBytes);
597 predIdx = rowBytes;
599 ok = gTrue;
602 StreamPredictor::~StreamPredictor() {
603 gfree(predLine);
606 int StreamPredictor::lookChar() {
607 if (predIdx >= rowBytes) {
608 if (!getNextLine()) {
609 return EOF;
612 return predLine[predIdx];
615 int StreamPredictor::getChar() {
616 if (predIdx >= rowBytes) {
617 if (!getNextLine()) {
618 return EOF;
621 return predLine[predIdx++];
624 int StreamPredictor::getChars(int nChars, Guchar *buffer) {
625 int n, m;
627 n = 0;
628 while (n < nChars) {
629 if (predIdx >= rowBytes) {
630 if (!getNextLine()) {
631 break;
634 m = rowBytes - predIdx;
635 if (m > nChars - n) {
636 m = nChars - n;
638 memcpy(buffer + n, predLine + predIdx, m);
639 predIdx += m;
640 n += m;
642 return n;
645 GBool StreamPredictor::getNextLine() {
646 int curPred;
647 Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
648 int left, up, upLeft, p, pa, pb, pc;
649 int c;
650 Gulong inBuf, outBuf, bitMask;
651 int inBits, outBits;
652 int i, j, k, kk;
654 // get PNG optimum predictor number
655 if (predictor >= 10) {
656 if ((curPred = str->getRawChar()) == EOF) {
657 return gFalse;
659 curPred += 10;
660 } else {
661 curPred = predictor;
664 // read the raw line, apply PNG (byte) predictor
665 int *rawCharLine = new int[rowBytes - pixBytes];
666 str->getRawChars(rowBytes - pixBytes, rawCharLine);
667 memset(upLeftBuf, 0, pixBytes + 1);
668 for (i = pixBytes; i < rowBytes; ++i) {
669 for (j = pixBytes; j > 0; --j) {
670 upLeftBuf[j] = upLeftBuf[j-1];
672 upLeftBuf[0] = predLine[i];
673 if ((c = rawCharLine[i - pixBytes]) == EOF) {
674 if (i > pixBytes) {
675 // this ought to return false, but some (broken) PDF files
676 // contain truncated image data, and Adobe apparently reads the
677 // last partial line
678 break;
680 delete[] rawCharLine;
681 return gFalse;
683 switch (curPred) {
684 case 11: // PNG sub
685 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
686 break;
687 case 12: // PNG up
688 predLine[i] = predLine[i] + (Guchar)c;
689 break;
690 case 13: // PNG average
691 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
692 (Guchar)c;
693 break;
694 case 14: // PNG Paeth
695 left = predLine[i - pixBytes];
696 up = predLine[i];
697 upLeft = upLeftBuf[pixBytes];
698 p = left + up - upLeft;
699 if ((pa = p - left) < 0)
700 pa = -pa;
701 if ((pb = p - up) < 0)
702 pb = -pb;
703 if ((pc = p - upLeft) < 0)
704 pc = -pc;
705 if (pa <= pb && pa <= pc)
706 predLine[i] = left + (Guchar)c;
707 else if (pb <= pc)
708 predLine[i] = up + (Guchar)c;
709 else
710 predLine[i] = upLeft + (Guchar)c;
711 break;
712 case 10: // PNG none
713 default: // no predictor or TIFF predictor
714 predLine[i] = (Guchar)c;
715 break;
718 delete[] rawCharLine;
720 // apply TIFF (component) predictor
721 if (predictor == 2) {
722 if (nBits == 1) {
723 inBuf = predLine[pixBytes - 1];
724 for (i = pixBytes; i < rowBytes; i += 8) {
725 // 1-bit add is just xor
726 inBuf = (inBuf << 8) | predLine[i];
727 predLine[i] ^= inBuf >> nComps;
729 } else if (nBits == 8) {
730 for (i = pixBytes; i < rowBytes; ++i) {
731 predLine[i] += predLine[i - nComps];
733 } else {
734 memset(upLeftBuf, 0, nComps + 1);
735 bitMask = (1 << nBits) - 1;
736 inBuf = outBuf = 0;
737 inBits = outBits = 0;
738 j = k = pixBytes;
739 for (i = 0; i < width; ++i) {
740 for (kk = 0; kk < nComps; ++kk) {
741 if (inBits < nBits) {
742 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
743 inBits += 8;
745 upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] +
746 (inBuf >> (inBits - nBits))) & bitMask);
747 inBits -= nBits;
748 outBuf = (outBuf << nBits) | upLeftBuf[kk];
749 outBits += nBits;
750 if (outBits >= 8) {
751 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
752 outBits -= 8;
756 if (outBits > 0) {
757 predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
758 (inBuf & ((1 << (8 - outBits)) - 1)));
763 // reset to start of line
764 predIdx = pixBytes;
766 return gTrue;
769 //------------------------------------------------------------------------
770 // FileStream
771 //------------------------------------------------------------------------
773 FileStream::FileStream(GooFile* fileA, Goffset startA, GBool limitedA,
774 Goffset lengthA, Object *dictA):
775 BaseStream(dictA, lengthA) {
776 file = fileA;
777 offset = start = startA;
778 limited = limitedA;
779 length = lengthA;
780 bufPtr = bufEnd = buf;
781 bufPos = start;
782 savePos = 0;
783 saved = gFalse;
786 FileStream::~FileStream() {
787 close();
790 BaseStream *FileStream::copy() {
791 return new FileStream(file, start, limited, length, &dict);
794 Stream *FileStream::makeSubStream(Goffset startA, GBool limitedA,
795 Goffset lengthA, Object *dictA) {
796 return new FileStream(file, startA, limitedA, lengthA, dictA);
799 void FileStream::reset() {
800 savePos = offset;
801 offset = start;
802 saved = gTrue;
803 bufPtr = bufEnd = buf;
804 bufPos = start;
807 void FileStream::close() {
808 if (saved) {
809 offset = savePos;
810 saved = gFalse;
814 GBool FileStream::fillBuf() {
815 int n;
817 bufPos += bufEnd - buf;
818 bufPtr = bufEnd = buf;
819 if (limited && bufPos >= start + length) {
820 return gFalse;
822 if (limited && bufPos + fileStreamBufSize > start + length) {
823 n = start + length - bufPos;
824 } else {
825 n = fileStreamBufSize;
827 n = file->read(buf, n, offset);
828 if (n == -1) {
829 return gFalse;
831 offset += n;
832 bufEnd = buf + n;
833 if (bufPtr >= bufEnd) {
834 return gFalse;
836 return gTrue;
839 void FileStream::setPos(Goffset pos, int dir) {
840 Goffset size;
842 if (dir >= 0) {
843 offset = bufPos = pos;
844 } else {
845 size = file->size();
846 if (pos > size)
847 pos = size;
848 offset = size - pos;
849 bufPos = offset;
851 bufPtr = bufEnd = buf;
854 void FileStream::moveStart(Goffset delta) {
855 start += delta;
856 bufPtr = bufEnd = buf;
857 bufPos = start;
860 //------------------------------------------------------------------------
861 // CachedFileStream
862 //------------------------------------------------------------------------
864 CachedFileStream::CachedFileStream(CachedFile *ccA, Goffset startA,
865 GBool limitedA, Goffset lengthA, Object *dictA)
866 : BaseStream(dictA, lengthA)
868 cc = ccA;
869 start = startA;
870 limited = limitedA;
871 length = lengthA;
872 bufPtr = bufEnd = buf;
873 bufPos = start;
874 savePos = 0;
875 saved = gFalse;
878 CachedFileStream::~CachedFileStream()
880 close();
881 cc->decRefCnt();
884 BaseStream *CachedFileStream::copy() {
885 cc->incRefCnt();
886 return new CachedFileStream(cc, start, limited, length, &dict);
889 Stream *CachedFileStream::makeSubStream(Goffset startA, GBool limitedA,
890 Goffset lengthA, Object *dictA)
892 cc->incRefCnt();
893 return new CachedFileStream(cc, startA, limitedA, lengthA, dictA);
896 void CachedFileStream::reset()
898 savePos = (Guint)cc->tell();
899 cc->seek(start, SEEK_SET);
901 saved = gTrue;
902 bufPtr = bufEnd = buf;
903 bufPos = start;
906 void CachedFileStream::close()
908 if (saved) {
909 cc->seek(savePos, SEEK_SET);
910 saved = gFalse;
914 GBool CachedFileStream::fillBuf()
916 int n;
918 bufPos += bufEnd - buf;
919 bufPtr = bufEnd = buf;
920 if (limited && bufPos >= start + length) {
921 return gFalse;
923 if (limited && bufPos + cachedStreamBufSize > start + length) {
924 n = start + length - bufPos;
925 } else {
926 n = cachedStreamBufSize - (bufPos % cachedStreamBufSize);
928 n = cc->read(buf, 1, n);
929 bufEnd = buf + n;
930 if (bufPtr >= bufEnd) {
931 return gFalse;
933 return gTrue;
936 void CachedFileStream::setPos(Goffset pos, int dir)
938 Guint size;
940 if (dir >= 0) {
941 cc->seek(pos, SEEK_SET);
942 bufPos = pos;
943 } else {
944 cc->seek(0, SEEK_END);
945 size = (Guint)cc->tell();
947 if (pos > size)
948 pos = (Guint)size;
950 cc->seek(-(int)pos, SEEK_END);
951 bufPos = (Guint)cc->tell();
954 bufPtr = bufEnd = buf;
957 void CachedFileStream::moveStart(Goffset delta)
959 start += delta;
960 bufPtr = bufEnd = buf;
961 bufPos = start;
964 //------------------------------------------------------------------------
965 // MemStream
966 //------------------------------------------------------------------------
968 MemStream::MemStream(char *bufA, Goffset startA, Goffset lengthA, Object *dictA):
969 BaseStream(dictA, lengthA) {
970 buf = bufA;
971 start = startA;
972 length = lengthA;
973 bufEnd = buf + start + length;
974 bufPtr = buf + start;
975 needFree = gFalse;
978 MemStream::~MemStream() {
979 if (needFree) {
980 gfree(buf);
984 BaseStream *MemStream::copy() {
985 return new MemStream(buf, start, length, &dict);
988 Stream *MemStream::makeSubStream(Goffset startA, GBool limited,
989 Goffset lengthA, Object *dictA) {
990 MemStream *subStr;
991 Goffset newLength;
993 if (!limited || startA + lengthA > start + length) {
994 newLength = start + length - startA;
995 } else {
996 newLength = lengthA;
998 subStr = new MemStream(buf, startA, newLength, dictA);
999 return subStr;
1002 void MemStream::reset() {
1003 bufPtr = buf + start;
1006 void MemStream::close() {
1009 int MemStream::getChars(int nChars, Guchar *buffer) {
1010 int n;
1012 if (nChars <= 0) {
1013 return 0;
1015 if (bufEnd - bufPtr < nChars) {
1016 n = (int)(bufEnd - bufPtr);
1017 } else {
1018 n = nChars;
1020 memcpy(buffer, bufPtr, n);
1021 bufPtr += n;
1022 return n;
1025 void MemStream::setPos(Goffset pos, int dir) {
1026 Guint i;
1028 if (dir >= 0) {
1029 i = pos;
1030 } else {
1031 i = start + length - pos;
1033 if (i < start) {
1034 i = start;
1035 } else if (i > start + length) {
1036 i = start + length;
1038 bufPtr = buf + i;
1041 void MemStream::moveStart(Goffset delta) {
1042 start += delta;
1043 length -= delta;
1044 bufPtr = buf + start;
1047 //------------------------------------------------------------------------
1048 // EmbedStream
1049 //------------------------------------------------------------------------
1051 EmbedStream::EmbedStream(Stream *strA, Object *dictA,
1052 GBool limitedA, Goffset lengthA):
1053 BaseStream(dictA, lengthA) {
1054 str = strA;
1055 limited = limitedA;
1056 length = lengthA;
1059 EmbedStream::~EmbedStream() {
1062 BaseStream *EmbedStream::copy() {
1063 error(errInternal, -1, "Called copy() on EmbedStream");
1064 return NULL;
1067 Stream *EmbedStream::makeSubStream(Goffset start, GBool limitedA,
1068 Goffset lengthA, Object *dictA) {
1069 error(errInternal, -1, "Called makeSubStream() on EmbedStream");
1070 return NULL;
1073 int EmbedStream::getChar() {
1074 if (limited && !length) {
1075 return EOF;
1077 --length;
1078 return str->getChar();
1081 int EmbedStream::lookChar() {
1082 if (limited && !length) {
1083 return EOF;
1085 return str->lookChar();
1088 int EmbedStream::getChars(int nChars, Guchar *buffer) {
1089 if (nChars <= 0) {
1090 return 0;
1092 if (limited && length < nChars) {
1093 nChars = length;
1095 return str->doGetChars(nChars, buffer);
1098 void EmbedStream::setPos(Goffset pos, int dir) {
1099 error(errInternal, -1, "Internal: called setPos() on EmbedStream");
1102 Goffset EmbedStream::getStart() {
1103 error(errInternal, -1, "Internal: called getStart() on EmbedStream");
1104 return 0;
1107 void EmbedStream::moveStart(Goffset delta) {
1108 error(errInternal, -1, "Internal: called moveStart() on EmbedStream");
1111 //------------------------------------------------------------------------
1112 // ASCIIHexStream
1113 //------------------------------------------------------------------------
1115 ASCIIHexStream::ASCIIHexStream(Stream *strA):
1116 FilterStream(strA) {
1117 buf = EOF;
1118 eof = gFalse;
1121 ASCIIHexStream::~ASCIIHexStream() {
1122 delete str;
1125 void ASCIIHexStream::reset() {
1126 str->reset();
1127 buf = EOF;
1128 eof = gFalse;
1131 int ASCIIHexStream::lookChar() {
1132 int c1, c2, x;
1134 if (buf != EOF)
1135 return buf;
1136 if (eof) {
1137 buf = EOF;
1138 return EOF;
1140 do {
1141 c1 = str->getChar();
1142 } while (isspace(c1));
1143 if (c1 == '>') {
1144 eof = gTrue;
1145 buf = EOF;
1146 return buf;
1148 do {
1149 c2 = str->getChar();
1150 } while (isspace(c2));
1151 if (c2 == '>') {
1152 eof = gTrue;
1153 c2 = '0';
1155 if (c1 >= '0' && c1 <= '9') {
1156 x = (c1 - '0') << 4;
1157 } else if (c1 >= 'A' && c1 <= 'F') {
1158 x = (c1 - 'A' + 10) << 4;
1159 } else if (c1 >= 'a' && c1 <= 'f') {
1160 x = (c1 - 'a' + 10) << 4;
1161 } else if (c1 == EOF) {
1162 eof = gTrue;
1163 x = 0;
1164 } else {
1165 error(errSyntaxError, getPos(),
1166 "Illegal character <{0:02x}> in ASCIIHex stream", c1);
1167 x = 0;
1169 if (c2 >= '0' && c2 <= '9') {
1170 x += c2 - '0';
1171 } else if (c2 >= 'A' && c2 <= 'F') {
1172 x += c2 - 'A' + 10;
1173 } else if (c2 >= 'a' && c2 <= 'f') {
1174 x += c2 - 'a' + 10;
1175 } else if (c2 == EOF) {
1176 eof = gTrue;
1177 x = 0;
1178 } else {
1179 error(errSyntaxError, getPos(),
1180 "Illegal character <{0:02x}> in ASCIIHex stream", c2);
1182 buf = x & 0xff;
1183 return buf;
1186 GooString *ASCIIHexStream::getPSFilter(int psLevel, const char *indent) {
1187 GooString *s;
1189 if (psLevel < 2) {
1190 return NULL;
1192 if (!(s = str->getPSFilter(psLevel, indent))) {
1193 return NULL;
1195 s->append(indent)->append("/ASCIIHexDecode filter\n");
1196 return s;
1199 GBool ASCIIHexStream::isBinary(GBool last) {
1200 return str->isBinary(gFalse);
1203 //------------------------------------------------------------------------
1204 // ASCII85Stream
1205 //------------------------------------------------------------------------
1207 ASCII85Stream::ASCII85Stream(Stream *strA):
1208 FilterStream(strA) {
1209 index = n = 0;
1210 eof = gFalse;
1213 ASCII85Stream::~ASCII85Stream() {
1214 delete str;
1217 void ASCII85Stream::reset() {
1218 str->reset();
1219 index = n = 0;
1220 eof = gFalse;
1223 int ASCII85Stream::lookChar() {
1224 int k;
1225 Gulong t;
1227 if (index >= n) {
1228 if (eof)
1229 return EOF;
1230 index = 0;
1231 do {
1232 c[0] = str->getChar();
1233 } while (Lexer::isSpace(c[0]));
1234 if (c[0] == '~' || c[0] == EOF) {
1235 eof = gTrue;
1236 n = 0;
1237 return EOF;
1238 } else if (c[0] == 'z') {
1239 b[0] = b[1] = b[2] = b[3] = 0;
1240 n = 4;
1241 } else {
1242 for (k = 1; k < 5; ++k) {
1243 do {
1244 c[k] = str->getChar();
1245 } while (Lexer::isSpace(c[k]));
1246 if (c[k] == '~' || c[k] == EOF)
1247 break;
1249 n = k - 1;
1250 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
1251 for (++k; k < 5; ++k)
1252 c[k] = 0x21 + 84;
1253 eof = gTrue;
1255 t = 0;
1256 for (k = 0; k < 5; ++k)
1257 t = t * 85 + (c[k] - 0x21);
1258 for (k = 3; k >= 0; --k) {
1259 b[k] = (int)(t & 0xff);
1260 t >>= 8;
1264 return b[index];
1267 GooString *ASCII85Stream::getPSFilter(int psLevel, const char *indent) {
1268 GooString *s;
1270 if (psLevel < 2) {
1271 return NULL;
1273 if (!(s = str->getPSFilter(psLevel, indent))) {
1274 return NULL;
1276 s->append(indent)->append("/ASCII85Decode filter\n");
1277 return s;
1280 GBool ASCII85Stream::isBinary(GBool last) {
1281 return str->isBinary(gFalse);
1284 //------------------------------------------------------------------------
1285 // LZWStream
1286 //------------------------------------------------------------------------
1288 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
1289 int bits, int earlyA):
1290 FilterStream(strA) {
1291 if (predictor != 1) {
1292 pred = new StreamPredictor(this, predictor, columns, colors, bits);
1293 if (!pred->isOk()) {
1294 delete pred;
1295 pred = NULL;
1297 } else {
1298 pred = NULL;
1300 early = earlyA;
1301 eof = gFalse;
1302 inputBits = 0;
1303 clearTable();
1306 LZWStream::~LZWStream() {
1307 if (pred) {
1308 delete pred;
1310 delete str;
1313 int LZWStream::getChar() {
1314 if (pred) {
1315 return pred->getChar();
1317 if (eof) {
1318 return EOF;
1320 if (seqIndex >= seqLength) {
1321 if (!processNextCode()) {
1322 return EOF;
1325 return seqBuf[seqIndex++];
1328 int LZWStream::lookChar() {
1329 if (pred) {
1330 return pred->lookChar();
1332 if (eof) {
1333 return EOF;
1335 if (seqIndex >= seqLength) {
1336 if (!processNextCode()) {
1337 return EOF;
1340 return seqBuf[seqIndex];
1343 void LZWStream::getRawChars(int nChars, int *buffer) {
1344 for (int i = 0; i < nChars; ++i)
1345 buffer[i] = doGetRawChar();
1348 int LZWStream::getRawChar() {
1349 return doGetRawChar();
1352 int LZWStream::getChars(int nChars, Guchar *buffer) {
1353 int n, m;
1355 if (pred) {
1356 return pred->getChars(nChars, buffer);
1358 if (eof) {
1359 return 0;
1361 n = 0;
1362 while (n < nChars) {
1363 if (seqIndex >= seqLength) {
1364 if (!processNextCode()) {
1365 break;
1368 m = seqLength - seqIndex;
1369 if (m > nChars - n) {
1370 m = nChars - n;
1372 memcpy(buffer + n, seqBuf + seqIndex, m);
1373 seqIndex += m;
1374 n += m;
1376 return n;
1379 void LZWStream::reset() {
1380 str->reset();
1381 eof = gFalse;
1382 inputBits = 0;
1383 clearTable();
1386 GBool LZWStream::processNextCode() {
1387 int code;
1388 int nextLength;
1389 int i, j;
1391 // check for EOF
1392 if (eof) {
1393 return gFalse;
1396 // check for eod and clear-table codes
1397 start:
1398 code = getCode();
1399 if (code == EOF || code == 257) {
1400 eof = gTrue;
1401 return gFalse;
1403 if (code == 256) {
1404 clearTable();
1405 goto start;
1407 if (nextCode >= 4097) {
1408 error(errSyntaxError, getPos(),
1409 "Bad LZW stream - expected clear-table code");
1410 clearTable();
1413 // process the next code
1414 nextLength = seqLength + 1;
1415 if (code < 256) {
1416 seqBuf[0] = code;
1417 seqLength = 1;
1418 } else if (code < nextCode) {
1419 seqLength = table[code].length;
1420 for (i = seqLength - 1, j = code; i > 0; --i) {
1421 seqBuf[i] = table[j].tail;
1422 j = table[j].head;
1424 seqBuf[0] = j;
1425 } else if (code == nextCode) {
1426 seqBuf[seqLength] = newChar;
1427 ++seqLength;
1428 } else {
1429 error(errSyntaxError, getPos(), "Bad LZW stream - unexpected code");
1430 eof = gTrue;
1431 return gFalse;
1433 newChar = seqBuf[0];
1434 if (first) {
1435 first = gFalse;
1436 } else {
1437 table[nextCode].length = nextLength;
1438 table[nextCode].head = prevCode;
1439 table[nextCode].tail = newChar;
1440 ++nextCode;
1441 if (nextCode + early == 512)
1442 nextBits = 10;
1443 else if (nextCode + early == 1024)
1444 nextBits = 11;
1445 else if (nextCode + early == 2048)
1446 nextBits = 12;
1448 prevCode = code;
1450 // reset buffer
1451 seqIndex = 0;
1453 return gTrue;
1456 void LZWStream::clearTable() {
1457 nextCode = 258;
1458 nextBits = 9;
1459 seqIndex = seqLength = 0;
1460 first = gTrue;
1463 int LZWStream::getCode() {
1464 int c;
1465 int code;
1467 while (inputBits < nextBits) {
1468 if ((c = str->getChar()) == EOF)
1469 return EOF;
1470 inputBuf = (inputBuf << 8) | (c & 0xff);
1471 inputBits += 8;
1473 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1474 inputBits -= nextBits;
1475 return code;
1478 GooString *LZWStream::getPSFilter(int psLevel, const char *indent) {
1479 GooString *s;
1481 if (psLevel < 2 || pred) {
1482 return NULL;
1484 if (!(s = str->getPSFilter(psLevel, indent))) {
1485 return NULL;
1487 s->append(indent)->append("<< ");
1488 if (!early) {
1489 s->append("/EarlyChange 0 ");
1491 s->append(">> /LZWDecode filter\n");
1492 return s;
1495 GBool LZWStream::isBinary(GBool last) {
1496 return str->isBinary(gTrue);
1499 //------------------------------------------------------------------------
1500 // RunLengthStream
1501 //------------------------------------------------------------------------
1503 RunLengthStream::RunLengthStream(Stream *strA):
1504 FilterStream(strA) {
1505 bufPtr = bufEnd = buf;
1506 eof = gFalse;
1509 RunLengthStream::~RunLengthStream() {
1510 delete str;
1513 void RunLengthStream::reset() {
1514 str->reset();
1515 bufPtr = bufEnd = buf;
1516 eof = gFalse;
1519 int RunLengthStream::getChars(int nChars, Guchar *buffer) {
1520 int n, m;
1522 n = 0;
1523 while (n < nChars) {
1524 if (bufPtr >= bufEnd) {
1525 if (!fillBuf()) {
1526 break;
1529 m = (int)(bufEnd - bufPtr);
1530 if (m > nChars - n) {
1531 m = nChars - n;
1533 memcpy(buffer + n, bufPtr, m);
1534 bufPtr += m;
1535 n += m;
1537 return n;
1540 GooString *RunLengthStream::getPSFilter(int psLevel, const char *indent) {
1541 GooString *s;
1543 if (psLevel < 2) {
1544 return NULL;
1546 if (!(s = str->getPSFilter(psLevel, indent))) {
1547 return NULL;
1549 s->append(indent)->append("/RunLengthDecode filter\n");
1550 return s;
1553 GBool RunLengthStream::isBinary(GBool last) {
1554 return str->isBinary(gTrue);
1557 GBool RunLengthStream::fillBuf() {
1558 int c;
1559 int n, i;
1561 if (eof)
1562 return gFalse;
1563 c = str->getChar();
1564 if (c == 0x80 || c == EOF) {
1565 eof = gTrue;
1566 return gFalse;
1568 if (c < 0x80) {
1569 n = c + 1;
1570 for (i = 0; i < n; ++i)
1571 buf[i] = (char)str->getChar();
1572 } else {
1573 n = 0x101 - c;
1574 c = str->getChar();
1575 for (i = 0; i < n; ++i)
1576 buf[i] = (char)c;
1578 bufPtr = buf;
1579 bufEnd = buf + n;
1580 return gTrue;
1583 //------------------------------------------------------------------------
1584 // CCITTFaxStream
1585 //------------------------------------------------------------------------
1587 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1588 GBool byteAlignA, int columnsA, int rowsA,
1589 GBool endOfBlockA, GBool blackA):
1590 FilterStream(strA) {
1591 encoding = encodingA;
1592 endOfLine = endOfLineA;
1593 byteAlign = byteAlignA;
1594 columns = columnsA;
1595 if (columns < 1) {
1596 columns = 1;
1597 } else if (columns > INT_MAX - 2) {
1598 columns = INT_MAX - 2;
1600 rows = rowsA;
1601 endOfBlock = endOfBlockA;
1602 black = blackA;
1603 // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
1604 // ---> max codingLine size = columns + 1
1605 // refLine has one extra guard entry at the end
1606 // ---> max refLine size = columns + 2
1607 codingLine = (int *)gmallocn_checkoverflow(columns + 1, sizeof(int));
1608 refLine = (int *)gmallocn_checkoverflow(columns + 2, sizeof(int));
1610 if (codingLine != NULL && refLine != NULL) {
1611 eof = gFalse;
1612 codingLine[0] = columns;
1613 } else {
1614 eof = gTrue;
1616 row = 0;
1617 nextLine2D = encoding < 0;
1618 inputBits = 0;
1619 a0i = 0;
1620 outputBits = 0;
1622 buf = EOF;
1625 CCITTFaxStream::~CCITTFaxStream() {
1626 delete str;
1627 gfree(refLine);
1628 gfree(codingLine);
1631 void CCITTFaxStream::ccittReset(GBool unfiltered) {
1632 if (unfiltered)
1633 str->unfilteredReset();
1634 else
1635 str->reset();
1637 row = 0;
1638 nextLine2D = encoding < 0;
1639 inputBits = 0;
1640 a0i = 0;
1641 outputBits = 0;
1642 buf = EOF;
1645 void CCITTFaxStream::unfilteredReset() {
1646 ccittReset(gTrue);
1649 void CCITTFaxStream::reset() {
1650 int code1;
1652 ccittReset(gFalse);
1654 if (codingLine != NULL && refLine != NULL) {
1655 eof = gFalse;
1656 codingLine[0] = columns;
1657 } else {
1658 eof = gTrue;
1661 // skip any initial zero bits and end-of-line marker, and get the 2D
1662 // encoding tag
1663 while ((code1 = lookBits(12)) == 0) {
1664 eatBits(1);
1666 if (code1 == 0x001) {
1667 eatBits(12);
1668 endOfLine = gTrue;
1670 if (encoding > 0) {
1671 nextLine2D = !lookBits(1);
1672 eatBits(1);
1676 inline void CCITTFaxStream::addPixels(int a1, int blackPixels) {
1677 if (a1 > codingLine[a0i]) {
1678 if (a1 > columns) {
1679 error(errSyntaxError, getPos(),
1680 "CCITTFax row is wrong length ({0:d})", a1);
1681 err = gTrue;
1682 a1 = columns;
1684 if ((a0i & 1) ^ blackPixels) {
1685 ++a0i;
1687 codingLine[a0i] = a1;
1691 inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) {
1692 if (a1 > codingLine[a0i]) {
1693 if (a1 > columns) {
1694 error(errSyntaxError, getPos(),
1695 "CCITTFax row is wrong length ({0:d})", a1);
1696 err = gTrue;
1697 a1 = columns;
1699 if ((a0i & 1) ^ blackPixels) {
1700 ++a0i;
1702 codingLine[a0i] = a1;
1703 } else if (a1 < codingLine[a0i]) {
1704 if (a1 < 0) {
1705 error(errSyntaxError, getPos(), "Invalid CCITTFax code");
1706 err = gTrue;
1707 a1 = 0;
1709 while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
1710 --a0i;
1712 codingLine[a0i] = a1;
1716 int CCITTFaxStream::lookChar() {
1717 int code1, code2, code3;
1718 int b1i, blackPixels, i, bits;
1719 GBool gotEOL;
1721 if (buf != EOF) {
1722 return buf;
1725 // read the next row
1726 if (outputBits == 0) {
1728 // if at eof just return EOF
1729 if (eof) {
1730 return EOF;
1733 err = gFalse;
1735 // 2-D encoding
1736 if (nextLine2D) {
1737 for (i = 0; i < columns && codingLine[i] < columns; ++i) {
1738 refLine[i] = codingLine[i];
1740 for (; i < columns + 2; ++i) {
1741 refLine[i] = columns;
1743 codingLine[0] = 0;
1744 a0i = 0;
1745 b1i = 0;
1746 blackPixels = 0;
1747 // invariant:
1748 // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
1749 // <= columns
1750 // exception at left edge:
1751 // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
1752 // exception at right edge:
1753 // refLine[b1i] = refLine[b1i+1] = columns is possible
1754 while (codingLine[a0i] < columns && !err) {
1755 code1 = getTwoDimCode();
1756 switch (code1) {
1757 case twoDimPass:
1758 if (likely(b1i + 1 < columns + 2)) {
1759 addPixels(refLine[b1i + 1], blackPixels);
1760 if (refLine[b1i + 1] < columns) {
1761 b1i += 2;
1764 break;
1765 case twoDimHoriz:
1766 code1 = code2 = 0;
1767 if (blackPixels) {
1768 do {
1769 code1 += code3 = getBlackCode();
1770 } while (code3 >= 64);
1771 do {
1772 code2 += code3 = getWhiteCode();
1773 } while (code3 >= 64);
1774 } else {
1775 do {
1776 code1 += code3 = getWhiteCode();
1777 } while (code3 >= 64);
1778 do {
1779 code2 += code3 = getBlackCode();
1780 } while (code3 >= 64);
1782 addPixels(codingLine[a0i] + code1, blackPixels);
1783 if (codingLine[a0i] < columns) {
1784 addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
1786 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1787 b1i += 2;
1788 if (unlikely(b1i > columns + 1)) {
1789 error(errSyntaxError, getPos(),
1790 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1791 err = gTrue;
1792 break;
1795 break;
1796 case twoDimVertR3:
1797 if (unlikely(b1i > columns + 1)) {
1798 error(errSyntaxError, getPos(),
1799 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1800 err = gTrue;
1801 break;
1803 addPixels(refLine[b1i] + 3, blackPixels);
1804 blackPixels ^= 1;
1805 if (codingLine[a0i] < columns) {
1806 ++b1i;
1807 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1808 b1i += 2;
1809 if (unlikely(b1i > columns + 1)) {
1810 error(errSyntaxError, getPos(),
1811 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1812 err = gTrue;
1813 break;
1817 break;
1818 case twoDimVertR2:
1819 if (unlikely(b1i > columns + 1)) {
1820 error(errSyntaxError, getPos(),
1821 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1822 err = gTrue;
1823 break;
1825 addPixels(refLine[b1i] + 2, blackPixels);
1826 blackPixels ^= 1;
1827 if (codingLine[a0i] < columns) {
1828 ++b1i;
1829 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1830 b1i += 2;
1831 if (unlikely(b1i > columns + 1)) {
1832 error(errSyntaxError, getPos(),
1833 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1834 err = gTrue;
1835 break;
1839 break;
1840 case twoDimVertR1:
1841 if (unlikely(b1i > columns + 1)) {
1842 error(errSyntaxError, getPos(),
1843 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1844 err = gTrue;
1845 break;
1847 addPixels(refLine[b1i] + 1, blackPixels);
1848 blackPixels ^= 1;
1849 if (codingLine[a0i] < columns) {
1850 ++b1i;
1851 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1852 b1i += 2;
1853 if (unlikely(b1i > columns + 1)) {
1854 error(errSyntaxError, getPos(),
1855 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1856 err = gTrue;
1857 break;
1861 break;
1862 case twoDimVert0:
1863 if (unlikely(b1i > columns + 1)) {
1864 error(errSyntaxError, getPos(),
1865 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1866 err = gTrue;
1867 break;
1869 addPixels(refLine[b1i], blackPixels);
1870 blackPixels ^= 1;
1871 if (codingLine[a0i] < columns) {
1872 ++b1i;
1873 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1874 b1i += 2;
1875 if (unlikely(b1i > columns + 1)) {
1876 error(errSyntaxError, getPos(),
1877 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1878 err = gTrue;
1879 break;
1883 break;
1884 case twoDimVertL3:
1885 if (unlikely(b1i > columns + 1)) {
1886 error(errSyntaxError, getPos(),
1887 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1888 err = gTrue;
1889 break;
1891 addPixelsNeg(refLine[b1i] - 3, blackPixels);
1892 blackPixels ^= 1;
1893 if (codingLine[a0i] < columns) {
1894 if (b1i > 0) {
1895 --b1i;
1896 } else {
1897 ++b1i;
1899 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1900 b1i += 2;
1901 if (unlikely(b1i > columns + 1)) {
1902 error(errSyntaxError, getPos(),
1903 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1904 err = gTrue;
1905 break;
1909 break;
1910 case twoDimVertL2:
1911 if (unlikely(b1i > columns + 1)) {
1912 error(errSyntaxError, getPos(),
1913 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1914 err = gTrue;
1915 break;
1917 addPixelsNeg(refLine[b1i] - 2, blackPixels);
1918 blackPixels ^= 1;
1919 if (codingLine[a0i] < columns) {
1920 if (b1i > 0) {
1921 --b1i;
1922 } else {
1923 ++b1i;
1925 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1926 b1i += 2;
1927 if (unlikely(b1i > columns + 1)) {
1928 error(errSyntaxError, getPos(),
1929 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1930 err = gTrue;
1931 break;
1935 break;
1936 case twoDimVertL1:
1937 if (unlikely(b1i > columns + 1)) {
1938 error(errSyntaxError, getPos(),
1939 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1940 err = gTrue;
1941 break;
1943 addPixelsNeg(refLine[b1i] - 1, blackPixels);
1944 blackPixels ^= 1;
1945 if (codingLine[a0i] < columns) {
1946 if (b1i > 0) {
1947 --b1i;
1948 } else {
1949 ++b1i;
1951 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1952 b1i += 2;
1953 if (unlikely(b1i > columns + 1)) {
1954 error(errSyntaxError, getPos(),
1955 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1956 err = gTrue;
1957 break;
1961 break;
1962 case EOF:
1963 addPixels(columns, 0);
1964 eof = gTrue;
1965 break;
1966 default:
1967 error(errSyntaxError, getPos(),
1968 "Bad 2D code {0:04x} in CCITTFax stream", code1);
1969 addPixels(columns, 0);
1970 err = gTrue;
1971 break;
1975 // 1-D encoding
1976 } else {
1977 codingLine[0] = 0;
1978 a0i = 0;
1979 blackPixels = 0;
1980 while (codingLine[a0i] < columns) {
1981 code1 = 0;
1982 if (blackPixels) {
1983 do {
1984 code1 += code3 = getBlackCode();
1985 } while (code3 >= 64);
1986 } else {
1987 do {
1988 code1 += code3 = getWhiteCode();
1989 } while (code3 >= 64);
1991 addPixels(codingLine[a0i] + code1, blackPixels);
1992 blackPixels ^= 1;
1996 // check for end-of-line marker, skipping over any extra zero bits
1997 // (if EncodedByteAlign is true and EndOfLine is false, there can
1998 // be "false" EOL markers -- i.e., if the last n unused bits in
1999 // row i are set to zero, and the first 11-n bits in row i+1
2000 // happen to be zero -- so we don't look for EOL markers in this
2001 // case)
2002 gotEOL = gFalse;
2003 if (!endOfBlock && row == rows - 1) {
2004 eof = gTrue;
2005 } else if (endOfLine || !byteAlign) {
2006 code1 = lookBits(12);
2007 if (endOfLine) {
2008 while (code1 != EOF && code1 != 0x001) {
2009 eatBits(1);
2010 code1 = lookBits(12);
2012 } else {
2013 while (code1 == 0) {
2014 eatBits(1);
2015 code1 = lookBits(12);
2018 if (code1 == 0x001) {
2019 eatBits(12);
2020 gotEOL = gTrue;
2024 // byte-align the row
2025 // (Adobe apparently doesn't do byte alignment after EOL markers
2026 // -- I've seen CCITT image data streams in two different formats,
2027 // both with the byteAlign flag set:
2028 // 1. xx:x0:01:yy:yy
2029 // 2. xx:00:1y:yy:yy
2030 // where xx is the previous line, yy is the next line, and colons
2031 // separate bytes.)
2032 if (byteAlign && !gotEOL) {
2033 inputBits &= ~7;
2036 // check for end of stream
2037 if (lookBits(1) == EOF) {
2038 eof = gTrue;
2041 // get 2D encoding tag
2042 if (!eof && encoding > 0) {
2043 nextLine2D = !lookBits(1);
2044 eatBits(1);
2047 // check for end-of-block marker
2048 if (endOfBlock && !endOfLine && byteAlign) {
2049 // in this case, we didn't check for an EOL code above, so we
2050 // need to check here
2051 code1 = lookBits(24);
2052 if (code1 == 0x001001) {
2053 eatBits(12);
2054 gotEOL = gTrue;
2057 if (endOfBlock && gotEOL) {
2058 code1 = lookBits(12);
2059 if (code1 == 0x001) {
2060 eatBits(12);
2061 if (encoding > 0) {
2062 lookBits(1);
2063 eatBits(1);
2065 if (encoding >= 0) {
2066 for (i = 0; i < 4; ++i) {
2067 code1 = lookBits(12);
2068 if (code1 != 0x001) {
2069 error(errSyntaxError, getPos(),
2070 "Bad RTC code in CCITTFax stream");
2072 eatBits(12);
2073 if (encoding > 0) {
2074 lookBits(1);
2075 eatBits(1);
2079 eof = gTrue;
2082 // look for an end-of-line marker after an error -- we only do
2083 // this if we know the stream contains end-of-line markers because
2084 // the "just plow on" technique tends to work better otherwise
2085 } else if (err && endOfLine) {
2086 while (1) {
2087 code1 = lookBits(13);
2088 if (code1 == EOF) {
2089 eof = gTrue;
2090 return EOF;
2092 if ((code1 >> 1) == 0x001) {
2093 break;
2095 eatBits(1);
2097 eatBits(12);
2098 if (encoding > 0) {
2099 eatBits(1);
2100 nextLine2D = !(code1 & 1);
2104 // set up for output
2105 if (codingLine[0] > 0) {
2106 outputBits = codingLine[a0i = 0];
2107 } else {
2108 outputBits = codingLine[a0i = 1];
2111 ++row;
2114 // get a byte
2115 if (outputBits >= 8) {
2116 buf = (a0i & 1) ? 0x00 : 0xff;
2117 outputBits -= 8;
2118 if (outputBits == 0 && codingLine[a0i] < columns) {
2119 ++a0i;
2120 outputBits = codingLine[a0i] - codingLine[a0i - 1];
2122 } else {
2123 bits = 8;
2124 buf = 0;
2125 do {
2126 if (outputBits > bits) {
2127 buf <<= bits;
2128 if (!(a0i & 1)) {
2129 buf |= 0xff >> (8 - bits);
2131 outputBits -= bits;
2132 bits = 0;
2133 } else {
2134 buf <<= outputBits;
2135 if (!(a0i & 1)) {
2136 buf |= 0xff >> (8 - outputBits);
2138 bits -= outputBits;
2139 outputBits = 0;
2140 if (codingLine[a0i] < columns) {
2141 ++a0i;
2142 if (unlikely(a0i > columns)) {
2143 error(errSyntaxError, getPos(),
2144 "Bad bits {0:04x} in CCITTFax stream", bits);
2145 err = gTrue;
2146 break;
2148 outputBits = codingLine[a0i] - codingLine[a0i - 1];
2149 } else if (bits > 0) {
2150 buf <<= bits;
2151 bits = 0;
2154 } while (bits);
2156 if (black) {
2157 buf ^= 0xff;
2159 return buf;
2162 short CCITTFaxStream::getTwoDimCode() {
2163 int code;
2164 const CCITTCode *p;
2165 int n;
2167 code = 0; // make gcc happy
2168 if (endOfBlock) {
2169 if ((code = lookBits(7)) != EOF) {
2170 p = &twoDimTab1[code];
2171 if (p->bits > 0) {
2172 eatBits(p->bits);
2173 return p->n;
2176 } else {
2177 for (n = 1; n <= 7; ++n) {
2178 if ((code = lookBits(n)) == EOF) {
2179 break;
2181 if (n < 7) {
2182 code <<= 7 - n;
2184 p = &twoDimTab1[code];
2185 if (p->bits == n) {
2186 eatBits(n);
2187 return p->n;
2191 error(errSyntaxError, getPos(),
2192 "Bad two dim code ({0:04x}) in CCITTFax stream", code);
2193 return EOF;
2196 short CCITTFaxStream::getWhiteCode() {
2197 short code;
2198 const CCITTCode *p;
2199 int n;
2201 code = 0; // make gcc happy
2202 if (endOfBlock) {
2203 code = lookBits(12);
2204 if (code == EOF) {
2205 return 1;
2207 if ((code >> 5) == 0) {
2208 p = &whiteTab1[code];
2209 } else {
2210 p = &whiteTab2[code >> 3];
2212 if (p->bits > 0) {
2213 eatBits(p->bits);
2214 return p->n;
2216 } else {
2217 for (n = 1; n <= 9; ++n) {
2218 code = lookBits(n);
2219 if (code == EOF) {
2220 return 1;
2222 if (n < 9) {
2223 code <<= 9 - n;
2225 p = &whiteTab2[code];
2226 if (p->bits == n) {
2227 eatBits(n);
2228 return p->n;
2231 for (n = 11; n <= 12; ++n) {
2232 code = lookBits(n);
2233 if (code == EOF) {
2234 return 1;
2236 if (n < 12) {
2237 code <<= 12 - n;
2239 p = &whiteTab1[code];
2240 if (p->bits == n) {
2241 eatBits(n);
2242 return p->n;
2246 error(errSyntaxError, getPos(),
2247 "Bad white code ({0:04x}) in CCITTFax stream", code);
2248 // eat a bit and return a positive number so that the caller doesn't
2249 // go into an infinite loop
2250 eatBits(1);
2251 return 1;
2254 short CCITTFaxStream::getBlackCode() {
2255 short code;
2256 const CCITTCode *p;
2257 int n;
2259 code = 0; // make gcc happy
2260 if (endOfBlock) {
2261 code = lookBits(13);
2262 if (code == EOF) {
2263 return 1;
2265 if ((code >> 7) == 0) {
2266 p = &blackTab1[code];
2267 } else if ((code >> 9) == 0 && (code >> 7) != 0) {
2268 p = &blackTab2[(code >> 1) - 64];
2269 } else {
2270 p = &blackTab3[code >> 7];
2272 if (p->bits > 0) {
2273 eatBits(p->bits);
2274 return p->n;
2276 } else {
2277 for (n = 2; n <= 6; ++n) {
2278 code = lookBits(n);
2279 if (code == EOF) {
2280 return 1;
2282 if (n < 6) {
2283 code <<= 6 - n;
2285 p = &blackTab3[code];
2286 if (p->bits == n) {
2287 eatBits(n);
2288 return p->n;
2291 for (n = 7; n <= 12; ++n) {
2292 code = lookBits(n);
2293 if (code == EOF) {
2294 return 1;
2296 if (n < 12) {
2297 code <<= 12 - n;
2299 if (code >= 64) {
2300 p = &blackTab2[code - 64];
2301 if (p->bits == n) {
2302 eatBits(n);
2303 return p->n;
2307 for (n = 10; n <= 13; ++n) {
2308 code = lookBits(n);
2309 if (code == EOF) {
2310 return 1;
2312 if (n < 13) {
2313 code <<= 13 - n;
2315 p = &blackTab1[code];
2316 if (p->bits == n) {
2317 eatBits(n);
2318 return p->n;
2322 error(errSyntaxError, getPos(),
2323 "Bad black code ({0:04x}) in CCITTFax stream", code);
2324 // eat a bit and return a positive number so that the caller doesn't
2325 // go into an infinite loop
2326 eatBits(1);
2327 return 1;
2330 short CCITTFaxStream::lookBits(int n) {
2331 int c;
2333 while (inputBits < n) {
2334 if ((c = str->getChar()) == EOF) {
2335 if (inputBits == 0) {
2336 return EOF;
2338 // near the end of the stream, the caller may ask for more bits
2339 // than are available, but there may still be a valid code in
2340 // however many bits are available -- we need to return correct
2341 // data in this case
2342 return (inputBuf << (n - inputBits)) & (0xffffffff >> (32 - n));
2344 inputBuf = (inputBuf << 8) + c;
2345 inputBits += 8;
2347 return (inputBuf >> (inputBits - n)) & (0xffffffff >> (32 - n));
2350 GooString *CCITTFaxStream::getPSFilter(int psLevel, const char *indent) {
2351 GooString *s;
2352 char s1[50];
2354 if (psLevel < 2) {
2355 return NULL;
2357 if (!(s = str->getPSFilter(psLevel, indent))) {
2358 return NULL;
2360 s->append(indent)->append("<< ");
2361 if (encoding != 0) {
2362 sprintf(s1, "/K %d ", encoding);
2363 s->append(s1);
2365 if (endOfLine) {
2366 s->append("/EndOfLine true ");
2368 if (byteAlign) {
2369 s->append("/EncodedByteAlign true ");
2371 sprintf(s1, "/Columns %d ", columns);
2372 s->append(s1);
2373 if (rows != 0) {
2374 sprintf(s1, "/Rows %d ", rows);
2375 s->append(s1);
2377 if (!endOfBlock) {
2378 s->append("/EndOfBlock false ");
2380 if (black) {
2381 s->append("/BlackIs1 true ");
2383 s->append(">> /CCITTFaxDecode filter\n");
2384 return s;
2387 GBool CCITTFaxStream::isBinary(GBool last) {
2388 return str->isBinary(gTrue);
2391 #ifndef ENABLE_LIBJPEG
2393 //------------------------------------------------------------------------
2394 // DCTStream
2395 //------------------------------------------------------------------------
2397 // IDCT constants (20.12 fixed point format)
2398 #define dctCos1 4017 // cos(pi/16)
2399 #define dctSin1 799 // sin(pi/16)
2400 #define dctCos3 3406 // cos(3*pi/16)
2401 #define dctSin3 2276 // sin(3*pi/16)
2402 #define dctCos6 1567 // cos(6*pi/16)
2403 #define dctSin6 3784 // sin(6*pi/16)
2404 #define dctSqrt2 5793 // sqrt(2)
2405 #define dctSqrt1d2 2896 // sqrt(2) / 2
2407 // color conversion parameters (16.16 fixed point format)
2408 #define dctCrToR 91881 // 1.4020
2409 #define dctCbToG -22553 // -0.3441363
2410 #define dctCrToG -46802 // -0.71413636
2411 #define dctCbToB 116130 // 1.772
2413 // clip [-256,511] --> [0,255]
2414 #define dctClipOffset 256
2415 #define dctClipLength 768
2416 static Guchar dctClip[dctClipLength];
2417 static int dctClipInit = 0;
2419 // zig zag decode map
2420 static const int dctZigZag[64] = {
2422 1, 8,
2423 16, 9, 2,
2424 3, 10, 17, 24,
2425 32, 25, 18, 11, 4,
2426 5, 12, 19, 26, 33, 40,
2427 48, 41, 34, 27, 20, 13, 6,
2428 7, 14, 21, 28, 35, 42, 49, 56,
2429 57, 50, 43, 36, 29, 22, 15,
2430 23, 30, 37, 44, 51, 58,
2431 59, 52, 45, 38, 31,
2432 39, 46, 53, 60,
2433 61, 54, 47,
2434 55, 62,
2438 DCTStream::DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion):
2439 FilterStream(strA) {
2440 int i, j;
2442 colorXform = colorXformA;
2443 progressive = interleaved = gFalse;
2444 width = height = 0;
2445 mcuWidth = mcuHeight = 0;
2446 numComps = 0;
2447 comp = 0;
2448 x = y = dy = 0;
2449 for (i = 0; i < 4; ++i) {
2450 for (j = 0; j < 32; ++j) {
2451 rowBuf[i][j] = NULL;
2453 frameBuf[i] = NULL;
2456 if (!dctClipInit) {
2457 for (i = -256; i < 0; ++i)
2458 dctClip[dctClipOffset + i] = 0;
2459 for (i = 0; i < 256; ++i)
2460 dctClip[dctClipOffset + i] = i;
2461 for (i = 256; i < 512; ++i)
2462 dctClip[dctClipOffset + i] = 255;
2463 dctClipInit = 1;
2467 DCTStream::~DCTStream() {
2468 close();
2469 delete str;
2472 void DCTStream::dctReset(GBool unfiltered) {
2473 if (unfiltered)
2474 str->unfilteredReset();
2475 else
2476 str->reset();
2478 progressive = interleaved = gFalse;
2479 width = height = 0;
2480 numComps = 0;
2481 numQuantTables = 0;
2482 numDCHuffTables = 0;
2483 numACHuffTables = 0;
2484 gotJFIFMarker = gFalse;
2485 gotAdobeMarker = gFalse;
2486 restartInterval = 0;
2489 void DCTStream::unfilteredReset() {
2490 dctReset(gTrue);
2493 void DCTStream::reset() {
2494 int i, j;
2496 dctReset(gFalse);
2498 if (!readHeader()) {
2499 y = height;
2500 return;
2503 // compute MCU size
2504 if (numComps == 1) {
2505 compInfo[0].hSample = compInfo[0].vSample = 1;
2507 mcuWidth = compInfo[0].hSample;
2508 mcuHeight = compInfo[0].vSample;
2509 for (i = 1; i < numComps; ++i) {
2510 if (compInfo[i].hSample > mcuWidth) {
2511 mcuWidth = compInfo[i].hSample;
2513 if (compInfo[i].vSample > mcuHeight) {
2514 mcuHeight = compInfo[i].vSample;
2517 mcuWidth *= 8;
2518 mcuHeight *= 8;
2520 // figure out color transform
2521 if (colorXform == -1) {
2522 if (numComps == 3) {
2523 if (gotJFIFMarker) {
2524 colorXform = 1;
2525 } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
2526 compInfo[2].id == 66) { // ASCII "RGB"
2527 colorXform = 0;
2528 } else {
2529 colorXform = 1;
2531 } else {
2532 colorXform = 0;
2536 if (progressive || !interleaved) {
2538 // allocate a buffer for the whole image
2539 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2540 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
2541 if (bufWidth <= 0 || bufHeight <= 0 ||
2542 bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
2543 error(errSyntaxError, getPos(), "Invalid image size in DCT stream");
2544 y = height;
2545 return;
2547 for (i = 0; i < numComps; ++i) {
2548 frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
2549 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
2552 // read the image data
2553 do {
2554 restartMarker = 0xd0;
2555 restart();
2556 readScan();
2557 } while (readHeader());
2559 // decode
2560 decodeImage();
2562 // initialize counters
2563 comp = 0;
2564 x = 0;
2565 y = 0;
2567 } else {
2569 // allocate a buffer for one row of MCUs
2570 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2571 for (i = 0; i < numComps; ++i) {
2572 for (j = 0; j < mcuHeight; ++j) {
2573 rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
2577 // initialize counters
2578 comp = 0;
2579 x = 0;
2580 y = 0;
2581 dy = mcuHeight;
2583 restartMarker = 0xd0;
2584 restart();
2588 void DCTStream::close() {
2589 int i, j;
2591 for (i = 0; i < 4; ++i) {
2592 for (j = 0; j < 32; ++j) {
2593 gfree(rowBuf[i][j]);
2594 rowBuf[i][j] = NULL;
2596 gfree(frameBuf[i]);
2597 frameBuf[i] = NULL;
2599 FilterStream::close();
2602 int DCTStream::getChar() {
2603 int c;
2605 if (y >= height) {
2606 return EOF;
2608 if (progressive || !interleaved) {
2609 c = frameBuf[comp][y * bufWidth + x];
2610 if (++comp == numComps) {
2611 comp = 0;
2612 if (++x == width) {
2613 x = 0;
2614 ++y;
2617 } else {
2618 if (dy >= mcuHeight) {
2619 if (!readMCURow()) {
2620 y = height;
2621 return EOF;
2623 comp = 0;
2624 x = 0;
2625 dy = 0;
2627 c = rowBuf[comp][dy][x];
2628 if (++comp == numComps) {
2629 comp = 0;
2630 if (++x == width) {
2631 x = 0;
2632 ++y;
2633 ++dy;
2634 if (y == height) {
2635 readTrailer();
2640 return c;
2643 int DCTStream::lookChar() {
2644 if (y >= height) {
2645 return EOF;
2647 if (progressive || !interleaved) {
2648 return frameBuf[comp][y * bufWidth + x];
2649 } else {
2650 if (dy >= mcuHeight) {
2651 if (!readMCURow()) {
2652 y = height;
2653 return EOF;
2655 comp = 0;
2656 x = 0;
2657 dy = 0;
2659 return rowBuf[comp][dy][x];
2663 void DCTStream::restart() {
2664 int i;
2666 inputBits = 0;
2667 restartCtr = restartInterval;
2668 for (i = 0; i < numComps; ++i) {
2669 compInfo[i].prevDC = 0;
2671 eobRun = 0;
2674 // Read one row of MCUs from a sequential JPEG stream.
2675 GBool DCTStream::readMCURow() {
2676 int data1[64];
2677 Guchar data2[64];
2678 Guchar *p1, *p2;
2679 int pY, pCb, pCr, pR, pG, pB;
2680 int h, v, horiz, vert, hSub, vSub;
2681 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2682 int c;
2684 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2686 // deal with restart marker
2687 if (restartInterval > 0 && restartCtr == 0) {
2688 c = readMarker();
2689 if (c != restartMarker) {
2690 error(errSyntaxError, getPos(),
2691 "Bad DCT data: incorrect restart marker");
2692 return gFalse;
2694 if (++restartMarker == 0xd8)
2695 restartMarker = 0xd0;
2696 restart();
2699 // read one MCU
2700 for (cc = 0; cc < numComps; ++cc) {
2701 h = compInfo[cc].hSample;
2702 v = compInfo[cc].vSample;
2703 horiz = mcuWidth / h;
2704 vert = mcuHeight / v;
2705 hSub = horiz / 8;
2706 vSub = vert / 8;
2707 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2708 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2709 if (unlikely(scanInfo.dcHuffTable[cc] >= 4) || unlikely(scanInfo.acHuffTable[cc] >= 4)) {
2710 return gFalse;
2712 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2713 &acHuffTables[scanInfo.acHuffTable[cc]],
2714 &compInfo[cc].prevDC,
2715 data1)) {
2716 return gFalse;
2718 transformDataUnit(quantTables[compInfo[cc].quantTable],
2719 data1, data2);
2720 if (hSub == 1 && vSub == 1) {
2721 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2722 p1 = &rowBuf[cc][y2+y3][x1+x2];
2723 p1[0] = data2[i];
2724 p1[1] = data2[i+1];
2725 p1[2] = data2[i+2];
2726 p1[3] = data2[i+3];
2727 p1[4] = data2[i+4];
2728 p1[5] = data2[i+5];
2729 p1[6] = data2[i+6];
2730 p1[7] = data2[i+7];
2732 } else if (hSub == 2 && vSub == 2) {
2733 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2734 p1 = &rowBuf[cc][y2+y3][x1+x2];
2735 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2736 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2737 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2738 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2739 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2740 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2741 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2742 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2743 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2745 } else {
2746 i = 0;
2747 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2748 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2749 for (y5 = 0; y5 < vSub; ++y5)
2750 for (x5 = 0; x5 < hSub; ++x5)
2751 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2752 ++i;
2759 --restartCtr;
2761 // color space conversion
2762 if (colorXform) {
2763 // convert YCbCr to RGB
2764 if (numComps == 3) {
2765 for (y2 = 0; y2 < mcuHeight; ++y2) {
2766 for (x2 = 0; x2 < mcuWidth; ++x2) {
2767 pY = rowBuf[0][y2][x1+x2];
2768 pCb = rowBuf[1][y2][x1+x2] - 128;
2769 pCr = rowBuf[2][y2][x1+x2] - 128;
2770 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2771 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2772 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2773 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2774 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2775 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2778 // convert YCbCrK to CMYK (K is passed through unchanged)
2779 } else if (numComps == 4) {
2780 for (y2 = 0; y2 < mcuHeight; ++y2) {
2781 for (x2 = 0; x2 < mcuWidth; ++x2) {
2782 pY = rowBuf[0][y2][x1+x2];
2783 pCb = rowBuf[1][y2][x1+x2] - 128;
2784 pCr = rowBuf[2][y2][x1+x2] - 128;
2785 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2786 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2787 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2788 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2789 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2790 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2796 return gTrue;
2799 // Read one scan from a progressive or non-interleaved JPEG stream.
2800 void DCTStream::readScan() {
2801 int data[64];
2802 int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2803 int h, v, horiz, vert, vSub;
2804 int *p1;
2805 int c;
2807 if (scanInfo.numComps == 1) {
2808 for (cc = 0; cc < numComps; ++cc) {
2809 if (scanInfo.comp[cc]) {
2810 break;
2813 dx1 = mcuWidth / compInfo[cc].hSample;
2814 dy1 = mcuHeight / compInfo[cc].vSample;
2815 } else {
2816 dx1 = mcuWidth;
2817 dy1 = mcuHeight;
2820 for (y1 = 0; y1 < height; y1 += dy1) {
2821 for (x1 = 0; x1 < width; x1 += dx1) {
2823 // deal with restart marker
2824 if (restartInterval > 0 && restartCtr == 0) {
2825 c = readMarker();
2826 if (c != restartMarker) {
2827 error(errSyntaxError, getPos(),
2828 "Bad DCT data: incorrect restart marker");
2829 return;
2831 if (++restartMarker == 0xd8) {
2832 restartMarker = 0xd0;
2834 restart();
2837 // read one MCU
2838 for (cc = 0; cc < numComps; ++cc) {
2839 if (!scanInfo.comp[cc]) {
2840 continue;
2843 h = compInfo[cc].hSample;
2844 v = compInfo[cc].vSample;
2845 horiz = mcuWidth / h;
2846 vert = mcuHeight / v;
2847 vSub = vert / 8;
2848 for (y2 = 0; y2 < dy1; y2 += vert) {
2849 for (x2 = 0; x2 < dx1; x2 += horiz) {
2851 // pull out the current values
2852 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2853 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2854 data[i] = p1[0];
2855 data[i+1] = p1[1];
2856 data[i+2] = p1[2];
2857 data[i+3] = p1[3];
2858 data[i+4] = p1[4];
2859 data[i+5] = p1[5];
2860 data[i+6] = p1[6];
2861 data[i+7] = p1[7];
2862 p1 += bufWidth * vSub;
2865 // read one data unit
2866 if (progressive) {
2867 if (!readProgressiveDataUnit(
2868 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2869 &acHuffTables[scanInfo.acHuffTable[cc]],
2870 &compInfo[cc].prevDC,
2871 data)) {
2872 return;
2874 } else {
2875 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2876 &acHuffTables[scanInfo.acHuffTable[cc]],
2877 &compInfo[cc].prevDC,
2878 data)) {
2879 return;
2883 // add the data unit into frameBuf
2884 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2885 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2886 p1[0] = data[i];
2887 p1[1] = data[i+1];
2888 p1[2] = data[i+2];
2889 p1[3] = data[i+3];
2890 p1[4] = data[i+4];
2891 p1[5] = data[i+5];
2892 p1[6] = data[i+6];
2893 p1[7] = data[i+7];
2894 p1 += bufWidth * vSub;
2899 --restartCtr;
2904 // Read one data unit from a sequential JPEG stream.
2905 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2906 DCTHuffTable *acHuffTable,
2907 int *prevDC, int data[64]) {
2908 int run, size, amp;
2909 int c;
2910 int i, j;
2912 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2913 return gFalse;
2915 if (size > 0) {
2916 if ((amp = readAmp(size)) == 9999) {
2917 return gFalse;
2919 } else {
2920 amp = 0;
2922 data[0] = *prevDC += amp;
2923 for (i = 1; i < 64; ++i) {
2924 data[i] = 0;
2926 i = 1;
2927 while (i < 64) {
2928 run = 0;
2929 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2930 run += 0x10;
2932 if (c == 9999) {
2933 return gFalse;
2935 if (c == 0x00) {
2936 break;
2937 } else {
2938 run += (c >> 4) & 0x0f;
2939 size = c & 0x0f;
2940 amp = readAmp(size);
2941 if (amp == 9999) {
2942 return gFalse;
2944 i += run;
2945 if (i < 64) {
2946 j = dctZigZag[i++];
2947 data[j] = amp;
2951 return gTrue;
2954 // Read one data unit from a sequential JPEG stream.
2955 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2956 DCTHuffTable *acHuffTable,
2957 int *prevDC, int data[64]) {
2958 int run, size, amp, bit, c;
2959 int i, j, k;
2961 // get the DC coefficient
2962 i = scanInfo.firstCoeff;
2963 if (i == 0) {
2964 if (scanInfo.ah == 0) {
2965 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2966 return gFalse;
2968 if (size > 0) {
2969 if ((amp = readAmp(size)) == 9999) {
2970 return gFalse;
2972 } else {
2973 amp = 0;
2975 data[0] += (*prevDC += amp) << scanInfo.al;
2976 } else {
2977 if ((bit = readBit()) == 9999) {
2978 return gFalse;
2980 data[0] += bit << scanInfo.al;
2982 ++i;
2984 if (scanInfo.lastCoeff == 0) {
2985 return gTrue;
2988 // check for an EOB run
2989 if (eobRun > 0) {
2990 while (i <= scanInfo.lastCoeff) {
2991 j = dctZigZag[i++];
2992 if (data[j] != 0) {
2993 if ((bit = readBit()) == EOF) {
2994 return gFalse;
2996 if (bit) {
2997 data[j] += 1 << scanInfo.al;
3001 --eobRun;
3002 return gTrue;
3005 // read the AC coefficients
3006 while (i <= scanInfo.lastCoeff) {
3007 if ((c = readHuffSym(acHuffTable)) == 9999) {
3008 return gFalse;
3011 // ZRL
3012 if (c == 0xf0) {
3013 k = 0;
3014 while (k < 16 && i <= scanInfo.lastCoeff) {
3015 j = dctZigZag[i++];
3016 if (data[j] == 0) {
3017 ++k;
3018 } else {
3019 if ((bit = readBit()) == EOF) {
3020 return gFalse;
3022 if (bit) {
3023 data[j] += 1 << scanInfo.al;
3028 // EOB run
3029 } else if ((c & 0x0f) == 0x00) {
3030 j = c >> 4;
3031 eobRun = 0;
3032 for (k = 0; k < j; ++k) {
3033 if ((bit = readBit()) == EOF) {
3034 return gFalse;
3036 eobRun = (eobRun << 1) | bit;
3038 eobRun += 1 << j;
3039 while (i <= scanInfo.lastCoeff) {
3040 j = dctZigZag[i++];
3041 if (data[j] != 0) {
3042 if ((bit = readBit()) == EOF) {
3043 return gFalse;
3045 if (bit) {
3046 data[j] += 1 << scanInfo.al;
3050 --eobRun;
3051 break;
3053 // zero run and one AC coefficient
3054 } else {
3055 run = (c >> 4) & 0x0f;
3056 size = c & 0x0f;
3057 if ((amp = readAmp(size)) == 9999) {
3058 return gFalse;
3060 j = 0; // make gcc happy
3061 for (k = 0; k <= run && i <= scanInfo.lastCoeff; ++k) {
3062 j = dctZigZag[i++];
3063 while (data[j] != 0 && i <= scanInfo.lastCoeff) {
3064 if ((bit = readBit()) == EOF) {
3065 return gFalse;
3067 if (bit) {
3068 data[j] += 1 << scanInfo.al;
3070 j = dctZigZag[i++];
3073 data[j] = amp << scanInfo.al;
3077 return gTrue;
3080 // Decode a progressive JPEG image.
3081 void DCTStream::decodeImage() {
3082 int dataIn[64];
3083 Guchar dataOut[64];
3084 Gushort *quantTable;
3085 int pY, pCb, pCr, pR, pG, pB;
3086 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
3087 int h, v, horiz, vert, hSub, vSub;
3088 int *p0, *p1, *p2;
3090 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
3091 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
3092 for (cc = 0; cc < numComps; ++cc) {
3093 quantTable = quantTables[compInfo[cc].quantTable];
3094 h = compInfo[cc].hSample;
3095 v = compInfo[cc].vSample;
3096 horiz = mcuWidth / h;
3097 vert = mcuHeight / v;
3098 hSub = horiz / 8;
3099 vSub = vert / 8;
3100 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
3101 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
3103 // pull out the coded data unit
3104 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3105 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3106 dataIn[i] = p1[0];
3107 dataIn[i+1] = p1[1];
3108 dataIn[i+2] = p1[2];
3109 dataIn[i+3] = p1[3];
3110 dataIn[i+4] = p1[4];
3111 dataIn[i+5] = p1[5];
3112 dataIn[i+6] = p1[6];
3113 dataIn[i+7] = p1[7];
3114 p1 += bufWidth * vSub;
3117 // transform
3118 transformDataUnit(quantTable, dataIn, dataOut);
3120 // store back into frameBuf, doing replication for
3121 // subsampled components
3122 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3123 if (hSub == 1 && vSub == 1) {
3124 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3125 p1[0] = dataOut[i] & 0xff;
3126 p1[1] = dataOut[i+1] & 0xff;
3127 p1[2] = dataOut[i+2] & 0xff;
3128 p1[3] = dataOut[i+3] & 0xff;
3129 p1[4] = dataOut[i+4] & 0xff;
3130 p1[5] = dataOut[i+5] & 0xff;
3131 p1[6] = dataOut[i+6] & 0xff;
3132 p1[7] = dataOut[i+7] & 0xff;
3133 p1 += bufWidth;
3135 } else if (hSub == 2 && vSub == 2) {
3136 p2 = p1 + bufWidth;
3137 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
3138 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
3139 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
3140 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
3141 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
3142 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
3143 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
3144 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
3145 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
3146 p1 += bufWidth * 2;
3147 p2 += bufWidth * 2;
3149 } else {
3150 i = 0;
3151 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
3152 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
3153 p2 = p1 + x4;
3154 for (y5 = 0; y5 < vSub; ++y5) {
3155 for (x5 = 0; x5 < hSub; ++x5) {
3156 p2[x5] = dataOut[i] & 0xff;
3158 p2 += bufWidth;
3160 ++i;
3162 p1 += bufWidth * vSub;
3169 // color space conversion
3170 if (colorXform) {
3171 // convert YCbCr to RGB
3172 if (numComps == 3) {
3173 for (y2 = 0; y2 < mcuHeight; ++y2) {
3174 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
3175 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
3176 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
3177 for (x2 = 0; x2 < mcuWidth; ++x2) {
3178 pY = *p0;
3179 pCb = *p1 - 128;
3180 pCr = *p2 - 128;
3181 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3182 *p0++ = dctClip[dctClipOffset + pR];
3183 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
3184 32768) >> 16;
3185 *p1++ = dctClip[dctClipOffset + pG];
3186 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3187 *p2++ = dctClip[dctClipOffset + pB];
3190 // convert YCbCrK to CMYK (K is passed through unchanged)
3191 } else if (numComps == 4) {
3192 for (y2 = 0; y2 < mcuHeight; ++y2) {
3193 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
3194 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
3195 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
3196 for (x2 = 0; x2 < mcuWidth; ++x2) {
3197 pY = *p0;
3198 pCb = *p1 - 128;
3199 pCr = *p2 - 128;
3200 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3201 *p0++ = 255 - dctClip[dctClipOffset + pR];
3202 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
3203 32768) >> 16;
3204 *p1++ = 255 - dctClip[dctClipOffset + pG];
3205 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3206 *p2++ = 255 - dctClip[dctClipOffset + pB];
3215 // Transform one data unit -- this performs the dequantization and
3216 // IDCT steps. This IDCT algorithm is taken from:
3217 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
3218 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
3219 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
3220 // 988-991.
3221 // The stage numbers mentioned in the comments refer to Figure 1 in this
3222 // paper.
3223 void DCTStream::transformDataUnit(Gushort *quantTable,
3224 int dataIn[64], Guchar dataOut[64]) {
3225 int v0, v1, v2, v3, v4, v5, v6, v7, t;
3226 int *p;
3227 int i;
3229 // dequant
3230 for (i = 0; i < 64; ++i) {
3231 dataIn[i] *= quantTable[i];
3234 // inverse DCT on rows
3235 for (i = 0; i < 64; i += 8) {
3236 p = dataIn + i;
3238 // check for all-zero AC coefficients
3239 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
3240 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
3241 t = (dctSqrt2 * p[0] + 512) >> 10;
3242 p[0] = t;
3243 p[1] = t;
3244 p[2] = t;
3245 p[3] = t;
3246 p[4] = t;
3247 p[5] = t;
3248 p[6] = t;
3249 p[7] = t;
3250 continue;
3253 // stage 4
3254 v0 = (dctSqrt2 * p[0] + 128) >> 8;
3255 v1 = (dctSqrt2 * p[4] + 128) >> 8;
3256 v2 = p[2];
3257 v3 = p[6];
3258 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
3259 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
3260 v5 = p[3] << 4;
3261 v6 = p[5] << 4;
3263 // stage 3
3264 t = (v0 - v1+ 1) >> 1;
3265 v0 = (v0 + v1 + 1) >> 1;
3266 v1 = t;
3267 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
3268 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
3269 v3 = t;
3270 t = (v4 - v6 + 1) >> 1;
3271 v4 = (v4 + v6 + 1) >> 1;
3272 v6 = t;
3273 t = (v7 + v5 + 1) >> 1;
3274 v5 = (v7 - v5 + 1) >> 1;
3275 v7 = t;
3277 // stage 2
3278 t = (v0 - v3 + 1) >> 1;
3279 v0 = (v0 + v3 + 1) >> 1;
3280 v3 = t;
3281 t = (v1 - v2 + 1) >> 1;
3282 v1 = (v1 + v2 + 1) >> 1;
3283 v2 = t;
3284 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
3285 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
3286 v7 = t;
3287 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
3288 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
3289 v6 = t;
3291 // stage 1
3292 p[0] = v0 + v7;
3293 p[7] = v0 - v7;
3294 p[1] = v1 + v6;
3295 p[6] = v1 - v6;
3296 p[2] = v2 + v5;
3297 p[5] = v2 - v5;
3298 p[3] = v3 + v4;
3299 p[4] = v3 - v4;
3302 // inverse DCT on columns
3303 for (i = 0; i < 8; ++i) {
3304 p = dataIn + i;
3306 // check for all-zero AC coefficients
3307 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
3308 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
3309 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
3310 p[0*8] = t;
3311 p[1*8] = t;
3312 p[2*8] = t;
3313 p[3*8] = t;
3314 p[4*8] = t;
3315 p[5*8] = t;
3316 p[6*8] = t;
3317 p[7*8] = t;
3318 continue;
3321 // stage 4
3322 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
3323 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
3324 v2 = p[2*8];
3325 v3 = p[6*8];
3326 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
3327 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
3328 v5 = p[3*8];
3329 v6 = p[5*8];
3331 // stage 3
3332 t = (v0 - v1 + 1) >> 1;
3333 v0 = (v0 + v1 + 1) >> 1;
3334 v1 = t;
3335 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
3336 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
3337 v3 = t;
3338 t = (v4 - v6 + 1) >> 1;
3339 v4 = (v4 + v6 + 1) >> 1;
3340 v6 = t;
3341 t = (v7 + v5 + 1) >> 1;
3342 v5 = (v7 - v5 + 1) >> 1;
3343 v7 = t;
3345 // stage 2
3346 t = (v0 - v3 + 1) >> 1;
3347 v0 = (v0 + v3 + 1) >> 1;
3348 v3 = t;
3349 t = (v1 - v2 + 1) >> 1;
3350 v1 = (v1 + v2 + 1) >> 1;
3351 v2 = t;
3352 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
3353 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
3354 v7 = t;
3355 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
3356 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
3357 v6 = t;
3359 // stage 1
3360 p[0*8] = v0 + v7;
3361 p[7*8] = v0 - v7;
3362 p[1*8] = v1 + v6;
3363 p[6*8] = v1 - v6;
3364 p[2*8] = v2 + v5;
3365 p[5*8] = v2 - v5;
3366 p[3*8] = v3 + v4;
3367 p[4*8] = v3 - v4;
3370 // convert to 8-bit integers
3371 for (i = 0; i < 64; ++i) {
3372 const int ix = dctClipOffset + 128 + ((dataIn[i] + 8) >> 4);
3373 if (unlikely(ix < 0 || ix >= dctClipLength)) {
3374 dataOut[i] = 0;
3375 } else {
3376 dataOut[i] = dctClip[ix];
3381 int DCTStream::readHuffSym(DCTHuffTable *table) {
3382 Gushort code;
3383 int bit;
3384 int codeBits;
3386 code = 0;
3387 codeBits = 0;
3388 do {
3389 // add a bit to the code
3390 if ((bit = readBit()) == EOF) {
3391 return 9999;
3393 code = (code << 1) + bit;
3394 ++codeBits;
3396 // look up code
3397 if (code < table->firstCode[codeBits]) {
3398 break;
3400 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
3401 code -= table->firstCode[codeBits];
3402 return table->sym[table->firstSym[codeBits] + code];
3404 } while (codeBits < 16);
3406 error(errSyntaxError, getPos(), "Bad Huffman code in DCT stream");
3407 return 9999;
3410 int DCTStream::readAmp(int size) {
3411 int amp, bit;
3412 int bits;
3414 amp = 0;
3415 for (bits = 0; bits < size; ++bits) {
3416 if ((bit = readBit()) == EOF)
3417 return 9999;
3418 amp = (amp << 1) + bit;
3420 if (amp < (1 << (size - 1)))
3421 amp -= (1 << size) - 1;
3422 return amp;
3425 int DCTStream::readBit() {
3426 int bit;
3427 int c, c2;
3429 if (inputBits == 0) {
3430 if ((c = str->getChar()) == EOF)
3431 return EOF;
3432 if (c == 0xff) {
3433 do {
3434 c2 = str->getChar();
3435 } while (c2 == 0xff);
3436 if (c2 != 0x00) {
3437 error(errSyntaxError, getPos(), "Bad DCT data: missing 00 after ff");
3438 return EOF;
3441 inputBuf = c;
3442 inputBits = 8;
3444 bit = (inputBuf >> (inputBits - 1)) & 1;
3445 --inputBits;
3446 return bit;
3449 GBool DCTStream::readHeader() {
3450 GBool doScan;
3451 int n;
3452 int c = 0;
3453 int i;
3455 // read headers
3456 doScan = gFalse;
3457 while (!doScan) {
3458 c = readMarker();
3459 switch (c) {
3460 case 0xc0: // SOF0 (sequential)
3461 case 0xc1: // SOF1 (extended sequential)
3462 if (!readBaselineSOF()) {
3463 return gFalse;
3465 break;
3466 case 0xc2: // SOF2 (progressive)
3467 if (!readProgressiveSOF()) {
3468 return gFalse;
3470 break;
3471 case 0xc4: // DHT
3472 if (!readHuffmanTables()) {
3473 return gFalse;
3475 break;
3476 case 0xd8: // SOI
3477 break;
3478 case 0xd9: // EOI
3479 return gFalse;
3480 case 0xda: // SOS
3481 if (!readScanInfo()) {
3482 return gFalse;
3484 doScan = gTrue;
3485 break;
3486 case 0xdb: // DQT
3487 if (!readQuantTables()) {
3488 return gFalse;
3490 break;
3491 case 0xdd: // DRI
3492 if (!readRestartInterval()) {
3493 return gFalse;
3495 break;
3496 case 0xe0: // APP0
3497 if (!readJFIFMarker()) {
3498 return gFalse;
3500 break;
3501 case 0xee: // APP14
3502 if (!readAdobeMarker()) {
3503 return gFalse;
3505 break;
3506 case EOF:
3507 error(errSyntaxError, getPos(), "Bad DCT header");
3508 return gFalse;
3509 default:
3510 // skip APPn / COM / etc.
3511 if (c >= 0xe0) {
3512 n = read16() - 2;
3513 for (i = 0; i < n; ++i) {
3514 str->getChar();
3516 } else {
3517 error(errSyntaxError, getPos(), "Unknown DCT marker <{0:02x}>", c);
3518 return gFalse;
3520 break;
3524 return gTrue;
3527 GBool DCTStream::readBaselineSOF() {
3528 int length;
3529 int prec;
3530 int i;
3531 int c;
3533 length = read16();
3534 prec = str->getChar();
3535 height = read16();
3536 width = read16();
3537 numComps = str->getChar();
3538 if (numComps <= 0 || numComps > 4) {
3539 error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
3540 numComps = 0;
3541 return gFalse;
3543 if (prec != 8) {
3544 error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
3545 return gFalse;
3547 for (i = 0; i < numComps; ++i) {
3548 compInfo[i].id = str->getChar();
3549 c = str->getChar();
3550 compInfo[i].hSample = (c >> 4) & 0x0f;
3551 compInfo[i].vSample = c & 0x0f;
3552 compInfo[i].quantTable = str->getChar();
3553 if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 ||
3554 compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
3555 error(errSyntaxError, getPos(), "Bad DCT sampling factor");
3556 return gFalse;
3558 if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
3559 error(errSyntaxError, getPos(), "Bad DCT quant table selector");
3560 return gFalse;
3563 progressive = gFalse;
3564 return gTrue;
3567 GBool DCTStream::readProgressiveSOF() {
3568 int length;
3569 int prec;
3570 int i;
3571 int c;
3573 length = read16();
3574 prec = str->getChar();
3575 height = read16();
3576 width = read16();
3577 numComps = str->getChar();
3578 if (prec != 8) {
3579 error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
3580 return gFalse;
3582 for (i = 0; i < numComps; ++i) {
3583 compInfo[i].id = str->getChar();
3584 c = str->getChar();
3585 compInfo[i].hSample = (c >> 4) & 0x0f;
3586 compInfo[i].vSample = c & 0x0f;
3587 compInfo[i].quantTable = str->getChar();
3588 if (compInfo[i].hSample < 1 || compInfo[i].hSample > 4 ||
3589 compInfo[i].vSample < 1 || compInfo[i].vSample > 4) {
3590 error(errSyntaxError, getPos(), "Bad DCT sampling factor");
3591 return gFalse;
3593 if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
3594 error(errSyntaxError, getPos(), "Bad DCT quant table selector");
3595 return gFalse;
3598 progressive = gTrue;
3599 return gTrue;
3602 GBool DCTStream::readScanInfo() {
3603 int length;
3604 int id, c;
3605 int i, j;
3607 length = read16() - 2;
3608 scanInfo.numComps = str->getChar();
3609 if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
3610 error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
3611 scanInfo.numComps = 0;
3612 return gFalse;
3614 --length;
3615 if (length != 2 * scanInfo.numComps + 3) {
3616 error(errSyntaxError, getPos(), "Bad DCT scan info block");
3617 return gFalse;
3619 interleaved = scanInfo.numComps == numComps;
3620 for (j = 0; j < numComps; ++j) {
3621 scanInfo.comp[j] = gFalse;
3622 scanInfo.dcHuffTable[j] = 0;
3623 scanInfo.acHuffTable[j] = 0;
3625 for (i = 0; i < scanInfo.numComps; ++i) {
3626 id = str->getChar();
3627 // some (broken) DCT streams reuse ID numbers, but at least they
3628 // keep the components in order, so we check compInfo[i] first to
3629 // work around the problem
3630 if (id == compInfo[i].id) {
3631 j = i;
3632 } else {
3633 for (j = 0; j < numComps; ++j) {
3634 if (id == compInfo[j].id) {
3635 break;
3638 if (j == numComps) {
3639 error(errSyntaxError, getPos(),
3640 "Bad DCT component ID in scan info block");
3641 return gFalse;
3644 scanInfo.comp[j] = gTrue;
3645 c = str->getChar();
3646 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
3647 scanInfo.acHuffTable[j] = c & 0x0f;
3649 scanInfo.firstCoeff = str->getChar();
3650 scanInfo.lastCoeff = str->getChar();
3651 if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
3652 scanInfo.firstCoeff > scanInfo.lastCoeff) {
3653 error(errSyntaxError, getPos(),
3654 "Bad DCT coefficient numbers in scan info block");
3655 return gFalse;
3657 c = str->getChar();
3658 scanInfo.ah = (c >> 4) & 0x0f;
3659 scanInfo.al = c & 0x0f;
3660 return gTrue;
3663 GBool DCTStream::readQuantTables() {
3664 int length, prec, i, index;
3666 length = read16() - 2;
3667 while (length > 0) {
3668 index = str->getChar();
3669 prec = (index >> 4) & 0x0f;
3670 index &= 0x0f;
3671 if (prec > 1 || index >= 4) {
3672 error(errSyntaxError, getPos(), "Bad DCT quantization table");
3673 return gFalse;
3675 if (index == numQuantTables) {
3676 numQuantTables = index + 1;
3678 for (i = 0; i < 64; ++i) {
3679 if (prec) {
3680 quantTables[index][dctZigZag[i]] = read16();
3681 } else {
3682 quantTables[index][dctZigZag[i]] = str->getChar();
3685 if (prec) {
3686 length -= 129;
3687 } else {
3688 length -= 65;
3691 return gTrue;
3694 GBool DCTStream::readHuffmanTables() {
3695 DCTHuffTable *tbl;
3696 int length;
3697 int index;
3698 Gushort code;
3699 Guchar sym;
3700 int i;
3701 int c;
3703 length = read16() - 2;
3704 while (length > 0) {
3705 index = str->getChar();
3706 --length;
3707 if ((index & 0x0f) >= 4) {
3708 error(errSyntaxError, getPos(), "Bad DCT Huffman table");
3709 return gFalse;
3711 if (index & 0x10) {
3712 index &= 0x0f;
3713 if (index >= numACHuffTables)
3714 numACHuffTables = index+1;
3715 tbl = &acHuffTables[index];
3716 } else {
3717 index &= 0x0f;
3718 if (index >= numDCHuffTables)
3719 numDCHuffTables = index+1;
3720 tbl = &dcHuffTables[index];
3722 sym = 0;
3723 code = 0;
3724 for (i = 1; i <= 16; ++i) {
3725 c = str->getChar();
3726 tbl->firstSym[i] = sym;
3727 tbl->firstCode[i] = code;
3728 tbl->numCodes[i] = c;
3729 sym += c;
3730 code = (code + c) << 1;
3732 length -= 16;
3733 for (i = 0; i < sym; ++i)
3734 tbl->sym[i] = str->getChar();
3735 length -= sym;
3737 return gTrue;
3740 GBool DCTStream::readRestartInterval() {
3741 int length;
3743 length = read16();
3744 if (length != 4) {
3745 error(errSyntaxError, getPos(), "Bad DCT restart interval");
3746 return gFalse;
3748 restartInterval = read16();
3749 return gTrue;
3752 GBool DCTStream::readJFIFMarker() {
3753 int length, i;
3754 char buf[5];
3755 int c;
3757 length = read16();
3758 length -= 2;
3759 if (length >= 5) {
3760 for (i = 0; i < 5; ++i) {
3761 if ((c = str->getChar()) == EOF) {
3762 error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
3763 return gFalse;
3765 buf[i] = c;
3767 length -= 5;
3768 if (!memcmp(buf, "JFIF\0", 5)) {
3769 gotJFIFMarker = gTrue;
3772 while (length > 0) {
3773 if (str->getChar() == EOF) {
3774 error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
3775 return gFalse;
3777 --length;
3779 return gTrue;
3782 GBool DCTStream::readAdobeMarker() {
3783 int length, i;
3784 char buf[12];
3785 int c;
3787 length = read16();
3788 if (length < 14) {
3789 goto err;
3791 for (i = 0; i < 12; ++i) {
3792 if ((c = str->getChar()) == EOF) {
3793 goto err;
3795 buf[i] = c;
3797 if (strncmp(buf, "Adobe", 5)) {
3798 goto err;
3800 colorXform = buf[11];
3801 gotAdobeMarker = gTrue;
3802 for (i = 14; i < length; ++i) {
3803 if (str->getChar() == EOF) {
3804 goto err;
3807 return gTrue;
3809 err:
3810 error(errSyntaxError, getPos(), "Bad DCT Adobe APP14 marker");
3811 return gFalse;
3814 GBool DCTStream::readTrailer() {
3815 int c;
3817 c = readMarker();
3818 if (c != 0xd9) { // EOI
3819 error(errSyntaxError, getPos(), "Bad DCT trailer");
3820 return gFalse;
3822 return gTrue;
3825 int DCTStream::readMarker() {
3826 int c;
3828 do {
3829 do {
3830 c = str->getChar();
3831 } while (c != 0xff && c != EOF);
3832 while (c == 0xff) {
3833 c = str->getChar();
3835 } while (c == 0x00);
3836 return c;
3839 int DCTStream::read16() {
3840 int c1, c2;
3842 if ((c1 = str->getChar()) == EOF)
3843 return EOF;
3844 if ((c2 = str->getChar()) == EOF)
3845 return EOF;
3846 return (c1 << 8) + c2;
3849 GooString *DCTStream::getPSFilter(int psLevel, const char *indent) {
3850 GooString *s;
3852 if (psLevel < 2) {
3853 return NULL;
3855 if (!(s = str->getPSFilter(psLevel, indent))) {
3856 return NULL;
3858 s->append(indent)->append("<< >> /DCTDecode filter\n");
3859 return s;
3862 GBool DCTStream::isBinary(GBool last) {
3863 return str->isBinary(gTrue);
3866 #endif
3868 #ifndef ENABLE_ZLIB
3869 //------------------------------------------------------------------------
3870 // FlateStream
3871 //------------------------------------------------------------------------
3873 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3874 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3877 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3878 {0, 3},
3879 {0, 4},
3880 {0, 5},
3881 {0, 6},
3882 {0, 7},
3883 {0, 8},
3884 {0, 9},
3885 {0, 10},
3886 {1, 11},
3887 {1, 13},
3888 {1, 15},
3889 {1, 17},
3890 {2, 19},
3891 {2, 23},
3892 {2, 27},
3893 {2, 31},
3894 {3, 35},
3895 {3, 43},
3896 {3, 51},
3897 {3, 59},
3898 {4, 67},
3899 {4, 83},
3900 {4, 99},
3901 {4, 115},
3902 {5, 131},
3903 {5, 163},
3904 {5, 195},
3905 {5, 227},
3906 {0, 258},
3907 {0, 258},
3908 {0, 258}
3911 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3912 { 0, 1},
3913 { 0, 2},
3914 { 0, 3},
3915 { 0, 4},
3916 { 1, 5},
3917 { 1, 7},
3918 { 2, 9},
3919 { 2, 13},
3920 { 3, 17},
3921 { 3, 25},
3922 { 4, 33},
3923 { 4, 49},
3924 { 5, 65},
3925 { 5, 97},
3926 { 6, 129},
3927 { 6, 193},
3928 { 7, 257},
3929 { 7, 385},
3930 { 8, 513},
3931 { 8, 769},
3932 { 9, 1025},
3933 { 9, 1537},
3934 {10, 2049},
3935 {10, 3073},
3936 {11, 4097},
3937 {11, 6145},
3938 {12, 8193},
3939 {12, 12289},
3940 {13, 16385},
3941 {13, 24577}
3944 static FlateCode flateFixedLitCodeTabCodes[512] = {
3945 {7, 0x0100},
3946 {8, 0x0050},
3947 {8, 0x0010},
3948 {8, 0x0118},
3949 {7, 0x0110},
3950 {8, 0x0070},
3951 {8, 0x0030},
3952 {9, 0x00c0},
3953 {7, 0x0108},
3954 {8, 0x0060},
3955 {8, 0x0020},
3956 {9, 0x00a0},
3957 {8, 0x0000},
3958 {8, 0x0080},
3959 {8, 0x0040},
3960 {9, 0x00e0},
3961 {7, 0x0104},
3962 {8, 0x0058},
3963 {8, 0x0018},
3964 {9, 0x0090},
3965 {7, 0x0114},
3966 {8, 0x0078},
3967 {8, 0x0038},
3968 {9, 0x00d0},
3969 {7, 0x010c},
3970 {8, 0x0068},
3971 {8, 0x0028},
3972 {9, 0x00b0},
3973 {8, 0x0008},
3974 {8, 0x0088},
3975 {8, 0x0048},
3976 {9, 0x00f0},
3977 {7, 0x0102},
3978 {8, 0x0054},
3979 {8, 0x0014},
3980 {8, 0x011c},
3981 {7, 0x0112},
3982 {8, 0x0074},
3983 {8, 0x0034},
3984 {9, 0x00c8},
3985 {7, 0x010a},
3986 {8, 0x0064},
3987 {8, 0x0024},
3988 {9, 0x00a8},
3989 {8, 0x0004},
3990 {8, 0x0084},
3991 {8, 0x0044},
3992 {9, 0x00e8},
3993 {7, 0x0106},
3994 {8, 0x005c},
3995 {8, 0x001c},
3996 {9, 0x0098},
3997 {7, 0x0116},
3998 {8, 0x007c},
3999 {8, 0x003c},
4000 {9, 0x00d8},
4001 {7, 0x010e},
4002 {8, 0x006c},
4003 {8, 0x002c},
4004 {9, 0x00b8},
4005 {8, 0x000c},
4006 {8, 0x008c},
4007 {8, 0x004c},
4008 {9, 0x00f8},
4009 {7, 0x0101},
4010 {8, 0x0052},
4011 {8, 0x0012},
4012 {8, 0x011a},
4013 {7, 0x0111},
4014 {8, 0x0072},
4015 {8, 0x0032},
4016 {9, 0x00c4},
4017 {7, 0x0109},
4018 {8, 0x0062},
4019 {8, 0x0022},
4020 {9, 0x00a4},
4021 {8, 0x0002},
4022 {8, 0x0082},
4023 {8, 0x0042},
4024 {9, 0x00e4},
4025 {7, 0x0105},
4026 {8, 0x005a},
4027 {8, 0x001a},
4028 {9, 0x0094},
4029 {7, 0x0115},
4030 {8, 0x007a},
4031 {8, 0x003a},
4032 {9, 0x00d4},
4033 {7, 0x010d},
4034 {8, 0x006a},
4035 {8, 0x002a},
4036 {9, 0x00b4},
4037 {8, 0x000a},
4038 {8, 0x008a},
4039 {8, 0x004a},
4040 {9, 0x00f4},
4041 {7, 0x0103},
4042 {8, 0x0056},
4043 {8, 0x0016},
4044 {8, 0x011e},
4045 {7, 0x0113},
4046 {8, 0x0076},
4047 {8, 0x0036},
4048 {9, 0x00cc},
4049 {7, 0x010b},
4050 {8, 0x0066},
4051 {8, 0x0026},
4052 {9, 0x00ac},
4053 {8, 0x0006},
4054 {8, 0x0086},
4055 {8, 0x0046},
4056 {9, 0x00ec},
4057 {7, 0x0107},
4058 {8, 0x005e},
4059 {8, 0x001e},
4060 {9, 0x009c},
4061 {7, 0x0117},
4062 {8, 0x007e},
4063 {8, 0x003e},
4064 {9, 0x00dc},
4065 {7, 0x010f},
4066 {8, 0x006e},
4067 {8, 0x002e},
4068 {9, 0x00bc},
4069 {8, 0x000e},
4070 {8, 0x008e},
4071 {8, 0x004e},
4072 {9, 0x00fc},
4073 {7, 0x0100},
4074 {8, 0x0051},
4075 {8, 0x0011},
4076 {8, 0x0119},
4077 {7, 0x0110},
4078 {8, 0x0071},
4079 {8, 0x0031},
4080 {9, 0x00c2},
4081 {7, 0x0108},
4082 {8, 0x0061},
4083 {8, 0x0021},
4084 {9, 0x00a2},
4085 {8, 0x0001},
4086 {8, 0x0081},
4087 {8, 0x0041},
4088 {9, 0x00e2},
4089 {7, 0x0104},
4090 {8, 0x0059},
4091 {8, 0x0019},
4092 {9, 0x0092},
4093 {7, 0x0114},
4094 {8, 0x0079},
4095 {8, 0x0039},
4096 {9, 0x00d2},
4097 {7, 0x010c},
4098 {8, 0x0069},
4099 {8, 0x0029},
4100 {9, 0x00b2},
4101 {8, 0x0009},
4102 {8, 0x0089},
4103 {8, 0x0049},
4104 {9, 0x00f2},
4105 {7, 0x0102},
4106 {8, 0x0055},
4107 {8, 0x0015},
4108 {8, 0x011d},
4109 {7, 0x0112},
4110 {8, 0x0075},
4111 {8, 0x0035},
4112 {9, 0x00ca},
4113 {7, 0x010a},
4114 {8, 0x0065},
4115 {8, 0x0025},
4116 {9, 0x00aa},
4117 {8, 0x0005},
4118 {8, 0x0085},
4119 {8, 0x0045},
4120 {9, 0x00ea},
4121 {7, 0x0106},
4122 {8, 0x005d},
4123 {8, 0x001d},
4124 {9, 0x009a},
4125 {7, 0x0116},
4126 {8, 0x007d},
4127 {8, 0x003d},
4128 {9, 0x00da},
4129 {7, 0x010e},
4130 {8, 0x006d},
4131 {8, 0x002d},
4132 {9, 0x00ba},
4133 {8, 0x000d},
4134 {8, 0x008d},
4135 {8, 0x004d},
4136 {9, 0x00fa},
4137 {7, 0x0101},
4138 {8, 0x0053},
4139 {8, 0x0013},
4140 {8, 0x011b},
4141 {7, 0x0111},
4142 {8, 0x0073},
4143 {8, 0x0033},
4144 {9, 0x00c6},
4145 {7, 0x0109},
4146 {8, 0x0063},
4147 {8, 0x0023},
4148 {9, 0x00a6},
4149 {8, 0x0003},
4150 {8, 0x0083},
4151 {8, 0x0043},
4152 {9, 0x00e6},
4153 {7, 0x0105},
4154 {8, 0x005b},
4155 {8, 0x001b},
4156 {9, 0x0096},
4157 {7, 0x0115},
4158 {8, 0x007b},
4159 {8, 0x003b},
4160 {9, 0x00d6},
4161 {7, 0x010d},
4162 {8, 0x006b},
4163 {8, 0x002b},
4164 {9, 0x00b6},
4165 {8, 0x000b},
4166 {8, 0x008b},
4167 {8, 0x004b},
4168 {9, 0x00f6},
4169 {7, 0x0103},
4170 {8, 0x0057},
4171 {8, 0x0017},
4172 {8, 0x011f},
4173 {7, 0x0113},
4174 {8, 0x0077},
4175 {8, 0x0037},
4176 {9, 0x00ce},
4177 {7, 0x010b},
4178 {8, 0x0067},
4179 {8, 0x0027},
4180 {9, 0x00ae},
4181 {8, 0x0007},
4182 {8, 0x0087},
4183 {8, 0x0047},
4184 {9, 0x00ee},
4185 {7, 0x0107},
4186 {8, 0x005f},
4187 {8, 0x001f},
4188 {9, 0x009e},
4189 {7, 0x0117},
4190 {8, 0x007f},
4191 {8, 0x003f},
4192 {9, 0x00de},
4193 {7, 0x010f},
4194 {8, 0x006f},
4195 {8, 0x002f},
4196 {9, 0x00be},
4197 {8, 0x000f},
4198 {8, 0x008f},
4199 {8, 0x004f},
4200 {9, 0x00fe},
4201 {7, 0x0100},
4202 {8, 0x0050},
4203 {8, 0x0010},
4204 {8, 0x0118},
4205 {7, 0x0110},
4206 {8, 0x0070},
4207 {8, 0x0030},
4208 {9, 0x00c1},
4209 {7, 0x0108},
4210 {8, 0x0060},
4211 {8, 0x0020},
4212 {9, 0x00a1},
4213 {8, 0x0000},
4214 {8, 0x0080},
4215 {8, 0x0040},
4216 {9, 0x00e1},
4217 {7, 0x0104},
4218 {8, 0x0058},
4219 {8, 0x0018},
4220 {9, 0x0091},
4221 {7, 0x0114},
4222 {8, 0x0078},
4223 {8, 0x0038},
4224 {9, 0x00d1},
4225 {7, 0x010c},
4226 {8, 0x0068},
4227 {8, 0x0028},
4228 {9, 0x00b1},
4229 {8, 0x0008},
4230 {8, 0x0088},
4231 {8, 0x0048},
4232 {9, 0x00f1},
4233 {7, 0x0102},
4234 {8, 0x0054},
4235 {8, 0x0014},
4236 {8, 0x011c},
4237 {7, 0x0112},
4238 {8, 0x0074},
4239 {8, 0x0034},
4240 {9, 0x00c9},
4241 {7, 0x010a},
4242 {8, 0x0064},
4243 {8, 0x0024},
4244 {9, 0x00a9},
4245 {8, 0x0004},
4246 {8, 0x0084},
4247 {8, 0x0044},
4248 {9, 0x00e9},
4249 {7, 0x0106},
4250 {8, 0x005c},
4251 {8, 0x001c},
4252 {9, 0x0099},
4253 {7, 0x0116},
4254 {8, 0x007c},
4255 {8, 0x003c},
4256 {9, 0x00d9},
4257 {7, 0x010e},
4258 {8, 0x006c},
4259 {8, 0x002c},
4260 {9, 0x00b9},
4261 {8, 0x000c},
4262 {8, 0x008c},
4263 {8, 0x004c},
4264 {9, 0x00f9},
4265 {7, 0x0101},
4266 {8, 0x0052},
4267 {8, 0x0012},
4268 {8, 0x011a},
4269 {7, 0x0111},
4270 {8, 0x0072},
4271 {8, 0x0032},
4272 {9, 0x00c5},
4273 {7, 0x0109},
4274 {8, 0x0062},
4275 {8, 0x0022},
4276 {9, 0x00a5},
4277 {8, 0x0002},
4278 {8, 0x0082},
4279 {8, 0x0042},
4280 {9, 0x00e5},
4281 {7, 0x0105},
4282 {8, 0x005a},
4283 {8, 0x001a},
4284 {9, 0x0095},
4285 {7, 0x0115},
4286 {8, 0x007a},
4287 {8, 0x003a},
4288 {9, 0x00d5},
4289 {7, 0x010d},
4290 {8, 0x006a},
4291 {8, 0x002a},
4292 {9, 0x00b5},
4293 {8, 0x000a},
4294 {8, 0x008a},
4295 {8, 0x004a},
4296 {9, 0x00f5},
4297 {7, 0x0103},
4298 {8, 0x0056},
4299 {8, 0x0016},
4300 {8, 0x011e},
4301 {7, 0x0113},
4302 {8, 0x0076},
4303 {8, 0x0036},
4304 {9, 0x00cd},
4305 {7, 0x010b},
4306 {8, 0x0066},
4307 {8, 0x0026},
4308 {9, 0x00ad},
4309 {8, 0x0006},
4310 {8, 0x0086},
4311 {8, 0x0046},
4312 {9, 0x00ed},
4313 {7, 0x0107},
4314 {8, 0x005e},
4315 {8, 0x001e},
4316 {9, 0x009d},
4317 {7, 0x0117},
4318 {8, 0x007e},
4319 {8, 0x003e},
4320 {9, 0x00dd},
4321 {7, 0x010f},
4322 {8, 0x006e},
4323 {8, 0x002e},
4324 {9, 0x00bd},
4325 {8, 0x000e},
4326 {8, 0x008e},
4327 {8, 0x004e},
4328 {9, 0x00fd},
4329 {7, 0x0100},
4330 {8, 0x0051},
4331 {8, 0x0011},
4332 {8, 0x0119},
4333 {7, 0x0110},
4334 {8, 0x0071},
4335 {8, 0x0031},
4336 {9, 0x00c3},
4337 {7, 0x0108},
4338 {8, 0x0061},
4339 {8, 0x0021},
4340 {9, 0x00a3},
4341 {8, 0x0001},
4342 {8, 0x0081},
4343 {8, 0x0041},
4344 {9, 0x00e3},
4345 {7, 0x0104},
4346 {8, 0x0059},
4347 {8, 0x0019},
4348 {9, 0x0093},
4349 {7, 0x0114},
4350 {8, 0x0079},
4351 {8, 0x0039},
4352 {9, 0x00d3},
4353 {7, 0x010c},
4354 {8, 0x0069},
4355 {8, 0x0029},
4356 {9, 0x00b3},
4357 {8, 0x0009},
4358 {8, 0x0089},
4359 {8, 0x0049},
4360 {9, 0x00f3},
4361 {7, 0x0102},
4362 {8, 0x0055},
4363 {8, 0x0015},
4364 {8, 0x011d},
4365 {7, 0x0112},
4366 {8, 0x0075},
4367 {8, 0x0035},
4368 {9, 0x00cb},
4369 {7, 0x010a},
4370 {8, 0x0065},
4371 {8, 0x0025},
4372 {9, 0x00ab},
4373 {8, 0x0005},
4374 {8, 0x0085},
4375 {8, 0x0045},
4376 {9, 0x00eb},
4377 {7, 0x0106},
4378 {8, 0x005d},
4379 {8, 0x001d},
4380 {9, 0x009b},
4381 {7, 0x0116},
4382 {8, 0x007d},
4383 {8, 0x003d},
4384 {9, 0x00db},
4385 {7, 0x010e},
4386 {8, 0x006d},
4387 {8, 0x002d},
4388 {9, 0x00bb},
4389 {8, 0x000d},
4390 {8, 0x008d},
4391 {8, 0x004d},
4392 {9, 0x00fb},
4393 {7, 0x0101},
4394 {8, 0x0053},
4395 {8, 0x0013},
4396 {8, 0x011b},
4397 {7, 0x0111},
4398 {8, 0x0073},
4399 {8, 0x0033},
4400 {9, 0x00c7},
4401 {7, 0x0109},
4402 {8, 0x0063},
4403 {8, 0x0023},
4404 {9, 0x00a7},
4405 {8, 0x0003},
4406 {8, 0x0083},
4407 {8, 0x0043},
4408 {9, 0x00e7},
4409 {7, 0x0105},
4410 {8, 0x005b},
4411 {8, 0x001b},
4412 {9, 0x0097},
4413 {7, 0x0115},
4414 {8, 0x007b},
4415 {8, 0x003b},
4416 {9, 0x00d7},
4417 {7, 0x010d},
4418 {8, 0x006b},
4419 {8, 0x002b},
4420 {9, 0x00b7},
4421 {8, 0x000b},
4422 {8, 0x008b},
4423 {8, 0x004b},
4424 {9, 0x00f7},
4425 {7, 0x0103},
4426 {8, 0x0057},
4427 {8, 0x0017},
4428 {8, 0x011f},
4429 {7, 0x0113},
4430 {8, 0x0077},
4431 {8, 0x0037},
4432 {9, 0x00cf},
4433 {7, 0x010b},
4434 {8, 0x0067},
4435 {8, 0x0027},
4436 {9, 0x00af},
4437 {8, 0x0007},
4438 {8, 0x0087},
4439 {8, 0x0047},
4440 {9, 0x00ef},
4441 {7, 0x0107},
4442 {8, 0x005f},
4443 {8, 0x001f},
4444 {9, 0x009f},
4445 {7, 0x0117},
4446 {8, 0x007f},
4447 {8, 0x003f},
4448 {9, 0x00df},
4449 {7, 0x010f},
4450 {8, 0x006f},
4451 {8, 0x002f},
4452 {9, 0x00bf},
4453 {8, 0x000f},
4454 {8, 0x008f},
4455 {8, 0x004f},
4456 {9, 0x00ff}
4459 FlateHuffmanTab FlateStream::fixedLitCodeTab = {
4460 flateFixedLitCodeTabCodes, 9
4463 static FlateCode flateFixedDistCodeTabCodes[32] = {
4464 {5, 0x0000},
4465 {5, 0x0010},
4466 {5, 0x0008},
4467 {5, 0x0018},
4468 {5, 0x0004},
4469 {5, 0x0014},
4470 {5, 0x000c},
4471 {5, 0x001c},
4472 {5, 0x0002},
4473 {5, 0x0012},
4474 {5, 0x000a},
4475 {5, 0x001a},
4476 {5, 0x0006},
4477 {5, 0x0016},
4478 {5, 0x000e},
4479 {0, 0x0000},
4480 {5, 0x0001},
4481 {5, 0x0011},
4482 {5, 0x0009},
4483 {5, 0x0019},
4484 {5, 0x0005},
4485 {5, 0x0015},
4486 {5, 0x000d},
4487 {5, 0x001d},
4488 {5, 0x0003},
4489 {5, 0x0013},
4490 {5, 0x000b},
4491 {5, 0x001b},
4492 {5, 0x0007},
4493 {5, 0x0017},
4494 {5, 0x000f},
4495 {0, 0x0000}
4498 FlateHuffmanTab FlateStream::fixedDistCodeTab = {
4499 flateFixedDistCodeTabCodes, 5
4502 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
4503 int colors, int bits):
4504 FilterStream(strA) {
4505 if (predictor != 1) {
4506 pred = new StreamPredictor(this, predictor, columns, colors, bits);
4507 if (!pred->isOk()) {
4508 delete pred;
4509 pred = NULL;
4511 } else {
4512 pred = NULL;
4514 litCodeTab.codes = NULL;
4515 distCodeTab.codes = NULL;
4516 memset(buf, 0, flateWindow);
4519 FlateStream::~FlateStream() {
4520 if (litCodeTab.codes != fixedLitCodeTab.codes) {
4521 gfree(litCodeTab.codes);
4523 if (distCodeTab.codes != fixedDistCodeTab.codes) {
4524 gfree(distCodeTab.codes);
4526 if (pred) {
4527 delete pred;
4529 delete str;
4532 void FlateStream::flateReset(GBool unfiltered) {
4533 if (unfiltered)
4534 str->unfilteredReset();
4535 else
4536 str->reset();
4538 index = 0;
4539 remain = 0;
4540 codeBuf = 0;
4541 codeSize = 0;
4542 compressedBlock = gFalse;
4543 endOfBlock = gTrue;
4544 eof = gTrue;
4547 void FlateStream::unfilteredReset() {
4548 flateReset(gTrue);
4551 void FlateStream::reset() {
4552 int cmf, flg;
4554 flateReset(gFalse);
4556 // read header
4557 //~ need to look at window size?
4558 endOfBlock = eof = gTrue;
4559 cmf = str->getChar();
4560 flg = str->getChar();
4561 if (cmf == EOF || flg == EOF)
4562 return;
4563 if ((cmf & 0x0f) != 0x08) {
4564 error(errSyntaxError, getPos(), "Unknown compression method in flate stream");
4565 return;
4567 if ((((cmf << 8) + flg) % 31) != 0) {
4568 error(errSyntaxError, getPos(), "Bad FCHECK in flate stream");
4569 return;
4571 if (flg & 0x20) {
4572 error(errSyntaxError, getPos(), "FDICT bit set in flate stream");
4573 return;
4576 eof = gFalse;
4579 int FlateStream::getChar() {
4580 if (pred) {
4581 return pred->getChar();
4583 return doGetRawChar();
4586 int FlateStream::getChars(int nChars, Guchar *buffer) {
4587 if (pred) {
4588 return pred->getChars(nChars, buffer);
4589 } else {
4590 for (int i = 0; i < nChars; ++i) {
4591 const int c = doGetRawChar();
4592 if (likely(c != EOF)) buffer[i] = c;
4593 else return i;
4595 return nChars;
4599 int FlateStream::lookChar() {
4600 int c;
4602 if (pred) {
4603 return pred->lookChar();
4605 while (remain == 0) {
4606 if (endOfBlock && eof)
4607 return EOF;
4608 readSome();
4610 c = buf[index];
4611 return c;
4614 void FlateStream::getRawChars(int nChars, int *buffer) {
4615 for (int i = 0; i < nChars; ++i)
4616 buffer[i] = doGetRawChar();
4619 int FlateStream::getRawChar() {
4620 return doGetRawChar();
4623 GooString *FlateStream::getPSFilter(int psLevel, const char *indent) {
4624 GooString *s;
4626 if (psLevel < 3 || pred) {
4627 return NULL;
4629 if (!(s = str->getPSFilter(psLevel, indent))) {
4630 return NULL;
4632 s->append(indent)->append("<< >> /FlateDecode filter\n");
4633 return s;
4636 GBool FlateStream::isBinary(GBool last) {
4637 return str->isBinary(gTrue);
4640 void FlateStream::readSome() {
4641 int code1, code2;
4642 int len, dist;
4643 int i, j, k;
4644 int c;
4646 if (endOfBlock) {
4647 if (!startBlock())
4648 return;
4651 if (compressedBlock) {
4652 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
4653 goto err;
4654 if (code1 < 256) {
4655 buf[index] = code1;
4656 remain = 1;
4657 } else if (code1 == 256) {
4658 endOfBlock = gTrue;
4659 remain = 0;
4660 } else {
4661 code1 -= 257;
4662 code2 = lengthDecode[code1].bits;
4663 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4664 goto err;
4665 len = lengthDecode[code1].first + code2;
4666 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
4667 goto err;
4668 code2 = distDecode[code1].bits;
4669 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4670 goto err;
4671 dist = distDecode[code1].first + code2;
4672 i = index;
4673 j = (index - dist) & flateMask;
4674 for (k = 0; k < len; ++k) {
4675 buf[i] = buf[j];
4676 i = (i + 1) & flateMask;
4677 j = (j + 1) & flateMask;
4679 remain = len;
4682 } else {
4683 len = (blockLen < flateWindow) ? blockLen : flateWindow;
4684 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
4685 if ((c = str->getChar()) == EOF) {
4686 endOfBlock = eof = gTrue;
4687 break;
4689 buf[j] = c & 0xff;
4691 remain = i;
4692 blockLen -= len;
4693 if (blockLen == 0)
4694 endOfBlock = gTrue;
4697 return;
4699 err:
4700 error(errSyntaxError, getPos(), "Unexpected end of file in flate stream");
4701 endOfBlock = eof = gTrue;
4702 remain = 0;
4705 GBool FlateStream::startBlock() {
4706 int blockHdr;
4707 int c;
4708 int check;
4710 // free the code tables from the previous block
4711 if (litCodeTab.codes != fixedLitCodeTab.codes) {
4712 gfree(litCodeTab.codes);
4714 litCodeTab.codes = NULL;
4715 if (distCodeTab.codes != fixedDistCodeTab.codes) {
4716 gfree(distCodeTab.codes);
4718 distCodeTab.codes = NULL;
4720 // read block header
4721 blockHdr = getCodeWord(3);
4722 if (blockHdr & 1)
4723 eof = gTrue;
4724 blockHdr >>= 1;
4726 // uncompressed block
4727 if (blockHdr == 0) {
4728 compressedBlock = gFalse;
4729 if ((c = str->getChar()) == EOF)
4730 goto err;
4731 blockLen = c & 0xff;
4732 if ((c = str->getChar()) == EOF)
4733 goto err;
4734 blockLen |= (c & 0xff) << 8;
4735 if ((c = str->getChar()) == EOF)
4736 goto err;
4737 check = c & 0xff;
4738 if ((c = str->getChar()) == EOF)
4739 goto err;
4740 check |= (c & 0xff) << 8;
4741 if (check != (~blockLen & 0xffff))
4742 error(errSyntaxError, getPos(), "Bad uncompressed block length in flate stream");
4743 codeBuf = 0;
4744 codeSize = 0;
4746 // compressed block with fixed codes
4747 } else if (blockHdr == 1) {
4748 compressedBlock = gTrue;
4749 loadFixedCodes();
4751 // compressed block with dynamic codes
4752 } else if (blockHdr == 2) {
4753 compressedBlock = gTrue;
4754 if (!readDynamicCodes()) {
4755 goto err;
4758 // unknown block type
4759 } else {
4760 goto err;
4763 endOfBlock = gFalse;
4764 return gTrue;
4766 err:
4767 error(errSyntaxError, getPos(), "Bad block header in flate stream");
4768 endOfBlock = eof = gTrue;
4769 return gFalse;
4772 void FlateStream::loadFixedCodes() {
4773 litCodeTab.codes = fixedLitCodeTab.codes;
4774 litCodeTab.maxLen = fixedLitCodeTab.maxLen;
4775 distCodeTab.codes = fixedDistCodeTab.codes;
4776 distCodeTab.maxLen = fixedDistCodeTab.maxLen;
4779 GBool FlateStream::readDynamicCodes() {
4780 int numCodeLenCodes;
4781 int numLitCodes;
4782 int numDistCodes;
4783 int codeLenCodeLengths[flateMaxCodeLenCodes];
4784 FlateHuffmanTab codeLenCodeTab;
4785 int len, repeat, code;
4786 int i;
4788 codeLenCodeTab.codes = NULL;
4790 // read lengths
4791 if ((numLitCodes = getCodeWord(5)) == EOF) {
4792 goto err;
4794 numLitCodes += 257;
4795 if ((numDistCodes = getCodeWord(5)) == EOF) {
4796 goto err;
4798 numDistCodes += 1;
4799 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
4800 goto err;
4802 numCodeLenCodes += 4;
4803 if (numLitCodes > flateMaxLitCodes ||
4804 numDistCodes > flateMaxDistCodes ||
4805 numCodeLenCodes > flateMaxCodeLenCodes) {
4806 goto err;
4809 // build the code length code table
4810 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
4811 codeLenCodeLengths[i] = 0;
4813 for (i = 0; i < numCodeLenCodes; ++i) {
4814 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
4815 goto err;
4818 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
4820 // build the literal and distance code tables
4821 len = 0;
4822 repeat = 0;
4823 i = 0;
4824 while (i < numLitCodes + numDistCodes) {
4825 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
4826 goto err;
4828 if (code == 16) {
4829 if ((repeat = getCodeWord(2)) == EOF) {
4830 goto err;
4832 repeat += 3;
4833 if (i + repeat > numLitCodes + numDistCodes) {
4834 goto err;
4836 for (; repeat > 0; --repeat) {
4837 codeLengths[i++] = len;
4839 } else if (code == 17) {
4840 if ((repeat = getCodeWord(3)) == EOF) {
4841 goto err;
4843 repeat += 3;
4844 if (i + repeat > numLitCodes + numDistCodes) {
4845 goto err;
4847 len = 0;
4848 for (; repeat > 0; --repeat) {
4849 codeLengths[i++] = 0;
4851 } else if (code == 18) {
4852 if ((repeat = getCodeWord(7)) == EOF) {
4853 goto err;
4855 repeat += 11;
4856 if (i + repeat > numLitCodes + numDistCodes) {
4857 goto err;
4859 len = 0;
4860 for (; repeat > 0; --repeat) {
4861 codeLengths[i++] = 0;
4863 } else {
4864 codeLengths[i++] = len = code;
4867 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
4868 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
4870 gfree(codeLenCodeTab.codes);
4871 return gTrue;
4873 err:
4874 error(errSyntaxError, getPos(), "Bad dynamic code table in flate stream");
4875 gfree(codeLenCodeTab.codes);
4876 return gFalse;
4879 // Convert an array <lengths> of <n> lengths, in value order, into a
4880 // Huffman code lookup table.
4881 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
4882 int tabSize, len, code, code2, skip, val, i, t;
4884 // find max code length
4885 tab->maxLen = 0;
4886 for (val = 0; val < n; ++val) {
4887 if (lengths[val] > tab->maxLen) {
4888 tab->maxLen = lengths[val];
4892 // allocate the table
4893 tabSize = 1 << tab->maxLen;
4894 tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
4896 // clear the table
4897 for (i = 0; i < tabSize; ++i) {
4898 tab->codes[i].len = 0;
4899 tab->codes[i].val = 0;
4902 // build the table
4903 for (len = 1, code = 0, skip = 2;
4904 len <= tab->maxLen;
4905 ++len, code <<= 1, skip <<= 1) {
4906 for (val = 0; val < n; ++val) {
4907 if (lengths[val] == len) {
4909 // bit-reverse the code
4910 code2 = 0;
4911 t = code;
4912 for (i = 0; i < len; ++i) {
4913 code2 = (code2 << 1) | (t & 1);
4914 t >>= 1;
4917 // fill in the table entries
4918 for (i = code2; i < tabSize; i += skip) {
4919 tab->codes[i].len = (Gushort)len;
4920 tab->codes[i].val = (Gushort)val;
4923 ++code;
4929 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
4930 FlateCode *code;
4931 int c;
4933 while (codeSize < tab->maxLen) {
4934 if ((c = str->getChar()) == EOF) {
4935 break;
4937 codeBuf |= (c & 0xff) << codeSize;
4938 codeSize += 8;
4940 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
4941 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
4942 return EOF;
4944 codeBuf >>= code->len;
4945 codeSize -= code->len;
4946 return (int)code->val;
4949 int FlateStream::getCodeWord(int bits) {
4950 int c;
4952 while (codeSize < bits) {
4953 if ((c = str->getChar()) == EOF)
4954 return EOF;
4955 codeBuf |= (c & 0xff) << codeSize;
4956 codeSize += 8;
4958 c = codeBuf & ((1 << bits) - 1);
4959 codeBuf >>= bits;
4960 codeSize -= bits;
4961 return c;
4963 #endif
4965 //------------------------------------------------------------------------
4966 // EOFStream
4967 //------------------------------------------------------------------------
4969 EOFStream::EOFStream(Stream *strA):
4970 FilterStream(strA) {
4973 EOFStream::~EOFStream() {
4974 delete str;
4977 //------------------------------------------------------------------------
4978 // BufStream
4979 //------------------------------------------------------------------------
4981 BufStream::BufStream(Stream *strA, int bufSizeA): FilterStream(strA) {
4982 bufSize = bufSizeA;
4983 buf = (int *)gmallocn(bufSize, sizeof(int));
4986 BufStream::~BufStream() {
4987 gfree(buf);
4988 delete str;
4991 void BufStream::reset() {
4992 int i;
4994 str->reset();
4995 for (i = 0; i < bufSize; ++i) {
4996 buf[i] = str->getChar();
5000 int BufStream::getChar() {
5001 int c, i;
5003 c = buf[0];
5004 for (i = 1; i < bufSize; ++i) {
5005 buf[i-1] = buf[i];
5007 buf[bufSize - 1] = str->getChar();
5008 return c;
5011 int BufStream::lookChar() {
5012 return buf[0];
5015 int BufStream::lookChar(int idx) {
5016 return buf[idx];
5019 GBool BufStream::isBinary(GBool last) {
5020 return str->isBinary(gTrue);
5023 //------------------------------------------------------------------------
5024 // FixedLengthEncoder
5025 //------------------------------------------------------------------------
5027 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
5028 FilterStream(strA) {
5029 length = lengthA;
5030 count = 0;
5033 FixedLengthEncoder::~FixedLengthEncoder() {
5034 if (str->isEncoder())
5035 delete str;
5038 void FixedLengthEncoder::reset() {
5039 str->reset();
5040 count = 0;
5043 int FixedLengthEncoder::getChar() {
5044 if (length >= 0 && count >= length)
5045 return EOF;
5046 ++count;
5047 return str->getChar();
5050 int FixedLengthEncoder::lookChar() {
5051 if (length >= 0 && count >= length)
5052 return EOF;
5053 return str->getChar();
5056 GBool FixedLengthEncoder::isBinary(GBool last) {
5057 return str->isBinary(gTrue);
5060 //------------------------------------------------------------------------
5061 // ASCIIHexEncoder
5062 //------------------------------------------------------------------------
5064 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
5065 FilterStream(strA) {
5066 bufPtr = bufEnd = buf;
5067 lineLen = 0;
5068 eof = gFalse;
5071 ASCIIHexEncoder::~ASCIIHexEncoder() {
5072 if (str->isEncoder()) {
5073 delete str;
5077 void ASCIIHexEncoder::reset() {
5078 str->reset();
5079 bufPtr = bufEnd = buf;
5080 lineLen = 0;
5081 eof = gFalse;
5084 GBool ASCIIHexEncoder::fillBuf() {
5085 static const char *hex = "0123456789abcdef";
5086 int c;
5088 if (eof) {
5089 return gFalse;
5091 bufPtr = bufEnd = buf;
5092 if ((c = str->getChar()) == EOF) {
5093 *bufEnd++ = '>';
5094 eof = gTrue;
5095 } else {
5096 if (lineLen >= 64) {
5097 *bufEnd++ = '\n';
5098 lineLen = 0;
5100 *bufEnd++ = hex[(c >> 4) & 0x0f];
5101 *bufEnd++ = hex[c & 0x0f];
5102 lineLen += 2;
5104 return gTrue;
5107 //------------------------------------------------------------------------
5108 // ASCII85Encoder
5109 //------------------------------------------------------------------------
5111 ASCII85Encoder::ASCII85Encoder(Stream *strA):
5112 FilterStream(strA) {
5113 bufPtr = bufEnd = buf;
5114 lineLen = 0;
5115 eof = gFalse;
5118 ASCII85Encoder::~ASCII85Encoder() {
5119 if (str->isEncoder())
5120 delete str;
5123 void ASCII85Encoder::reset() {
5124 str->reset();
5125 bufPtr = bufEnd = buf;
5126 lineLen = 0;
5127 eof = gFalse;
5130 GBool ASCII85Encoder::fillBuf() {
5131 Guint t;
5132 char buf1[5];
5133 int c0, c1, c2, c3;
5134 int n, i;
5136 if (eof) {
5137 return gFalse;
5139 c0 = str->getChar();
5140 c1 = str->getChar();
5141 c2 = str->getChar();
5142 c3 = str->getChar();
5143 bufPtr = bufEnd = buf;
5144 if (c3 == EOF) {
5145 if (c0 == EOF) {
5146 n = 0;
5147 t = 0;
5148 } else {
5149 if (c1 == EOF) {
5150 n = 1;
5151 t = c0 << 24;
5152 } else if (c2 == EOF) {
5153 n = 2;
5154 t = (c0 << 24) | (c1 << 16);
5155 } else {
5156 n = 3;
5157 t = (c0 << 24) | (c1 << 16) | (c2 << 8);
5159 for (i = 4; i >= 0; --i) {
5160 buf1[i] = (char)(t % 85 + 0x21);
5161 t /= 85;
5163 for (i = 0; i <= n; ++i) {
5164 *bufEnd++ = buf1[i];
5165 if (++lineLen == 65) {
5166 *bufEnd++ = '\n';
5167 lineLen = 0;
5171 *bufEnd++ = '~';
5172 *bufEnd++ = '>';
5173 eof = gTrue;
5174 } else {
5175 t = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
5176 if (t == 0) {
5177 *bufEnd++ = 'z';
5178 if (++lineLen == 65) {
5179 *bufEnd++ = '\n';
5180 lineLen = 0;
5182 } else {
5183 for (i = 4; i >= 0; --i) {
5184 buf1[i] = (char)(t % 85 + 0x21);
5185 t /= 85;
5187 for (i = 0; i <= 4; ++i) {
5188 *bufEnd++ = buf1[i];
5189 if (++lineLen == 65) {
5190 *bufEnd++ = '\n';
5191 lineLen = 0;
5196 return gTrue;
5199 //------------------------------------------------------------------------
5200 // RunLengthEncoder
5201 //------------------------------------------------------------------------
5203 RunLengthEncoder::RunLengthEncoder(Stream *strA):
5204 FilterStream(strA) {
5205 bufPtr = bufEnd = nextEnd = buf;
5206 eof = gFalse;
5209 RunLengthEncoder::~RunLengthEncoder() {
5210 if (str->isEncoder())
5211 delete str;
5214 void RunLengthEncoder::reset() {
5215 str->reset();
5216 bufPtr = bufEnd = nextEnd = buf;
5217 eof = gFalse;
5221 // When fillBuf finishes, buf[] looks like this:
5222 // +-----+--------------+-----------------+--
5223 // + tag | ... data ... | next 0, 1, or 2 |
5224 // +-----+--------------+-----------------+--
5225 // ^ ^ ^
5226 // bufPtr bufEnd nextEnd
5228 GBool RunLengthEncoder::fillBuf() {
5229 int c, c1, c2;
5230 int n;
5232 // already hit EOF?
5233 if (eof)
5234 return gFalse;
5236 // grab two bytes
5237 if (nextEnd < bufEnd + 1) {
5238 if ((c1 = str->getChar()) == EOF) {
5239 eof = gTrue;
5240 return gFalse;
5242 } else {
5243 c1 = bufEnd[0] & 0xff;
5245 if (nextEnd < bufEnd + 2) {
5246 if ((c2 = str->getChar()) == EOF) {
5247 eof = gTrue;
5248 buf[0] = 0;
5249 buf[1] = c1;
5250 bufPtr = buf;
5251 bufEnd = &buf[2];
5252 return gTrue;
5254 } else {
5255 c2 = bufEnd[1] & 0xff;
5258 // check for repeat
5259 c = 0; // make gcc happy
5260 if (c1 == c2) {
5261 n = 2;
5262 while (n < 128 && (c = str->getChar()) == c1)
5263 ++n;
5264 buf[0] = (char)(257 - n);
5265 buf[1] = c1;
5266 bufEnd = &buf[2];
5267 if (c == EOF) {
5268 eof = gTrue;
5269 } else if (n < 128) {
5270 buf[2] = c;
5271 nextEnd = &buf[3];
5272 } else {
5273 nextEnd = bufEnd;
5276 // get up to 128 chars
5277 } else {
5278 buf[1] = c1;
5279 buf[2] = c2;
5280 n = 2;
5281 while (n < 128) {
5282 if ((c = str->getChar()) == EOF) {
5283 eof = gTrue;
5284 break;
5286 ++n;
5287 buf[n] = c;
5288 if (buf[n] == buf[n-1])
5289 break;
5291 if (buf[n] == buf[n-1]) {
5292 buf[0] = (char)(n-2-1);
5293 bufEnd = &buf[n-1];
5294 nextEnd = &buf[n+1];
5295 } else {
5296 buf[0] = (char)(n-1);
5297 bufEnd = nextEnd = &buf[n+1];
5300 bufPtr = buf;
5301 return gTrue;
5304 //------------------------------------------------------------------------
5305 // CMYKGrayEncoder
5306 //------------------------------------------------------------------------
5308 CMYKGrayEncoder::CMYKGrayEncoder(Stream *strA):
5309 FilterStream(strA) {
5310 bufPtr = bufEnd = buf;
5311 eof = gFalse;
5314 CMYKGrayEncoder::~CMYKGrayEncoder() {
5315 if (str->isEncoder())
5316 delete str;
5319 void CMYKGrayEncoder::reset() {
5320 str->reset();
5321 bufPtr = bufEnd = buf;
5322 eof = gFalse;
5325 GBool CMYKGrayEncoder::fillBuf() {
5326 int c0, c1, c2, c3;
5327 int i;
5329 if (eof) {
5330 return gFalse;
5332 c0 = str->getChar();
5333 c1 = str->getChar();
5334 c2 = str->getChar();
5335 c3 = str->getChar();
5336 if (c3 == EOF) {
5337 eof = gTrue;
5338 return gFalse;
5340 i = (3 * c0 + 6 * c1 + c2) / 10 + c3;
5341 if (i > 255) i = 255;
5342 bufPtr = bufEnd = buf;
5343 *bufEnd++ = (char) i;
5344 return gTrue;
5347 //------------------------------------------------------------------------
5348 // RGBGrayEncoder
5349 //------------------------------------------------------------------------
5351 RGBGrayEncoder::RGBGrayEncoder(Stream *strA):
5352 FilterStream(strA) {
5353 bufPtr = bufEnd = buf;
5354 eof = gFalse;
5357 RGBGrayEncoder::~RGBGrayEncoder() {
5358 if (str->isEncoder())
5359 delete str;
5362 void RGBGrayEncoder::reset() {
5363 str->reset();
5364 bufPtr = bufEnd = buf;
5365 eof = gFalse;
5368 GBool RGBGrayEncoder::fillBuf() {
5369 int c0, c1, c2;
5370 int i;
5372 if (eof) {
5373 return gFalse;
5375 c0 = str->getChar();
5376 c1 = str->getChar();
5377 c2 = str->getChar();
5378 if (c2 == EOF) {
5379 eof = gTrue;
5380 return gFalse;
5382 i = 255 - (3 * c0 + 6 * c1 + c2) / 10;
5383 if (i < 0) i = 0;
5384 bufPtr = bufEnd = buf;
5385 *bufEnd++ = (char) i;
5386 return gTrue;