fixed windows access violation which occurs if one tries to retrieve
[swftools.git] / pdf2swf / xpdf / Stream.cc
blobc47c5af0e5300264e96a21ddbc8bb1a76685de4d
1 //========================================================================
2 //
3 // Stream.cc
4 //
5 // Copyright 1996-2002 Glyph & Cog, LLC
6 //
7 //========================================================================
9 #ifdef __GNUC__
10 #pragma implementation
11 #endif
13 #include <aconf.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stddef.h>
17 #ifndef WIN32
18 #include <unistd.h>
19 #else
20 extern "C" int unlink(char *filename);
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 #ifndef NO_DECRYPTION
30 #include "Decrypt.h"
31 #endif
32 #include "Stream.h"
33 #include "Stream-CCITT.h"
35 #ifdef __DJGPP__
36 static GBool setDJSYSFLAGS = gFalse;
37 #endif
39 #ifdef VMS
40 #if (__VMS_VER < 70000000)
41 extern "C" int unlink(char *filename);
42 #endif
43 #ifdef __GNUC__
44 #define SEEK_SET 0
45 #define SEEK_CUR 1
46 #define SEEK_END 2
47 #endif
48 #endif
50 #ifdef MACOS
51 #include "StuffItEngineLib.h"
52 #endif
54 //------------------------------------------------------------------------
55 // Stream (base class)
56 //------------------------------------------------------------------------
58 Stream::Stream() {
59 ref = 1;
62 Stream::~Stream() {
65 void Stream::close() {
68 int Stream::getRawChar() {
69 error(-1, "Internal: called getRawChar() on non-predictor stream");
70 return EOF;
73 char *Stream::getLine(char *buf, int size) {
74 int i;
75 int c;
77 if (lookChar() == EOF)
78 return NULL;
79 for (i = 0; i < size - 1; ++i) {
80 c = getChar();
81 if (c == EOF || c == '\n')
82 break;
83 if (c == '\r') {
84 if ((c = lookChar()) == '\n')
85 getChar();
86 break;
88 buf[i] = c;
90 buf[i] = '\0';
91 return buf;
94 GString *Stream::getPSFilter(char *indent) {
95 return new GString();
98 Stream *Stream::addFilters(Object *dict) {
99 Object obj, obj2;
100 Object params, params2;
101 Stream *str;
102 int i;
104 str = this;
105 dict->dictLookup("Filter", &obj);
106 if (obj.isNull()) {
107 obj.free();
108 dict->dictLookup("F", &obj);
110 dict->dictLookup("DecodeParms", &params);
111 if (params.isNull()) {
112 params.free();
113 dict->dictLookup("DP", &params);
115 if (obj.isName()) {
116 str = makeFilter(obj.getName(), str, &params);
117 } else if (obj.isArray()) {
118 for (i = 0; i < obj.arrayGetLength(); ++i) {
119 obj.arrayGet(i, &obj2);
120 if (params.isArray())
121 params.arrayGet(i, &params2);
122 else
123 params2.initNull();
124 if (obj2.isName()) {
125 str = makeFilter(obj2.getName(), str, &params2);
126 } else {
127 error(getPos(), "Bad filter name");
128 str = new EOFStream(str);
130 obj2.free();
131 params2.free();
133 } else if (!obj.isNull()) {
134 error(getPos(), "Bad 'Filter' attribute in stream");
136 obj.free();
137 params.free();
139 return str;
142 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
143 int pred; // parameters
144 int colors;
145 int bits;
146 int early;
147 int encoding;
148 GBool endOfLine, byteAlign, endOfBlock, black;
149 int columns, rows;
150 Object obj;
152 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
153 str = new ASCIIHexStream(str);
154 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
155 str = new ASCII85Stream(str);
156 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
157 pred = 1;
158 columns = 1;
159 colors = 1;
160 bits = 8;
161 early = 1;
162 if (params->isDict()) {
163 params->dictLookup("Predictor", &obj);
164 if (obj.isInt())
165 pred = obj.getInt();
166 obj.free();
167 params->dictLookup("Columns", &obj);
168 if (obj.isInt())
169 columns = obj.getInt();
170 obj.free();
171 params->dictLookup("Colors", &obj);
172 if (obj.isInt())
173 colors = obj.getInt();
174 obj.free();
175 params->dictLookup("BitsPerComponent", &obj);
176 if (obj.isInt())
177 bits = obj.getInt();
178 obj.free();
179 params->dictLookup("EarlyChange", &obj);
180 if (obj.isInt())
181 early = obj.getInt();
182 obj.free();
184 str = new LZWStream(str, pred, columns, colors, bits, early);
185 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
186 str = new RunLengthStream(str);
187 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
188 encoding = 0;
189 endOfLine = gFalse;
190 byteAlign = gFalse;
191 columns = 1728;
192 rows = 0;
193 endOfBlock = gTrue;
194 black = gFalse;
195 if (params->isDict()) {
196 params->dictLookup("K", &obj);
197 if (obj.isInt()) {
198 encoding = obj.getInt();
200 obj.free();
201 params->dictLookup("EndOfLine", &obj);
202 if (obj.isBool()) {
203 endOfLine = obj.getBool();
205 obj.free();
206 params->dictLookup("EncodedByteAlign", &obj);
207 if (obj.isBool()) {
208 byteAlign = obj.getBool();
210 obj.free();
211 params->dictLookup("Columns", &obj);
212 if (obj.isInt()) {
213 columns = obj.getInt();
215 obj.free();
216 params->dictLookup("Rows", &obj);
217 if (obj.isInt()) {
218 rows = obj.getInt();
220 obj.free();
221 params->dictLookup("EndOfBlock", &obj);
222 if (obj.isBool()) {
223 endOfBlock = obj.getBool();
225 obj.free();
226 params->dictLookup("BlackIs1", &obj);
227 if (obj.isBool()) {
228 black = obj.getBool();
230 obj.free();
232 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
233 columns, rows, endOfBlock, black);
234 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
235 str = new DCTStream(str);
236 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
237 pred = 1;
238 columns = 1;
239 colors = 1;
240 bits = 8;
241 if (params->isDict()) {
242 params->dictLookup("Predictor", &obj);
243 if (obj.isInt())
244 pred = obj.getInt();
245 obj.free();
246 params->dictLookup("Columns", &obj);
247 if (obj.isInt())
248 columns = obj.getInt();
249 obj.free();
250 params->dictLookup("Colors", &obj);
251 if (obj.isInt())
252 colors = obj.getInt();
253 obj.free();
254 params->dictLookup("BitsPerComponent", &obj);
255 if (obj.isInt())
256 bits = obj.getInt();
257 obj.free();
259 str = new FlateStream(str, pred, columns, colors, bits);
260 } else {
261 error(getPos(), "Unknown filter '%s'", name);
262 str = new EOFStream(str);
264 return str;
267 //------------------------------------------------------------------------
268 // BaseStream
269 //------------------------------------------------------------------------
271 BaseStream::BaseStream(Object *dictA) {
272 dict = *dictA;
273 #ifndef NO_DECRYPTION
274 decrypt = NULL;
275 #endif
278 BaseStream::~BaseStream() {
279 dict.free();
280 #ifndef NO_DECRYPTION
281 if (decrypt)
282 delete decrypt;
283 #endif
286 #ifndef NO_DECRYPTION
287 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
288 int objNum, int objGen) {
289 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
291 #endif
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 *)gmalloc(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 Gulong buf, bitMask;
344 int bits;
345 int c;
346 int i;
348 if (imgIdx >= nVals) {
350 // read one line of image pixels
351 if (nBits == 1) {
352 for (i = 0; i < nVals; i += 8) {
353 c = str->getChar();
354 imgLine[i+0] = (Guchar)((c >> 7) & 1);
355 imgLine[i+1] = (Guchar)((c >> 6) & 1);
356 imgLine[i+2] = (Guchar)((c >> 5) & 1);
357 imgLine[i+3] = (Guchar)((c >> 4) & 1);
358 imgLine[i+4] = (Guchar)((c >> 3) & 1);
359 imgLine[i+5] = (Guchar)((c >> 2) & 1);
360 imgLine[i+6] = (Guchar)((c >> 1) & 1);
361 imgLine[i+7] = (Guchar)(c & 1);
363 } else if (nBits == 8) {
364 for (i = 0; i < nVals; ++i) {
365 imgLine[i] = str->getChar();
367 } else {
368 bitMask = (1 << nBits) - 1;
369 buf = 0;
370 bits = 0;
371 for (i = 0; i < nVals; ++i) {
372 if (bits < nBits) {
373 buf = (buf << 8) | (str->getChar() & 0xff);
374 bits += 8;
376 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
377 bits -= nBits;
381 // reset to start of line
382 imgIdx = 0;
385 for (i = 0; i < nComps; ++i)
386 pix[i] = imgLine[imgIdx++];
387 return gTrue;
390 void ImageStream::skipLine() {
391 int n, i;
393 n = (nVals * nBits + 7) >> 3;
394 for (i = 0; i < n; ++i) {
395 str->getChar();
399 //------------------------------------------------------------------------
400 // StreamPredictor
401 //------------------------------------------------------------------------
403 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
404 int widthA, int nCompsA, int nBitsA) {
405 str = strA;
406 predictor = predictorA;
407 width = widthA;
408 nComps = nCompsA;
409 nBits = nBitsA;
411 nVals = width * nComps;
412 pixBytes = (nComps * nBits + 7) >> 3;
413 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
414 predLine = (Guchar *)gmalloc(rowBytes);
415 memset(predLine, 0, rowBytes);
416 predIdx = rowBytes;
419 StreamPredictor::~StreamPredictor() {
420 gfree(predLine);
423 int StreamPredictor::lookChar() {
424 if (predIdx >= rowBytes) {
425 if (!getNextLine()) {
426 return EOF;
429 return predLine[predIdx];
432 int StreamPredictor::getChar() {
433 if (predIdx >= rowBytes) {
434 if (!getNextLine()) {
435 return EOF;
438 return predLine[predIdx++];
441 GBool StreamPredictor::getNextLine() {
442 int curPred;
443 Guchar upLeftBuf[4];
444 int left, up, upLeft, p, pa, pb, pc;
445 int c;
446 Gulong inBuf, outBuf, bitMask;
447 int inBits, outBits;
448 int i, j, k;
450 // get PNG optimum predictor number
451 if (predictor == 15) {
452 if ((curPred = str->getRawChar()) == EOF) {
453 return gFalse;
455 curPred += 10;
456 } else {
457 curPred = predictor;
460 // read the raw line, apply PNG (byte) predictor
461 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
462 for (i = pixBytes; i < rowBytes; ++i) {
463 upLeftBuf[3] = upLeftBuf[2];
464 upLeftBuf[2] = upLeftBuf[1];
465 upLeftBuf[1] = upLeftBuf[0];
466 upLeftBuf[0] = predLine[i];
467 if ((c = str->getRawChar()) == EOF) {
468 break;
470 switch (curPred) {
471 case 11: // PNG sub
472 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
473 break;
474 case 12: // PNG up
475 predLine[i] = predLine[i] + (Guchar)c;
476 break;
477 case 13: // PNG average
478 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
479 (Guchar)c;
480 break;
481 case 14: // PNG Paeth
482 left = predLine[i - pixBytes];
483 up = predLine[i];
484 upLeft = upLeftBuf[pixBytes];
485 p = left + up - upLeft;
486 if ((pa = p - left) < 0)
487 pa = -pa;
488 if ((pb = p - up) < 0)
489 pb = -pb;
490 if ((pc = p - upLeft) < 0)
491 pc = -pc;
492 if (pa <= pb && pa <= pc)
493 predLine[i] = left + (Guchar)c;
494 else if (pb <= pc)
495 predLine[i] = up + (Guchar)c;
496 else
497 predLine[i] = upLeft + (Guchar)c;
498 break;
499 case 10: // PNG none
500 default: // no predictor or TIFF predictor
501 predLine[i] = (Guchar)c;
502 break;
506 // apply TIFF (component) predictor
507 //~ this is completely untested
508 if (predictor == 2) {
509 if (nBits == 1) {
510 inBuf = predLine[pixBytes - 1];
511 for (i = pixBytes; i < rowBytes; i += 8) {
512 // 1-bit add is just xor
513 inBuf = (inBuf << 8) | predLine[i];
514 predLine[i] ^= inBuf >> nComps;
516 } else if (nBits == 8) {
517 for (i = pixBytes; i < rowBytes; ++i) {
518 predLine[i] += predLine[i - nComps];
520 } else {
521 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
522 bitMask = (1 << nBits) - 1;
523 inBuf = outBuf = 0;
524 inBits = outBits = 0;
525 j = k = pixBytes;
526 for (i = 0; i < nVals; ++i) {
527 if (inBits < nBits) {
528 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
529 inBits += 8;
531 upLeftBuf[3] = upLeftBuf[2];
532 upLeftBuf[2] = upLeftBuf[1];
533 upLeftBuf[1] = upLeftBuf[0];
534 upLeftBuf[0] = (upLeftBuf[nComps] +
535 (inBuf >> (inBits - nBits))) & bitMask;
536 outBuf = (outBuf << nBits) | upLeftBuf[0];
537 inBits -= nBits;
538 outBits += nBits;
539 if (outBits > 8) {
540 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
543 if (outBits > 0) {
544 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
549 // reset to start of line
550 predIdx = pixBytes;
552 return gTrue;
555 //------------------------------------------------------------------------
556 // FileStream
557 //------------------------------------------------------------------------
559 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
560 Guint lengthA, Object *dictA):
561 BaseStream(dictA) {
562 f = fA;
563 start = startA;
564 limited = limitedA;
565 length = lengthA;
566 bufPtr = bufEnd = buf;
567 bufPos = start;
568 savePos = 0;
569 saved = gFalse;
572 FileStream::~FileStream() {
573 close();
576 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
577 Guint lengthA, Object *dictA) {
578 return new FileStream(f, startA, limitedA, lengthA, dictA);
581 void FileStream::reset() {
582 #if HAVE_FSEEK64
583 savePos = (Guint)ftell64(f);
584 fseek64(f, start, SEEK_SET);
585 #else
586 savePos = (Guint)ftell(f);
587 fseek(f, start, SEEK_SET);
588 #endif
589 saved = gTrue;
590 bufPtr = bufEnd = buf;
591 bufPos = start;
592 #ifndef NO_DECRYPTION
593 if (decrypt)
594 decrypt->reset();
595 #endif
598 void FileStream::close() {
599 if (saved) {
600 #if HAVE_FSEEK64
601 fseek64(f, savePos, SEEK_SET);
602 #else
603 fseek(f, savePos, SEEK_SET);
604 #endif
605 saved = gFalse;
609 GBool FileStream::fillBuf() {
610 int n;
611 #ifndef NO_DECRYPTION
612 char *p;
613 #endif
615 bufPos += bufEnd - buf;
616 bufPtr = bufEnd = buf;
617 if (limited && bufPos >= start + length) {
618 return gFalse;
620 if (limited && bufPos + fileStreamBufSize > start + length) {
621 n = start + length - bufPos;
622 } else {
623 n = fileStreamBufSize;
625 n = fread(buf, 1, n, f);
626 bufEnd = buf + n;
627 if (bufPtr >= bufEnd) {
628 return gFalse;
630 #ifndef NO_DECRYPTION
631 if (decrypt) {
632 for (p = buf; p < bufEnd; ++p) {
633 *p = (char)decrypt->decryptByte((Guchar)*p);
636 #endif
637 return gTrue;
640 void FileStream::setPos(Guint pos, int dir) {
641 Guint size;
643 if (dir >= 0) {
644 #if HAVE_FSEEK64
645 fseek64(f, pos, SEEK_SET);
646 #else
647 fseek(f, pos, SEEK_SET);
648 #endif
649 bufPos = pos;
650 } else {
651 #if HAVE_FSEEK64
652 fseek64(f, 0, SEEK_END);
653 size = (Guint)ftell64(f);
654 #else
655 fseek(f, 0, SEEK_END);
656 size = (Guint)ftell(f);
657 #endif
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 #if HAVE_FSEEK64
665 fseek64(f, -(int)pos, SEEK_END);
666 bufPos = (Guint)ftell64(f);
667 #else
668 fseek(f, -(int)pos, SEEK_END);
669 bufPos = (Guint)ftell(f);
670 #endif
672 bufPtr = bufEnd = buf;
675 void FileStream::moveStart(int delta) {
676 start += delta;
677 bufPtr = bufEnd = buf;
678 bufPos = start;
681 //------------------------------------------------------------------------
682 // MemStream
683 //------------------------------------------------------------------------
685 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
686 BaseStream(dictA) {
687 buf = bufA;
688 needFree = gFalse;
689 length = lengthA;
690 bufEnd = buf + length;
691 bufPtr = buf;
694 MemStream::~MemStream() {
695 if (needFree) {
696 gfree(buf);
700 Stream *MemStream::makeSubStream(Guint start, GBool limited,
701 Guint lengthA, Object *dictA) {
702 Guint newLength;
704 if (!limited || start + lengthA > length) {
705 newLength = length - start;
706 } else {
707 newLength = lengthA;
709 return new MemStream(buf + start, newLength, dictA);
712 void MemStream::reset() {
713 bufPtr = buf;
714 #ifndef NO_DECRYPTION
715 if (decrypt) {
716 decrypt->reset();
718 #endif
721 void MemStream::close() {
724 void MemStream::setPos(Guint pos, int dir) {
725 if (dir >= 0) {
726 if (pos > length) {
727 bufPtr = bufEnd;
728 } else {
729 bufPtr = buf + pos;
731 } else {
732 if (pos > length) {
733 bufPtr = buf;
734 } else {
735 bufPtr = bufEnd - pos;
740 void MemStream::moveStart(int delta) {
741 buf += delta;
742 bufPtr = buf;
745 #ifndef NO_DECRYPTION
746 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
747 int objNum, int objGen) {
748 char *newBuf;
749 char *p, *q;
751 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
752 if (decrypt) {
753 newBuf = (char *)gmalloc(bufEnd - buf);
754 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
755 *q = (char)decrypt->decryptByte((Guchar)*p);
757 bufEnd = newBuf + (bufEnd - buf);
758 bufPtr = newBuf + (bufPtr - buf);
759 buf = newBuf;
760 needFree = gTrue;
763 #endif
765 //------------------------------------------------------------------------
766 // EmbedStream
767 //------------------------------------------------------------------------
769 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
770 BaseStream(dictA) {
771 str = strA;
774 EmbedStream::~EmbedStream() {
777 Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
778 Guint length, Object *dictA) {
779 error(-1, "Internal: called makeSubStream() on EmbedStream");
780 return NULL;
783 void EmbedStream::setPos(Guint pos, int dir) {
784 error(-1, "Internal: called setPos() on EmbedStream");
787 Guint EmbedStream::getStart() {
788 error(-1, "Internal: called getStart() on EmbedStream");
789 return 0;
792 void EmbedStream::moveStart(int delta) {
793 error(-1, "Internal: called moveStart() on EmbedStream");
796 //------------------------------------------------------------------------
797 // ASCIIHexStream
798 //------------------------------------------------------------------------
800 ASCIIHexStream::ASCIIHexStream(Stream *strA):
801 FilterStream(strA) {
802 buf = EOF;
803 eof = gFalse;
806 ASCIIHexStream::~ASCIIHexStream() {
807 delete str;
810 void ASCIIHexStream::reset() {
811 str->reset();
812 buf = EOF;
813 eof = gFalse;
816 int ASCIIHexStream::lookChar() {
817 int c1, c2, x;
819 if (buf != EOF)
820 return buf;
821 if (eof) {
822 buf = EOF;
823 return EOF;
825 do {
826 c1 = str->getChar();
827 } while (isspace(c1));
828 if (c1 == '>') {
829 eof = gTrue;
830 buf = EOF;
831 return buf;
833 do {
834 c2 = str->getChar();
835 } while (isspace(c2));
836 if (c2 == '>') {
837 eof = gTrue;
838 c2 = '0';
840 if (c1 >= '0' && c1 <= '9') {
841 x = (c1 - '0') << 4;
842 } else if (c1 >= 'A' && c1 <= 'F') {
843 x = (c1 - 'A' + 10) << 4;
844 } else if (c1 >= 'a' && c1 <= 'f') {
845 x = (c1 - 'a' + 10) << 4;
846 } else if (c1 == EOF) {
847 eof = gTrue;
848 x = 0;
849 } else {
850 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
851 x = 0;
853 if (c2 >= '0' && c2 <= '9') {
854 x += c2 - '0';
855 } else if (c2 >= 'A' && c2 <= 'F') {
856 x += c2 - 'A' + 10;
857 } else if (c2 >= 'a' && c2 <= 'f') {
858 x += c2 - 'a' + 10;
859 } else if (c2 == EOF) {
860 eof = gTrue;
861 x = 0;
862 } else {
863 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
865 buf = x & 0xff;
866 return buf;
869 GString *ASCIIHexStream::getPSFilter(char *indent) {
870 GString *s;
872 if (!(s = str->getPSFilter(indent))) {
873 return NULL;
875 s->append(indent)->append("/ASCIIHexDecode filter\n");
876 return s;
879 GBool ASCIIHexStream::isBinary(GBool last) {
880 return str->isBinary(gFalse);
883 //------------------------------------------------------------------------
884 // ASCII85Stream
885 //------------------------------------------------------------------------
887 ASCII85Stream::ASCII85Stream(Stream *strA):
888 FilterStream(strA) {
889 index = n = 0;
890 eof = gFalse;
893 ASCII85Stream::~ASCII85Stream() {
894 delete str;
897 void ASCII85Stream::reset() {
898 str->reset();
899 index = n = 0;
900 eof = gFalse;
903 int ASCII85Stream::lookChar() {
904 int k;
905 Gulong t;
907 if (index >= n) {
908 if (eof)
909 return EOF;
910 index = 0;
911 do {
912 c[0] = str->getChar();
913 } while (c[0] == '\n' || c[0] == '\r');
914 if (c[0] == '~' || c[0] == EOF) {
915 eof = gTrue;
916 n = 0;
917 return EOF;
918 } else if (c[0] == 'z') {
919 b[0] = b[1] = b[2] = b[3] = 0;
920 n = 4;
921 } else {
922 for (k = 1; k < 5; ++k) {
923 do {
924 c[k] = str->getChar();
925 } while (c[k] == '\n' || c[k] == '\r');
926 if (c[k] == '~' || c[k] == EOF)
927 break;
929 n = k - 1;
930 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
931 for (++k; k < 5; ++k)
932 c[k] = 0x21 + 84;
933 eof = gTrue;
935 t = 0;
936 for (k = 0; k < 5; ++k)
937 t = t * 85 + (c[k] - 0x21);
938 for (k = 3; k >= 0; --k) {
939 b[k] = (int)(t & 0xff);
940 t >>= 8;
944 return b[index];
947 GString *ASCII85Stream::getPSFilter(char *indent) {
948 GString *s;
950 if (!(s = str->getPSFilter(indent))) {
951 return NULL;
953 s->append(indent)->append("/ASCII85Decode filter\n");
954 return s;
957 GBool ASCII85Stream::isBinary(GBool last) {
958 return str->isBinary(gFalse);
961 //------------------------------------------------------------------------
962 // LZWStream
963 //------------------------------------------------------------------------
965 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
966 int bits, int earlyA):
967 FilterStream(strA) {
968 if (predictor != 1) {
969 pred = new StreamPredictor(this, predictor, columns, colors, bits);
970 } else {
971 pred = NULL;
973 early = earlyA;
974 zPipe = NULL;
975 bufPtr = bufEnd = buf;
978 LZWStream::~LZWStream() {
979 if (zPipe) {
980 #ifdef HAVE_POPEN
981 pclose(zPipe);
982 #else
983 fclose(zPipe);
984 #endif
985 zPipe = NULL;
986 unlink(zName->getCString());
987 delete zName;
989 if (pred) {
990 delete pred;
992 delete str;
995 int LZWStream::getChar() {
996 if (pred) {
997 return pred->getChar();
999 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1002 int LZWStream::lookChar() {
1003 if (pred) {
1004 return pred->lookChar();
1006 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
1009 int LZWStream::getRawChar() {
1010 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1013 void LZWStream::reset() {
1014 FILE *f;
1015 GString *zCmd;
1017 //----- close old LZW stream
1018 if (zPipe) {
1019 #ifdef HAVE_POPEN
1020 pclose(zPipe);
1021 #else
1022 fclose(zPipe);
1023 #endif
1024 zPipe = NULL;
1025 unlink(zName->getCString());
1026 delete zName;
1029 //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
1030 // to run gzip
1031 #if __DJGPP__
1032 if (!setDJSYSFLAGS) {
1033 setenv("DJSYSFLAGS", "0x0002", 0);
1034 setDJSYSFLAGS = gTrue;
1036 #endif
1038 //----- create the .Z file
1039 if (!openTempFile(&zName, &f, "wb", ".Z")) {
1040 error(getPos(), "Couldn't create temporary file for LZW stream");
1041 return;
1043 dumpFile(f);
1044 fclose(f);
1046 //----- execute uncompress / gzip
1047 #ifdef WIN32
1048 zCmd = new GString("c:\\swftools\\gzip.exe");
1049 #else
1050 zCmd = new GString(uncompressCmd);
1051 #endif
1052 zCmd->append(' ');
1053 zCmd->append(zName);
1054 #if defined(MACOS)
1055 long magicCookie;
1056 // first we open the engine up
1057 OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
1058 // if we found it - let's use it!
1059 if (!err && magicCookie) {
1060 // make sure we have the correct version of the Engine
1061 if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
1062 FSSpec myFSS;
1063 Str255 pName;
1064 strcpy((char *)pName, zName->getCString());
1065 c2pstr((char *)pName);
1066 FSMakeFSSpec(0, 0, pName, &myFSS);
1067 short ftype = DetermineFileType(magicCookie, &myFSS);
1068 OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
1069 NULL, NULL, kCreateFolderNever,
1070 kDeleteOriginal, kTextConvertSmart);
1073 #elif defined(HAVE_POPEN)
1074 if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
1075 error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
1076 unlink(zName->getCString());
1077 delete zName;
1078 return;
1080 #else // HAVE_POPEN
1081 if (!executeCommand(zCmd->getCString())) {
1082 error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
1083 unlink(zName->getCString());
1084 delete zName;
1085 return;
1087 zName->del(zName->getLength() - 2, 2);
1088 if (!(zPipe = fopen(zName->getCString(), "rb"))) {
1089 error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
1090 unlink(zName->getCString());
1091 delete zName;
1092 return;
1094 #endif // HAVE_POPEN
1096 //----- clean up
1097 delete zCmd;
1099 //----- initialize buffer
1100 bufPtr = bufEnd = buf;
1103 void LZWStream::dumpFile(FILE *f) {
1104 int outCodeBits; // size of output code
1105 int outBits; // max output code
1106 int outBuf[8]; // output buffer
1107 int outData; // temporary output buffer
1108 int inCode, outCode; // input and output codes
1109 int nextCode; // next code index
1110 GBool eof; // set when EOF is reached
1111 GBool clear; // set if table needs to be cleared
1112 GBool first; // indicates first code word after clear
1113 int i, j;
1115 str->reset();
1117 // magic number
1118 fputc(0x1f, f);
1119 fputc(0x9d, f);
1121 // max code length, block mode flag
1122 fputc(0x8c, f);
1124 // init input side
1125 inCodeBits = 9;
1126 inputBuf = 0;
1127 inputBits = 0;
1128 eof = gFalse;
1130 // init output side
1131 outCodeBits = 9;
1133 // clear table
1134 first = gTrue;
1135 nextCode = 258;
1137 clear = gFalse;
1138 do {
1139 for (i = 0; i < 8; ++i) {
1140 // check for table overflow
1141 if (nextCode + early > 0x1001) {
1142 inCode = 256;
1144 // read input code
1145 } else {
1146 do {
1147 inCode = getCode();
1148 if (inCode == EOF) {
1149 eof = gTrue;
1150 inCode = 0;
1152 } while (first && inCode == 256);
1155 // compute output code
1156 if (inCode < 256) {
1157 outCode = inCode;
1158 } else if (inCode == 256) {
1159 outCode = 256;
1160 clear = gTrue;
1161 } else if (inCode == 257) {
1162 outCode = 0;
1163 eof = gTrue;
1164 } else {
1165 outCode = inCode - 1;
1167 outBuf[i] = outCode;
1169 // next code index
1170 if (first)
1171 first = gFalse;
1172 else
1173 ++nextCode;
1175 // check input code size
1176 if (nextCode + early == 0x200)
1177 inCodeBits = 10;
1178 else if (nextCode + early == 0x400) {
1179 inCodeBits = 11;
1180 } else if (nextCode + early == 0x800) {
1181 inCodeBits = 12;
1184 // check for eof/clear
1185 if (eof)
1186 break;
1187 if (clear) {
1188 i = 8;
1189 break;
1193 // write output block
1194 outData = 0;
1195 outBits = 0;
1196 j = 0;
1197 while (j < i || outBits > 0) {
1198 if (outBits < 8 && j < i) {
1199 outData = outData | (outBuf[j++] << outBits);
1200 outBits += outCodeBits;
1202 fputc(outData & 0xff, f);
1203 outData >>= 8;
1204 outBits -= 8;
1207 // check output code size
1208 if (nextCode - 1 == 512 ||
1209 nextCode - 1 == 1024 ||
1210 nextCode - 1 == 2048 ||
1211 nextCode - 1 == 4096) {
1212 outCodeBits = inCodeBits;
1215 // clear table if necessary
1216 if (clear) {
1217 inCodeBits = 9;
1218 outCodeBits = 9;
1219 first = gTrue;
1220 nextCode = 258;
1221 clear = gFalse;
1223 } while (!eof);
1226 int LZWStream::getCode() {
1227 int c;
1228 int code;
1230 while (inputBits < inCodeBits) {
1231 if ((c = str->getChar()) == EOF)
1232 return EOF;
1233 inputBuf = (inputBuf << 8) | (c & 0xff);
1234 inputBits += 8;
1236 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1237 inputBits -= inCodeBits;
1238 return code;
1241 GBool LZWStream::fillBuf() {
1242 int n;
1244 if (!zPipe)
1245 return gFalse;
1246 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1247 #ifdef HAVE_POPEN
1248 pclose(zPipe);
1249 #else
1250 fclose(zPipe);
1251 #endif
1252 zPipe = NULL;
1253 unlink(zName->getCString());
1254 delete zName;
1256 bufPtr = buf;
1257 bufEnd = buf + n;
1258 return n > 0;
1261 GString *LZWStream::getPSFilter(char *indent) {
1262 GString *s;
1264 if (pred) {
1265 return NULL;
1267 if (!(s = str->getPSFilter(indent))) {
1268 return NULL;
1270 s->append(indent)->append("/LZWDecode filter\n");
1271 return s;
1274 GBool LZWStream::isBinary(GBool last) {
1275 return str->isBinary(gTrue);
1278 //------------------------------------------------------------------------
1279 // RunLengthStream
1280 //------------------------------------------------------------------------
1282 RunLengthStream::RunLengthStream(Stream *strA):
1283 FilterStream(strA) {
1284 bufPtr = bufEnd = buf;
1285 eof = gFalse;
1288 RunLengthStream::~RunLengthStream() {
1289 delete str;
1292 void RunLengthStream::reset() {
1293 str->reset();
1294 bufPtr = bufEnd = buf;
1295 eof = gFalse;
1298 GString *RunLengthStream::getPSFilter(char *indent) {
1299 GString *s;
1301 if (!(s = str->getPSFilter(indent))) {
1302 return NULL;
1304 s->append(indent)->append("/RunLengthDecode filter\n");
1305 return s;
1308 GBool RunLengthStream::isBinary(GBool last) {
1309 return str->isBinary(gTrue);
1312 GBool RunLengthStream::fillBuf() {
1313 int c;
1314 int n, i;
1316 if (eof)
1317 return gFalse;
1318 c = str->getChar();
1319 if (c == 0x80 || c == EOF) {
1320 eof = gTrue;
1321 return gFalse;
1323 if (c < 0x80) {
1324 n = c + 1;
1325 for (i = 0; i < n; ++i)
1326 buf[i] = (char)str->getChar();
1327 } else {
1328 n = 0x101 - c;
1329 c = str->getChar();
1330 for (i = 0; i < n; ++i)
1331 buf[i] = (char)c;
1333 bufPtr = buf;
1334 bufEnd = buf + n;
1335 return gTrue;
1338 //------------------------------------------------------------------------
1339 // CCITTFaxStream
1340 //------------------------------------------------------------------------
1342 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1343 GBool byteAlignA, int columnsA, int rowsA,
1344 GBool endOfBlockA, GBool blackA):
1345 FilterStream(strA) {
1346 encoding = encodingA;
1347 endOfLine = endOfLineA;
1348 byteAlign = byteAlignA;
1349 columns = columnsA;
1350 rows = rowsA;
1351 endOfBlock = endOfBlockA;
1352 black = blackA;
1353 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1354 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1356 eof = gFalse;
1357 row = 0;
1358 nextLine2D = encoding < 0;
1359 inputBits = 0;
1360 codingLine[0] = 0;
1361 codingLine[1] = refLine[2] = columns;
1362 a0 = 1;
1364 buf = EOF;
1367 CCITTFaxStream::~CCITTFaxStream() {
1368 delete str;
1369 gfree(refLine);
1370 gfree(codingLine);
1373 void CCITTFaxStream::reset() {
1374 int n;
1376 str->reset();
1377 eof = gFalse;
1378 row = 0;
1379 nextLine2D = encoding < 0;
1380 inputBits = 0;
1381 codingLine[0] = 0;
1382 codingLine[1] = refLine[2] = columns;
1383 a0 = 1;
1384 buf = EOF;
1386 // get initial end-of-line marker and 2D encoding tag
1387 if (endOfBlock) {
1388 if (lookBits(12) == 0x001) {
1389 eatBits(12);
1391 } else {
1392 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1393 if (n == 11 && lookBits(12) == 0x001) {
1394 eatBits(12);
1397 if (encoding > 0) {
1398 nextLine2D = !lookBits(1);
1399 eatBits(1);
1403 int CCITTFaxStream::lookChar() {
1404 short code1, code2, code3;
1405 int a0New;
1406 #if 0
1407 GBool err;
1408 #endif
1409 GBool gotEOL;
1410 int ret;
1411 int bits, i;
1413 // if at eof just return EOF
1414 if (eof && codingLine[a0] >= columns) {
1415 return EOF;
1418 // read the next row
1419 #if 0
1420 err = gFalse;
1421 #endif
1422 if (codingLine[a0] >= columns) {
1424 // 2-D encoding
1425 if (nextLine2D) {
1426 for (i = 0; codingLine[i] < columns; ++i)
1427 refLine[i] = codingLine[i];
1428 refLine[i] = refLine[i + 1] = columns;
1429 b1 = 1;
1430 a0New = codingLine[a0 = 0] = 0;
1431 do {
1432 code1 = getTwoDimCode();
1433 switch (code1) {
1434 case twoDimPass:
1435 if (refLine[b1] < columns) {
1436 a0New = refLine[b1 + 1];
1437 b1 += 2;
1439 break;
1440 case twoDimHoriz:
1441 if ((a0 & 1) == 0) {
1442 code1 = code2 = 0;
1443 do {
1444 code1 += code3 = getWhiteCode();
1445 } while (code3 >= 64);
1446 do {
1447 code2 += code3 = getBlackCode();
1448 } while (code3 >= 64);
1449 } else {
1450 code1 = code2 = 0;
1451 do {
1452 code1 += code3 = getBlackCode();
1453 } while (code3 >= 64);
1454 do {
1455 code2 += code3 = getWhiteCode();
1456 } while (code3 >= 64);
1458 codingLine[a0 + 1] = a0New + code1;
1459 ++a0;
1460 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1461 ++a0;
1462 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1463 b1 += 2;
1464 break;
1465 case twoDimVert0:
1466 a0New = codingLine[++a0] = refLine[b1];
1467 if (refLine[b1] < columns) {
1468 ++b1;
1469 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1470 b1 += 2;
1472 break;
1473 case twoDimVertR1:
1474 a0New = codingLine[++a0] = refLine[b1] + 1;
1475 if (refLine[b1] < columns) {
1476 ++b1;
1477 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1478 b1 += 2;
1480 break;
1481 case twoDimVertL1:
1482 a0New = codingLine[++a0] = refLine[b1] - 1;
1483 --b1;
1484 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1485 b1 += 2;
1486 break;
1487 case twoDimVertR2:
1488 a0New = codingLine[++a0] = refLine[b1] + 2;
1489 if (refLine[b1] < columns) {
1490 ++b1;
1491 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1492 b1 += 2;
1494 break;
1495 case twoDimVertL2:
1496 a0New = codingLine[++a0] = refLine[b1] - 2;
1497 --b1;
1498 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1499 b1 += 2;
1500 break;
1501 case twoDimVertR3:
1502 a0New = codingLine[++a0] = refLine[b1] + 3;
1503 if (refLine[b1] < columns) {
1504 ++b1;
1505 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1506 b1 += 2;
1508 break;
1509 case twoDimVertL3:
1510 a0New = codingLine[++a0] = refLine[b1] - 3;
1511 --b1;
1512 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1513 b1 += 2;
1514 break;
1515 case EOF:
1516 eof = gTrue;
1517 codingLine[a0 = 0] = columns;
1518 return EOF;
1519 default:
1520 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1521 #if 0
1522 err = gTrue;
1523 break;
1524 #else
1525 eof = gTrue;
1526 return EOF;
1527 #endif
1529 } while (codingLine[a0] < columns);
1531 // 1-D encoding
1532 } else {
1533 codingLine[a0 = 0] = 0;
1534 while (1) {
1535 code1 = 0;
1536 do {
1537 code1 += code3 = getWhiteCode();
1538 } while (code3 >= 64);
1539 codingLine[a0+1] = codingLine[a0] + code1;
1540 ++a0;
1541 if (codingLine[a0] >= columns)
1542 break;
1543 code2 = 0;
1544 do {
1545 code2 += code3 = getBlackCode();
1546 } while (code3 >= 64);
1547 codingLine[a0+1] = codingLine[a0] + code2;
1548 ++a0;
1549 if (codingLine[a0] >= columns)
1550 break;
1554 if (codingLine[a0] != columns) {
1555 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1556 #if 0
1557 err = gTrue;
1558 #endif
1561 // byte-align the row
1562 if (byteAlign) {
1563 inputBits &= ~7;
1566 // check for end-of-line marker, skipping over any extra zero bits
1567 gotEOL = gFalse;
1568 if (!endOfBlock && row == rows - 1) {
1569 eof = gTrue;
1570 } else {
1571 code1 = lookBits(12);
1572 while (code1 == 0) {
1573 eatBits(1);
1574 code1 = lookBits(12);
1576 if (code1 == 0x001) {
1577 eatBits(12);
1578 gotEOL = gTrue;
1579 } else if (code1 == EOF) {
1580 eof = gTrue;
1584 // get 2D encoding tag
1585 if (!eof && encoding > 0) {
1586 nextLine2D = !lookBits(1);
1587 eatBits(1);
1590 // check for end-of-block marker
1591 if (endOfBlock && gotEOL) {
1592 code1 = lookBits(12);
1593 if (code1 == 0x001) {
1594 eatBits(12);
1595 if (encoding > 0) {
1596 lookBits(1);
1597 eatBits(1);
1599 if (encoding >= 0) {
1600 for (i = 0; i < 4; ++i) {
1601 code1 = lookBits(12);
1602 if (code1 != 0x001) {
1603 error(getPos(), "Bad RTC code in CCITTFax stream");
1605 eatBits(12);
1606 if (encoding > 0) {
1607 lookBits(1);
1608 eatBits(1);
1612 eof = gTrue;
1616 #if 0
1617 // This looks for an end-of-line marker after an error, however
1618 // some (most?) CCITT streams in PDF files don't use end-of-line
1619 // markers, and the just-plow-on technique works better in those
1620 // cases.
1621 else if (err) {
1622 do {
1623 if (code1 == EOF) {
1624 eof = gTrue;
1625 return EOF;
1627 eatBits(1);
1628 code1 = look13Bits();
1629 } while ((code1 >> 1) != 0x001);
1630 eatBits(12);
1631 codingLine[++a0] = columns;
1632 if (encoding > 0) {
1633 eatBits(1);
1634 nextLine2D = !(code1 & 1);
1637 #endif
1639 a0 = 0;
1640 outputBits = codingLine[1] - codingLine[0];
1641 if (outputBits == 0) {
1642 a0 = 1;
1643 outputBits = codingLine[2] - codingLine[1];
1646 ++row;
1649 // get a byte
1650 if (outputBits >= 8) {
1651 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1652 if ((outputBits -= 8) == 0) {
1653 ++a0;
1654 if (codingLine[a0] < columns) {
1655 outputBits = codingLine[a0 + 1] - codingLine[a0];
1658 } else {
1659 bits = 8;
1660 ret = 0;
1661 do {
1662 if (outputBits > bits) {
1663 i = bits;
1664 bits = 0;
1665 if ((a0 & 1) == 0) {
1666 ret |= 0xff >> (8 - i);
1668 outputBits -= i;
1669 } else {
1670 i = outputBits;
1671 bits -= outputBits;
1672 if ((a0 & 1) == 0) {
1673 ret |= (0xff >> (8 - i)) << bits;
1675 outputBits = 0;
1676 ++a0;
1677 if (codingLine[a0] < columns) {
1678 outputBits = codingLine[a0 + 1] - codingLine[a0];
1681 } while (bits > 0 && codingLine[a0] < columns);
1683 buf = black ? (ret ^ 0xff) : ret;
1684 return buf;
1687 short CCITTFaxStream::getTwoDimCode() {
1688 short code;
1689 CCITTCode *p;
1690 int n;
1692 code = 0; // make gcc happy
1693 if (endOfBlock) {
1694 code = lookBits(7);
1695 p = &twoDimTab1[code];
1696 if (p->bits > 0) {
1697 eatBits(p->bits);
1698 return p->n;
1700 } else {
1701 for (n = 1; n <= 7; ++n) {
1702 code = lookBits(n);
1703 if (n < 7) {
1704 code <<= 7 - n;
1706 p = &twoDimTab1[code];
1707 if (p->bits == n) {
1708 eatBits(n);
1709 return p->n;
1713 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1714 return EOF;
1717 short CCITTFaxStream::getWhiteCode() {
1718 short code;
1719 CCITTCode *p;
1720 int n;
1722 code = 0; // make gcc happy
1723 if (endOfBlock) {
1724 code = lookBits(12);
1725 if ((code >> 5) == 0) {
1726 p = &whiteTab1[code];
1727 } else {
1728 p = &whiteTab2[code >> 3];
1730 if (p->bits > 0) {
1731 eatBits(p->bits);
1732 return p->n;
1734 } else {
1735 for (n = 1; n <= 9; ++n) {
1736 code = lookBits(n);
1737 if (n < 9) {
1738 code <<= 9 - n;
1740 p = &whiteTab2[code];
1741 if (p->bits == n) {
1742 eatBits(n);
1743 return p->n;
1746 for (n = 11; n <= 12; ++n) {
1747 code = lookBits(n);
1748 if (n < 12) {
1749 code <<= 12 - n;
1751 p = &whiteTab1[code];
1752 if (p->bits == n) {
1753 eatBits(n);
1754 return p->n;
1758 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1759 // eat a bit and return a positive number so that the caller doesn't
1760 // go into an infinite loop
1761 eatBits(1);
1762 return 1;
1765 short CCITTFaxStream::getBlackCode() {
1766 short code;
1767 CCITTCode *p;
1768 int n;
1770 code = 0; // make gcc happy
1771 if (endOfBlock) {
1772 code = lookBits(13);
1773 if ((code >> 7) == 0) {
1774 p = &blackTab1[code];
1775 } else if ((code >> 9) == 0) {
1776 p = &blackTab2[(code >> 1) - 64];
1777 } else {
1778 p = &blackTab3[code >> 7];
1780 if (p->bits > 0) {
1781 eatBits(p->bits);
1782 return p->n;
1784 } else {
1785 for (n = 2; n <= 6; ++n) {
1786 code = lookBits(n);
1787 if (n < 6) {
1788 code <<= 6 - n;
1790 p = &blackTab3[code];
1791 if (p->bits == n) {
1792 eatBits(n);
1793 return p->n;
1796 for (n = 7; n <= 12; ++n) {
1797 code = lookBits(n);
1798 if (n < 12) {
1799 code <<= 12 - n;
1801 if (code >= 64) {
1802 p = &blackTab2[code - 64];
1803 if (p->bits == n) {
1804 eatBits(n);
1805 return p->n;
1809 for (n = 10; n <= 13; ++n) {
1810 code = lookBits(n);
1811 if (n < 13) {
1812 code <<= 13 - n;
1814 p = &blackTab1[code];
1815 if (p->bits == n) {
1816 eatBits(n);
1817 return p->n;
1821 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1822 // eat a bit and return a positive number so that the caller doesn't
1823 // go into an infinite loop
1824 eatBits(1);
1825 return 1;
1828 short CCITTFaxStream::lookBits(int n) {
1829 int c;
1831 while (inputBits < n) {
1832 if ((c = str->getChar()) == EOF) {
1833 if (inputBits == 0) {
1834 return EOF;
1836 // near the end of the stream, the caller may ask for more bits
1837 // than are available, but there may still be a valid code in
1838 // however many bits are available -- we need to return correct
1839 // data in this case
1840 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1842 inputBuf = (inputBuf << 8) + c;
1843 inputBits += 8;
1845 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1848 GString *CCITTFaxStream::getPSFilter(char *indent) {
1849 GString *s;
1850 char s1[50];
1852 if (!(s = str->getPSFilter(indent))) {
1853 return NULL;
1855 s->append(indent)->append("<< ");
1856 if (encoding != 0) {
1857 sprintf(s1, "/K %d ", encoding);
1858 s->append(s1);
1860 if (endOfLine) {
1861 s->append("/EndOfLine true ");
1863 if (byteAlign) {
1864 s->append("/EncodedByteAlign true ");
1866 sprintf(s1, "/Columns %d ", columns);
1867 s->append(s1);
1868 if (rows != 0) {
1869 sprintf(s1, "/Rows %d ", rows);
1870 s->append(s1);
1872 if (!endOfBlock) {
1873 s->append("/EndOfBlock false ");
1875 if (black) {
1876 s->append("/BlackIs1 true ");
1878 s->append(">> /CCITTFaxDecode filter\n");
1879 return s;
1882 GBool CCITTFaxStream::isBinary(GBool last) {
1883 return str->isBinary(gTrue);
1886 //------------------------------------------------------------------------
1887 // DCTStream
1888 //------------------------------------------------------------------------
1890 // IDCT constants (20.12 fixed point format)
1891 #ifndef FP_IDCT
1892 #define dctCos1 4017 // cos(pi/16)
1893 #define dctSin1 799 // sin(pi/16)
1894 #define dctCos3 3406 // cos(3*pi/16)
1895 #define dctSin3 2276 // sin(3*pi/16)
1896 #define dctCos6 1567 // cos(6*pi/16)
1897 #define dctSin6 3784 // sin(6*pi/16)
1898 #define dctSqrt2 5793 // sqrt(2)
1899 #define dctSqrt1d2 2896 // sqrt(2) / 2
1900 #endif
1902 // IDCT constants
1903 #ifdef FP_IDCT
1904 #define dctCos1 0.98078528 // cos(pi/16)
1905 #define dctSin1 0.19509032 // sin(pi/16)
1906 #define dctCos3 0.83146961 // cos(3*pi/16)
1907 #define dctSin3 0.55557023 // sin(3*pi/16)
1908 #define dctCos6 0.38268343 // cos(6*pi/16)
1909 #define dctSin6 0.92387953 // sin(6*pi/16)
1910 #define dctSqrt2 1.41421356 // sqrt(2)
1911 #define dctSqrt1d2 0.70710678 // sqrt(2) / 2
1912 #endif
1914 // color conversion parameters (16.16 fixed point format)
1915 #define dctCrToR 91881 // 1.4020
1916 #define dctCbToG -22553 // -0.3441363
1917 #define dctCrToG -46802 // -0.71413636
1918 #define dctCbToB 116130 // 1.772
1920 // clip [-256,511] --> [0,255]
1921 #define dctClipOffset 256
1922 static Guchar dctClip[768];
1923 static int dctClipInit = 0;
1925 // zig zag decode map
1926 static int dctZigZag[64] = {
1928 1, 8,
1929 16, 9, 2,
1930 3, 10, 17, 24,
1931 32, 25, 18, 11, 4,
1932 5, 12, 19, 26, 33, 40,
1933 48, 41, 34, 27, 20, 13, 6,
1934 7, 14, 21, 28, 35, 42, 49, 56,
1935 57, 50, 43, 36, 29, 22, 15,
1936 23, 30, 37, 44, 51, 58,
1937 59, 52, 45, 38, 31,
1938 39, 46, 53, 60,
1939 61, 54, 47,
1940 55, 62,
1944 DCTStream::DCTStream(Stream *strA):
1945 FilterStream(strA) {
1946 int i, j;
1948 width = height = 0;
1949 mcuWidth = mcuHeight = 0;
1950 numComps = 0;
1951 comp = 0;
1952 x = y = dy = 0;
1953 for (i = 0; i < 4; ++i)
1954 for (j = 0; j < 32; ++j)
1955 rowBuf[i][j] = NULL;
1957 if (!dctClipInit) {
1958 for (i = -256; i < 0; ++i)
1959 dctClip[dctClipOffset + i] = 0;
1960 for (i = 0; i < 256; ++i)
1961 dctClip[dctClipOffset + i] = i;
1962 for (i = 256; i < 512; ++i)
1963 dctClip[dctClipOffset + i] = 255;
1964 dctClipInit = 1;
1968 DCTStream::~DCTStream() {
1969 int i, j;
1971 delete str;
1972 for (i = 0; i < numComps; ++i)
1973 for (j = 0; j < mcuHeight; ++j)
1974 gfree(rowBuf[i][j]);
1977 void DCTStream::reset() {
1978 str->reset();
1979 if (!readHeader()) {
1980 y = height;
1981 return;
1983 restartMarker = 0xd0;
1984 restart();
1987 int DCTStream::getChar() {
1988 int c;
1990 c = lookChar();
1991 if (c == EOF)
1992 return EOF;
1993 if (++comp == numComps) {
1994 comp = 0;
1995 if (++x == width) {
1996 x = 0;
1997 ++y;
1998 ++dy;
2001 if (y == height)
2002 readTrailer();
2003 return c;
2006 int DCTStream::lookChar() {
2007 if (y >= height)
2008 return EOF;
2009 if (dy >= mcuHeight) {
2010 if (!readMCURow()) {
2011 y = height;
2012 return EOF;
2014 comp = 0;
2015 x = 0;
2016 dy = 0;
2018 return rowBuf[comp][dy][x];
2021 void DCTStream::restart() {
2022 int i;
2024 inputBits = 0;
2025 restartCtr = restartInterval;
2026 for (i = 0; i < numComps; ++i)
2027 compInfo[i].prevDC = 0;
2030 GBool DCTStream::readMCURow() {
2031 Guchar data[64];
2032 Guchar *p1, *p2;
2033 int pY, pCb, pCr, pR, pG, pB;
2034 int h, v, horiz, vert, hSub, vSub;
2035 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2036 int c;
2038 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2040 // deal with restart marker
2041 if (restartInterval > 0 && restartCtr == 0) {
2042 c = readMarker();
2043 if (c != restartMarker) {
2044 error(getPos(), "Bad DCT data: incorrect restart marker");
2045 return gFalse;
2047 if (++restartMarker == 0xd8)
2048 restartMarker = 0xd0;
2049 restart();
2052 // read one MCU
2053 for (cc = 0; cc < numComps; ++cc) {
2054 h = compInfo[cc].hSample;
2055 v = compInfo[cc].vSample;
2056 horiz = mcuWidth / h;
2057 vert = mcuHeight / v;
2058 hSub = horiz / 8;
2059 vSub = vert / 8;
2060 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2061 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2062 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
2063 &acHuffTables[compInfo[cc].acHuffTable],
2064 quantTables[compInfo[cc].quantTable],
2065 &compInfo[cc].prevDC,
2066 data))
2067 return gFalse;
2068 if (hSub == 1 && vSub == 1) {
2069 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2070 p1 = &rowBuf[cc][y2+y3][x1+x2];
2071 p1[0] = data[i];
2072 p1[1] = data[i+1];
2073 p1[2] = data[i+2];
2074 p1[3] = data[i+3];
2075 p1[4] = data[i+4];
2076 p1[5] = data[i+5];
2077 p1[6] = data[i+6];
2078 p1[7] = data[i+7];
2080 } else if (hSub == 2 && vSub == 2) {
2081 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2082 p1 = &rowBuf[cc][y2+y3][x1+x2];
2083 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2084 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
2085 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
2086 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
2087 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
2088 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
2089 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
2090 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
2091 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
2093 } else {
2094 i = 0;
2095 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2096 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2097 for (y5 = 0; y5 < vSub; ++y5)
2098 for (x5 = 0; x5 < hSub; ++x5)
2099 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
2100 ++i;
2107 --restartCtr;
2109 // color space conversion
2110 if (colorXform) {
2111 // convert YCbCr to RGB
2112 if (numComps == 3) {
2113 for (y2 = 0; y2 < mcuHeight; ++y2) {
2114 for (x2 = 0; x2 < mcuWidth; ++x2) {
2115 pY = rowBuf[0][y2][x1+x2];
2116 pCb = rowBuf[1][y2][x1+x2] - 128;
2117 pCr = rowBuf[2][y2][x1+x2] - 128;
2118 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2119 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2120 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2121 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2122 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2123 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2126 // convert YCbCrK to CMYK (K is passed through unchanged)
2127 } else if (numComps == 4) {
2128 for (y2 = 0; y2 < mcuHeight; ++y2) {
2129 for (x2 = 0; x2 < mcuWidth; ++x2) {
2130 pY = rowBuf[0][y2][x1+x2];
2131 pCb = rowBuf[1][y2][x1+x2] - 128;
2132 pCr = rowBuf[2][y2][x1+x2] - 128;
2133 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2134 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2135 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2136 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2137 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2138 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2144 return gTrue;
2147 // This IDCT algorithm is taken from:
2148 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2149 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2150 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2151 // 988-991.
2152 // The stage numbers mentioned in the comments refer to Figure 1 in this
2153 // paper.
2154 #ifndef FP_IDCT
2155 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2156 DCTHuffTable *acHuffTable,
2157 Guchar quantTable[64], int *prevDC,
2158 Guchar data[64]) {
2159 int tmp1[64];
2160 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2161 int run, size, amp;
2162 int c;
2163 int i, j;
2165 // Huffman decode and dequantize
2166 size = readHuffSym(dcHuffTable);
2167 if (size == 9999)
2168 return gFalse;
2169 if (size > 0) {
2170 amp = readAmp(size);
2171 if (amp == 9999)
2172 return gFalse;
2173 } else {
2174 amp = 0;
2176 tmp1[0] = (*prevDC += amp) * quantTable[0];
2177 for (i = 1; i < 64; ++i)
2178 tmp1[i] = 0;
2179 i = 1;
2180 while (i < 64) {
2181 run = 0;
2182 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2183 run += 0x10;
2184 if (c == 9999)
2185 return gFalse;
2186 if (c == 0x00) {
2187 break;
2188 } else {
2189 run += (c >> 4) & 0x0f;
2190 size = c & 0x0f;
2191 amp = readAmp(size);
2192 if (amp == 9999)
2193 return gFalse;
2194 i += run;
2195 j = dctZigZag[i++];
2196 tmp1[j] = amp * quantTable[j];
2200 // inverse DCT on rows
2201 for (i = 0; i < 64; i += 8) {
2203 // stage 4
2204 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
2205 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
2206 v2 = tmp1[i+2];
2207 v3 = tmp1[i+6];
2208 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
2209 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
2210 v5 = tmp1[i+3] << 4;
2211 v6 = tmp1[i+5] << 4;
2213 // stage 3
2214 t = (v0 - v1+ 1) >> 1;
2215 v0 = (v0 + v1 + 1) >> 1;
2216 v1 = t;
2217 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2218 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2219 v3 = t;
2220 t = (v4 - v6 + 1) >> 1;
2221 v4 = (v4 + v6 + 1) >> 1;
2222 v6 = t;
2223 t = (v7 + v5 + 1) >> 1;
2224 v5 = (v7 - v5 + 1) >> 1;
2225 v7 = t;
2227 // stage 2
2228 t = (v0 - v3 + 1) >> 1;
2229 v0 = (v0 + v3 + 1) >> 1;
2230 v3 = t;
2231 t = (v1 - v2 + 1) >> 1;
2232 v1 = (v1 + v2 + 1) >> 1;
2233 v2 = t;
2234 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2235 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2236 v7 = t;
2237 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2238 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2239 v6 = t;
2241 // stage 1
2242 tmp1[i+0] = v0 + v7;
2243 tmp1[i+7] = v0 - v7;
2244 tmp1[i+1] = v1 + v6;
2245 tmp1[i+6] = v1 - v6;
2246 tmp1[i+2] = v2 + v5;
2247 tmp1[i+5] = v2 - v5;
2248 tmp1[i+3] = v3 + v4;
2249 tmp1[i+4] = v3 - v4;
2252 // inverse DCT on columns
2253 for (i = 0; i < 8; ++i) {
2255 // stage 4
2256 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2257 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2258 v2 = tmp1[2*8+i];
2259 v3 = tmp1[6*8+i];
2260 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2261 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2262 v5 = tmp1[3*8+i];
2263 v6 = tmp1[5*8+i];
2265 // stage 3
2266 t = (v0 - v1 + 1) >> 1;
2267 v0 = (v0 + v1 + 1) >> 1;
2268 v1 = t;
2269 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2270 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2271 v3 = t;
2272 t = (v4 - v6 + 1) >> 1;
2273 v4 = (v4 + v6 + 1) >> 1;
2274 v6 = t;
2275 t = (v7 + v5 + 1) >> 1;
2276 v5 = (v7 - v5 + 1) >> 1;
2277 v7 = t;
2279 // stage 2
2280 t = (v0 - v3 + 1) >> 1;
2281 v0 = (v0 + v3 + 1) >> 1;
2282 v3 = t;
2283 t = (v1 - v2 + 1) >> 1;
2284 v1 = (v1 + v2 + 1) >> 1;
2285 v2 = t;
2286 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2287 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2288 v7 = t;
2289 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2290 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2291 v6 = t;
2293 // stage 1
2294 tmp1[0*8+i] = v0 + v7;
2295 tmp1[7*8+i] = v0 - v7;
2296 tmp1[1*8+i] = v1 + v6;
2297 tmp1[6*8+i] = v1 - v6;
2298 tmp1[2*8+i] = v2 + v5;
2299 tmp1[5*8+i] = v2 - v5;
2300 tmp1[3*8+i] = v3 + v4;
2301 tmp1[4*8+i] = v3 - v4;
2304 // convert to 8-bit integers
2305 for (i = 0; i < 64; ++i)
2306 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2308 return gTrue;
2310 #endif
2312 #ifdef FP_IDCT
2313 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2314 DCTHuffTable *acHuffTable,
2315 Guchar quantTable[64], int *prevDC,
2316 Guchar data[64]) {
2317 double tmp1[64];
2318 double v0, v1, v2, v3, v4, v5, v6, v7, t;
2319 int run, size, amp;
2320 int c;
2321 int i, j;
2323 // Huffman decode and dequantize
2324 size = readHuffSym(dcHuffTable);
2325 if (size == 9999)
2326 return gFalse;
2327 if (size > 0) {
2328 amp = readAmp(size);
2329 if (amp == 9999)
2330 return gFalse;
2331 } else {
2332 amp = 0;
2334 tmp1[0] = (*prevDC += amp) * quantTable[0];
2335 for (i = 1; i < 64; ++i)
2336 tmp1[i] = 0;
2337 i = 1;
2338 while (i < 64) {
2339 run = 0;
2340 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2341 run += 0x10;
2342 if (c == 9999)
2343 return gFalse;
2344 if (c == 0x00) {
2345 break;
2346 } else {
2347 run += (c >> 4) & 0x0f;
2348 size = c & 0x0f;
2349 amp = readAmp(size);
2350 if (amp == 9999)
2351 return gFalse;
2352 i += run;
2353 j = dctZigZag[i++];
2354 tmp1[j] = amp * quantTable[j];
2358 // inverse DCT on rows
2359 for (i = 0; i < 64; i += 8) {
2361 // stage 4
2362 v0 = dctSqrt2 * tmp1[i+0];
2363 v1 = dctSqrt2 * tmp1[i+4];
2364 v2 = tmp1[i+2];
2365 v3 = tmp1[i+6];
2366 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2367 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2368 v5 = tmp1[i+3];
2369 v6 = tmp1[i+5];
2371 // stage 3
2372 t = 0.5 * (v0 - v1);
2373 v0 = 0.5 * (v0 + v1);
2374 v1 = t;
2375 t = v2 * dctSin6 + v3 * dctCos6;
2376 v2 = v2 * dctCos6 - v3 * dctSin6;
2377 v3 = t;
2378 t = 0.5 * (v4 - v6);
2379 v4 = 0.5 * (v4 + v6);
2380 v6 = t;
2381 t = 0.5 * (v7 + v5);
2382 v5 = 0.5 * (v7 - v5);
2383 v7 = t;
2385 // stage 2
2386 t = 0.5 * (v0 - v3);
2387 v0 = 0.5 * (v0 + v3);
2388 v3 = t;
2389 t = 0.5 * (v1 - v2);
2390 v1 = 0.5 * (v1 + v2);
2391 v2 = t;
2392 t = v4 * dctSin3 + v7 * dctCos3;
2393 v4 = v4 * dctCos3 - v7 * dctSin3;
2394 v7 = t;
2395 t = v5 * dctSin1 + v6 * dctCos1;
2396 v5 = v5 * dctCos1 - v6 * dctSin1;
2397 v6 = t;
2399 // stage 1
2400 tmp1[i+0] = v0 + v7;
2401 tmp1[i+7] = v0 - v7;
2402 tmp1[i+1] = v1 + v6;
2403 tmp1[i+6] = v1 - v6;
2404 tmp1[i+2] = v2 + v5;
2405 tmp1[i+5] = v2 - v5;
2406 tmp1[i+3] = v3 + v4;
2407 tmp1[i+4] = v3 - v4;
2410 // inverse DCT on columns
2411 for (i = 0; i < 8; ++i) {
2413 // stage 4
2414 v0 = dctSqrt2 * tmp1[0*8+i];
2415 v1 = dctSqrt2 * tmp1[4*8+i];
2416 v2 = tmp1[2*8+i];
2417 v3 = tmp1[6*8+i];
2418 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2419 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2420 v5 = tmp1[3*8+i];
2421 v6 = tmp1[5*8+i];
2423 // stage 3
2424 t = 0.5 * (v0 - v1);
2425 v0 = 0.5 * (v0 + v1);
2426 v1 = t;
2427 t = v2 * dctSin6 + v3 * dctCos6;
2428 v2 = v2 * dctCos6 - v3 * dctSin6;
2429 v3 = t;
2430 t = 0.5 * (v4 - v6);
2431 v4 = 0.5 * (v4 + v6);
2432 v6 = t;
2433 t = 0.5 * (v7 + v5);
2434 v5 = 0.5 * (v7 - v5);
2435 v7 = t;
2437 // stage 2
2438 t = 0.5 * (v0 - v3);
2439 v0 = 0.5 * (v0 + v3);
2440 v3 = t;
2441 t = 0.5 * (v1 - v2);
2442 v1 = 0.5 * (v1 + v2);
2443 v2 = t;
2444 t = v4 * dctSin3 + v7 * dctCos3;
2445 v4 = v4 * dctCos3 - v7 * dctSin3;
2446 v7 = t;
2447 t = v5 * dctSin1 + v6 * dctCos1;
2448 v5 = v5 * dctCos1 - v6 * dctSin1;
2449 v6 = t;
2451 // stage 1
2452 tmp1[0*8+i] = v0 + v7;
2453 tmp1[7*8+i] = v0 - v7;
2454 tmp1[1*8+i] = v1 + v6;
2455 tmp1[6*8+i] = v1 - v6;
2456 tmp1[2*8+i] = v2 + v5;
2457 tmp1[5*8+i] = v2 - v5;
2458 tmp1[3*8+i] = v3 + v4;
2459 tmp1[4*8+i] = v3 - v4;
2462 // convert to 8-bit integers
2463 for (i = 0; i < 64; ++i)
2464 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2466 return gTrue;
2468 #endif
2470 int DCTStream::readHuffSym(DCTHuffTable *table) {
2471 Gushort code;
2472 int bit;
2473 int codeBits;
2475 code = 0;
2476 codeBits = 0;
2477 do {
2478 // add a bit to the code
2479 if ((bit = readBit()) == EOF)
2480 return 9999;
2481 code = (code << 1) + bit;
2482 ++codeBits;
2484 // look up code
2485 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2486 code -= table->firstCode[codeBits];
2487 return table->sym[table->firstSym[codeBits] + code];
2489 } while (codeBits < 16);
2491 error(getPos(), "Bad Huffman code in DCT stream");
2492 return 9999;
2495 int DCTStream::readAmp(int size) {
2496 int amp, bit;
2497 int bits;
2499 amp = 0;
2500 for (bits = 0; bits < size; ++bits) {
2501 if ((bit = readBit()) == EOF)
2502 return 9999;
2503 amp = (amp << 1) + bit;
2505 if (amp < (1 << (size - 1)))
2506 amp -= (1 << size) - 1;
2507 return amp;
2510 int DCTStream::readBit() {
2511 int bit;
2512 int c, c2;
2514 if (inputBits == 0) {
2515 if ((c = str->getChar()) == EOF)
2516 return EOF;
2517 if (c == 0xff) {
2518 do {
2519 c2 = str->getChar();
2520 } while (c2 == 0xff);
2521 if (c2 != 0x00) {
2522 error(getPos(), "Bad DCT data: missing 00 after ff");
2523 return EOF;
2526 inputBuf = c;
2527 inputBits = 8;
2529 bit = (inputBuf >> (inputBits - 1)) & 1;
2530 --inputBits;
2531 return bit;
2534 GBool DCTStream::readHeader() {
2535 GBool doScan;
2536 int minHSample, minVSample;
2537 int bufWidth;
2538 int n;
2539 int c = 0;
2540 int i, j;
2542 width = height = 0;
2543 numComps = 0;
2544 numQuantTables = 0;
2545 numDCHuffTables = 0;
2546 numACHuffTables = 0;
2547 colorXform = 0;
2548 gotAdobeMarker = gFalse;
2549 restartInterval = 0;
2551 // read headers
2552 doScan = gFalse;
2553 while (!doScan) {
2554 c = readMarker();
2555 switch (c) {
2556 case 0xc0: // SOF0
2557 if (!readFrameInfo())
2558 return gFalse;
2559 break;
2560 case 0xc4: // DHT
2561 if (!readHuffmanTables())
2562 return gFalse;
2563 break;
2564 case 0xd8: // SOI
2565 break;
2566 case 0xda: // SOS
2567 if (!readScanInfo())
2568 return gFalse;
2569 doScan = gTrue;
2570 break;
2571 case 0xdb: // DQT
2572 if (!readQuantTables())
2573 return gFalse;
2574 break;
2575 case 0xdd: // DRI
2576 if (!readRestartInterval())
2577 return gFalse;
2578 break;
2579 case 0xee: // APP14
2580 if (!readAdobeMarker())
2581 return gFalse;
2582 break;
2583 case EOF:
2584 error(getPos(), "Bad DCT header");
2585 return gFalse;
2586 default:
2587 // skip APPn / COM / etc.
2588 if (c >= 0xe0) {
2589 n = read16() - 2;
2590 for (i = 0; i < n; ++i)
2591 str->getChar();
2592 } else {
2593 error(getPos(), "Unknown DCT marker <%02x>", c);
2594 return gFalse;
2596 break;
2600 // compute MCU size
2601 mcuWidth = minHSample = compInfo[0].hSample;
2602 mcuHeight = minVSample = compInfo[0].vSample;
2603 for (i = 1; i < numComps; ++i) {
2604 if (compInfo[i].hSample < minHSample)
2605 minHSample = compInfo[i].hSample;
2606 if (compInfo[i].vSample < minVSample)
2607 minVSample = compInfo[i].vSample;
2608 if (compInfo[i].hSample > mcuWidth)
2609 mcuWidth = compInfo[i].hSample;
2610 if (compInfo[i].vSample > mcuHeight)
2611 mcuHeight = compInfo[i].vSample;
2613 for (i = 0; i < numComps; ++i) {
2614 compInfo[i].hSample /= minHSample;
2615 compInfo[i].vSample /= minVSample;
2617 mcuWidth = (mcuWidth / minHSample) * 8;
2618 mcuHeight = (mcuHeight / minVSample) * 8;
2620 // allocate buffers
2621 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2622 for (i = 0; i < numComps; ++i)
2623 for (j = 0; j < mcuHeight; ++j)
2624 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2626 // figure out color transform
2627 if (!gotAdobeMarker && numComps == 3) {
2628 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2629 colorXform = 1;
2633 // initialize counters
2634 comp = 0;
2635 x = 0;
2636 y = 0;
2637 dy = mcuHeight;
2639 return gTrue;
2642 GBool DCTStream::readFrameInfo() {
2643 int length;
2644 int prec;
2645 int i;
2646 int c;
2648 length = read16() - 2;
2649 prec = str->getChar();
2650 height = read16();
2651 width = read16();
2652 numComps = str->getChar();
2653 length -= 6;
2654 if (prec != 8) {
2655 error(getPos(), "Bad DCT precision %d", prec);
2656 return gFalse;
2658 for (i = 0; i < numComps; ++i) {
2659 compInfo[i].id = str->getChar();
2660 compInfo[i].inScan = gFalse;
2661 c = str->getChar();
2662 compInfo[i].hSample = (c >> 4) & 0x0f;
2663 compInfo[i].vSample = c & 0x0f;
2664 compInfo[i].quantTable = str->getChar();
2665 compInfo[i].dcHuffTable = 0;
2666 compInfo[i].acHuffTable = 0;
2668 return gTrue;
2671 GBool DCTStream::readScanInfo() {
2672 int length;
2673 int scanComps, id, c;
2674 int i, j;
2676 length = read16() - 2;
2677 scanComps = str->getChar();
2678 --length;
2679 if (length != 2 * scanComps + 3) {
2680 error(getPos(), "Bad DCT scan info block");
2681 return gFalse;
2683 for (i = 0; i < scanComps; ++i) {
2684 id = str->getChar();
2685 for (j = 0; j < numComps; ++j) {
2686 if (id == compInfo[j].id)
2687 break;
2689 if (j == numComps) {
2690 error(getPos(), "Bad DCT component ID in scan info block");
2691 return gFalse;
2693 compInfo[j].inScan = gTrue;
2694 c = str->getChar();
2695 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2696 compInfo[j].acHuffTable = c & 0x0f;
2698 str->getChar();
2699 str->getChar();
2700 str->getChar();
2701 return gTrue;
2704 GBool DCTStream::readQuantTables() {
2705 int length;
2706 int i;
2707 int index;
2709 length = read16() - 2;
2710 while (length > 0) {
2711 index = str->getChar();
2712 if ((index & 0xf0) || index >= 4) {
2713 error(getPos(), "Bad DCT quantization table");
2714 return gFalse;
2716 if (index == numQuantTables)
2717 numQuantTables = index + 1;
2718 for (i = 0; i < 64; ++i)
2719 quantTables[index][dctZigZag[i]] = str->getChar();
2720 length -= 65;
2722 return gTrue;
2725 GBool DCTStream::readHuffmanTables() {
2726 DCTHuffTable *tbl;
2727 int length;
2728 int index;
2729 Gushort code;
2730 Guchar sym;
2731 int i;
2732 int c;
2734 length = read16() - 2;
2735 while (length > 0) {
2736 index = str->getChar();
2737 --length;
2738 if ((index & 0x0f) >= 4) {
2739 error(getPos(), "Bad DCT Huffman table");
2740 return gFalse;
2742 if (index & 0x10) {
2743 index &= 0x0f;
2744 if (index >= numACHuffTables)
2745 numACHuffTables = index+1;
2746 tbl = &acHuffTables[index];
2747 } else {
2748 if (index >= numDCHuffTables)
2749 numDCHuffTables = index+1;
2750 tbl = &dcHuffTables[index];
2752 sym = 0;
2753 code = 0;
2754 for (i = 1; i <= 16; ++i) {
2755 c = str->getChar();
2756 tbl->firstSym[i] = sym;
2757 tbl->firstCode[i] = code;
2758 tbl->numCodes[i] = c;
2759 sym += c;
2760 code = (code + c) << 1;
2762 length -= 16;
2763 for (i = 0; i < sym; ++i)
2764 tbl->sym[i] = str->getChar();
2765 length -= sym;
2767 return gTrue;
2770 GBool DCTStream::readRestartInterval() {
2771 int length;
2773 length = read16();
2774 if (length != 4) {
2775 error(getPos(), "Bad DCT restart interval");
2776 return gFalse;
2778 restartInterval = read16();
2779 return gTrue;
2782 GBool DCTStream::readAdobeMarker() {
2783 int length, i;
2784 char buf[12];
2785 int c;
2787 length = read16();
2788 if (length != 14)
2789 goto err;
2790 for (i = 0; i < 12; ++i) {
2791 if ((c = str->getChar()) == EOF)
2792 goto err;
2793 buf[i] = c;
2795 if (strncmp(buf, "Adobe", 5))
2796 goto err;
2797 colorXform = buf[11];
2798 gotAdobeMarker = gTrue;
2799 return gTrue;
2801 err:
2802 error(getPos(), "Bad DCT Adobe APP14 marker");
2803 return gFalse;
2806 GBool DCTStream::readTrailer() {
2807 int c;
2809 c = readMarker();
2810 if (c != 0xd9) { // EOI
2811 error(getPos(), "Bad DCT trailer");
2812 return gFalse;
2814 return gTrue;
2817 int DCTStream::readMarker() {
2818 int c;
2820 do {
2821 do {
2822 c = str->getChar();
2823 } while (c != 0xff);
2824 do {
2825 c = str->getChar();
2826 } while (c == 0xff);
2827 } while (c == 0x00);
2828 return c;
2831 int DCTStream::read16() {
2832 int c1, c2;
2834 if ((c1 = str->getChar()) == EOF)
2835 return EOF;
2836 if ((c2 = str->getChar()) == EOF)
2837 return EOF;
2838 return (c1 << 8) + c2;
2841 GString *DCTStream::getPSFilter(char *indent) {
2842 GString *s;
2844 if (!(s = str->getPSFilter(indent))) {
2845 return NULL;
2847 s->append(indent)->append("<< >> /DCTDecode filter\n");
2848 return s;
2851 GBool DCTStream::isBinary(GBool last) {
2852 return str->isBinary(gTrue);
2855 //------------------------------------------------------------------------
2856 // FlateStream
2857 //------------------------------------------------------------------------
2859 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2860 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2863 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2864 {0, 3},
2865 {0, 4},
2866 {0, 5},
2867 {0, 6},
2868 {0, 7},
2869 {0, 8},
2870 {0, 9},
2871 {0, 10},
2872 {1, 11},
2873 {1, 13},
2874 {1, 15},
2875 {1, 17},
2876 {2, 19},
2877 {2, 23},
2878 {2, 27},
2879 {2, 31},
2880 {3, 35},
2881 {3, 43},
2882 {3, 51},
2883 {3, 59},
2884 {4, 67},
2885 {4, 83},
2886 {4, 99},
2887 {4, 115},
2888 {5, 131},
2889 {5, 163},
2890 {5, 195},
2891 {5, 227},
2892 {0, 258}
2895 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2896 { 0, 1},
2897 { 0, 2},
2898 { 0, 3},
2899 { 0, 4},
2900 { 1, 5},
2901 { 1, 7},
2902 { 2, 9},
2903 { 2, 13},
2904 { 3, 17},
2905 { 3, 25},
2906 { 4, 33},
2907 { 4, 49},
2908 { 5, 65},
2909 { 5, 97},
2910 { 6, 129},
2911 { 6, 193},
2912 { 7, 257},
2913 { 7, 385},
2914 { 8, 513},
2915 { 8, 769},
2916 { 9, 1025},
2917 { 9, 1537},
2918 {10, 2049},
2919 {10, 3073},
2920 {11, 4097},
2921 {11, 6145},
2922 {12, 8193},
2923 {12, 12289},
2924 {13, 16385},
2925 {13, 24577}
2928 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
2929 int colors, int bits):
2930 FilterStream(strA) {
2931 if (predictor != 1) {
2932 pred = new StreamPredictor(this, predictor, columns, colors, bits);
2933 } else {
2934 pred = NULL;
2938 FlateStream::~FlateStream() {
2939 if (pred) {
2940 delete pred;
2942 delete str;
2945 void FlateStream::reset() {
2946 int cmf, flg;
2948 index = 0;
2949 remain = 0;
2950 codeBuf = 0;
2951 codeSize = 0;
2952 compressedBlock = gFalse;
2953 endOfBlock = gTrue;
2954 eof = gTrue;
2956 str->reset();
2958 // read header
2959 //~ need to look at window size?
2960 endOfBlock = eof = gTrue;
2961 cmf = str->getChar();
2962 flg = str->getChar();
2963 if (cmf == EOF || flg == EOF)
2964 return;
2965 if ((cmf & 0x0f) != 0x08) {
2966 error(getPos(), "Unknown compression method in flate stream");
2967 return;
2969 if ((((cmf << 8) + flg) % 31) != 0) {
2970 error(getPos(), "Bad FCHECK in flate stream");
2971 return;
2973 if (flg & 0x20) {
2974 error(getPos(), "FDICT bit set in flate stream");
2975 return;
2978 eof = gFalse;
2981 int FlateStream::getChar() {
2982 int c;
2984 if (pred) {
2985 return pred->getChar();
2987 while (remain == 0) {
2988 if (endOfBlock && eof)
2989 return EOF;
2990 readSome();
2992 c = buf[index];
2993 index = (index + 1) & flateMask;
2994 --remain;
2995 return c;
2998 int FlateStream::lookChar() {
2999 int c;
3001 if (pred) {
3002 return pred->lookChar();
3004 while (remain == 0) {
3005 if (endOfBlock && eof)
3006 return EOF;
3007 readSome();
3009 c = buf[index];
3010 return c;
3013 int FlateStream::getRawChar() {
3014 int c;
3016 while (remain == 0) {
3017 if (endOfBlock && eof)
3018 return EOF;
3019 readSome();
3021 c = buf[index];
3022 index = (index + 1) & flateMask;
3023 --remain;
3024 return c;
3027 GString *FlateStream::getPSFilter(char *indent) {
3028 return NULL;
3031 GBool FlateStream::isBinary(GBool last) {
3032 return str->isBinary(gTrue);
3035 void FlateStream::readSome() {
3036 int code1, code2;
3037 int len, dist;
3038 int i, j, k;
3039 int c;
3041 if (endOfBlock) {
3042 if (!startBlock())
3043 return;
3046 if (compressedBlock) {
3047 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3048 goto err;
3049 if (code1 < 256) {
3050 buf[index] = code1;
3051 remain = 1;
3052 } else if (code1 == 256) {
3053 endOfBlock = gTrue;
3054 remain = 0;
3055 } else {
3056 code1 -= 257;
3057 code2 = lengthDecode[code1].bits;
3058 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3059 goto err;
3060 len = lengthDecode[code1].first + code2;
3061 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3062 goto err;
3063 code2 = distDecode[code1].bits;
3064 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3065 goto err;
3066 dist = distDecode[code1].first + code2;
3067 i = index;
3068 j = (index - dist) & flateMask;
3069 for (k = 0; k < len; ++k) {
3070 buf[i] = buf[j];
3071 i = (i + 1) & flateMask;
3072 j = (j + 1) & flateMask;
3074 remain = len;
3077 } else {
3078 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3079 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3080 if ((c = str->getChar()) == EOF) {
3081 endOfBlock = eof = gTrue;
3082 break;
3084 buf[j] = c & 0xff;
3086 remain = i;
3087 blockLen -= len;
3088 if (blockLen == 0)
3089 endOfBlock = gTrue;
3092 return;
3094 err:
3095 error(getPos(), "Unexpected end of file in flate stream");
3096 endOfBlock = eof = gTrue;
3097 remain = 0;
3100 GBool FlateStream::startBlock() {
3101 int blockHdr;
3102 int c;
3103 int check;
3105 // read block header
3106 blockHdr = getCodeWord(3);
3107 if (blockHdr & 1)
3108 eof = gTrue;
3109 blockHdr >>= 1;
3111 // uncompressed block
3112 if (blockHdr == 0) {
3113 compressedBlock = gFalse;
3114 if ((c = str->getChar()) == EOF)
3115 goto err;
3116 blockLen = c & 0xff;
3117 if ((c = str->getChar()) == EOF)
3118 goto err;
3119 blockLen |= (c & 0xff) << 8;
3120 if ((c = str->getChar()) == EOF)
3121 goto err;
3122 check = c & 0xff;
3123 if ((c = str->getChar()) == EOF)
3124 goto err;
3125 check |= (c & 0xff) << 8;
3126 if (check != (~blockLen & 0xffff))
3127 error(getPos(), "Bad uncompressed block length in flate stream");
3128 codeBuf = 0;
3129 codeSize = 0;
3131 // compressed block with fixed codes
3132 } else if (blockHdr == 1) {
3133 compressedBlock = gTrue;
3134 loadFixedCodes();
3136 // compressed block with dynamic codes
3137 } else if (blockHdr == 2) {
3138 compressedBlock = gTrue;
3139 if (!readDynamicCodes())
3140 goto err;
3142 // unknown block type
3143 } else {
3144 goto err;
3147 endOfBlock = gFalse;
3148 return gTrue;
3150 err:
3151 error(getPos(), "Bad block header in flate stream");
3152 endOfBlock = eof = gTrue;
3153 return gFalse;
3156 void FlateStream::loadFixedCodes() {
3157 int i;
3159 // set up code arrays
3160 litCodeTab.codes = allCodes;
3161 distCodeTab.codes = allCodes + flateMaxLitCodes;
3163 // initialize literal code table
3164 for (i = 0; i <= 143; ++i)
3165 litCodeTab.codes[i].len = 8;
3166 for (i = 144; i <= 255; ++i)
3167 litCodeTab.codes[i].len = 9;
3168 for (i = 256; i <= 279; ++i)
3169 litCodeTab.codes[i].len = 7;
3170 for (i = 280; i <= 287; ++i)
3171 litCodeTab.codes[i].len = 8;
3172 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
3174 // initialize distance code table
3175 for (i = 0; i <= 5; ++i) {
3176 distCodeTab.start[i] = 0;
3178 for (i = 6; i <= flateMaxHuffman+1; ++i) {
3179 distCodeTab.start[i] = flateMaxDistCodes;
3181 for (i = 0; i < flateMaxDistCodes; ++i) {
3182 distCodeTab.codes[i].len = 5;
3183 distCodeTab.codes[i].code = i;
3184 distCodeTab.codes[i].val = i;
3188 GBool FlateStream::readDynamicCodes() {
3189 int numCodeLenCodes;
3190 int numLitCodes;
3191 int numDistCodes;
3192 FlateCode codeLenCodes[flateMaxCodeLenCodes];
3193 FlateHuffmanTab codeLenCodeTab;
3194 int len, repeat, code;
3195 int i;
3197 // read lengths
3198 if ((numLitCodes = getCodeWord(5)) == EOF)
3199 goto err;
3200 numLitCodes += 257;
3201 if ((numDistCodes = getCodeWord(5)) == EOF)
3202 goto err;
3203 numDistCodes += 1;
3204 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
3205 goto err;
3206 numCodeLenCodes += 4;
3207 if (numLitCodes > flateMaxLitCodes ||
3208 numDistCodes > flateMaxDistCodes ||
3209 numCodeLenCodes > flateMaxCodeLenCodes)
3210 goto err;
3212 // read code length code table
3213 codeLenCodeTab.codes = codeLenCodes;
3214 for (i = 0; i < flateMaxCodeLenCodes; ++i)
3215 codeLenCodes[i].len = 0;
3216 for (i = 0; i < numCodeLenCodes; ++i) {
3217 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
3218 goto err;
3220 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
3222 // set up code arrays
3223 litCodeTab.codes = allCodes;
3224 distCodeTab.codes = allCodes + numLitCodes;
3226 // read literal and distance code tables
3227 len = 0;
3228 repeat = 0;
3229 i = 0;
3230 while (i < numLitCodes + numDistCodes) {
3231 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3232 goto err;
3233 if (code == 16) {
3234 if ((repeat = getCodeWord(2)) == EOF)
3235 goto err;
3236 for (repeat += 3; repeat > 0; --repeat)
3237 allCodes[i++].len = len;
3238 } else if (code == 17) {
3239 if ((repeat = getCodeWord(3)) == EOF)
3240 goto err;
3241 len = 0;
3242 for (repeat += 3; repeat > 0; --repeat)
3243 allCodes[i++].len = 0;
3244 } else if (code == 18) {
3245 if ((repeat = getCodeWord(7)) == EOF)
3246 goto err;
3247 len = 0;
3248 for (repeat += 11; repeat > 0; --repeat)
3249 allCodes[i++].len = 0;
3250 } else {
3251 allCodes[i++].len = len = code;
3254 compHuffmanCodes(&litCodeTab, numLitCodes);
3255 compHuffmanCodes(&distCodeTab, numDistCodes);
3257 return gTrue;
3259 err:
3260 error(getPos(), "Bad dynamic code table in flate stream");
3261 return gFalse;
3264 // On entry, the <tab->codes> array contains the lengths of each code,
3265 // stored in code value order. This function computes the code words.
3266 // The result is sorted in order of (1) code length and (2) code word.
3267 // The length values are no longer valid. The <tab->start> array is
3268 // filled with the indexes of the first code of each length.
3269 void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3270 int numLengths[flateMaxHuffman+1];
3271 int nextCode[flateMaxHuffman+1];
3272 int nextIndex[flateMaxHuffman+2];
3273 int code;
3274 int i, j;
3276 // count number of codes for each code length
3277 for (i = 0; i <= flateMaxHuffman; ++i)
3278 numLengths[i] = 0;
3279 for (i = 0; i < n; ++i)
3280 ++numLengths[tab->codes[i].len];
3282 // compute first index for each length
3283 tab->start[0] = nextIndex[0] = 0;
3284 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3285 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3287 // compute first code for each length
3288 code = 0;
3289 numLengths[0] = 0;
3290 for (i = 1; i <= flateMaxHuffman; ++i) {
3291 code = (code + numLengths[i-1]) << 1;
3292 nextCode[i] = code;
3295 // compute the codes -- this permutes the codes array from value
3296 // order to length/code order
3297 for (i = 0; i < n; ++i) {
3298 j = nextIndex[tab->codes[i].len]++;
3299 if (tab->codes[i].len == 0)
3300 tab->codes[j].code = 0;
3301 else
3302 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3303 tab->codes[j].val = i;
3307 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3308 int len;
3309 int code;
3310 int c;
3311 int i, j;
3313 code = 0;
3314 for (len = 1; len <= flateMaxHuffman; ++len) {
3316 // add a bit to the code
3317 if (codeSize == 0) {
3318 if ((c = str->getChar()) == EOF)
3319 return EOF;
3320 codeBuf = c & 0xff;
3321 codeSize = 8;
3323 code = (code << 1) | (codeBuf & 1);
3324 codeBuf >>= 1;
3325 --codeSize;
3327 // look for code
3328 i = tab->start[len];
3329 j = tab->start[len + 1];
3330 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3331 i += code - tab->codes[i].code;
3332 return tab->codes[i].val;
3336 // not found
3337 error(getPos(), "Bad code (%04x) in flate stream", code);
3338 return EOF;
3341 int FlateStream::getCodeWord(int bits) {
3342 int c;
3344 while (codeSize < bits) {
3345 if ((c = str->getChar()) == EOF)
3346 return EOF;
3347 codeBuf |= (c & 0xff) << codeSize;
3348 codeSize += 8;
3350 c = codeBuf & ((1 << bits) - 1);
3351 codeBuf >>= bits;
3352 codeSize -= bits;
3353 return c;
3356 //------------------------------------------------------------------------
3357 // EOFStream
3358 //------------------------------------------------------------------------
3360 EOFStream::EOFStream(Stream *strA):
3361 FilterStream(strA) {
3364 EOFStream::~EOFStream() {
3365 delete str;
3368 //------------------------------------------------------------------------
3369 // FixedLengthEncoder
3370 //------------------------------------------------------------------------
3372 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3373 FilterStream(strA) {
3374 length = lengthA;
3375 count = 0;
3378 FixedLengthEncoder::~FixedLengthEncoder() {
3379 if (str->isEncoder())
3380 delete str;
3383 void FixedLengthEncoder::reset() {
3384 str->reset();
3385 count = 0;
3388 void FixedLengthEncoder::close() {
3391 int FixedLengthEncoder::getChar() {
3392 if (length >= 0 && count >= length)
3393 return EOF;
3394 ++count;
3395 return str->getChar();
3398 int FixedLengthEncoder::lookChar() {
3399 if (length >= 0 && count >= length)
3400 return EOF;
3401 return str->getChar();
3404 //------------------------------------------------------------------------
3405 // ASCIIHexEncoder
3406 //------------------------------------------------------------------------
3408 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3409 FilterStream(strA) {
3410 bufPtr = bufEnd = buf;
3411 lineLen = 0;
3412 eof = gFalse;
3415 ASCIIHexEncoder::~ASCIIHexEncoder() {
3416 if (str->isEncoder()) {
3417 delete str;
3421 void ASCIIHexEncoder::reset() {
3422 str->reset();
3423 bufPtr = bufEnd = buf;
3424 lineLen = 0;
3425 eof = gFalse;
3428 void ASCIIHexEncoder::close() {
3431 GBool ASCIIHexEncoder::fillBuf() {
3432 static char *hex = "0123456789abcdef";
3433 int c;
3435 if (eof) {
3436 return gFalse;
3438 bufPtr = bufEnd = buf;
3439 if ((c = str->getChar()) == EOF) {
3440 *bufEnd++ = '>';
3441 eof = gTrue;
3442 } else {
3443 if (lineLen >= 64) {
3444 *bufEnd++ = '\n';
3445 lineLen = 0;
3447 *bufEnd++ = hex[(c >> 4) & 0x0f];
3448 *bufEnd++ = hex[c & 0x0f];
3449 lineLen += 2;
3451 return gTrue;
3454 //------------------------------------------------------------------------
3455 // ASCII85Encoder
3456 //------------------------------------------------------------------------
3458 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3459 FilterStream(strA) {
3460 bufPtr = bufEnd = buf;
3461 lineLen = 0;
3462 eof = gFalse;
3465 ASCII85Encoder::~ASCII85Encoder() {
3466 if (str->isEncoder())
3467 delete str;
3470 void ASCII85Encoder::reset() {
3471 str->reset();
3472 bufPtr = bufEnd = buf;
3473 lineLen = 0;
3474 eof = gFalse;
3477 void ASCII85Encoder::close() {
3480 GBool ASCII85Encoder::fillBuf() {
3481 Gulong t;
3482 char buf1[5];
3483 int c;
3484 int n, i;
3486 if (eof)
3487 return gFalse;
3488 t = 0;
3489 for (n = 0; n < 4; ++n) {
3490 if ((c = str->getChar()) == EOF)
3491 break;
3492 t = (t << 8) + c;
3494 bufPtr = bufEnd = buf;
3495 if (n > 0) {
3496 if (n == 4 && t == 0) {
3497 *bufEnd++ = 'z';
3498 if (++lineLen == 65) {
3499 *bufEnd++ = '\n';
3500 lineLen = 0;
3502 } else {
3503 if (n < 4)
3504 t <<= 8 * (4 - n);
3505 for (i = 4; i >= 0; --i) {
3506 buf1[i] = (char)(t % 85 + 0x21);
3507 t /= 85;
3509 for (i = 0; i <= n; ++i) {
3510 *bufEnd++ = buf1[i];
3511 if (++lineLen == 65) {
3512 *bufEnd++ = '\n';
3513 lineLen = 0;
3518 if (n < 4) {
3519 *bufEnd++ = '~';
3520 *bufEnd++ = '>';
3521 eof = gTrue;
3523 return bufPtr < bufEnd;
3526 //------------------------------------------------------------------------
3527 // RunLengthEncoder
3528 //------------------------------------------------------------------------
3530 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3531 FilterStream(strA) {
3532 bufPtr = bufEnd = nextEnd = buf;
3533 eof = gFalse;
3536 RunLengthEncoder::~RunLengthEncoder() {
3537 if (str->isEncoder())
3538 delete str;
3541 void RunLengthEncoder::reset() {
3542 str->reset();
3543 bufPtr = bufEnd = nextEnd = buf;
3544 eof = gFalse;
3547 void RunLengthEncoder::close() {
3551 // When fillBuf finishes, buf[] looks like this:
3552 // +-----+--------------+-----------------+--
3553 // + tag | ... data ... | next 0, 1, or 2 |
3554 // +-----+--------------+-----------------+--
3555 // ^ ^ ^
3556 // bufPtr bufEnd nextEnd
3558 GBool RunLengthEncoder::fillBuf() {
3559 int c, c1, c2;
3560 int n;
3562 // already hit EOF?
3563 if (eof)
3564 return gFalse;
3566 // grab two bytes
3567 if (nextEnd < bufEnd + 1) {
3568 if ((c1 = str->getChar()) == EOF) {
3569 eof = gTrue;
3570 return gFalse;
3572 } else {
3573 c1 = bufEnd[0] & 0xff;
3575 if (nextEnd < bufEnd + 2) {
3576 if ((c2 = str->getChar()) == EOF) {
3577 eof = gTrue;
3578 buf[0] = 0;
3579 buf[1] = c1;
3580 bufPtr = buf;
3581 bufEnd = &buf[2];
3582 return gTrue;
3584 } else {
3585 c2 = bufEnd[1] & 0xff;
3588 // check for repeat
3589 c = 0; // make gcc happy
3590 if (c1 == c2) {
3591 n = 2;
3592 while (n < 128 && (c = str->getChar()) == c1)
3593 ++n;
3594 buf[0] = (char)(257 - n);
3595 buf[1] = c1;
3596 bufEnd = &buf[2];
3597 if (c == EOF) {
3598 eof = gTrue;
3599 } else if (n < 128) {
3600 buf[2] = c;
3601 nextEnd = &buf[3];
3602 } else {
3603 nextEnd = bufEnd;
3606 // get up to 128 chars
3607 } else {
3608 buf[1] = c1;
3609 buf[2] = c2;
3610 n = 2;
3611 while (n < 128) {
3612 if ((c = str->getChar()) == EOF) {
3613 eof = gTrue;
3614 break;
3616 ++n;
3617 buf[n] = c;
3618 if (buf[n] == buf[n-1])
3619 break;
3621 if (buf[n] == buf[n-1]) {
3622 buf[0] = (char)(n-2-1);
3623 bufEnd = &buf[n-1];
3624 nextEnd = &buf[n+1];
3625 } else {
3626 buf[0] = (char)(n-1);
3627 bufEnd = nextEnd = &buf[n+1];
3630 bufPtr = buf;
3631 return gTrue;