Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / xpdf / Stream.cc
blobfe11fc897baf4af54f1f6606b1296e7bebe0632c
1 //========================================================================
2 //
3 // Stream.cc
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 #include <aconf.h>
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stddef.h>
18 #include <limits.h>
19 #ifndef WIN32
20 #include <unistd.h>
21 #endif
22 #include <string.h>
23 #include <ctype.h>
24 #include "gmem.h"
25 #include "gfile.h"
26 #include "config.h"
27 #include "Error.h"
28 #include "Object.h"
29 #include "Lexer.h"
30 #include "Decrypt.h"
31 #include "GfxState.h"
32 #include "Stream.h"
33 #include "JBIG2Stream.h"
34 #include "JPXStream.h"
35 #include "Stream-CCITT.h"
37 #ifdef __DJGPP__
38 static GBool setDJSYSFLAGS = gFalse;
39 #endif
41 #ifdef VMS
42 #ifdef __GNUC__
43 #define SEEK_SET 0
44 #define SEEK_CUR 1
45 #define SEEK_END 2
46 #endif
47 #endif
49 //------------------------------------------------------------------------
50 // Stream (base class)
51 //------------------------------------------------------------------------
53 Stream::Stream() {
54 ref = 1;
57 Stream::~Stream() {
60 void Stream::close() {
63 int Stream::getRawChar() {
64 error(-1, "Internal: called getRawChar() on non-predictor stream");
65 return EOF;
68 char *Stream::getLine(char *buf, int size) {
69 int i;
70 int c;
72 if (lookChar() == EOF)
73 return NULL;
74 for (i = 0; i < size - 1; ++i) {
75 c = getChar();
76 if (c == EOF || c == '\n')
77 break;
78 if (c == '\r') {
79 if ((c = lookChar()) == '\n')
80 getChar();
81 break;
83 buf[i] = c;
85 buf[i] = '\0';
86 return buf;
89 GString *Stream::getPSFilter(int psLevel, char *indent) {
90 return new GString();
93 Stream *Stream::addFilters(Object *dict) {
94 Object obj, obj2;
95 Object params, params2;
96 Stream *str;
97 int i;
99 str = this;
100 dict->dictLookup("Filter", &obj);
101 if (obj.isNull()) {
102 obj.free();
103 dict->dictLookup("F", &obj);
105 dict->dictLookup("DecodeParms", &params);
106 if (params.isNull()) {
107 params.free();
108 dict->dictLookup("DP", &params);
110 if (obj.isName()) {
111 str = makeFilter(obj.getName(), str, &params);
112 } else if (obj.isArray()) {
113 for (i = 0; i < obj.arrayGetLength(); ++i) {
114 obj.arrayGet(i, &obj2);
115 if (params.isArray())
116 params.arrayGet(i, &params2);
117 else
118 params2.initNull();
119 if (obj2.isName()) {
120 str = makeFilter(obj2.getName(), str, &params2);
121 } else {
122 error(getPos(), "Bad filter name");
123 str = new EOFStream(str);
125 obj2.free();
126 params2.free();
128 } else if (!obj.isNull()) {
129 error(getPos(), "Bad 'Filter' attribute in stream");
131 obj.free();
132 params.free();
134 return str;
137 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
138 int pred; // parameters
139 int colors;
140 int bits;
141 int early;
142 int encoding;
143 GBool endOfLine, byteAlign, endOfBlock, black;
144 int columns, rows;
145 Object globals, obj;
147 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
148 str = new ASCIIHexStream(str);
149 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
150 str = new ASCII85Stream(str);
151 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
152 pred = 1;
153 columns = 1;
154 colors = 1;
155 bits = 8;
156 early = 1;
157 if (params->isDict()) {
158 params->dictLookup("Predictor", &obj);
159 if (obj.isInt())
160 pred = obj.getInt();
161 obj.free();
162 params->dictLookup("Columns", &obj);
163 if (obj.isInt())
164 columns = obj.getInt();
165 obj.free();
166 params->dictLookup("Colors", &obj);
167 if (obj.isInt())
168 colors = obj.getInt();
169 obj.free();
170 params->dictLookup("BitsPerComponent", &obj);
171 if (obj.isInt())
172 bits = obj.getInt();
173 obj.free();
174 params->dictLookup("EarlyChange", &obj);
175 if (obj.isInt())
176 early = obj.getInt();
177 obj.free();
179 str = new LZWStream(str, pred, columns, colors, bits, early);
180 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
181 str = new RunLengthStream(str);
182 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
183 encoding = 0;
184 endOfLine = gFalse;
185 byteAlign = gFalse;
186 columns = 1728;
187 rows = 0;
188 endOfBlock = gTrue;
189 black = gFalse;
190 if (params->isDict()) {
191 params->dictLookup("K", &obj);
192 if (obj.isInt()) {
193 encoding = obj.getInt();
195 obj.free();
196 params->dictLookup("EndOfLine", &obj);
197 if (obj.isBool()) {
198 endOfLine = obj.getBool();
200 obj.free();
201 params->dictLookup("EncodedByteAlign", &obj);
202 if (obj.isBool()) {
203 byteAlign = obj.getBool();
205 obj.free();
206 params->dictLookup("Columns", &obj);
207 if (obj.isInt()) {
208 columns = obj.getInt();
210 obj.free();
211 params->dictLookup("Rows", &obj);
212 if (obj.isInt()) {
213 rows = obj.getInt();
215 obj.free();
216 params->dictLookup("EndOfBlock", &obj);
217 if (obj.isBool()) {
218 endOfBlock = obj.getBool();
220 obj.free();
221 params->dictLookup("BlackIs1", &obj);
222 if (obj.isBool()) {
223 black = obj.getBool();
225 obj.free();
227 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
228 columns, rows, endOfBlock, black);
229 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
230 str = new DCTStream(str);
231 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
232 pred = 1;
233 columns = 1;
234 colors = 1;
235 bits = 8;
236 if (params->isDict()) {
237 params->dictLookup("Predictor", &obj);
238 if (obj.isInt())
239 pred = obj.getInt();
240 obj.free();
241 params->dictLookup("Columns", &obj);
242 if (obj.isInt())
243 columns = obj.getInt();
244 obj.free();
245 params->dictLookup("Colors", &obj);
246 if (obj.isInt())
247 colors = obj.getInt();
248 obj.free();
249 params->dictLookup("BitsPerComponent", &obj);
250 if (obj.isInt())
251 bits = obj.getInt();
252 obj.free();
254 str = new FlateStream(str, pred, columns, colors, bits);
255 } else if (!strcmp(name, "JBIG2Decode")) {
256 if (params->isDict()) {
257 params->dictLookup("JBIG2Globals", &globals);
259 str = new JBIG2Stream(str, &globals);
260 globals.free();
261 } else if (!strcmp(name, "JPXDecode")) {
262 str = new JPXStream(str);
263 } else {
264 error(getPos(), "Unknown filter '%s'", name);
265 str = new EOFStream(str);
267 return str;
270 //------------------------------------------------------------------------
271 // BaseStream
272 //------------------------------------------------------------------------
274 BaseStream::BaseStream(Object *dictA) {
275 dict = *dictA;
276 #ifdef DEBUG_MEM
277 dictA->free();
278 #endif
279 decrypt = NULL;
282 BaseStream::~BaseStream() {
283 dict.free();
284 if (decrypt)
285 delete decrypt;
288 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
289 int objNum, int objGen) {
290 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
293 //------------------------------------------------------------------------
294 // FilterStream
295 //------------------------------------------------------------------------
297 FilterStream::FilterStream(Stream *strA) {
298 str = strA;
301 FilterStream::~FilterStream() {
304 void FilterStream::close() {
305 str->close();
308 void FilterStream::setPos(Guint pos, int dir) {
309 error(-1, "Internal: called setPos() on FilterStream");
312 //------------------------------------------------------------------------
313 // ImageStream
314 //------------------------------------------------------------------------
316 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
317 int imgLineSize;
319 str = strA;
320 width = widthA;
321 nComps = nCompsA;
322 nBits = nBitsA;
324 nVals = width * nComps;
325 if (nBits == 1) {
326 imgLineSize = (nVals + 7) & ~7;
327 } else {
328 imgLineSize = nVals;
330 imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
331 imgIdx = nVals;
334 ImageStream::~ImageStream() {
335 gfree(imgLine);
338 void ImageStream::reset() {
339 str->reset();
342 GBool ImageStream::getPixel(Guchar *pix) {
343 int i;
345 if (imgIdx >= nVals) {
346 getLine();
347 imgIdx = 0;
349 for (i = 0; i < nComps; ++i) {
350 pix[i] = imgLine[imgIdx++];
352 return gTrue;
355 Guchar *ImageStream::getLine() {
356 Gulong buf, bitMask;
357 int bits;
358 int c;
359 int i;
361 if (nBits == 1) {
362 for (i = 0; i < nVals; i += 8) {
363 c = str->getChar();
364 imgLine[i+0] = (Guchar)((c >> 7) & 1);
365 imgLine[i+1] = (Guchar)((c >> 6) & 1);
366 imgLine[i+2] = (Guchar)((c >> 5) & 1);
367 imgLine[i+3] = (Guchar)((c >> 4) & 1);
368 imgLine[i+4] = (Guchar)((c >> 3) & 1);
369 imgLine[i+5] = (Guchar)((c >> 2) & 1);
370 imgLine[i+6] = (Guchar)((c >> 1) & 1);
371 imgLine[i+7] = (Guchar)(c & 1);
373 } else if (nBits == 8) {
374 for (i = 0; i < nVals; ++i) {
375 imgLine[i] = str->getChar();
377 } else {
378 bitMask = (1 << nBits) - 1;
379 buf = 0;
380 bits = 0;
381 for (i = 0; i < nVals; ++i) {
382 if (bits < nBits) {
383 buf = (buf << 8) | (str->getChar() & 0xff);
384 bits += 8;
386 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
387 bits -= nBits;
390 return imgLine;
393 void ImageStream::skipLine() {
394 int n, i;
396 n = (nVals * nBits + 7) >> 3;
397 for (i = 0; i < n; ++i) {
398 str->getChar();
402 //------------------------------------------------------------------------
403 // StreamPredictor
404 //------------------------------------------------------------------------
406 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
407 int widthA, int nCompsA, int nBitsA) {
408 str = strA;
409 predictor = predictorA;
410 width = widthA;
411 nComps = nCompsA;
412 nBits = nBitsA;
413 predLine = NULL;
414 ok = gFalse;
416 nVals = width * nComps;
417 if (width <= 0 || nComps <= 0 || nBits <= 0 ||
418 nComps >= INT_MAX / nBits ||
419 width >= INT_MAX / nComps / nBits ||
420 nVals * nBits + 7 < 0) {
421 return;
423 pixBytes = (nComps * nBits + 7) >> 3;
424 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
425 if (rowBytes <= 0) {
426 return;
428 predLine = (Guchar *)gmalloc(rowBytes);
429 memset(predLine, 0, rowBytes);
430 predIdx = rowBytes;
432 ok = gTrue;
435 StreamPredictor::~StreamPredictor() {
436 gfree(predLine);
439 int StreamPredictor::lookChar() {
440 if (predIdx >= rowBytes) {
441 if (!getNextLine()) {
442 return EOF;
445 return predLine[predIdx];
448 int StreamPredictor::getChar() {
449 if (predIdx >= rowBytes) {
450 if (!getNextLine()) {
451 return EOF;
454 return predLine[predIdx++];
457 GBool StreamPredictor::getNextLine() {
458 int curPred;
459 Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
460 int left, up, upLeft, p, pa, pb, pc;
461 int c;
462 Gulong inBuf, outBuf, bitMask;
463 int inBits, outBits;
464 int i, j, k, kk;
466 // get PNG optimum predictor number
467 if (predictor >= 10) {
468 if ((curPred = str->getRawChar()) == EOF) {
469 return gFalse;
471 curPred += 10;
472 } else {
473 curPred = predictor;
476 // read the raw line, apply PNG (byte) predictor
477 memset(upLeftBuf, 0, pixBytes + 1);
478 for (i = pixBytes; i < rowBytes; ++i) {
479 for (j = pixBytes; j > 0; --j) {
480 upLeftBuf[j] = upLeftBuf[j-1];
482 upLeftBuf[0] = predLine[i];
483 if ((c = str->getRawChar()) == EOF) {
484 if (i > pixBytes) {
485 // this ought to return false, but some (broken) PDF files
486 // contain truncated image data, and Adobe apparently reads the
487 // last partial line
488 break;
490 return gFalse;
492 switch (curPred) {
493 case 11: // PNG sub
494 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
495 break;
496 case 12: // PNG up
497 predLine[i] = predLine[i] + (Guchar)c;
498 break;
499 case 13: // PNG average
500 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
501 (Guchar)c;
502 break;
503 case 14: // PNG Paeth
504 left = predLine[i - pixBytes];
505 up = predLine[i];
506 upLeft = upLeftBuf[pixBytes];
507 p = left + up - upLeft;
508 if ((pa = p - left) < 0)
509 pa = -pa;
510 if ((pb = p - up) < 0)
511 pb = -pb;
512 if ((pc = p - upLeft) < 0)
513 pc = -pc;
514 if (pa <= pb && pa <= pc)
515 predLine[i] = left + (Guchar)c;
516 else if (pb <= pc)
517 predLine[i] = up + (Guchar)c;
518 else
519 predLine[i] = upLeft + (Guchar)c;
520 break;
521 case 10: // PNG none
522 default: // no predictor or TIFF predictor
523 predLine[i] = (Guchar)c;
524 break;
528 // apply TIFF (component) predictor
529 if (predictor == 2) {
530 if (nBits == 1) {
531 inBuf = predLine[pixBytes - 1];
532 for (i = pixBytes; i < rowBytes; i += 8) {
533 // 1-bit add is just xor
534 inBuf = (inBuf << 8) | predLine[i];
535 predLine[i] ^= inBuf >> nComps;
537 } else if (nBits == 8) {
538 for (i = pixBytes; i < rowBytes; ++i) {
539 predLine[i] += predLine[i - nComps];
541 } else {
542 memset(upLeftBuf, 0, nComps + 1);
543 bitMask = (1 << nBits) - 1;
544 inBuf = outBuf = 0;
545 inBits = outBits = 0;
546 j = k = pixBytes;
547 for (i = 0; i < width; ++i) {
548 for (kk = 0; kk < nComps; ++kk) {
549 if (inBits < nBits) {
550 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
551 inBits += 8;
553 upLeftBuf[kk] = (upLeftBuf[kk] +
554 (inBuf >> (inBits - nBits))) & bitMask;
555 inBits -= nBits;
556 outBuf = (outBuf << nBits) | upLeftBuf[kk];
557 outBits += nBits;
558 if (outBits >= 8) {
559 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
560 outBits -= 8;
564 if (outBits > 0) {
565 predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
566 (inBuf & ((1 << (8 - outBits)) - 1)));
571 // reset to start of line
572 predIdx = pixBytes;
574 return gTrue;
577 //------------------------------------------------------------------------
578 // FileStream
579 //------------------------------------------------------------------------
581 FileStream::FileStream(myFILE *fA, Guint startA, GBool limitedA,
582 Guint lengthA, Object *dictA):
583 BaseStream(dictA) {
584 f = fA;
585 start = startA;
586 limited = limitedA;
587 length = lengthA;
588 bufPtr = bufEnd = buf;
589 bufPos = start;
590 savePos = 0;
591 saved = gFalse;
592 if (length > 0)
593 f->preread(start, length);
596 FileStream::~FileStream() {
597 close();
600 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
601 Guint lengthA, Object *dictA) {
602 return new FileStream(f, startA, limitedA, lengthA, dictA);
605 void FileStream::reset() {
606 savePos = (Guint)myftell(f);
607 myfseek(f, start, SEEK_SET);
608 saved = gTrue;
609 bufPtr = bufEnd = buf;
610 bufPos = start;
611 if (decrypt)
612 decrypt->reset();
615 void FileStream::close() {
616 if (saved) {
617 myfseek(f, savePos, SEEK_SET);
618 saved = gFalse;
622 GBool FileStream::fillBuf() {
623 int n;
624 char *p;
626 bufPos += bufEnd - buf;
627 bufPtr = bufEnd = buf;
628 if (limited && bufPos >= start + length) {
629 return gFalse;
631 if (limited && bufPos + fileStreamBufSize > start + length) {
632 n = start + length - bufPos;
633 } else {
634 n = fileStreamBufSize;
636 n = myfread(buf, 1, n, f);
637 bufEnd = buf + n;
638 if (bufPtr >= bufEnd) {
639 return gFalse;
641 if (decrypt) {
642 for (p = buf; p < bufEnd; ++p) {
643 *p = (char)decrypt->decryptByte((Guchar)*p);
646 return gTrue;
649 void FileStream::setPos(Guint pos, int dir) {
650 Guint size;
652 if (dir >= 0) {
653 myfseek(f, pos, SEEK_SET);
654 bufPos = pos;
655 } else {
656 myfseek(f, 0, SEEK_END);
657 size = (Guint)myftell(f);
658 if (pos > size)
659 pos = (Guint)size;
660 #ifdef __CYGWIN32__
661 //~ work around a bug in cygwin's implementation of fseek
662 rewind(f);
663 #endif
664 myfseek(f, -(int)pos, SEEK_END);
665 bufPos = (Guint)myftell(f);
667 bufPtr = bufEnd = buf;
670 void FileStream::moveStart(int delta) {
671 start += delta;
672 bufPtr = bufEnd = buf;
673 bufPos = start;
676 void FileStream::preRead(int pos, int length) {
677 f->preread(pos, length);
680 void FileStream::removeParts() {
681 f->remove_parts();
684 //------------------------------------------------------------------------
685 // MemStream
686 //------------------------------------------------------------------------
688 MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
689 BaseStream(dictA) {
690 buf = bufA;
691 start = startA;
692 length = lengthA;
693 bufEnd = buf + start + length;
694 bufPtr = buf + start;
695 needFree = gFalse;
698 MemStream::~MemStream() {
699 if (needFree) {
700 gfree(buf);
704 Stream *MemStream::makeSubStream(Guint startA, GBool limited,
705 Guint lengthA, Object *dictA) {
706 MemStream *subStr;
707 Guint newLength;
709 if (!limited || startA + lengthA > start + length) {
710 newLength = start + length - startA;
711 } else {
712 newLength = lengthA;
714 subStr = new MemStream(buf, startA, newLength, dictA);
715 return subStr;
718 void MemStream::reset() {
719 bufPtr = buf + start;
720 if (decrypt) {
721 decrypt->reset();
725 void MemStream::close() {
728 void MemStream::setPos(Guint pos, int dir) {
729 Guint i;
731 if (dir >= 0) {
732 i = pos;
733 } else {
734 i = start + length - pos;
736 if (i < start) {
737 i = start;
738 } else if (i > start + length) {
739 i = start + length;
741 bufPtr = buf + i;
744 void MemStream::moveStart(int delta) {
745 start += delta;
746 length -= delta;
747 bufPtr = buf + start;
750 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
751 int objNum, int objGen) {
752 char *newBuf;
753 char *p, *q;
755 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
756 if (decrypt) {
757 newBuf = (char *)gmalloc(length);
758 for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
759 *q = (char)decrypt->decryptByte((Guchar)*p);
761 bufEnd = newBuf + length;
762 bufPtr = newBuf + (bufPtr - (buf + start));
763 start = 0;
764 buf = newBuf;
765 needFree = gTrue;
769 //------------------------------------------------------------------------
770 // EmbedStream
771 //------------------------------------------------------------------------
773 EmbedStream::EmbedStream(Stream *strA, Object *dictA,
774 GBool limitedA, Guint lengthA):
775 BaseStream(dictA) {
776 str = strA;
777 limited = limitedA;
778 length = lengthA;
781 EmbedStream::~EmbedStream() {
784 Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
785 Guint lengthA, Object *dictA) {
786 error(-1, "Internal: called makeSubStream() on EmbedStream");
787 return NULL;
790 int EmbedStream::getChar() {
791 if (limited && !length) {
792 return EOF;
794 --length;
795 return str->getChar();
798 int EmbedStream::lookChar() {
799 if (limited && !length) {
800 return EOF;
802 return str->lookChar();
805 void EmbedStream::setPos(Guint pos, int dir) {
806 error(-1, "Internal: called setPos() on EmbedStream");
809 Guint EmbedStream::getStart() {
810 error(-1, "Internal: called getStart() on EmbedStream");
811 return 0;
814 void EmbedStream::moveStart(int delta) {
815 error(-1, "Internal: called moveStart() on EmbedStream");
818 //------------------------------------------------------------------------
819 // ASCIIHexStream
820 //------------------------------------------------------------------------
822 ASCIIHexStream::ASCIIHexStream(Stream *strA):
823 FilterStream(strA) {
824 buf = EOF;
825 eof = gFalse;
828 ASCIIHexStream::~ASCIIHexStream() {
829 delete str;
832 void ASCIIHexStream::reset() {
833 str->reset();
834 buf = EOF;
835 eof = gFalse;
838 int ASCIIHexStream::lookChar() {
839 int c1, c2, x;
841 if (buf != EOF)
842 return buf;
843 if (eof) {
844 buf = EOF;
845 return EOF;
847 do {
848 c1 = str->getChar();
849 } while (isspace(c1));
850 if (c1 == '>') {
851 eof = gTrue;
852 buf = EOF;
853 return buf;
855 do {
856 c2 = str->getChar();
857 } while (isspace(c2));
858 if (c2 == '>') {
859 eof = gTrue;
860 c2 = '0';
862 if (c1 >= '0' && c1 <= '9') {
863 x = (c1 - '0') << 4;
864 } else if (c1 >= 'A' && c1 <= 'F') {
865 x = (c1 - 'A' + 10) << 4;
866 } else if (c1 >= 'a' && c1 <= 'f') {
867 x = (c1 - 'a' + 10) << 4;
868 } else if (c1 == EOF) {
869 eof = gTrue;
870 x = 0;
871 } else {
872 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
873 x = 0;
875 if (c2 >= '0' && c2 <= '9') {
876 x += c2 - '0';
877 } else if (c2 >= 'A' && c2 <= 'F') {
878 x += c2 - 'A' + 10;
879 } else if (c2 >= 'a' && c2 <= 'f') {
880 x += c2 - 'a' + 10;
881 } else if (c2 == EOF) {
882 eof = gTrue;
883 x = 0;
884 } else {
885 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
887 buf = x & 0xff;
888 return buf;
891 GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
892 GString *s;
894 if (psLevel < 2) {
895 return NULL;
897 if (!(s = str->getPSFilter(psLevel, indent))) {
898 return NULL;
900 s->append(indent)->append("/ASCIIHexDecode filter\n");
901 return s;
904 GBool ASCIIHexStream::isBinary(GBool last) {
905 return str->isBinary(gFalse);
908 //------------------------------------------------------------------------
909 // ASCII85Stream
910 //------------------------------------------------------------------------
912 ASCII85Stream::ASCII85Stream(Stream *strA):
913 FilterStream(strA) {
914 index = n = 0;
915 eof = gFalse;
918 ASCII85Stream::~ASCII85Stream() {
919 delete str;
922 void ASCII85Stream::reset() {
923 str->reset();
924 index = n = 0;
925 eof = gFalse;
928 int ASCII85Stream::lookChar() {
929 int k;
930 Gulong t;
932 if (index >= n) {
933 if (eof)
934 return EOF;
935 index = 0;
936 do {
937 c[0] = str->getChar();
938 } while (Lexer::isSpace(c[0]));
939 if (c[0] == '~' || c[0] == EOF) {
940 eof = gTrue;
941 n = 0;
942 return EOF;
943 } else if (c[0] == 'z') {
944 b[0] = b[1] = b[2] = b[3] = 0;
945 n = 4;
946 } else {
947 for (k = 1; k < 5; ++k) {
948 do {
949 c[k] = str->getChar();
950 } while (Lexer::isSpace(c[k]));
951 if (c[k] == '~' || c[k] == EOF)
952 break;
954 n = k - 1;
955 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
956 for (++k; k < 5; ++k)
957 c[k] = 0x21 + 84;
958 eof = gTrue;
960 t = 0;
961 for (k = 0; k < 5; ++k)
962 t = t * 85 + (c[k] - 0x21);
963 for (k = 3; k >= 0; --k) {
964 b[k] = (int)(t & 0xff);
965 t >>= 8;
969 return b[index];
972 GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
973 GString *s;
975 if (psLevel < 2) {
976 return NULL;
978 if (!(s = str->getPSFilter(psLevel, indent))) {
979 return NULL;
981 s->append(indent)->append("/ASCII85Decode filter\n");
982 return s;
985 GBool ASCII85Stream::isBinary(GBool last) {
986 return str->isBinary(gFalse);
989 //------------------------------------------------------------------------
990 // LZWStream
991 //------------------------------------------------------------------------
993 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
994 int bits, int earlyA):
995 FilterStream(strA) {
996 if (predictor != 1) {
997 pred = new StreamPredictor(this, predictor, columns, colors, bits);
998 if (!pred->isOk()) {
999 delete pred;
1000 pred = NULL;
1002 } else {
1003 pred = NULL;
1005 early = earlyA;
1006 eof = gFalse;
1007 inputBits = 0;
1008 clearTable();
1011 LZWStream::~LZWStream() {
1012 if (pred) {
1013 delete pred;
1015 delete str;
1018 int LZWStream::getChar() {
1019 if (pred) {
1020 return pred->getChar();
1022 if (eof) {
1023 return EOF;
1025 if (seqIndex >= seqLength) {
1026 if (!processNextCode()) {
1027 return EOF;
1030 return seqBuf[seqIndex++];
1033 int LZWStream::lookChar() {
1034 if (pred) {
1035 return pred->lookChar();
1037 if (eof) {
1038 return EOF;
1040 if (seqIndex >= seqLength) {
1041 if (!processNextCode()) {
1042 return EOF;
1045 return seqBuf[seqIndex];
1048 int LZWStream::getRawChar() {
1049 if (eof) {
1050 return EOF;
1052 if (seqIndex >= seqLength) {
1053 if (!processNextCode()) {
1054 return EOF;
1057 return seqBuf[seqIndex++];
1060 void LZWStream::reset() {
1061 str->reset();
1062 eof = gFalse;
1063 inputBits = 0;
1064 clearTable();
1067 GBool LZWStream::processNextCode() {
1068 int code;
1069 int nextLength;
1070 int i, j;
1072 // check for EOF
1073 if (eof) {
1074 return gFalse;
1077 // check for eod and clear-table codes
1078 start:
1079 code = getCode();
1080 if (code == EOF || code == 257) {
1081 eof = gTrue;
1082 return gFalse;
1084 if (code == 256) {
1085 clearTable();
1086 goto start;
1088 if (nextCode >= 4097) {
1089 error(getPos(), "Bad LZW stream - expected clear-table code");
1090 clearTable();
1093 // process the next code
1094 nextLength = seqLength + 1;
1095 if (code < 256) {
1096 seqBuf[0] = code;
1097 seqLength = 1;
1098 } else if (code < nextCode) {
1099 seqLength = table[code].length;
1100 for (i = seqLength - 1, j = code; i > 0; --i) {
1101 seqBuf[i] = table[j].tail;
1102 j = table[j].head;
1104 seqBuf[0] = j;
1105 } else if (code == nextCode) {
1106 seqBuf[seqLength] = newChar;
1107 ++seqLength;
1108 } else {
1109 error(getPos(), "Bad LZW stream - unexpected code");
1110 eof = gTrue;
1111 return gFalse;
1113 newChar = seqBuf[0];
1114 if (first) {
1115 first = gFalse;
1116 } else {
1117 table[nextCode].length = nextLength;
1118 table[nextCode].head = prevCode;
1119 table[nextCode].tail = newChar;
1120 ++nextCode;
1121 if (nextCode + early == 512)
1122 nextBits = 10;
1123 else if (nextCode + early == 1024)
1124 nextBits = 11;
1125 else if (nextCode + early == 2048)
1126 nextBits = 12;
1128 prevCode = code;
1130 // reset buffer
1131 seqIndex = 0;
1133 return gTrue;
1136 void LZWStream::clearTable() {
1137 nextCode = 258;
1138 nextBits = 9;
1139 seqIndex = seqLength = 0;
1140 first = gTrue;
1143 int LZWStream::getCode() {
1144 int c;
1145 int code;
1147 while (inputBits < nextBits) {
1148 if ((c = str->getChar()) == EOF)
1149 return EOF;
1150 inputBuf = (inputBuf << 8) | (c & 0xff);
1151 inputBits += 8;
1153 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1154 inputBits -= nextBits;
1155 return code;
1158 GString *LZWStream::getPSFilter(int psLevel, char *indent) {
1159 GString *s;
1161 if (psLevel < 2 || pred) {
1162 return NULL;
1164 if (!(s = str->getPSFilter(psLevel, indent))) {
1165 return NULL;
1167 s->append(indent)->append("<< ");
1168 if (!early) {
1169 s->append("/EarlyChange 0 ");
1171 s->append(">> /LZWDecode filter\n");
1172 return s;
1175 GBool LZWStream::isBinary(GBool last) {
1176 return str->isBinary(gTrue);
1179 //------------------------------------------------------------------------
1180 // RunLengthStream
1181 //------------------------------------------------------------------------
1183 RunLengthStream::RunLengthStream(Stream *strA):
1184 FilterStream(strA) {
1185 bufPtr = bufEnd = buf;
1186 eof = gFalse;
1189 RunLengthStream::~RunLengthStream() {
1190 delete str;
1193 void RunLengthStream::reset() {
1194 str->reset();
1195 bufPtr = bufEnd = buf;
1196 eof = gFalse;
1199 GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
1200 GString *s;
1202 if (psLevel < 2) {
1203 return NULL;
1205 if (!(s = str->getPSFilter(psLevel, indent))) {
1206 return NULL;
1208 s->append(indent)->append("/RunLengthDecode filter\n");
1209 return s;
1212 GBool RunLengthStream::isBinary(GBool last) {
1213 return str->isBinary(gTrue);
1216 GBool RunLengthStream::fillBuf() {
1217 int c;
1218 int n, i;
1220 if (eof)
1221 return gFalse;
1222 c = str->getChar();
1223 if (c == 0x80 || c == EOF) {
1224 eof = gTrue;
1225 return gFalse;
1227 if (c < 0x80) {
1228 n = c + 1;
1229 for (i = 0; i < n; ++i)
1230 buf[i] = (char)str->getChar();
1231 } else {
1232 n = 0x101 - c;
1233 c = str->getChar();
1234 for (i = 0; i < n; ++i)
1235 buf[i] = (char)c;
1237 bufPtr = buf;
1238 bufEnd = buf + n;
1239 return gTrue;
1242 //------------------------------------------------------------------------
1243 // CCITTFaxStream
1244 //------------------------------------------------------------------------
1246 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1247 GBool byteAlignA, int columnsA, int rowsA,
1248 GBool endOfBlockA, GBool blackA):
1249 FilterStream(strA) {
1250 encoding = encodingA;
1251 endOfLine = endOfLineA;
1252 byteAlign = byteAlignA;
1253 columns = columnsA;
1254 if (columns < 1) {
1255 columns = 1;
1257 if (columns + 4 <= 0) {
1258 columns = INT_MAX - 4;
1260 rows = rowsA;
1261 endOfBlock = endOfBlockA;
1262 black = blackA;
1263 refLine = (short *)gmallocn(columns + 4, sizeof(short));
1264 codingLine = (short *)gmallocn(columns + 3, sizeof(short));
1266 eof = gFalse;
1267 row = 0;
1268 nextLine2D = encoding < 0;
1269 inputBits = 0;
1270 codingLine[0] = 0;
1271 codingLine[1] = refLine[2] = columns;
1272 a0 = 1;
1274 buf = EOF;
1277 CCITTFaxStream::~CCITTFaxStream() {
1278 delete str;
1279 gfree(refLine);
1280 gfree(codingLine);
1283 void CCITTFaxStream::reset() {
1284 short code1;
1286 str->reset();
1287 eof = gFalse;
1288 row = 0;
1289 nextLine2D = encoding < 0;
1290 inputBits = 0;
1291 codingLine[0] = 0;
1292 codingLine[1] = refLine[2] = columns;
1293 a0 = 1;
1294 buf = EOF;
1296 // skip any initial zero bits and end-of-line marker, and get the 2D
1297 // encoding tag
1298 while ((code1 = lookBits(12)) == 0) {
1299 eatBits(1);
1301 if (code1 == 0x001) {
1302 eatBits(12);
1304 if (encoding > 0) {
1305 nextLine2D = !lookBits(1);
1306 eatBits(1);
1310 int CCITTFaxStream::lookChar() {
1311 short code1, code2, code3;
1312 int a0New;
1313 GBool err, gotEOL;
1314 int ret;
1315 int bits, i;
1317 // if at eof just return EOF
1318 if (eof && codingLine[a0] >= columns) {
1319 return EOF;
1322 // read the next row
1323 err = gFalse;
1324 if (codingLine[a0] >= columns) {
1326 // 2-D encoding
1327 if (nextLine2D) {
1328 for (i = 0; codingLine[i] < columns; ++i)
1329 refLine[i] = codingLine[i];
1330 refLine[i] = refLine[i + 1] = columns;
1331 b1 = 1;
1332 a0New = codingLine[a0 = 0] = 0;
1333 do {
1334 code1 = getTwoDimCode();
1335 switch (code1) {
1336 case twoDimPass:
1337 if (refLine[b1] < columns) {
1338 a0New = refLine[b1 + 1];
1339 b1 += 2;
1341 break;
1342 case twoDimHoriz:
1343 if ((a0 & 1) == 0) {
1344 code1 = code2 = 0;
1345 do {
1346 code1 += code3 = getWhiteCode();
1347 } while (code3 >= 64);
1348 do {
1349 code2 += code3 = getBlackCode();
1350 } while (code3 >= 64);
1351 } else {
1352 code1 = code2 = 0;
1353 do {
1354 code1 += code3 = getBlackCode();
1355 } while (code3 >= 64);
1356 do {
1357 code2 += code3 = getWhiteCode();
1358 } while (code3 >= 64);
1360 if (code1 > 0 || code2 > 0) {
1361 codingLine[a0 + 1] = a0New + code1;
1362 ++a0;
1363 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1364 ++a0;
1365 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1366 b1 += 2;
1368 break;
1369 case twoDimVert0:
1370 a0New = codingLine[++a0] = refLine[b1];
1371 if (refLine[b1] < columns) {
1372 ++b1;
1373 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1374 b1 += 2;
1376 break;
1377 case twoDimVertR1:
1378 a0New = codingLine[++a0] = refLine[b1] + 1;
1379 if (refLine[b1] < columns) {
1380 ++b1;
1381 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1382 b1 += 2;
1384 break;
1385 case twoDimVertL1:
1386 if (a0 == 0 || refLine[b1] - 1 > a0New) {
1387 a0New = codingLine[++a0] = refLine[b1] - 1;
1388 --b1;
1389 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1390 b1 += 2;
1392 break;
1393 case twoDimVertR2:
1394 a0New = codingLine[++a0] = refLine[b1] + 2;
1395 if (refLine[b1] < columns) {
1396 ++b1;
1397 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1398 b1 += 2;
1400 break;
1401 case twoDimVertL2:
1402 if (a0 == 0 || refLine[b1] - 2 > a0New) {
1403 a0New = codingLine[++a0] = refLine[b1] - 2;
1404 --b1;
1405 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1406 b1 += 2;
1408 break;
1409 case twoDimVertR3:
1410 a0New = codingLine[++a0] = refLine[b1] + 3;
1411 if (refLine[b1] < columns) {
1412 ++b1;
1413 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1414 b1 += 2;
1416 break;
1417 case twoDimVertL3:
1418 if (a0 == 0 || refLine[b1] - 3 > a0New) {
1419 a0New = codingLine[++a0] = refLine[b1] - 3;
1420 --b1;
1421 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1422 b1 += 2;
1424 break;
1425 case EOF:
1426 eof = gTrue;
1427 codingLine[a0 = 0] = columns;
1428 return EOF;
1429 default:
1430 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1431 err = gTrue;
1432 break;
1434 } while (codingLine[a0] < columns);
1436 // 1-D encoding
1437 } else {
1438 codingLine[a0 = 0] = 0;
1439 while (1) {
1440 code1 = 0;
1441 do {
1442 code1 += code3 = getWhiteCode();
1443 } while (code3 >= 64);
1444 codingLine[a0+1] = codingLine[a0] + code1;
1445 ++a0;
1446 if (codingLine[a0] >= columns)
1447 break;
1448 code2 = 0;
1449 do {
1450 code2 += code3 = getBlackCode();
1451 } while (code3 >= 64);
1452 codingLine[a0+1] = codingLine[a0] + code2;
1453 ++a0;
1454 if (codingLine[a0] >= columns)
1455 break;
1459 if (codingLine[a0] != columns) {
1460 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1461 // force the row to be the correct length
1462 while (codingLine[a0] > columns) {
1463 --a0;
1465 codingLine[++a0] = columns;
1466 err = gTrue;
1469 // byte-align the row
1470 if (byteAlign) {
1471 inputBits &= ~7;
1474 // check for end-of-line marker, skipping over any extra zero bits
1475 gotEOL = gFalse;
1476 if (!endOfBlock && row == rows - 1) {
1477 eof = gTrue;
1478 } else {
1479 code1 = lookBits(12);
1480 while (code1 == 0) {
1481 eatBits(1);
1482 code1 = lookBits(12);
1484 if (code1 == 0x001) {
1485 eatBits(12);
1486 gotEOL = gTrue;
1487 } else if (code1 == EOF) {
1488 eof = gTrue;
1492 // get 2D encoding tag
1493 if (!eof && encoding > 0) {
1494 nextLine2D = !lookBits(1);
1495 eatBits(1);
1498 // check for end-of-block marker
1499 if (endOfBlock && gotEOL) {
1500 code1 = lookBits(12);
1501 if (code1 == 0x001) {
1502 eatBits(12);
1503 if (encoding > 0) {
1504 lookBits(1);
1505 eatBits(1);
1507 if (encoding >= 0) {
1508 for (i = 0; i < 4; ++i) {
1509 code1 = lookBits(12);
1510 if (code1 != 0x001) {
1511 error(getPos(), "Bad RTC code in CCITTFax stream");
1513 eatBits(12);
1514 if (encoding > 0) {
1515 lookBits(1);
1516 eatBits(1);
1520 eof = gTrue;
1523 // look for an end-of-line marker after an error -- we only do
1524 // this if we know the stream contains end-of-line markers because
1525 // the "just plow on" technique tends to work better otherwise
1526 } else if (err && endOfLine) {
1527 do {
1528 if (code1 == EOF) {
1529 eof = gTrue;
1530 return EOF;
1532 eatBits(1);
1533 code1 = lookBits(13);
1534 } while ((code1 >> 1) != 0x001);
1535 eatBits(12);
1536 if (encoding > 0) {
1537 eatBits(1);
1538 nextLine2D = !(code1 & 1);
1542 a0 = 0;
1543 outputBits = codingLine[1] - codingLine[0];
1544 if (outputBits == 0) {
1545 a0 = 1;
1546 outputBits = codingLine[2] - codingLine[1];
1549 ++row;
1552 // get a byte
1553 if (outputBits >= 8) {
1554 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1555 if ((outputBits -= 8) == 0) {
1556 ++a0;
1557 if (codingLine[a0] < columns) {
1558 outputBits = codingLine[a0 + 1] - codingLine[a0];
1561 } else {
1562 bits = 8;
1563 ret = 0;
1564 do {
1565 if (outputBits > bits) {
1566 i = bits;
1567 bits = 0;
1568 if ((a0 & 1) == 0) {
1569 ret |= 0xff >> (8 - i);
1571 outputBits -= i;
1572 } else {
1573 i = outputBits;
1574 bits -= outputBits;
1575 if ((a0 & 1) == 0) {
1576 ret |= (0xff >> (8 - i)) << bits;
1578 outputBits = 0;
1579 ++a0;
1580 if (codingLine[a0] < columns) {
1581 outputBits = codingLine[a0 + 1] - codingLine[a0];
1584 } while (bits > 0 && codingLine[a0] < columns);
1586 buf = black ? (ret ^ 0xff) : ret;
1587 return buf;
1590 short CCITTFaxStream::getTwoDimCode() {
1591 short code;
1592 CCITTCode *p;
1593 int n;
1595 code = 0; // make gcc happy
1596 if (endOfBlock) {
1597 code = lookBits(7);
1598 p = &twoDimTab1[code];
1599 if (p->bits > 0) {
1600 eatBits(p->bits);
1601 return p->n;
1603 } else {
1604 for (n = 1; n <= 7; ++n) {
1605 code = lookBits(n);
1606 if (n < 7) {
1607 code <<= 7 - n;
1609 p = &twoDimTab1[code];
1610 if (p->bits == n) {
1611 eatBits(n);
1612 return p->n;
1616 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1617 return EOF;
1620 short CCITTFaxStream::getWhiteCode() {
1621 short code;
1622 CCITTCode *p;
1623 int n;
1625 code = 0; // make gcc happy
1626 if (endOfBlock) {
1627 code = lookBits(12);
1628 if ((code >> 5) == 0) {
1629 p = &whiteTab1[code];
1630 } else {
1631 p = &whiteTab2[code >> 3];
1633 if (p->bits > 0) {
1634 eatBits(p->bits);
1635 return p->n;
1637 } else {
1638 for (n = 1; n <= 9; ++n) {
1639 code = lookBits(n);
1640 if (n < 9) {
1641 code <<= 9 - n;
1643 p = &whiteTab2[code];
1644 if (p->bits == n) {
1645 eatBits(n);
1646 return p->n;
1649 for (n = 11; n <= 12; ++n) {
1650 code = lookBits(n);
1651 if (n < 12) {
1652 code <<= 12 - n;
1654 p = &whiteTab1[code];
1655 if (p->bits == n) {
1656 eatBits(n);
1657 return p->n;
1661 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1662 // eat a bit and return a positive number so that the caller doesn't
1663 // go into an infinite loop
1664 eatBits(1);
1665 return 1;
1668 short CCITTFaxStream::getBlackCode() {
1669 short code;
1670 CCITTCode *p;
1671 int n;
1673 code = 0; // make gcc happy
1674 if (endOfBlock) {
1675 code = lookBits(13);
1676 if ((code >> 7) == 0) {
1677 p = &blackTab1[code];
1678 } else if ((code >> 9) == 0) {
1679 p = &blackTab2[(code >> 1) - 64];
1680 } else {
1681 p = &blackTab3[code >> 7];
1683 if (p->bits > 0) {
1684 eatBits(p->bits);
1685 return p->n;
1687 } else {
1688 for (n = 2; n <= 6; ++n) {
1689 code = lookBits(n);
1690 if (n < 6) {
1691 code <<= 6 - n;
1693 p = &blackTab3[code];
1694 if (p->bits == n) {
1695 eatBits(n);
1696 return p->n;
1699 for (n = 7; n <= 12; ++n) {
1700 code = lookBits(n);
1701 if (n < 12) {
1702 code <<= 12 - n;
1704 if (code >= 64) {
1705 p = &blackTab2[code - 64];
1706 if (p->bits == n) {
1707 eatBits(n);
1708 return p->n;
1712 for (n = 10; n <= 13; ++n) {
1713 code = lookBits(n);
1714 if (n < 13) {
1715 code <<= 13 - n;
1717 p = &blackTab1[code];
1718 if (p->bits == n) {
1719 eatBits(n);
1720 return p->n;
1724 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1725 // eat a bit and return a positive number so that the caller doesn't
1726 // go into an infinite loop
1727 eatBits(1);
1728 return 1;
1731 short CCITTFaxStream::lookBits(int n) {
1732 int c;
1734 while (inputBits < n) {
1735 if ((c = str->getChar()) == EOF) {
1736 if (inputBits == 0) {
1737 return EOF;
1739 // near the end of the stream, the caller may ask for more bits
1740 // than are available, but there may still be a valid code in
1741 // however many bits are available -- we need to return correct
1742 // data in this case
1743 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1745 inputBuf = (inputBuf << 8) + c;
1746 inputBits += 8;
1748 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1751 GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
1752 GString *s;
1753 char s1[50];
1755 if (psLevel < 2) {
1756 return NULL;
1758 if (!(s = str->getPSFilter(psLevel, indent))) {
1759 return NULL;
1761 s->append(indent)->append("<< ");
1762 if (encoding != 0) {
1763 sprintf(s1, "/K %d ", encoding);
1764 s->append(s1);
1766 if (endOfLine) {
1767 s->append("/EndOfLine true ");
1769 if (byteAlign) {
1770 s->append("/EncodedByteAlign true ");
1772 sprintf(s1, "/Columns %d ", columns);
1773 s->append(s1);
1774 if (rows != 0) {
1775 sprintf(s1, "/Rows %d ", rows);
1776 s->append(s1);
1778 if (!endOfBlock) {
1779 s->append("/EndOfBlock false ");
1781 if (black) {
1782 s->append("/BlackIs1 true ");
1784 s->append(">> /CCITTFaxDecode filter\n");
1785 return s;
1788 GBool CCITTFaxStream::isBinary(GBool last) {
1789 return str->isBinary(gTrue);
1792 //------------------------------------------------------------------------
1793 // DCTStream
1794 //------------------------------------------------------------------------
1796 // IDCT constants (20.12 fixed point format)
1797 #define dctCos1 4017 // cos(pi/16)
1798 #define dctSin1 799 // sin(pi/16)
1799 #define dctCos3 3406 // cos(3*pi/16)
1800 #define dctSin3 2276 // sin(3*pi/16)
1801 #define dctCos6 1567 // cos(6*pi/16)
1802 #define dctSin6 3784 // sin(6*pi/16)
1803 #define dctSqrt2 5793 // sqrt(2)
1804 #define dctSqrt1d2 2896 // sqrt(2) / 2
1806 // color conversion parameters (16.16 fixed point format)
1807 #define dctCrToR 91881 // 1.4020
1808 #define dctCbToG -22553 // -0.3441363
1809 #define dctCrToG -46802 // -0.71413636
1810 #define dctCbToB 116130 // 1.772
1812 // clip [-256,511] --> [0,255]
1813 #define dctClipOffset 256
1814 static Guchar dctClip[768];
1815 static int dctClipInit = 0;
1817 // zig zag decode map
1818 static int dctZigZag[64] = {
1820 1, 8,
1821 16, 9, 2,
1822 3, 10, 17, 24,
1823 32, 25, 18, 11, 4,
1824 5, 12, 19, 26, 33, 40,
1825 48, 41, 34, 27, 20, 13, 6,
1826 7, 14, 21, 28, 35, 42, 49, 56,
1827 57, 50, 43, 36, 29, 22, 15,
1828 23, 30, 37, 44, 51, 58,
1829 59, 52, 45, 38, 31,
1830 39, 46, 53, 60,
1831 61, 54, 47,
1832 55, 62,
1836 DCTStream::DCTStream(Stream *strA):
1837 FilterStream(strA) {
1838 int i, j;
1840 progressive = interleaved = gFalse;
1841 width = height = 0;
1842 mcuWidth = mcuHeight = 0;
1843 numComps = 0;
1844 comp = 0;
1845 x = y = dy = 0;
1846 for (i = 0; i < 4; ++i) {
1847 for (j = 0; j < 32; ++j) {
1848 rowBuf[i][j] = NULL;
1850 frameBuf[i] = NULL;
1853 if (!dctClipInit) {
1854 for (i = -256; i < 0; ++i)
1855 dctClip[dctClipOffset + i] = 0;
1856 for (i = 0; i < 256; ++i)
1857 dctClip[dctClipOffset + i] = i;
1858 for (i = 256; i < 512; ++i)
1859 dctClip[dctClipOffset + i] = 255;
1860 dctClipInit = 1;
1864 DCTStream::~DCTStream() {
1865 int i, j;
1867 delete str;
1868 if (progressive || !interleaved) {
1869 for (i = 0; i < numComps; ++i) {
1870 gfree(frameBuf[i]);
1872 } else {
1873 for (i = 0; i < numComps; ++i) {
1874 for (j = 0; j < mcuHeight; ++j) {
1875 gfree(rowBuf[i][j]);
1881 void DCTStream::reset() {
1882 int i, j;
1884 str->reset();
1886 progressive = interleaved = gFalse;
1887 width = height = 0;
1888 numComps = 0;
1889 numQuantTables = 0;
1890 numDCHuffTables = 0;
1891 numACHuffTables = 0;
1892 colorXform = 0;
1893 gotJFIFMarker = gFalse;
1894 gotAdobeMarker = gFalse;
1895 restartInterval = 0;
1897 if (!readHeader()) {
1898 y = height;
1899 return;
1902 // compute MCU size
1903 if (numComps == 1) {
1904 compInfo[0].hSample = compInfo[0].vSample = 1;
1906 mcuWidth = compInfo[0].hSample;
1907 mcuHeight = compInfo[0].vSample;
1908 for (i = 1; i < numComps; ++i) {
1909 if (compInfo[i].hSample > mcuWidth) {
1910 mcuWidth = compInfo[i].hSample;
1912 if (compInfo[i].vSample > mcuHeight) {
1913 mcuHeight = compInfo[i].vSample;
1916 mcuWidth *= 8;
1917 mcuHeight *= 8;
1919 // figure out color transform
1920 if (!gotAdobeMarker && numComps == 3) {
1921 if (gotJFIFMarker) {
1922 colorXform = 1;
1923 } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
1924 compInfo[2].id == 66) { // ASCII "RGB"
1925 colorXform = 0;
1926 } else {
1927 colorXform = 1;
1931 if (progressive || !interleaved) {
1933 // allocate a buffer for the whole image
1934 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1935 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
1936 for (i = 0; i < numComps; ++i) {
1937 frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
1938 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
1941 // read the image data
1942 do {
1943 restartMarker = 0xd0;
1944 restart();
1945 readScan();
1946 } while (readHeader());
1948 // decode
1949 decodeImage();
1951 // initialize counters
1952 comp = 0;
1953 x = 0;
1954 y = 0;
1956 } else {
1958 // allocate a buffer for one row of MCUs
1959 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1960 for (i = 0; i < numComps; ++i) {
1961 for (j = 0; j < mcuHeight; ++j) {
1962 rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
1966 // initialize counters
1967 comp = 0;
1968 x = 0;
1969 y = 0;
1970 dy = mcuHeight;
1972 restartMarker = 0xd0;
1973 restart();
1977 int DCTStream::getChar() {
1978 int c;
1980 if (y >= height) {
1981 return EOF;
1983 if (progressive || !interleaved) {
1984 c = frameBuf[comp][y * bufWidth + x];
1985 if (++comp == numComps) {
1986 comp = 0;
1987 if (++x == width) {
1988 x = 0;
1989 ++y;
1992 } else {
1993 if (dy >= mcuHeight) {
1994 if (!readMCURow()) {
1995 y = height;
1996 return EOF;
1998 comp = 0;
1999 x = 0;
2000 dy = 0;
2002 c = rowBuf[comp][dy][x];
2003 if (++comp == numComps) {
2004 comp = 0;
2005 if (++x == width) {
2006 x = 0;
2007 ++y;
2008 ++dy;
2009 if (y == height) {
2010 readTrailer();
2015 return c;
2018 int DCTStream::lookChar() {
2019 if (y >= height) {
2020 return EOF;
2022 if (progressive || !interleaved) {
2023 return frameBuf[comp][y * bufWidth + x];
2024 } else {
2025 if (dy >= mcuHeight) {
2026 if (!readMCURow()) {
2027 y = height;
2028 return EOF;
2030 comp = 0;
2031 x = 0;
2032 dy = 0;
2034 return rowBuf[comp][dy][x];
2038 void DCTStream::restart() {
2039 int i;
2041 inputBits = 0;
2042 restartCtr = restartInterval;
2043 for (i = 0; i < numComps; ++i) {
2044 compInfo[i].prevDC = 0;
2046 eobRun = 0;
2049 // Read one row of MCUs from a sequential JPEG stream.
2050 GBool DCTStream::readMCURow() {
2051 int data1[64];
2052 Guchar data2[64];
2053 Guchar *p1, *p2;
2054 int pY, pCb, pCr, pR, pG, pB;
2055 int h, v, horiz, vert, hSub, vSub;
2056 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2057 int c;
2059 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2061 // deal with restart marker
2062 if (restartInterval > 0 && restartCtr == 0) {
2063 c = readMarker();
2064 if (c != restartMarker) {
2065 error(getPos(), "Bad DCT data: incorrect restart marker");
2066 return gFalse;
2068 if (++restartMarker == 0xd8)
2069 restartMarker = 0xd0;
2070 restart();
2073 // read one MCU
2074 for (cc = 0; cc < numComps; ++cc) {
2075 h = compInfo[cc].hSample;
2076 v = compInfo[cc].vSample;
2077 horiz = mcuWidth / h;
2078 vert = mcuHeight / v;
2079 hSub = horiz / 8;
2080 vSub = vert / 8;
2081 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2082 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2083 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2084 &acHuffTables[scanInfo.acHuffTable[cc]],
2085 &compInfo[cc].prevDC,
2086 data1)) {
2087 return gFalse;
2089 transformDataUnit(quantTables[compInfo[cc].quantTable],
2090 data1, data2);
2091 if (hSub == 1 && vSub == 1) {
2092 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2093 p1 = &rowBuf[cc][y2+y3][x1+x2];
2094 p1[0] = data2[i];
2095 p1[1] = data2[i+1];
2096 p1[2] = data2[i+2];
2097 p1[3] = data2[i+3];
2098 p1[4] = data2[i+4];
2099 p1[5] = data2[i+5];
2100 p1[6] = data2[i+6];
2101 p1[7] = data2[i+7];
2103 } else if (hSub == 2 && vSub == 2) {
2104 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2105 p1 = &rowBuf[cc][y2+y3][x1+x2];
2106 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2107 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2108 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2109 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2110 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2111 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2112 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2113 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2114 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2116 } else {
2117 i = 0;
2118 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2119 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2120 for (y5 = 0; y5 < vSub; ++y5)
2121 for (x5 = 0; x5 < hSub; ++x5)
2122 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2123 ++i;
2130 --restartCtr;
2132 // color space conversion
2133 if (colorXform) {
2134 // convert YCbCr to RGB
2135 if (numComps == 3) {
2136 for (y2 = 0; y2 < mcuHeight; ++y2) {
2137 for (x2 = 0; x2 < mcuWidth; ++x2) {
2138 pY = rowBuf[0][y2][x1+x2];
2139 pCb = rowBuf[1][y2][x1+x2] - 128;
2140 pCr = rowBuf[2][y2][x1+x2] - 128;
2141 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2142 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2143 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2144 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2145 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2146 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2149 // convert YCbCrK to CMYK (K is passed through unchanged)
2150 } else if (numComps == 4) {
2151 for (y2 = 0; y2 < mcuHeight; ++y2) {
2152 for (x2 = 0; x2 < mcuWidth; ++x2) {
2153 pY = rowBuf[0][y2][x1+x2];
2154 pCb = rowBuf[1][y2][x1+x2] - 128;
2155 pCr = rowBuf[2][y2][x1+x2] - 128;
2156 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2157 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2158 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2159 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2160 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2161 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2167 return gTrue;
2170 // Read one scan from a progressive or non-interleaved JPEG stream.
2171 void DCTStream::readScan() {
2172 int data[64];
2173 int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2174 int h, v, horiz, vert, vSub;
2175 int *p1;
2176 int c;
2178 if (scanInfo.numComps == 1) {
2179 for (cc = 0; cc < numComps; ++cc) {
2180 if (scanInfo.comp[cc]) {
2181 break;
2184 dx1 = mcuWidth / compInfo[cc].hSample;
2185 dy1 = mcuHeight / compInfo[cc].vSample;
2186 } else {
2187 dx1 = mcuWidth;
2188 dy1 = mcuHeight;
2191 for (y1 = 0; y1 < height; y1 += dy1) {
2192 for (x1 = 0; x1 < width; x1 += dx1) {
2194 // deal with restart marker
2195 if (restartInterval > 0 && restartCtr == 0) {
2196 c = readMarker();
2197 if (c != restartMarker) {
2198 error(getPos(), "Bad DCT data: incorrect restart marker");
2199 return;
2201 if (++restartMarker == 0xd8) {
2202 restartMarker = 0xd0;
2204 restart();
2207 // read one MCU
2208 for (cc = 0; cc < numComps; ++cc) {
2209 if (!scanInfo.comp[cc]) {
2210 continue;
2213 h = compInfo[cc].hSample;
2214 v = compInfo[cc].vSample;
2215 horiz = mcuWidth / h;
2216 vert = mcuHeight / v;
2217 vSub = vert / 8;
2218 for (y2 = 0; y2 < dy1; y2 += vert) {
2219 for (x2 = 0; x2 < dx1; x2 += horiz) {
2221 // pull out the current values
2222 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2223 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2224 data[i] = p1[0];
2225 data[i+1] = p1[1];
2226 data[i+2] = p1[2];
2227 data[i+3] = p1[3];
2228 data[i+4] = p1[4];
2229 data[i+5] = p1[5];
2230 data[i+6] = p1[6];
2231 data[i+7] = p1[7];
2232 p1 += bufWidth * vSub;
2235 // read one data unit
2236 if (progressive) {
2237 if (!readProgressiveDataUnit(
2238 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2239 &acHuffTables[scanInfo.acHuffTable[cc]],
2240 &compInfo[cc].prevDC,
2241 data)) {
2242 return;
2244 } else {
2245 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2246 &acHuffTables[scanInfo.acHuffTable[cc]],
2247 &compInfo[cc].prevDC,
2248 data)) {
2249 return;
2253 // add the data unit into frameBuf
2254 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2255 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2256 p1[0] = data[i];
2257 p1[1] = data[i+1];
2258 p1[2] = data[i+2];
2259 p1[3] = data[i+3];
2260 p1[4] = data[i+4];
2261 p1[5] = data[i+5];
2262 p1[6] = data[i+6];
2263 p1[7] = data[i+7];
2264 p1 += bufWidth * vSub;
2269 --restartCtr;
2274 // Read one data unit from a sequential JPEG stream.
2275 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2276 DCTHuffTable *acHuffTable,
2277 int *prevDC, int data[64]) {
2278 int run, size, amp;
2279 int c;
2280 int i, j;
2282 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2283 return gFalse;
2285 if (size > 0) {
2286 if ((amp = readAmp(size)) == 9999) {
2287 return gFalse;
2289 } else {
2290 amp = 0;
2292 data[0] = *prevDC += amp;
2293 for (i = 1; i < 64; ++i) {
2294 data[i] = 0;
2296 i = 1;
2297 while (i < 64) {
2298 run = 0;
2299 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2300 run += 0x10;
2302 if (c == 9999) {
2303 return gFalse;
2305 if (c == 0x00) {
2306 break;
2307 } else {
2308 run += (c >> 4) & 0x0f;
2309 size = c & 0x0f;
2310 amp = readAmp(size);
2311 if (amp == 9999) {
2312 return gFalse;
2314 i += run;
2315 if (i < 64) {
2316 j = dctZigZag[i++];
2317 data[j] = amp;
2321 return gTrue;
2324 // Read one data unit from a sequential JPEG stream.
2325 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2326 DCTHuffTable *acHuffTable,
2327 int *prevDC, int data[64]) {
2328 int run, size, amp, bit, c;
2329 int i, j, k;
2331 // get the DC coefficient
2332 i = scanInfo.firstCoeff;
2333 if (i == 0) {
2334 if (scanInfo.ah == 0) {
2335 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2336 return gFalse;
2338 if (size > 0) {
2339 if ((amp = readAmp(size)) == 9999) {
2340 return gFalse;
2342 } else {
2343 amp = 0;
2345 data[0] += (*prevDC += amp) << scanInfo.al;
2346 } else {
2347 if ((bit = readBit()) == 9999) {
2348 return gFalse;
2350 data[0] += bit << scanInfo.al;
2352 ++i;
2354 if (scanInfo.lastCoeff == 0) {
2355 return gTrue;
2358 // check for an EOB run
2359 if (eobRun > 0) {
2360 while (i <= scanInfo.lastCoeff) {
2361 j = dctZigZag[i++];
2362 if (data[j] != 0) {
2363 if ((bit = readBit()) == EOF) {
2364 return gFalse;
2366 if (bit) {
2367 data[j] += 1 << scanInfo.al;
2371 --eobRun;
2372 return gTrue;
2375 // read the AC coefficients
2376 while (i <= scanInfo.lastCoeff) {
2377 if ((c = readHuffSym(acHuffTable)) == 9999) {
2378 return gFalse;
2381 // ZRL
2382 if (c == 0xf0) {
2383 k = 0;
2384 while (k < 16) {
2385 j = dctZigZag[i++];
2386 if (data[j] == 0) {
2387 ++k;
2388 } else {
2389 if ((bit = readBit()) == EOF) {
2390 return gFalse;
2392 if (bit) {
2393 data[j] += 1 << scanInfo.al;
2398 // EOB run
2399 } else if ((c & 0x0f) == 0x00) {
2400 j = c >> 4;
2401 eobRun = 0;
2402 for (k = 0; k < j; ++k) {
2403 if ((bit = readBit()) == EOF) {
2404 return gFalse;
2406 eobRun = (eobRun << 1) | bit;
2408 eobRun += 1 << j;
2409 while (i <= scanInfo.lastCoeff) {
2410 j = dctZigZag[i++];
2411 if (data[j] != 0) {
2412 if ((bit = readBit()) == EOF) {
2413 return gFalse;
2415 if (bit) {
2416 data[j] += 1 << scanInfo.al;
2420 --eobRun;
2421 break;
2423 // zero run and one AC coefficient
2424 } else {
2425 run = (c >> 4) & 0x0f;
2426 size = c & 0x0f;
2427 if ((amp = readAmp(size)) == 9999) {
2428 return gFalse;
2430 k = 0;
2431 do {
2432 j = dctZigZag[i++];
2433 while (data[j] != 0) {
2434 if ((bit = readBit()) == EOF) {
2435 return gFalse;
2437 if (bit) {
2438 data[j] += 1 << scanInfo.al;
2440 j = dctZigZag[i++];
2442 ++k;
2443 } while (k <= run);
2444 data[j] = amp << scanInfo.al;
2448 return gTrue;
2451 // Decode a progressive JPEG image.
2452 void DCTStream::decodeImage() {
2453 int dataIn[64];
2454 Guchar dataOut[64];
2455 Gushort *quantTable;
2456 int pY, pCb, pCr, pR, pG, pB;
2457 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2458 int h, v, horiz, vert, hSub, vSub;
2459 int *p0, *p1, *p2;
2461 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2462 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2463 for (cc = 0; cc < numComps; ++cc) {
2464 quantTable = quantTables[compInfo[cc].quantTable];
2465 h = compInfo[cc].hSample;
2466 v = compInfo[cc].vSample;
2467 horiz = mcuWidth / h;
2468 vert = mcuHeight / v;
2469 hSub = horiz / 8;
2470 vSub = vert / 8;
2471 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2472 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2474 // pull out the coded data unit
2475 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2476 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2477 dataIn[i] = p1[0];
2478 dataIn[i+1] = p1[1];
2479 dataIn[i+2] = p1[2];
2480 dataIn[i+3] = p1[3];
2481 dataIn[i+4] = p1[4];
2482 dataIn[i+5] = p1[5];
2483 dataIn[i+6] = p1[6];
2484 dataIn[i+7] = p1[7];
2485 p1 += bufWidth * vSub;
2488 // transform
2489 transformDataUnit(quantTable, dataIn, dataOut);
2491 // store back into frameBuf, doing replication for
2492 // subsampled components
2493 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2494 if (hSub == 1 && vSub == 1) {
2495 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2496 p1[0] = dataOut[i] & 0xff;
2497 p1[1] = dataOut[i+1] & 0xff;
2498 p1[2] = dataOut[i+2] & 0xff;
2499 p1[3] = dataOut[i+3] & 0xff;
2500 p1[4] = dataOut[i+4] & 0xff;
2501 p1[5] = dataOut[i+5] & 0xff;
2502 p1[6] = dataOut[i+6] & 0xff;
2503 p1[7] = dataOut[i+7] & 0xff;
2504 p1 += bufWidth;
2506 } else if (hSub == 2 && vSub == 2) {
2507 p2 = p1 + bufWidth;
2508 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2509 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2510 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2511 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2512 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2513 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2514 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2515 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2516 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2517 p1 += bufWidth * 2;
2518 p2 += bufWidth * 2;
2520 } else {
2521 i = 0;
2522 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2523 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2524 p2 = p1 + x4;
2525 for (y5 = 0; y5 < vSub; ++y5) {
2526 for (x5 = 0; x5 < hSub; ++x5) {
2527 p2[x5] = dataOut[i] & 0xff;
2529 p2 += bufWidth;
2531 ++i;
2533 p1 += bufWidth * vSub;
2540 // color space conversion
2541 if (colorXform) {
2542 // convert YCbCr to RGB
2543 if (numComps == 3) {
2544 for (y2 = 0; y2 < mcuHeight; ++y2) {
2545 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2546 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2547 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2548 for (x2 = 0; x2 < mcuWidth; ++x2) {
2549 pY = *p0;
2550 pCb = *p1 - 128;
2551 pCr = *p2 - 128;
2552 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2553 *p0++ = dctClip[dctClipOffset + pR];
2554 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2555 32768) >> 16;
2556 *p1++ = dctClip[dctClipOffset + pG];
2557 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2558 *p2++ = dctClip[dctClipOffset + pB];
2561 // convert YCbCrK to CMYK (K is passed through unchanged)
2562 } else if (numComps == 4) {
2563 for (y2 = 0; y2 < mcuHeight; ++y2) {
2564 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2565 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2566 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2567 for (x2 = 0; x2 < mcuWidth; ++x2) {
2568 pY = *p0;
2569 pCb = *p1 - 128;
2570 pCr = *p2 - 128;
2571 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2572 *p0++ = 255 - dctClip[dctClipOffset + pR];
2573 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2574 32768) >> 16;
2575 *p1++ = 255 - dctClip[dctClipOffset + pG];
2576 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2577 *p2++ = 255 - dctClip[dctClipOffset + pB];
2586 // Transform one data unit -- this performs the dequantization and
2587 // IDCT steps. This IDCT algorithm is taken from:
2588 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2589 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2590 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2591 // 988-991.
2592 // The stage numbers mentioned in the comments refer to Figure 1 in this
2593 // paper.
2594 void DCTStream::transformDataUnit(Gushort *quantTable,
2595 int dataIn[64], Guchar dataOut[64]) {
2596 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2597 int *p;
2598 int i;
2600 // dequant
2601 for (i = 0; i < 64; ++i) {
2602 dataIn[i] *= quantTable[i];
2605 // inverse DCT on rows
2606 for (i = 0; i < 64; i += 8) {
2607 p = dataIn + i;
2609 // check for all-zero AC coefficients
2610 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2611 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2612 t = (dctSqrt2 * p[0] + 512) >> 10;
2613 p[0] = t;
2614 p[1] = t;
2615 p[2] = t;
2616 p[3] = t;
2617 p[4] = t;
2618 p[5] = t;
2619 p[6] = t;
2620 p[7] = t;
2621 continue;
2624 // stage 4
2625 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2626 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2627 v2 = p[2];
2628 v3 = p[6];
2629 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2630 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2631 v5 = p[3] << 4;
2632 v6 = p[5] << 4;
2634 // stage 3
2635 t = (v0 - v1+ 1) >> 1;
2636 v0 = (v0 + v1 + 1) >> 1;
2637 v1 = t;
2638 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2639 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2640 v3 = t;
2641 t = (v4 - v6 + 1) >> 1;
2642 v4 = (v4 + v6 + 1) >> 1;
2643 v6 = t;
2644 t = (v7 + v5 + 1) >> 1;
2645 v5 = (v7 - v5 + 1) >> 1;
2646 v7 = t;
2648 // stage 2
2649 t = (v0 - v3 + 1) >> 1;
2650 v0 = (v0 + v3 + 1) >> 1;
2651 v3 = t;
2652 t = (v1 - v2 + 1) >> 1;
2653 v1 = (v1 + v2 + 1) >> 1;
2654 v2 = t;
2655 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2656 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2657 v7 = t;
2658 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2659 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2660 v6 = t;
2662 // stage 1
2663 p[0] = v0 + v7;
2664 p[7] = v0 - v7;
2665 p[1] = v1 + v6;
2666 p[6] = v1 - v6;
2667 p[2] = v2 + v5;
2668 p[5] = v2 - v5;
2669 p[3] = v3 + v4;
2670 p[4] = v3 - v4;
2673 // inverse DCT on columns
2674 for (i = 0; i < 8; ++i) {
2675 p = dataIn + i;
2677 // check for all-zero AC coefficients
2678 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2679 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2680 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2681 p[0*8] = t;
2682 p[1*8] = t;
2683 p[2*8] = t;
2684 p[3*8] = t;
2685 p[4*8] = t;
2686 p[5*8] = t;
2687 p[6*8] = t;
2688 p[7*8] = t;
2689 continue;
2692 // stage 4
2693 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2694 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2695 v2 = p[2*8];
2696 v3 = p[6*8];
2697 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2698 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2699 v5 = p[3*8];
2700 v6 = p[5*8];
2702 // stage 3
2703 t = (v0 - v1 + 1) >> 1;
2704 v0 = (v0 + v1 + 1) >> 1;
2705 v1 = t;
2706 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2707 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2708 v3 = t;
2709 t = (v4 - v6 + 1) >> 1;
2710 v4 = (v4 + v6 + 1) >> 1;
2711 v6 = t;
2712 t = (v7 + v5 + 1) >> 1;
2713 v5 = (v7 - v5 + 1) >> 1;
2714 v7 = t;
2716 // stage 2
2717 t = (v0 - v3 + 1) >> 1;
2718 v0 = (v0 + v3 + 1) >> 1;
2719 v3 = t;
2720 t = (v1 - v2 + 1) >> 1;
2721 v1 = (v1 + v2 + 1) >> 1;
2722 v2 = t;
2723 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2724 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2725 v7 = t;
2726 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2727 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2728 v6 = t;
2730 // stage 1
2731 p[0*8] = v0 + v7;
2732 p[7*8] = v0 - v7;
2733 p[1*8] = v1 + v6;
2734 p[6*8] = v1 - v6;
2735 p[2*8] = v2 + v5;
2736 p[5*8] = v2 - v5;
2737 p[3*8] = v3 + v4;
2738 p[4*8] = v3 - v4;
2741 // convert to 8-bit integers
2742 for (i = 0; i < 64; ++i) {
2743 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2747 int DCTStream::readHuffSym(DCTHuffTable *table) {
2748 Gushort code;
2749 int bit;
2750 int codeBits;
2752 code = 0;
2753 codeBits = 0;
2754 do {
2755 // add a bit to the code
2756 if ((bit = readBit()) == EOF)
2757 return 9999;
2758 code = (code << 1) + bit;
2759 ++codeBits;
2761 // look up code
2762 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2763 code -= table->firstCode[codeBits];
2764 return table->sym[table->firstSym[codeBits] + code];
2766 } while (codeBits < 16);
2768 error(getPos(), "Bad Huffman code in DCT stream");
2769 return 9999;
2772 int DCTStream::readAmp(int size) {
2773 int amp, bit;
2774 int bits;
2776 amp = 0;
2777 for (bits = 0; bits < size; ++bits) {
2778 if ((bit = readBit()) == EOF)
2779 return 9999;
2780 amp = (amp << 1) + bit;
2782 if (amp < (1 << (size - 1)))
2783 amp -= (1 << size) - 1;
2784 return amp;
2787 int DCTStream::readBit() {
2788 int bit;
2789 int c, c2;
2791 if (inputBits == 0) {
2792 if ((c = str->getChar()) == EOF)
2793 return EOF;
2794 if (c == 0xff) {
2795 do {
2796 c2 = str->getChar();
2797 } while (c2 == 0xff);
2798 if (c2 != 0x00) {
2799 error(getPos(), "Bad DCT data: missing 00 after ff");
2800 return EOF;
2803 inputBuf = c;
2804 inputBits = 8;
2806 bit = (inputBuf >> (inputBits - 1)) & 1;
2807 --inputBits;
2808 return bit;
2811 GBool DCTStream::readHeader() {
2812 GBool doScan;
2813 int n;
2814 int c = 0;
2815 int i;
2817 // read headers
2818 doScan = gFalse;
2819 while (!doScan) {
2820 c = readMarker();
2821 switch (c) {
2822 case 0xc0: // SOF0 (sequential)
2823 case 0xc1: // SOF1 (extended sequential)
2824 if (!readBaselineSOF()) {
2825 return gFalse;
2827 break;
2828 case 0xc2: // SOF2 (progressive)
2829 if (!readProgressiveSOF()) {
2830 return gFalse;
2832 break;
2833 case 0xc4: // DHT
2834 if (!readHuffmanTables()) {
2835 return gFalse;
2837 break;
2838 case 0xd8: // SOI
2839 break;
2840 case 0xd9: // EOI
2841 return gFalse;
2842 case 0xda: // SOS
2843 if (!readScanInfo()) {
2844 return gFalse;
2846 doScan = gTrue;
2847 break;
2848 case 0xdb: // DQT
2849 if (!readQuantTables()) {
2850 return gFalse;
2852 break;
2853 case 0xdd: // DRI
2854 if (!readRestartInterval()) {
2855 return gFalse;
2857 break;
2858 case 0xe0: // APP0
2859 if (!readJFIFMarker()) {
2860 return gFalse;
2862 break;
2863 case 0xee: // APP14
2864 if (!readAdobeMarker()) {
2865 return gFalse;
2867 break;
2868 case EOF:
2869 error(getPos(), "Bad DCT header");
2870 return gFalse;
2871 default:
2872 // skip APPn / COM / etc.
2873 if (c >= 0xe0) {
2874 n = read16() - 2;
2875 for (i = 0; i < n; ++i) {
2876 str->getChar();
2878 } else {
2879 error(getPos(), "Unknown DCT marker <%02x>", c);
2880 return gFalse;
2882 break;
2886 return gTrue;
2889 GBool DCTStream::readBaselineSOF() {
2890 int length;
2891 int prec;
2892 int i;
2893 int c;
2895 length = read16();
2896 prec = str->getChar();
2897 height = read16();
2898 width = read16();
2899 numComps = str->getChar();
2900 if (numComps <= 0 || numComps > 4) {
2901 error(getPos(), "Bad number of components in DCT stream");
2902 numComps = 0;
2903 return gFalse;
2905 if (prec != 8) {
2906 error(getPos(), "Bad DCT precision %d", prec);
2907 return gFalse;
2909 for (i = 0; i < numComps; ++i) {
2910 compInfo[i].id = str->getChar();
2911 c = str->getChar();
2912 compInfo[i].hSample = (c >> 4) & 0x0f;
2913 compInfo[i].vSample = c & 0x0f;
2914 compInfo[i].quantTable = str->getChar();
2916 progressive = gFalse;
2917 return gTrue;
2920 GBool DCTStream::readProgressiveSOF() {
2921 int length;
2922 int prec;
2923 int i;
2924 int c;
2926 length = read16();
2927 prec = str->getChar();
2928 height = read16();
2929 width = read16();
2930 numComps = str->getChar();
2931 if (numComps <= 0 || numComps > 4) {
2932 error(getPos(), "Bad number of components in DCT stream");
2933 numComps = 0;
2934 return gFalse;
2936 if (prec != 8) {
2937 error(getPos(), "Bad DCT precision %d", prec);
2938 return gFalse;
2940 for (i = 0; i < numComps; ++i) {
2941 compInfo[i].id = str->getChar();
2942 c = str->getChar();
2943 compInfo[i].hSample = (c >> 4) & 0x0f;
2944 compInfo[i].vSample = c & 0x0f;
2945 compInfo[i].quantTable = str->getChar();
2947 progressive = gTrue;
2948 return gTrue;
2951 GBool DCTStream::readScanInfo() {
2952 int length;
2953 int id, c;
2954 int i, j;
2956 length = read16() - 2;
2957 scanInfo.numComps = str->getChar();
2958 if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
2959 error(getPos(), "Bad number of components in DCT stream");
2960 scanInfo.numComps = 0;
2961 return gFalse;
2963 --length;
2964 if (length != 2 * scanInfo.numComps + 3) {
2965 error(getPos(), "Bad DCT scan info block");
2966 return gFalse;
2968 interleaved = scanInfo.numComps == numComps;
2969 for (j = 0; j < numComps; ++j) {
2970 scanInfo.comp[j] = gFalse;
2972 for (i = 0; i < scanInfo.numComps; ++i) {
2973 id = str->getChar();
2974 // some (broken) DCT streams reuse ID numbers, but at least they
2975 // keep the components in order, so we check compInfo[i] first to
2976 // work around the problem
2977 if (id == compInfo[i].id) {
2978 j = i;
2979 } else {
2980 for (j = 0; j < numComps; ++j) {
2981 if (id == compInfo[j].id) {
2982 break;
2985 if (j == numComps) {
2986 error(getPos(), "Bad DCT component ID in scan info block");
2987 return gFalse;
2990 scanInfo.comp[j] = gTrue;
2991 c = str->getChar();
2992 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
2993 scanInfo.acHuffTable[j] = c & 0x0f;
2995 scanInfo.firstCoeff = str->getChar();
2996 scanInfo.lastCoeff = str->getChar();
2997 c = str->getChar();
2998 scanInfo.ah = (c >> 4) & 0x0f;
2999 scanInfo.al = c & 0x0f;
3000 return gTrue;
3003 GBool DCTStream::readQuantTables() {
3004 int length, prec, i, index;
3006 length = read16() - 2;
3007 while (length > 0) {
3008 index = str->getChar();
3009 prec = (index >> 4) & 0x0f;
3010 index &= 0x0f;
3011 if (prec > 1 || index >= 4) {
3012 error(getPos(), "Bad DCT quantization table");
3013 return gFalse;
3015 if (index == numQuantTables) {
3016 numQuantTables = index + 1;
3018 for (i = 0; i < 64; ++i) {
3019 if (prec) {
3020 quantTables[index][dctZigZag[i]] = read16();
3021 } else {
3022 quantTables[index][dctZigZag[i]] = str->getChar();
3025 if (prec) {
3026 length -= 129;
3027 } else {
3028 length -= 65;
3031 return gTrue;
3034 GBool DCTStream::readHuffmanTables() {
3035 DCTHuffTable *tbl;
3036 int length;
3037 int index;
3038 Gushort code;
3039 Guchar sym;
3040 int i;
3041 int c;
3043 length = read16() - 2;
3044 while (length > 0) {
3045 index = str->getChar();
3046 --length;
3047 if ((index & 0x0f) >= 4) {
3048 error(getPos(), "Bad DCT Huffman table");
3049 return gFalse;
3051 if (index & 0x10) {
3052 index &= 0x0f;
3053 if (index >= numACHuffTables)
3054 numACHuffTables = index+1;
3055 tbl = &acHuffTables[index];
3056 } else {
3057 index &= 0x0f;
3058 if (index >= numDCHuffTables)
3059 numDCHuffTables = index+1;
3060 tbl = &dcHuffTables[index];
3062 sym = 0;
3063 code = 0;
3064 for (i = 1; i <= 16; ++i) {
3065 c = str->getChar();
3066 tbl->firstSym[i] = sym;
3067 tbl->firstCode[i] = code;
3068 tbl->numCodes[i] = c;
3069 sym += c;
3070 code = (code + c) << 1;
3072 length -= 16;
3073 for (i = 0; i < sym; ++i)
3074 tbl->sym[i] = str->getChar();
3075 length -= sym;
3077 return gTrue;
3080 GBool DCTStream::readRestartInterval() {
3081 int length;
3083 length = read16();
3084 if (length != 4) {
3085 error(getPos(), "Bad DCT restart interval");
3086 return gFalse;
3088 restartInterval = read16();
3089 return gTrue;
3092 GBool DCTStream::readJFIFMarker() {
3093 int length, i;
3094 char buf[5];
3095 int c;
3097 length = read16();
3098 length -= 2;
3099 if (length >= 5) {
3100 for (i = 0; i < 5; ++i) {
3101 if ((c = str->getChar()) == EOF) {
3102 error(getPos(), "Bad DCT APP0 marker");
3103 return gFalse;
3105 buf[i] = c;
3107 length -= 5;
3108 if (!memcmp(buf, "JFIF\0", 5)) {
3109 gotJFIFMarker = gTrue;
3112 while (length > 0) {
3113 if (str->getChar() == EOF) {
3114 error(getPos(), "Bad DCT APP0 marker");
3115 return gFalse;
3117 --length;
3119 return gTrue;
3122 GBool DCTStream::readAdobeMarker() {
3123 int length, i;
3124 char buf[12];
3125 int c;
3127 length = read16();
3128 if (length < 14) {
3129 goto err;
3131 for (i = 0; i < 12; ++i) {
3132 if ((c = str->getChar()) == EOF) {
3133 goto err;
3135 buf[i] = c;
3137 if (strncmp(buf, "Adobe", 5)) {
3138 goto err;
3140 colorXform = buf[11];
3141 gotAdobeMarker = gTrue;
3142 for (i = 14; i < length; ++i) {
3143 if (str->getChar() == EOF) {
3144 goto err;
3147 return gTrue;
3149 err:
3150 error(getPos(), "Bad DCT Adobe APP14 marker");
3151 return gFalse;
3154 GBool DCTStream::readTrailer() {
3155 int c;
3157 c = readMarker();
3158 if (c != 0xd9) { // EOI
3159 error(getPos(), "Bad DCT trailer");
3160 return gFalse;
3162 return gTrue;
3165 int DCTStream::readMarker() {
3166 int c;
3168 do {
3169 do {
3170 c = str->getChar();
3171 } while (c != 0xff && c != EOF);
3172 do {
3173 c = str->getChar();
3174 } while (c == 0xff);
3175 } while (c == 0x00);
3176 return c;
3179 int DCTStream::read16() {
3180 int c1, c2;
3182 if ((c1 = str->getChar()) == EOF)
3183 return EOF;
3184 if ((c2 = str->getChar()) == EOF)
3185 return EOF;
3186 return (c1 << 8) + c2;
3189 GString *DCTStream::getPSFilter(int psLevel, char *indent) {
3190 GString *s;
3192 if (psLevel < 2) {
3193 return NULL;
3195 if (!(s = str->getPSFilter(psLevel, indent))) {
3196 return NULL;
3198 s->append(indent)->append("<< >> /DCTDecode filter\n");
3199 return s;
3202 GBool DCTStream::isBinary(GBool last) {
3203 return str->isBinary(gTrue);
3206 //------------------------------------------------------------------------
3207 // FlateStream
3208 //------------------------------------------------------------------------
3210 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3211 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3214 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3215 {0, 3},
3216 {0, 4},
3217 {0, 5},
3218 {0, 6},
3219 {0, 7},
3220 {0, 8},
3221 {0, 9},
3222 {0, 10},
3223 {1, 11},
3224 {1, 13},
3225 {1, 15},
3226 {1, 17},
3227 {2, 19},
3228 {2, 23},
3229 {2, 27},
3230 {2, 31},
3231 {3, 35},
3232 {3, 43},
3233 {3, 51},
3234 {3, 59},
3235 {4, 67},
3236 {4, 83},
3237 {4, 99},
3238 {4, 115},
3239 {5, 131},
3240 {5, 163},
3241 {5, 195},
3242 {5, 227},
3243 {0, 258},
3244 {0, 258},
3245 {0, 258}
3248 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3249 { 0, 1},
3250 { 0, 2},
3251 { 0, 3},
3252 { 0, 4},
3253 { 1, 5},
3254 { 1, 7},
3255 { 2, 9},
3256 { 2, 13},
3257 { 3, 17},
3258 { 3, 25},
3259 { 4, 33},
3260 { 4, 49},
3261 { 5, 65},
3262 { 5, 97},
3263 { 6, 129},
3264 { 6, 193},
3265 { 7, 257},
3266 { 7, 385},
3267 { 8, 513},
3268 { 8, 769},
3269 { 9, 1025},
3270 { 9, 1537},
3271 {10, 2049},
3272 {10, 3073},
3273 {11, 4097},
3274 {11, 6145},
3275 {12, 8193},
3276 {12, 12289},
3277 {13, 16385},
3278 {13, 24577}
3281 static FlateCode flateFixedLitCodeTabCodes[512] = {
3282 {7, 0x0100},
3283 {8, 0x0050},
3284 {8, 0x0010},
3285 {8, 0x0118},
3286 {7, 0x0110},
3287 {8, 0x0070},
3288 {8, 0x0030},
3289 {9, 0x00c0},
3290 {7, 0x0108},
3291 {8, 0x0060},
3292 {8, 0x0020},
3293 {9, 0x00a0},
3294 {8, 0x0000},
3295 {8, 0x0080},
3296 {8, 0x0040},
3297 {9, 0x00e0},
3298 {7, 0x0104},
3299 {8, 0x0058},
3300 {8, 0x0018},
3301 {9, 0x0090},
3302 {7, 0x0114},
3303 {8, 0x0078},
3304 {8, 0x0038},
3305 {9, 0x00d0},
3306 {7, 0x010c},
3307 {8, 0x0068},
3308 {8, 0x0028},
3309 {9, 0x00b0},
3310 {8, 0x0008},
3311 {8, 0x0088},
3312 {8, 0x0048},
3313 {9, 0x00f0},
3314 {7, 0x0102},
3315 {8, 0x0054},
3316 {8, 0x0014},
3317 {8, 0x011c},
3318 {7, 0x0112},
3319 {8, 0x0074},
3320 {8, 0x0034},
3321 {9, 0x00c8},
3322 {7, 0x010a},
3323 {8, 0x0064},
3324 {8, 0x0024},
3325 {9, 0x00a8},
3326 {8, 0x0004},
3327 {8, 0x0084},
3328 {8, 0x0044},
3329 {9, 0x00e8},
3330 {7, 0x0106},
3331 {8, 0x005c},
3332 {8, 0x001c},
3333 {9, 0x0098},
3334 {7, 0x0116},
3335 {8, 0x007c},
3336 {8, 0x003c},
3337 {9, 0x00d8},
3338 {7, 0x010e},
3339 {8, 0x006c},
3340 {8, 0x002c},
3341 {9, 0x00b8},
3342 {8, 0x000c},
3343 {8, 0x008c},
3344 {8, 0x004c},
3345 {9, 0x00f8},
3346 {7, 0x0101},
3347 {8, 0x0052},
3348 {8, 0x0012},
3349 {8, 0x011a},
3350 {7, 0x0111},
3351 {8, 0x0072},
3352 {8, 0x0032},
3353 {9, 0x00c4},
3354 {7, 0x0109},
3355 {8, 0x0062},
3356 {8, 0x0022},
3357 {9, 0x00a4},
3358 {8, 0x0002},
3359 {8, 0x0082},
3360 {8, 0x0042},
3361 {9, 0x00e4},
3362 {7, 0x0105},
3363 {8, 0x005a},
3364 {8, 0x001a},
3365 {9, 0x0094},
3366 {7, 0x0115},
3367 {8, 0x007a},
3368 {8, 0x003a},
3369 {9, 0x00d4},
3370 {7, 0x010d},
3371 {8, 0x006a},
3372 {8, 0x002a},
3373 {9, 0x00b4},
3374 {8, 0x000a},
3375 {8, 0x008a},
3376 {8, 0x004a},
3377 {9, 0x00f4},
3378 {7, 0x0103},
3379 {8, 0x0056},
3380 {8, 0x0016},
3381 {8, 0x011e},
3382 {7, 0x0113},
3383 {8, 0x0076},
3384 {8, 0x0036},
3385 {9, 0x00cc},
3386 {7, 0x010b},
3387 {8, 0x0066},
3388 {8, 0x0026},
3389 {9, 0x00ac},
3390 {8, 0x0006},
3391 {8, 0x0086},
3392 {8, 0x0046},
3393 {9, 0x00ec},
3394 {7, 0x0107},
3395 {8, 0x005e},
3396 {8, 0x001e},
3397 {9, 0x009c},
3398 {7, 0x0117},
3399 {8, 0x007e},
3400 {8, 0x003e},
3401 {9, 0x00dc},
3402 {7, 0x010f},
3403 {8, 0x006e},
3404 {8, 0x002e},
3405 {9, 0x00bc},
3406 {8, 0x000e},
3407 {8, 0x008e},
3408 {8, 0x004e},
3409 {9, 0x00fc},
3410 {7, 0x0100},
3411 {8, 0x0051},
3412 {8, 0x0011},
3413 {8, 0x0119},
3414 {7, 0x0110},
3415 {8, 0x0071},
3416 {8, 0x0031},
3417 {9, 0x00c2},
3418 {7, 0x0108},
3419 {8, 0x0061},
3420 {8, 0x0021},
3421 {9, 0x00a2},
3422 {8, 0x0001},
3423 {8, 0x0081},
3424 {8, 0x0041},
3425 {9, 0x00e2},
3426 {7, 0x0104},
3427 {8, 0x0059},
3428 {8, 0x0019},
3429 {9, 0x0092},
3430 {7, 0x0114},
3431 {8, 0x0079},
3432 {8, 0x0039},
3433 {9, 0x00d2},
3434 {7, 0x010c},
3435 {8, 0x0069},
3436 {8, 0x0029},
3437 {9, 0x00b2},
3438 {8, 0x0009},
3439 {8, 0x0089},
3440 {8, 0x0049},
3441 {9, 0x00f2},
3442 {7, 0x0102},
3443 {8, 0x0055},
3444 {8, 0x0015},
3445 {8, 0x011d},
3446 {7, 0x0112},
3447 {8, 0x0075},
3448 {8, 0x0035},
3449 {9, 0x00ca},
3450 {7, 0x010a},
3451 {8, 0x0065},
3452 {8, 0x0025},
3453 {9, 0x00aa},
3454 {8, 0x0005},
3455 {8, 0x0085},
3456 {8, 0x0045},
3457 {9, 0x00ea},
3458 {7, 0x0106},
3459 {8, 0x005d},
3460 {8, 0x001d},
3461 {9, 0x009a},
3462 {7, 0x0116},
3463 {8, 0x007d},
3464 {8, 0x003d},
3465 {9, 0x00da},
3466 {7, 0x010e},
3467 {8, 0x006d},
3468 {8, 0x002d},
3469 {9, 0x00ba},
3470 {8, 0x000d},
3471 {8, 0x008d},
3472 {8, 0x004d},
3473 {9, 0x00fa},
3474 {7, 0x0101},
3475 {8, 0x0053},
3476 {8, 0x0013},
3477 {8, 0x011b},
3478 {7, 0x0111},
3479 {8, 0x0073},
3480 {8, 0x0033},
3481 {9, 0x00c6},
3482 {7, 0x0109},
3483 {8, 0x0063},
3484 {8, 0x0023},
3485 {9, 0x00a6},
3486 {8, 0x0003},
3487 {8, 0x0083},
3488 {8, 0x0043},
3489 {9, 0x00e6},
3490 {7, 0x0105},
3491 {8, 0x005b},
3492 {8, 0x001b},
3493 {9, 0x0096},
3494 {7, 0x0115},
3495 {8, 0x007b},
3496 {8, 0x003b},
3497 {9, 0x00d6},
3498 {7, 0x010d},
3499 {8, 0x006b},
3500 {8, 0x002b},
3501 {9, 0x00b6},
3502 {8, 0x000b},
3503 {8, 0x008b},
3504 {8, 0x004b},
3505 {9, 0x00f6},
3506 {7, 0x0103},
3507 {8, 0x0057},
3508 {8, 0x0017},
3509 {8, 0x011f},
3510 {7, 0x0113},
3511 {8, 0x0077},
3512 {8, 0x0037},
3513 {9, 0x00ce},
3514 {7, 0x010b},
3515 {8, 0x0067},
3516 {8, 0x0027},
3517 {9, 0x00ae},
3518 {8, 0x0007},
3519 {8, 0x0087},
3520 {8, 0x0047},
3521 {9, 0x00ee},
3522 {7, 0x0107},
3523 {8, 0x005f},
3524 {8, 0x001f},
3525 {9, 0x009e},
3526 {7, 0x0117},
3527 {8, 0x007f},
3528 {8, 0x003f},
3529 {9, 0x00de},
3530 {7, 0x010f},
3531 {8, 0x006f},
3532 {8, 0x002f},
3533 {9, 0x00be},
3534 {8, 0x000f},
3535 {8, 0x008f},
3536 {8, 0x004f},
3537 {9, 0x00fe},
3538 {7, 0x0100},
3539 {8, 0x0050},
3540 {8, 0x0010},
3541 {8, 0x0118},
3542 {7, 0x0110},
3543 {8, 0x0070},
3544 {8, 0x0030},
3545 {9, 0x00c1},
3546 {7, 0x0108},
3547 {8, 0x0060},
3548 {8, 0x0020},
3549 {9, 0x00a1},
3550 {8, 0x0000},
3551 {8, 0x0080},
3552 {8, 0x0040},
3553 {9, 0x00e1},
3554 {7, 0x0104},
3555 {8, 0x0058},
3556 {8, 0x0018},
3557 {9, 0x0091},
3558 {7, 0x0114},
3559 {8, 0x0078},
3560 {8, 0x0038},
3561 {9, 0x00d1},
3562 {7, 0x010c},
3563 {8, 0x0068},
3564 {8, 0x0028},
3565 {9, 0x00b1},
3566 {8, 0x0008},
3567 {8, 0x0088},
3568 {8, 0x0048},
3569 {9, 0x00f1},
3570 {7, 0x0102},
3571 {8, 0x0054},
3572 {8, 0x0014},
3573 {8, 0x011c},
3574 {7, 0x0112},
3575 {8, 0x0074},
3576 {8, 0x0034},
3577 {9, 0x00c9},
3578 {7, 0x010a},
3579 {8, 0x0064},
3580 {8, 0x0024},
3581 {9, 0x00a9},
3582 {8, 0x0004},
3583 {8, 0x0084},
3584 {8, 0x0044},
3585 {9, 0x00e9},
3586 {7, 0x0106},
3587 {8, 0x005c},
3588 {8, 0x001c},
3589 {9, 0x0099},
3590 {7, 0x0116},
3591 {8, 0x007c},
3592 {8, 0x003c},
3593 {9, 0x00d9},
3594 {7, 0x010e},
3595 {8, 0x006c},
3596 {8, 0x002c},
3597 {9, 0x00b9},
3598 {8, 0x000c},
3599 {8, 0x008c},
3600 {8, 0x004c},
3601 {9, 0x00f9},
3602 {7, 0x0101},
3603 {8, 0x0052},
3604 {8, 0x0012},
3605 {8, 0x011a},
3606 {7, 0x0111},
3607 {8, 0x0072},
3608 {8, 0x0032},
3609 {9, 0x00c5},
3610 {7, 0x0109},
3611 {8, 0x0062},
3612 {8, 0x0022},
3613 {9, 0x00a5},
3614 {8, 0x0002},
3615 {8, 0x0082},
3616 {8, 0x0042},
3617 {9, 0x00e5},
3618 {7, 0x0105},
3619 {8, 0x005a},
3620 {8, 0x001a},
3621 {9, 0x0095},
3622 {7, 0x0115},
3623 {8, 0x007a},
3624 {8, 0x003a},
3625 {9, 0x00d5},
3626 {7, 0x010d},
3627 {8, 0x006a},
3628 {8, 0x002a},
3629 {9, 0x00b5},
3630 {8, 0x000a},
3631 {8, 0x008a},
3632 {8, 0x004a},
3633 {9, 0x00f5},
3634 {7, 0x0103},
3635 {8, 0x0056},
3636 {8, 0x0016},
3637 {8, 0x011e},
3638 {7, 0x0113},
3639 {8, 0x0076},
3640 {8, 0x0036},
3641 {9, 0x00cd},
3642 {7, 0x010b},
3643 {8, 0x0066},
3644 {8, 0x0026},
3645 {9, 0x00ad},
3646 {8, 0x0006},
3647 {8, 0x0086},
3648 {8, 0x0046},
3649 {9, 0x00ed},
3650 {7, 0x0107},
3651 {8, 0x005e},
3652 {8, 0x001e},
3653 {9, 0x009d},
3654 {7, 0x0117},
3655 {8, 0x007e},
3656 {8, 0x003e},
3657 {9, 0x00dd},
3658 {7, 0x010f},
3659 {8, 0x006e},
3660 {8, 0x002e},
3661 {9, 0x00bd},
3662 {8, 0x000e},
3663 {8, 0x008e},
3664 {8, 0x004e},
3665 {9, 0x00fd},
3666 {7, 0x0100},
3667 {8, 0x0051},
3668 {8, 0x0011},
3669 {8, 0x0119},
3670 {7, 0x0110},
3671 {8, 0x0071},
3672 {8, 0x0031},
3673 {9, 0x00c3},
3674 {7, 0x0108},
3675 {8, 0x0061},
3676 {8, 0x0021},
3677 {9, 0x00a3},
3678 {8, 0x0001},
3679 {8, 0x0081},
3680 {8, 0x0041},
3681 {9, 0x00e3},
3682 {7, 0x0104},
3683 {8, 0x0059},
3684 {8, 0x0019},
3685 {9, 0x0093},
3686 {7, 0x0114},
3687 {8, 0x0079},
3688 {8, 0x0039},
3689 {9, 0x00d3},
3690 {7, 0x010c},
3691 {8, 0x0069},
3692 {8, 0x0029},
3693 {9, 0x00b3},
3694 {8, 0x0009},
3695 {8, 0x0089},
3696 {8, 0x0049},
3697 {9, 0x00f3},
3698 {7, 0x0102},
3699 {8, 0x0055},
3700 {8, 0x0015},
3701 {8, 0x011d},
3702 {7, 0x0112},
3703 {8, 0x0075},
3704 {8, 0x0035},
3705 {9, 0x00cb},
3706 {7, 0x010a},
3707 {8, 0x0065},
3708 {8, 0x0025},
3709 {9, 0x00ab},
3710 {8, 0x0005},
3711 {8, 0x0085},
3712 {8, 0x0045},
3713 {9, 0x00eb},
3714 {7, 0x0106},
3715 {8, 0x005d},
3716 {8, 0x001d},
3717 {9, 0x009b},
3718 {7, 0x0116},
3719 {8, 0x007d},
3720 {8, 0x003d},
3721 {9, 0x00db},
3722 {7, 0x010e},
3723 {8, 0x006d},
3724 {8, 0x002d},
3725 {9, 0x00bb},
3726 {8, 0x000d},
3727 {8, 0x008d},
3728 {8, 0x004d},
3729 {9, 0x00fb},
3730 {7, 0x0101},
3731 {8, 0x0053},
3732 {8, 0x0013},
3733 {8, 0x011b},
3734 {7, 0x0111},
3735 {8, 0x0073},
3736 {8, 0x0033},
3737 {9, 0x00c7},
3738 {7, 0x0109},
3739 {8, 0x0063},
3740 {8, 0x0023},
3741 {9, 0x00a7},
3742 {8, 0x0003},
3743 {8, 0x0083},
3744 {8, 0x0043},
3745 {9, 0x00e7},
3746 {7, 0x0105},
3747 {8, 0x005b},
3748 {8, 0x001b},
3749 {9, 0x0097},
3750 {7, 0x0115},
3751 {8, 0x007b},
3752 {8, 0x003b},
3753 {9, 0x00d7},
3754 {7, 0x010d},
3755 {8, 0x006b},
3756 {8, 0x002b},
3757 {9, 0x00b7},
3758 {8, 0x000b},
3759 {8, 0x008b},
3760 {8, 0x004b},
3761 {9, 0x00f7},
3762 {7, 0x0103},
3763 {8, 0x0057},
3764 {8, 0x0017},
3765 {8, 0x011f},
3766 {7, 0x0113},
3767 {8, 0x0077},
3768 {8, 0x0037},
3769 {9, 0x00cf},
3770 {7, 0x010b},
3771 {8, 0x0067},
3772 {8, 0x0027},
3773 {9, 0x00af},
3774 {8, 0x0007},
3775 {8, 0x0087},
3776 {8, 0x0047},
3777 {9, 0x00ef},
3778 {7, 0x0107},
3779 {8, 0x005f},
3780 {8, 0x001f},
3781 {9, 0x009f},
3782 {7, 0x0117},
3783 {8, 0x007f},
3784 {8, 0x003f},
3785 {9, 0x00df},
3786 {7, 0x010f},
3787 {8, 0x006f},
3788 {8, 0x002f},
3789 {9, 0x00bf},
3790 {8, 0x000f},
3791 {8, 0x008f},
3792 {8, 0x004f},
3793 {9, 0x00ff}
3796 FlateHuffmanTab FlateStream::fixedLitCodeTab = {
3797 flateFixedLitCodeTabCodes, 9
3800 static FlateCode flateFixedDistCodeTabCodes[32] = {
3801 {5, 0x0000},
3802 {5, 0x0010},
3803 {5, 0x0008},
3804 {5, 0x0018},
3805 {5, 0x0004},
3806 {5, 0x0014},
3807 {5, 0x000c},
3808 {5, 0x001c},
3809 {5, 0x0002},
3810 {5, 0x0012},
3811 {5, 0x000a},
3812 {5, 0x001a},
3813 {5, 0x0006},
3814 {5, 0x0016},
3815 {5, 0x000e},
3816 {0, 0x0000},
3817 {5, 0x0001},
3818 {5, 0x0011},
3819 {5, 0x0009},
3820 {5, 0x0019},
3821 {5, 0x0005},
3822 {5, 0x0015},
3823 {5, 0x000d},
3824 {5, 0x001d},
3825 {5, 0x0003},
3826 {5, 0x0013},
3827 {5, 0x000b},
3828 {5, 0x001b},
3829 {5, 0x0007},
3830 {5, 0x0017},
3831 {5, 0x000f},
3832 {0, 0x0000}
3835 FlateHuffmanTab FlateStream::fixedDistCodeTab = {
3836 flateFixedDistCodeTabCodes, 5
3839 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3840 int colors, int bits):
3841 FilterStream(strA) {
3842 if (predictor != 1) {
3843 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3844 if (!pred->isOk()) {
3845 delete pred;
3846 pred = NULL;
3848 } else {
3849 pred = NULL;
3851 litCodeTab.codes = NULL;
3852 distCodeTab.codes = NULL;
3855 FlateStream::~FlateStream() {
3856 if (litCodeTab.codes != fixedLitCodeTab.codes) {
3857 gfree(litCodeTab.codes);
3859 if (distCodeTab.codes != fixedDistCodeTab.codes) {
3860 gfree(distCodeTab.codes);
3862 if (pred) {
3863 delete pred;
3865 delete str;
3868 void FlateStream::reset() {
3869 int cmf, flg;
3871 index = 0;
3872 remain = 0;
3873 codeBuf = 0;
3874 codeSize = 0;
3875 compressedBlock = gFalse;
3876 endOfBlock = gTrue;
3877 eof = gTrue;
3879 str->reset();
3881 // read header
3882 //~ need to look at window size?
3883 endOfBlock = eof = gTrue;
3884 cmf = str->getChar();
3885 flg = str->getChar();
3886 if (cmf == EOF || flg == EOF)
3887 return;
3888 if ((cmf & 0x0f) != 0x08) {
3889 error(getPos(), "Unknown compression method in flate stream");
3890 return;
3892 if ((((cmf << 8) + flg) % 31) != 0) {
3893 error(getPos(), "Bad FCHECK in flate stream");
3894 return;
3896 if (flg & 0x20) {
3897 error(getPos(), "FDICT bit set in flate stream");
3898 return;
3901 eof = gFalse;
3904 int FlateStream::getChar() {
3905 int c;
3907 if (pred) {
3908 return pred->getChar();
3910 while (remain == 0) {
3911 if (endOfBlock && eof)
3912 return EOF;
3913 readSome();
3915 c = buf[index];
3916 index = (index + 1) & flateMask;
3917 --remain;
3918 return c;
3921 int FlateStream::lookChar() {
3922 int c;
3924 if (pred) {
3925 return pred->lookChar();
3927 while (remain == 0) {
3928 if (endOfBlock && eof)
3929 return EOF;
3930 readSome();
3932 c = buf[index];
3933 return c;
3936 int FlateStream::getRawChar() {
3937 int c;
3939 while (remain == 0) {
3940 if (endOfBlock && eof)
3941 return EOF;
3942 readSome();
3944 c = buf[index];
3945 index = (index + 1) & flateMask;
3946 --remain;
3947 return c;
3950 GString *FlateStream::getPSFilter(int psLevel, char *indent) {
3951 GString *s;
3953 if (psLevel < 3 || pred) {
3954 return NULL;
3956 if (!(s = str->getPSFilter(psLevel, indent))) {
3957 return NULL;
3959 s->append(indent)->append("<< >> /FlateDecode filter\n");
3960 return s;
3963 GBool FlateStream::isBinary(GBool last) {
3964 return str->isBinary(gTrue);
3967 void FlateStream::readSome() {
3968 int code1, code2;
3969 int len, dist;
3970 int i, j, k;
3971 int c;
3973 if (endOfBlock) {
3974 if (!startBlock())
3975 return;
3978 if (compressedBlock) {
3979 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3980 goto err;
3981 if (code1 < 256) {
3982 buf[index] = code1;
3983 remain = 1;
3984 } else if (code1 == 256) {
3985 endOfBlock = gTrue;
3986 remain = 0;
3987 } else {
3988 code1 -= 257;
3989 code2 = lengthDecode[code1].bits;
3990 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3991 goto err;
3992 len = lengthDecode[code1].first + code2;
3993 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3994 goto err;
3995 code2 = distDecode[code1].bits;
3996 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3997 goto err;
3998 dist = distDecode[code1].first + code2;
3999 i = index;
4000 j = (index - dist) & flateMask;
4001 for (k = 0; k < len; ++k) {
4002 buf[i] = buf[j];
4003 i = (i + 1) & flateMask;
4004 j = (j + 1) & flateMask;
4006 remain = len;
4009 } else {
4010 len = (blockLen < flateWindow) ? blockLen : flateWindow;
4011 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
4012 if ((c = str->getChar()) == EOF) {
4013 endOfBlock = eof = gTrue;
4014 break;
4016 buf[j] = c & 0xff;
4018 remain = i;
4019 blockLen -= len;
4020 if (blockLen == 0)
4021 endOfBlock = gTrue;
4024 return;
4026 err:
4027 error(getPos(), "Unexpected end of file in flate stream");
4028 endOfBlock = eof = gTrue;
4029 remain = 0;
4032 GBool FlateStream::startBlock() {
4033 int blockHdr;
4034 int c;
4035 int check;
4037 // free the code tables from the previous block
4038 if (litCodeTab.codes != fixedLitCodeTab.codes) {
4039 gfree(litCodeTab.codes);
4041 litCodeTab.codes = NULL;
4042 if (distCodeTab.codes != fixedDistCodeTab.codes) {
4043 gfree(distCodeTab.codes);
4045 distCodeTab.codes = NULL;
4047 // read block header
4048 blockHdr = getCodeWord(3);
4049 if (blockHdr & 1)
4050 eof = gTrue;
4051 blockHdr >>= 1;
4053 // uncompressed block
4054 if (blockHdr == 0) {
4055 compressedBlock = gFalse;
4056 if ((c = str->getChar()) == EOF)
4057 goto err;
4058 blockLen = c & 0xff;
4059 if ((c = str->getChar()) == EOF)
4060 goto err;
4061 blockLen |= (c & 0xff) << 8;
4062 if ((c = str->getChar()) == EOF)
4063 goto err;
4064 check = c & 0xff;
4065 if ((c = str->getChar()) == EOF)
4066 goto err;
4067 check |= (c & 0xff) << 8;
4068 if (check != (~blockLen & 0xffff))
4069 error(getPos(), "Bad uncompressed block length in flate stream");
4070 codeBuf = 0;
4071 codeSize = 0;
4073 // compressed block with fixed codes
4074 } else if (blockHdr == 1) {
4075 compressedBlock = gTrue;
4076 loadFixedCodes();
4078 // compressed block with dynamic codes
4079 } else if (blockHdr == 2) {
4080 compressedBlock = gTrue;
4081 if (!readDynamicCodes()) {
4082 goto err;
4085 // unknown block type
4086 } else {
4087 goto err;
4090 endOfBlock = gFalse;
4091 return gTrue;
4093 err:
4094 error(getPos(), "Bad block header in flate stream");
4095 endOfBlock = eof = gTrue;
4096 return gFalse;
4099 void FlateStream::loadFixedCodes() {
4100 litCodeTab.codes = fixedLitCodeTab.codes;
4101 litCodeTab.maxLen = fixedLitCodeTab.maxLen;
4102 distCodeTab.codes = fixedDistCodeTab.codes;
4103 distCodeTab.maxLen = fixedDistCodeTab.maxLen;
4106 GBool FlateStream::readDynamicCodes() {
4107 int numCodeLenCodes;
4108 int numLitCodes;
4109 int numDistCodes;
4110 int codeLenCodeLengths[flateMaxCodeLenCodes];
4111 FlateHuffmanTab codeLenCodeTab;
4112 int len, repeat, code;
4113 int i;
4115 codeLenCodeTab.codes = NULL;
4117 // read lengths
4118 if ((numLitCodes = getCodeWord(5)) == EOF) {
4119 goto err;
4121 numLitCodes += 257;
4122 if ((numDistCodes = getCodeWord(5)) == EOF) {
4123 goto err;
4125 numDistCodes += 1;
4126 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
4127 goto err;
4129 numCodeLenCodes += 4;
4130 if (numLitCodes > flateMaxLitCodes ||
4131 numDistCodes > flateMaxDistCodes ||
4132 numCodeLenCodes > flateMaxCodeLenCodes) {
4133 goto err;
4136 // build the code length code table
4137 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
4138 codeLenCodeLengths[i] = 0;
4140 for (i = 0; i < numCodeLenCodes; ++i) {
4141 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
4142 goto err;
4145 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
4147 // build the literal and distance code tables
4148 len = 0;
4149 repeat = 0;
4150 i = 0;
4151 while (i < numLitCodes + numDistCodes) {
4152 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
4153 goto err;
4155 if (code == 16) {
4156 if ((repeat = getCodeWord(2)) == EOF) {
4157 goto err;
4159 repeat += 3;
4160 if (i + repeat > numLitCodes + numDistCodes) {
4161 goto err;
4163 for (; repeat > 0; --repeat) {
4164 codeLengths[i++] = len;
4166 } else if (code == 17) {
4167 if ((repeat = getCodeWord(3)) == EOF) {
4168 goto err;
4170 repeat += 3;
4171 if (i + repeat > numLitCodes + numDistCodes) {
4172 goto err;
4174 len = 0;
4175 for (; repeat > 0; --repeat) {
4176 codeLengths[i++] = 0;
4178 } else if (code == 18) {
4179 if ((repeat = getCodeWord(7)) == EOF) {
4180 goto err;
4182 repeat += 11;
4183 if (i + repeat > numLitCodes + numDistCodes) {
4184 goto err;
4186 len = 0;
4187 for (; repeat > 0; --repeat) {
4188 codeLengths[i++] = 0;
4190 } else {
4191 codeLengths[i++] = len = code;
4194 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
4195 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
4197 gfree(codeLenCodeTab.codes);
4198 return gTrue;
4200 err:
4201 error(getPos(), "Bad dynamic code table in flate stream");
4202 gfree(codeLenCodeTab.codes);
4203 return gFalse;
4206 // Convert an array <lengths> of <n> lengths, in value order, into a
4207 // Huffman code lookup table.
4208 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
4209 int tabSize, len, code, code2, skip, val, i, t;
4211 // find max code length
4212 tab->maxLen = 0;
4213 for (val = 0; val < n; ++val) {
4214 if (lengths[val] > tab->maxLen) {
4215 tab->maxLen = lengths[val];
4219 // allocate the table
4220 tabSize = 1 << tab->maxLen;
4221 tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
4223 // clear the table
4224 for (i = 0; i < tabSize; ++i) {
4225 tab->codes[i].len = 0;
4226 tab->codes[i].val = 0;
4229 // build the table
4230 for (len = 1, code = 0, skip = 2;
4231 len <= tab->maxLen;
4232 ++len, code <<= 1, skip <<= 1) {
4233 for (val = 0; val < n; ++val) {
4234 if (lengths[val] == len) {
4236 // bit-reverse the code
4237 code2 = 0;
4238 t = code;
4239 for (i = 0; i < len; ++i) {
4240 code2 = (code2 << 1) | (t & 1);
4241 t >>= 1;
4244 // fill in the table entries
4245 for (i = code2; i < tabSize; i += skip) {
4246 tab->codes[i].len = (Gushort)len;
4247 tab->codes[i].val = (Gushort)val;
4250 ++code;
4256 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
4257 FlateCode *code;
4258 int c;
4260 while (codeSize < tab->maxLen) {
4261 if ((c = str->getChar()) == EOF) {
4262 break;
4264 codeBuf |= (c & 0xff) << codeSize;
4265 codeSize += 8;
4267 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
4268 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
4269 return EOF;
4271 codeBuf >>= code->len;
4272 codeSize -= code->len;
4273 return (int)code->val;
4276 int FlateStream::getCodeWord(int bits) {
4277 int c;
4279 while (codeSize < bits) {
4280 if ((c = str->getChar()) == EOF)
4281 return EOF;
4282 codeBuf |= (c & 0xff) << codeSize;
4283 codeSize += 8;
4285 c = codeBuf & ((1 << bits) - 1);
4286 codeBuf >>= bits;
4287 codeSize -= bits;
4288 return c;
4291 //------------------------------------------------------------------------
4292 // EOFStream
4293 //------------------------------------------------------------------------
4295 EOFStream::EOFStream(Stream *strA):
4296 FilterStream(strA) {
4299 EOFStream::~EOFStream() {
4300 delete str;
4303 //------------------------------------------------------------------------
4304 // FixedLengthEncoder
4305 //------------------------------------------------------------------------
4307 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
4308 FilterStream(strA) {
4309 length = lengthA;
4310 count = 0;
4313 FixedLengthEncoder::~FixedLengthEncoder() {
4314 if (str->isEncoder())
4315 delete str;
4318 void FixedLengthEncoder::reset() {
4319 str->reset();
4320 count = 0;
4323 int FixedLengthEncoder::getChar() {
4324 if (length >= 0 && count >= length)
4325 return EOF;
4326 ++count;
4327 return str->getChar();
4330 int FixedLengthEncoder::lookChar() {
4331 if (length >= 0 && count >= length)
4332 return EOF;
4333 return str->getChar();
4336 GBool FixedLengthEncoder::isBinary(GBool last) {
4337 return str->isBinary(gTrue);
4340 //------------------------------------------------------------------------
4341 // ASCIIHexEncoder
4342 //------------------------------------------------------------------------
4344 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
4345 FilterStream(strA) {
4346 bufPtr = bufEnd = buf;
4347 lineLen = 0;
4348 eof = gFalse;
4351 ASCIIHexEncoder::~ASCIIHexEncoder() {
4352 if (str->isEncoder()) {
4353 delete str;
4357 void ASCIIHexEncoder::reset() {
4358 str->reset();
4359 bufPtr = bufEnd = buf;
4360 lineLen = 0;
4361 eof = gFalse;
4364 GBool ASCIIHexEncoder::fillBuf() {
4365 static char *hex = "0123456789abcdef";
4366 int c;
4368 if (eof) {
4369 return gFalse;
4371 bufPtr = bufEnd = buf;
4372 if ((c = str->getChar()) == EOF) {
4373 *bufEnd++ = '>';
4374 eof = gTrue;
4375 } else {
4376 if (lineLen >= 64) {
4377 *bufEnd++ = '\n';
4378 lineLen = 0;
4380 *bufEnd++ = hex[(c >> 4) & 0x0f];
4381 *bufEnd++ = hex[c & 0x0f];
4382 lineLen += 2;
4384 return gTrue;
4387 //------------------------------------------------------------------------
4388 // ASCII85Encoder
4389 //------------------------------------------------------------------------
4391 ASCII85Encoder::ASCII85Encoder(Stream *strA):
4392 FilterStream(strA) {
4393 bufPtr = bufEnd = buf;
4394 lineLen = 0;
4395 eof = gFalse;
4398 ASCII85Encoder::~ASCII85Encoder() {
4399 if (str->isEncoder())
4400 delete str;
4403 void ASCII85Encoder::reset() {
4404 str->reset();
4405 bufPtr = bufEnd = buf;
4406 lineLen = 0;
4407 eof = gFalse;
4410 GBool ASCII85Encoder::fillBuf() {
4411 Gulong t;
4412 char buf1[5];
4413 int c;
4414 int n, i;
4416 if (eof)
4417 return gFalse;
4418 t = 0;
4419 for (n = 0; n < 4; ++n) {
4420 if ((c = str->getChar()) == EOF)
4421 break;
4422 t = (t << 8) + c;
4424 bufPtr = bufEnd = buf;
4425 if (n > 0) {
4426 if (n == 4 && t == 0) {
4427 *bufEnd++ = 'z';
4428 if (++lineLen == 65) {
4429 *bufEnd++ = '\n';
4430 lineLen = 0;
4432 } else {
4433 if (n < 4)
4434 t <<= 8 * (4 - n);
4435 for (i = 4; i >= 0; --i) {
4436 buf1[i] = (char)(t % 85 + 0x21);
4437 t /= 85;
4439 for (i = 0; i <= n; ++i) {
4440 *bufEnd++ = buf1[i];
4441 if (++lineLen == 65) {
4442 *bufEnd++ = '\n';
4443 lineLen = 0;
4448 if (n < 4) {
4449 *bufEnd++ = '~';
4450 *bufEnd++ = '>';
4451 eof = gTrue;
4453 return bufPtr < bufEnd;
4456 //------------------------------------------------------------------------
4457 // RunLengthEncoder
4458 //------------------------------------------------------------------------
4460 RunLengthEncoder::RunLengthEncoder(Stream *strA):
4461 FilterStream(strA) {
4462 bufPtr = bufEnd = nextEnd = buf;
4463 eof = gFalse;
4466 RunLengthEncoder::~RunLengthEncoder() {
4467 if (str->isEncoder())
4468 delete str;
4471 void RunLengthEncoder::reset() {
4472 str->reset();
4473 bufPtr = bufEnd = nextEnd = buf;
4474 eof = gFalse;
4478 // When fillBuf finishes, buf[] looks like this:
4479 // +-----+--------------+-----------------+--
4480 // + tag | ... data ... | next 0, 1, or 2 |
4481 // +-----+--------------+-----------------+--
4482 // ^ ^ ^
4483 // bufPtr bufEnd nextEnd
4485 GBool RunLengthEncoder::fillBuf() {
4486 int c, c1, c2;
4487 int n;
4489 // already hit EOF?
4490 if (eof)
4491 return gFalse;
4493 // grab two bytes
4494 if (nextEnd < bufEnd + 1) {
4495 if ((c1 = str->getChar()) == EOF) {
4496 eof = gTrue;
4497 return gFalse;
4499 } else {
4500 c1 = bufEnd[0] & 0xff;
4502 if (nextEnd < bufEnd + 2) {
4503 if ((c2 = str->getChar()) == EOF) {
4504 eof = gTrue;
4505 buf[0] = 0;
4506 buf[1] = c1;
4507 bufPtr = buf;
4508 bufEnd = &buf[2];
4509 return gTrue;
4511 } else {
4512 c2 = bufEnd[1] & 0xff;
4515 // check for repeat
4516 c = 0; // make gcc happy
4517 if (c1 == c2) {
4518 n = 2;
4519 while (n < 128 && (c = str->getChar()) == c1)
4520 ++n;
4521 buf[0] = (char)(257 - n);
4522 buf[1] = c1;
4523 bufEnd = &buf[2];
4524 if (c == EOF) {
4525 eof = gTrue;
4526 } else if (n < 128) {
4527 buf[2] = c;
4528 nextEnd = &buf[3];
4529 } else {
4530 nextEnd = bufEnd;
4533 // get up to 128 chars
4534 } else {
4535 buf[1] = c1;
4536 buf[2] = c2;
4537 n = 2;
4538 while (n < 128) {
4539 if ((c = str->getChar()) == EOF) {
4540 eof = gTrue;
4541 break;
4543 ++n;
4544 buf[n] = c;
4545 if (buf[n] == buf[n-1])
4546 break;
4548 if (buf[n] == buf[n-1]) {
4549 buf[0] = (char)(n-2-1);
4550 bufEnd = &buf[n-1];
4551 nextEnd = &buf[n+1];
4552 } else {
4553 buf[0] = (char)(n-1);
4554 bufEnd = nextEnd = &buf[n+1];
4557 bufPtr = buf;
4558 return gTrue;
4562 //------------------------------------------------------------------------
4563 // StrStream
4564 //------------------------------------------------------------------------
4566 StrStream::StrStream(GString *str, Object *dict):
4567 BaseStream(dict) {
4568 this->str = str;
4569 buf = str->getCString();
4570 bufPtr = buf;
4571 bufEnd = buf + str->getLength();
4574 StrStream::~StrStream() {
4575 delete str;