summaryrefslogtreecommitdiff
path: root/noncore/unsupported/qpdf/xpdf/Stream.cc
Unidiff
Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/Stream.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/unsupported/qpdf/xpdf/Stream.cc3467
1 files changed, 3467 insertions, 0 deletions
diff --git a/noncore/unsupported/qpdf/xpdf/Stream.cc b/noncore/unsupported/qpdf/xpdf/Stream.cc
new file mode 100644
index 0000000..18490d4
--- a/dev/null
+++ b/noncore/unsupported/qpdf/xpdf/Stream.cc
@@ -0,0 +1,3467 @@
1//========================================================================
2//
3// Stream.cc
4//
5// Copyright 1996 Derek B. Noonburg
6//
7//========================================================================
8
9#ifdef __GNUC__
10#pragma implementation
11#endif
12
13#include <aconf.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <stddef.h>
17#ifndef WIN32
18#include <unistd.h>
19#endif
20#include <string.h>
21#include <ctype.h>
22#include "gmem.h"
23#include "gfile.h"
24#include "config.h"
25#include "Error.h"
26#include "Object.h"
27#ifndef NO_DECRYPTION
28#include "Decrypt.h"
29#endif
30#include "Stream.h"
31#include "Stream-CCITT.h"
32
33#ifdef __DJGPP__
34static GBool setDJSYSFLAGS = gFalse;
35#endif
36
37#ifdef VMS
38#if (__VMS_VER < 70000000)
39extern "C" int unlink(char *filename);
40#endif
41#ifdef __GNUC__
42#define SEEK_SET 0
43#define SEEK_CUR 1
44#define SEEK_END 2
45#endif
46#endif
47
48#ifdef MACOS
49#include "StuffItEngineLib.h"
50#endif
51
52//------------------------------------------------------------------------
53// Stream (base class)
54//------------------------------------------------------------------------
55
56Stream::Stream() {
57 ref = 1;
58}
59
60Stream::~Stream() {
61}
62
63void Stream::close() {
64}
65
66int Stream::getRawChar() {
67 error(-1, "Internal: called getRawChar() on non-predictor stream");
68 return EOF;
69}
70
71char *Stream::getLine(char *buf, int size) {
72 int i;
73 int c;
74
75 if (lookChar() == EOF)
76 return NULL;
77 for (i = 0; i < size - 1; ++i) {
78 c = getChar();
79 if (c == EOF || c == '\n')
80 break;
81 if (c == '\r') {
82 if ((c = lookChar()) == '\n')
83 getChar();
84 break;
85 }
86 buf[i] = c;
87 }
88 buf[i] = '\0';
89 return buf;
90}
91
92GString *Stream::getPSFilter(char *indent) {
93 return new GString();
94}
95
96Stream *Stream::addFilters(Object *dict) {
97 Object obj, obj2;
98 Object params, params2;
99 Stream *str;
100 int i;
101
102 str = this;
103 dict->dictLookup("Filter", &obj);
104 if (obj.isNull()) {
105 obj.free();
106 dict->dictLookup("F", &obj);
107 }
108 dict->dictLookup("DecodeParms", &params);
109 if (params.isNull()) {
110 params.free();
111 dict->dictLookup("DP", &params);
112 }
113 if (obj.isName()) {
114 str = makeFilter(obj.getName(), str, &params);
115 } else if (obj.isArray()) {
116 for (i = 0; i < obj.arrayGetLength(); ++i) {
117 obj.arrayGet(i, &obj2);
118 if (params.isArray())
119 params.arrayGet(i, &params2);
120 else
121 params2.initNull();
122 if (obj2.isName()) {
123 str = makeFilter(obj2.getName(), str, &params2);
124 } else {
125 error(getPos(), "Bad filter name");
126 str = new EOFStream(str);
127 }
128 obj2.free();
129 params2.free();
130 }
131 } else if (!obj.isNull()) {
132 error(getPos(), "Bad 'Filter' attribute in stream");
133 }
134 obj.free();
135 params.free();
136
137 return str;
138}
139
140Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
141 int pred; // parameters
142 int colors;
143 int bits;
144 int early;
145 int encoding;
146 GBool endOfLine, byteAlign, endOfBlock, black;
147 int columns, rows;
148 Object obj;
149
150 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
151 str = new ASCIIHexStream(str);
152 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
153 str = new ASCII85Stream(str);
154 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
155 pred = 1;
156 columns = 1;
157 colors = 1;
158 bits = 8;
159 early = 1;
160 if (params->isDict()) {
161 params->dictLookup("Predictor", &obj);
162 if (obj.isInt())
163 pred = obj.getInt();
164 obj.free();
165 params->dictLookup("Columns", &obj);
166 if (obj.isInt())
167 columns = obj.getInt();
168 obj.free();
169 params->dictLookup("Colors", &obj);
170 if (obj.isInt())
171 colors = obj.getInt();
172 obj.free();
173 params->dictLookup("BitsPerComponent", &obj);
174 if (obj.isInt())
175 bits = obj.getInt();
176 obj.free();
177 params->dictLookup("EarlyChange", &obj);
178 if (obj.isInt())
179 early = obj.getInt();
180 obj.free();
181 }
182 str = new LZWStream(str, pred, columns, colors, bits, early);
183 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
184 str = new RunLengthStream(str);
185 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
186 encoding = 0;
187 endOfLine = gFalse;
188 byteAlign = gFalse;
189 columns = 1728;
190 rows = 0;
191 endOfBlock = gTrue;
192 black = gFalse;
193 if (params->isDict()) {
194 params->dictLookup("K", &obj);
195 if (obj.isInt()) {
196 encoding = obj.getInt();
197 }
198 obj.free();
199 params->dictLookup("EndOfLine", &obj);
200 if (obj.isBool()) {
201 endOfLine = obj.getBool();
202 }
203 obj.free();
204 params->dictLookup("EncodedByteAlign", &obj);
205 if (obj.isBool()) {
206 byteAlign = obj.getBool();
207 }
208 obj.free();
209 params->dictLookup("Columns", &obj);
210 if (obj.isInt()) {
211 columns = obj.getInt();
212 }
213 obj.free();
214 params->dictLookup("Rows", &obj);
215 if (obj.isInt()) {
216 rows = obj.getInt();
217 }
218 obj.free();
219 params->dictLookup("EndOfBlock", &obj);
220 if (obj.isBool()) {
221 endOfBlock = obj.getBool();
222 }
223 obj.free();
224 params->dictLookup("BlackIs1", &obj);
225 if (obj.isBool()) {
226 black = obj.getBool();
227 }
228 obj.free();
229 }
230 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
231 columns, rows, endOfBlock, black);
232 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
233 str = new DCTStream(str);
234 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
235 pred = 1;
236 columns = 1;
237 colors = 1;
238 bits = 8;
239 if (params->isDict()) {
240 params->dictLookup("Predictor", &obj);
241 if (obj.isInt())
242 pred = obj.getInt();
243 obj.free();
244 params->dictLookup("Columns", &obj);
245 if (obj.isInt())
246 columns = obj.getInt();
247 obj.free();
248 params->dictLookup("Colors", &obj);
249 if (obj.isInt())
250 colors = obj.getInt();
251 obj.free();
252 params->dictLookup("BitsPerComponent", &obj);
253 if (obj.isInt())
254 bits = obj.getInt();
255 obj.free();
256 }
257 str = new FlateStream(str, pred, columns, colors, bits);
258 } else {
259 error(getPos(), "Unknown filter '%s'", name);
260 str = new EOFStream(str);
261 }
262 return str;
263}
264
265//------------------------------------------------------------------------
266// BaseStream
267//------------------------------------------------------------------------
268
269BaseStream::BaseStream(Object *dictA) {
270 dict = *dictA;
271#ifndef NO_DECRYPTION
272 decrypt = NULL;
273#endif
274}
275
276BaseStream::~BaseStream() {
277 dict.free();
278#ifndef NO_DECRYPTION
279 if (decrypt)
280 delete decrypt;
281#endif
282}
283
284#ifndef NO_DECRYPTION
285void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
286 int objNum, int objGen) {
287 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
288}
289#endif
290
291//------------------------------------------------------------------------
292// FilterStream
293//------------------------------------------------------------------------
294
295FilterStream::FilterStream(Stream *strA) {
296 str = strA;
297}
298
299FilterStream::~FilterStream() {
300}
301
302void FilterStream::close() {
303 str->close();
304}
305
306void FilterStream::setPos(int pos) {
307 error(-1, "Internal: called setPos() on FilterStream");
308}
309
310//------------------------------------------------------------------------
311// ImageStream
312//------------------------------------------------------------------------
313
314ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
315 int imgLineSize;
316
317 str = strA;
318 width = widthA;
319 nComps = nCompsA;
320 nBits = nBitsA;
321
322 nVals = width * nComps;
323 if (nBits == 1) {
324 imgLineSize = (nVals + 7) & ~7;
325 } else {
326 imgLineSize = nVals;
327 }
328 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
329 imgIdx = nVals;
330}
331
332ImageStream::~ImageStream() {
333 gfree(imgLine);
334}
335
336void ImageStream::reset() {
337 str->reset();
338}
339
340GBool ImageStream::getPixel(Guchar *pix) {
341 Gulong buf, bitMask;
342 int bits;
343 int c;
344 int i;
345
346 if (imgIdx >= nVals) {
347
348 // read one line of image pixels
349 if (nBits == 1) {
350 for (i = 0; i < nVals; i += 8) {
351 c = str->getChar();
352 imgLine[i+0] = (Guchar)((c >> 7) & 1);
353 imgLine[i+1] = (Guchar)((c >> 6) & 1);
354 imgLine[i+2] = (Guchar)((c >> 5) & 1);
355 imgLine[i+3] = (Guchar)((c >> 4) & 1);
356 imgLine[i+4] = (Guchar)((c >> 3) & 1);
357 imgLine[i+5] = (Guchar)((c >> 2) & 1);
358 imgLine[i+6] = (Guchar)((c >> 1) & 1);
359 imgLine[i+7] = (Guchar)(c & 1);
360 }
361 } else if (nBits == 8) {
362 for (i = 0; i < nVals; ++i) {
363 imgLine[i] = str->getChar();
364 }
365 } else {
366 bitMask = (1 << nBits) - 1;
367 buf = 0;
368 bits = 0;
369 for (i = 0; i < nVals; ++i) {
370 if (bits < nBits) {
371 buf = (buf << 8) | (str->getChar() & 0xff);
372 bits += 8;
373 }
374 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
375 bits -= nBits;
376 }
377 }
378
379 // reset to start of line
380 imgIdx = 0;
381 }
382
383 for (i = 0; i < nComps; ++i)
384 pix[i] = imgLine[imgIdx++];
385 return gTrue;
386}
387
388void ImageStream::skipLine() {
389 int n, i;
390
391 n = (nVals * nBits + 7) >> 3;
392 for (i = 0; i < n; ++i) {
393 str->getChar();
394 }
395}
396
397//------------------------------------------------------------------------
398// StreamPredictor
399//------------------------------------------------------------------------
400
401StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
402 int widthA, int nCompsA, int nBitsA) {
403 str = strA;
404 predictor = predictorA;
405 width = widthA;
406 nComps = nCompsA;
407 nBits = nBitsA;
408
409 nVals = width * nComps;
410 pixBytes = (nComps * nBits + 7) >> 3;
411 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
412 predLine = (Guchar *)gmalloc(rowBytes);
413 memset(predLine, 0, rowBytes);
414 predIdx = rowBytes;
415}
416
417StreamPredictor::~StreamPredictor() {
418 gfree(predLine);
419}
420
421int StreamPredictor::lookChar() {
422 if (predIdx >= rowBytes) {
423 if (!getNextLine()) {
424 return EOF;
425 }
426 }
427 return predLine[predIdx];
428}
429
430int StreamPredictor::getChar() {
431 if (predIdx >= rowBytes) {
432 if (!getNextLine()) {
433 return EOF;
434 }
435 }
436 return predLine[predIdx++];
437}
438
439GBool StreamPredictor::getNextLine() {
440 int curPred;
441 Guchar upLeftBuf[4];
442 int left, up, upLeft, p, pa, pb, pc;
443 int c;
444 Gulong inBuf, outBuf, bitMask;
445 int inBits, outBits;
446 int i, j, k;
447
448 // get PNG optimum predictor number
449 if (predictor == 15) {
450 if ((curPred = str->getRawChar()) == EOF) {
451 return gFalse;
452 }
453 curPred += 10;
454 } else {
455 curPred = predictor;
456 }
457
458 // read the raw line, apply PNG (byte) predictor
459 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
460 for (i = pixBytes; i < rowBytes; ++i) {
461 upLeftBuf[3] = upLeftBuf[2];
462 upLeftBuf[2] = upLeftBuf[1];
463 upLeftBuf[1] = upLeftBuf[0];
464 upLeftBuf[0] = predLine[i];
465 if ((c = str->getRawChar()) == EOF) {
466 break;
467 }
468 switch (curPred) {
469 case 11: // PNG sub
470 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
471 break;
472 case 12: // PNG up
473 predLine[i] = predLine[i] + (Guchar)c;
474 break;
475 case 13: // PNG average
476 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
477 (Guchar)c;
478 break;
479 case 14: // PNG Paeth
480 left = predLine[i - pixBytes];
481 up = predLine[i];
482 upLeft = upLeftBuf[pixBytes];
483 p = left + up - upLeft;
484 if ((pa = p - left) < 0)
485 pa = -pa;
486 if ((pb = p - up) < 0)
487 pb = -pb;
488 if ((pc = p - upLeft) < 0)
489 pc = -pc;
490 if (pa <= pb && pa <= pc)
491 predLine[i] = left + (Guchar)c;
492 else if (pb <= pc)
493 predLine[i] = up + (Guchar)c;
494 else
495 predLine[i] = upLeft + (Guchar)c;
496 break;
497 case 10: // PNG none
498 default: // no predictor or TIFF predictor
499 predLine[i] = (Guchar)c;
500 break;
501 }
502 }
503
504 // apply TIFF (component) predictor
505 //~ this is completely untested
506 if (predictor == 2) {
507 if (nBits == 1) {
508 inBuf = predLine[pixBytes - 1];
509 for (i = pixBytes; i < rowBytes; i += 8) {
510 // 1-bit add is just xor
511 inBuf = (inBuf << 8) | predLine[i];
512 predLine[i] ^= inBuf >> nComps;
513 }
514 } else if (nBits == 8) {
515 for (i = pixBytes; i < rowBytes; ++i) {
516 predLine[i] += predLine[i - nComps];
517 }
518 } else {
519 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
520 bitMask = (1 << nBits) - 1;
521 inBuf = outBuf = 0;
522 inBits = outBits = 0;
523 j = k = pixBytes;
524 for (i = 0; i < nVals; ++i) {
525 if (inBits < nBits) {
526 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
527 inBits += 8;
528 }
529 upLeftBuf[3] = upLeftBuf[2];
530 upLeftBuf[2] = upLeftBuf[1];
531 upLeftBuf[1] = upLeftBuf[0];
532 upLeftBuf[0] = (upLeftBuf[nComps] +
533 (inBuf >> (inBits - nBits))) & bitMask;
534 outBuf = (outBuf << nBits) | upLeftBuf[0];
535 inBits -= nBits;
536 outBits += nBits;
537 if (outBits > 8) {
538 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
539 }
540 }
541 if (outBits > 0) {
542 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
543 }
544 }
545 }
546
547 // reset to start of line
548 predIdx = pixBytes;
549
550 return gTrue;
551}
552
553//------------------------------------------------------------------------
554// FileStream
555//------------------------------------------------------------------------
556
557FileStream::FileStream(FILE *fA, int startA, int lengthA, Object *dictA):
558 BaseStream(dictA) {
559 f = fA;
560 start = startA;
561 length = lengthA;
562 bufPtr = bufEnd = buf;
563 bufPos = start;
564 savePos = -1;
565}
566
567FileStream::~FileStream() {
568 close();
569}
570
571Stream *FileStream::makeSubStream(int startA, int lengthA, Object *dictA) {
572 return new FileStream(f, startA, lengthA, dictA);
573}
574
575void FileStream::reset() {
576 savePos = (int)ftell(f);
577 fseek(f, start, SEEK_SET);
578 bufPtr = bufEnd = buf;
579 bufPos = start;
580#ifndef NO_DECRYPTION
581 if (decrypt)
582 decrypt->reset();
583#endif
584}
585
586void FileStream::close() {
587 if (savePos >= 0) {
588 fseek(f, savePos, SEEK_SET);
589 savePos = -1;
590 }
591}
592
593GBool FileStream::fillBuf() {
594 int n;
595#ifndef NO_DECRYPTION
596 char *p;
597#endif
598
599 bufPos += bufEnd - buf;
600 bufPtr = bufEnd = buf;
601 if (length >= 0 && bufPos >= start + length) {
602 return gFalse;
603 }
604 if (length >= 0 && bufPos + fileStreamBufSize > start + length) {
605 n = start + length - bufPos;
606 } else {
607 n = fileStreamBufSize;
608 }
609 n = fread(buf, 1, n, f);
610 bufEnd = buf + n;
611 if (bufPtr >= bufEnd) {
612 return gFalse;
613 }
614#ifndef NO_DECRYPTION
615 if (decrypt) {
616 for (p = buf; p < bufEnd; ++p) {
617 *p = (char)decrypt->decryptByte((Guchar)*p);
618 }
619 }
620#endif
621 return gTrue;
622}
623
624void FileStream::setPos(int pos) {
625 long size;
626
627 if (pos >= 0) {
628 fseek(f, pos, SEEK_SET);
629 bufPos = pos;
630 } else {
631 fseek(f, 0, SEEK_END);
632 size = ftell(f);
633 if (pos < -size)
634 pos = (int)(-size);
635#ifdef __CYGWIN32__
636 //~ work around a bug in cygwin's implementation of fseek
637 rewind(f);
638#endif
639 fseek(f, pos, SEEK_END);
640 bufPos = (int)ftell(f);
641 }
642 bufPtr = bufEnd = buf;
643}
644
645void FileStream::moveStart(int delta) {
646 start += delta;
647 bufPtr = bufEnd = buf;
648 bufPos = start;
649}
650
651//------------------------------------------------------------------------
652// EmbedStream
653//------------------------------------------------------------------------
654
655EmbedStream::EmbedStream(Stream *strA, Object *dictA):
656 BaseStream(dictA) {
657 str = strA;
658}
659
660EmbedStream::~EmbedStream() {
661}
662
663Stream *EmbedStream::makeSubStream(int start, int length, Object *dictA) {
664 error(-1, "Internal: called makeSubStream() on EmbedStream");
665 return NULL;
666}
667
668void EmbedStream::setPos(int pos) {
669 error(-1, "Internal: called setPos() on EmbedStream");
670}
671
672int EmbedStream::getStart() {
673 error(-1, "Internal: called getStart() on EmbedStream");
674 return 0;
675}
676
677void EmbedStream::moveStart(int start) {
678 error(-1, "Internal: called moveStart() on EmbedStream");
679}
680
681//------------------------------------------------------------------------
682// ASCIIHexStream
683//------------------------------------------------------------------------
684
685ASCIIHexStream::ASCIIHexStream(Stream *strA):
686 FilterStream(strA) {
687 buf = EOF;
688 eof = gFalse;
689}
690
691ASCIIHexStream::~ASCIIHexStream() {
692 delete str;
693}
694
695void ASCIIHexStream::reset() {
696 str->reset();
697 buf = EOF;
698 eof = gFalse;
699}
700
701int ASCIIHexStream::lookChar() {
702 int c1, c2, x;
703
704 if (buf != EOF)
705 return buf;
706 if (eof) {
707 buf = EOF;
708 return EOF;
709 }
710 do {
711 c1 = str->getChar();
712 } while (isspace(c1));
713 if (c1 == '>') {
714 eof = gTrue;
715 buf = EOF;
716 return buf;
717 }
718 do {
719 c2 = str->getChar();
720 } while (isspace(c2));
721 if (c2 == '>') {
722 eof = gTrue;
723 c2 = '0';
724 }
725 if (c1 >= '0' && c1 <= '9') {
726 x = (c1 - '0') << 4;
727 } else if (c1 >= 'A' && c1 <= 'F') {
728 x = (c1 - 'A' + 10) << 4;
729 } else if (c1 >= 'a' && c1 <= 'f') {
730 x = (c1 - 'a' + 10) << 4;
731 } else if (c1 == EOF) {
732 eof = gTrue;
733 x = 0;
734 } else {
735 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
736 x = 0;
737 }
738 if (c2 >= '0' && c2 <= '9') {
739 x += c2 - '0';
740 } else if (c2 >= 'A' && c2 <= 'F') {
741 x += c2 - 'A' + 10;
742 } else if (c2 >= 'a' && c2 <= 'f') {
743 x += c2 - 'a' + 10;
744 } else if (c2 == EOF) {
745 eof = gTrue;
746 x = 0;
747 } else {
748 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
749 }
750 buf = x & 0xff;
751 return buf;
752}
753
754GString *ASCIIHexStream::getPSFilter(char *indent) {
755 GString *s;
756
757 if (!(s = str->getPSFilter(indent))) {
758 return NULL;
759 }
760 s->append(indent)->append("/ASCIIHexDecode filter\n");
761 return s;
762}
763
764GBool ASCIIHexStream::isBinary(GBool last) {
765 return str->isBinary(gFalse);
766}
767
768//------------------------------------------------------------------------
769// ASCII85Stream
770//------------------------------------------------------------------------
771
772ASCII85Stream::ASCII85Stream(Stream *strA):
773 FilterStream(strA) {
774 index = n = 0;
775 eof = gFalse;
776}
777
778ASCII85Stream::~ASCII85Stream() {
779 delete str;
780}
781
782void ASCII85Stream::reset() {
783 str->reset();
784 index = n = 0;
785 eof = gFalse;
786}
787
788int ASCII85Stream::lookChar() {
789 int k;
790 Gulong t;
791
792 if (index >= n) {
793 if (eof)
794 return EOF;
795 index = 0;
796 do {
797 c[0] = str->getChar();
798 } while (c[0] == '\n' || c[0] == '\r');
799 if (c[0] == '~' || c[0] == EOF) {
800 eof = gTrue;
801 n = 0;
802 return EOF;
803 } else if (c[0] == 'z') {
804 b[0] = b[1] = b[2] = b[3] = 0;
805 n = 4;
806 } else {
807 for (k = 1; k < 5; ++k) {
808 do {
809 c[k] = str->getChar();
810 } while (c[k] == '\n' || c[k] == '\r');
811 if (c[k] == '~' || c[k] == EOF)
812 break;
813 }
814 n = k - 1;
815 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
816 for (++k; k < 5; ++k)
817 c[k] = 0x21 + 84;
818 eof = gTrue;
819 }
820 t = 0;
821 for (k = 0; k < 5; ++k)
822 t = t * 85 + (c[k] - 0x21);
823 for (k = 3; k >= 0; --k) {
824 b[k] = (int)(t & 0xff);
825 t >>= 8;
826 }
827 }
828 }
829 return b[index];
830}
831
832GString *ASCII85Stream::getPSFilter(char *indent) {
833 GString *s;
834
835 if (!(s = str->getPSFilter(indent))) {
836 return NULL;
837 }
838 s->append(indent)->append("/ASCII85Decode filter\n");
839 return s;
840}
841
842GBool ASCII85Stream::isBinary(GBool last) {
843 return str->isBinary(gFalse);
844}
845
846//------------------------------------------------------------------------
847// LZWStream
848//------------------------------------------------------------------------
849
850LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
851 int bits, int earlyA):
852 FilterStream(strA) {
853 if (predictor != 1) {
854 pred = new StreamPredictor(this, predictor, columns, colors, bits);
855 } else {
856 pred = NULL;
857 }
858 early = earlyA;
859 zPipe = NULL;
860 bufPtr = bufEnd = buf;
861}
862
863LZWStream::~LZWStream() {
864 if (zPipe) {
865#ifdef HAVE_POPEN
866 pclose(zPipe);
867#else
868 fclose(zPipe);
869#endif
870 zPipe = NULL;
871 unlink(zName->getCString());
872 delete zName;
873 }
874 if (pred) {
875 delete pred;
876 }
877 delete str;
878}
879
880int LZWStream::getChar() {
881 if (pred) {
882 return pred->getChar();
883 }
884 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
885}
886
887int LZWStream::lookChar() {
888 if (pred) {
889 return pred->lookChar();
890 }
891 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
892}
893
894int LZWStream::getRawChar() {
895 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
896}
897
898void LZWStream::reset() {
899 FILE *f;
900 GString *zCmd;
901
902 //----- close old LZW stream
903 if (zPipe) {
904#ifdef HAVE_POPEN
905 pclose(zPipe);
906#else
907 fclose(zPipe);
908#endif
909 zPipe = NULL;
910 unlink(zName->getCString());
911 delete zName;
912 }
913
914 //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
915 // to run gzip
916#if __DJGPP__
917 if (!setDJSYSFLAGS) {
918 setenv("DJSYSFLAGS", "0x0002", 0);
919 setDJSYSFLAGS = gTrue;
920 }
921#endif
922
923 //----- create the .Z file
924 if (!openTempFile(&zName, &f, "wb", ".Z")) {
925 error(getPos(), "Couldn't create temporary file for LZW stream");
926 return;
927 }
928 dumpFile(f);
929 fclose(f);
930
931 //----- execute uncompress / gzip
932 zCmd = new GString(uncompressCmd);
933 zCmd->append(' ');
934 zCmd->append(zName);
935#if defined(MACOS)
936 long magicCookie;
937 // first we open the engine up
938 OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
939 // if we found it - let's use it!
940 if (!err && magicCookie) {
941 // make sure we have the correct version of the Engine
942 if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
943 FSSpec myFSS;
944 Str255 pName;
945 strcpy((char *)pName, zName->getCString());
946 c2pstr((char *)pName);
947 FSMakeFSSpec(0, 0, pName, &myFSS);
948 short ftype = DetermineFileType(magicCookie, &myFSS);
949 OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
950 NULL, NULL, kCreateFolderNever,
951 kDeleteOriginal, kTextConvertSmart);
952 }
953 }
954#elif defined(HAVE_POPEN)
955 if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
956 error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
957 unlink(zName->getCString());
958 delete zName;
959 return;
960 }
961#else // HAVE_POPEN
962#ifdef VMS
963 if (!system(zCmd->getCString())) {
964#else
965 if (system(zCmd->getCString())) {
966#endif
967 error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
968 unlink(zName->getCString());
969 delete zName;
970 return;
971 }
972 zName->del(zName->getLength() - 2, 2);
973 if (!(zPipe = fopen(zName->getCString(), "rb"))) {
974 error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
975 unlink(zName->getCString());
976 delete zName;
977 return;
978 }
979#endif // HAVE_POPEN
980
981 //----- clean up
982 delete zCmd;
983
984 //----- initialize buffer
985 bufPtr = bufEnd = buf;
986}
987
988void LZWStream::dumpFile(FILE *f) {
989 int outCodeBits; // size of output code
990 int outBits; // max output code
991 int outBuf[8]; // output buffer
992 int outData; // temporary output buffer
993 int inCode, outCode; // input and output codes
994 int nextCode; // next code index
995 GBool eof; // set when EOF is reached
996 GBool clear; // set if table needs to be cleared
997 GBool first; // indicates first code word after clear
998 int i, j;
999
1000 str->reset();
1001
1002 // magic number
1003 fputc(0x1f, f);
1004 fputc(0x9d, f);
1005
1006 // max code length, block mode flag
1007 fputc(0x8c, f);
1008
1009 // init input side
1010 inCodeBits = 9;
1011 inputBuf = 0;
1012 inputBits = 0;
1013 eof = gFalse;
1014
1015 // init output side
1016 outCodeBits = 9;
1017
1018 // clear table
1019 first = gTrue;
1020 nextCode = 258;
1021
1022 clear = gFalse;
1023 do {
1024 for (i = 0; i < 8; ++i) {
1025 // check for table overflow
1026 if (nextCode + early > 0x1001) {
1027 inCode = 256;
1028
1029 // read input code
1030 } else {
1031 do {
1032 inCode = getCode();
1033 if (inCode == EOF) {
1034 eof = gTrue;
1035 inCode = 0;
1036 }
1037 } while (first && inCode == 256);
1038 }
1039
1040 // compute output code
1041 if (inCode < 256) {
1042 outCode = inCode;
1043 } else if (inCode == 256) {
1044 outCode = 256;
1045 clear = gTrue;
1046 } else if (inCode == 257) {
1047 outCode = 0;
1048 eof = gTrue;
1049 } else {
1050 outCode = inCode - 1;
1051 }
1052 outBuf[i] = outCode;
1053
1054 // next code index
1055 if (first)
1056 first = gFalse;
1057 else
1058 ++nextCode;
1059
1060 // check input code size
1061 if (nextCode + early == 0x200)
1062 inCodeBits = 10;
1063 else if (nextCode + early == 0x400) {
1064 inCodeBits = 11;
1065 } else if (nextCode + early == 0x800) {
1066 inCodeBits = 12;
1067 }
1068
1069 // check for eof/clear
1070 if (eof)
1071 break;
1072 if (clear) {
1073 i = 8;
1074 break;
1075 }
1076 }
1077
1078 // write output block
1079 outData = 0;
1080 outBits = 0;
1081 j = 0;
1082 while (j < i || outBits > 0) {
1083 if (outBits < 8 && j < i) {
1084 outData = outData | (outBuf[j++] << outBits);
1085 outBits += outCodeBits;
1086 }
1087 fputc(outData & 0xff, f);
1088 outData >>= 8;
1089 outBits -= 8;
1090 }
1091
1092 // check output code size
1093 if (nextCode - 1 == 512 ||
1094 nextCode - 1 == 1024 ||
1095 nextCode - 1 == 2048 ||
1096 nextCode - 1 == 4096) {
1097 outCodeBits = inCodeBits;
1098 }
1099
1100 // clear table if necessary
1101 if (clear) {
1102 inCodeBits = 9;
1103 outCodeBits = 9;
1104 first = gTrue;
1105 nextCode = 258;
1106 clear = gFalse;
1107 }
1108 } while (!eof);
1109}
1110
1111int LZWStream::getCode() {
1112 int c;
1113 int code;
1114
1115 while (inputBits < inCodeBits) {
1116 if ((c = str->getChar()) == EOF)
1117 return EOF;
1118 inputBuf = (inputBuf << 8) | (c & 0xff);
1119 inputBits += 8;
1120 }
1121 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1122 inputBits -= inCodeBits;
1123 return code;
1124}
1125
1126GBool LZWStream::fillBuf() {
1127 int n;
1128
1129 if (!zPipe)
1130 return gFalse;
1131 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1132#ifdef HAVE_POPEN
1133 pclose(zPipe);
1134#else
1135 fclose(zPipe);
1136#endif
1137 zPipe = NULL;
1138 unlink(zName->getCString());
1139 delete zName;
1140 }
1141 bufPtr = buf;
1142 bufEnd = buf + n;
1143 return n > 0;
1144}
1145
1146GString *LZWStream::getPSFilter(char *indent) {
1147 GString *s;
1148
1149 if (pred) {
1150 return NULL;
1151 }
1152 if (!(s = str->getPSFilter(indent))) {
1153 return NULL;
1154 }
1155 s->append(indent)->append("/LZWDecode filter\n");
1156 return s;
1157}
1158
1159GBool LZWStream::isBinary(GBool last) {
1160 return str->isBinary(gTrue);
1161}
1162
1163//------------------------------------------------------------------------
1164// RunLengthStream
1165//------------------------------------------------------------------------
1166
1167RunLengthStream::RunLengthStream(Stream *strA):
1168 FilterStream(strA) {
1169 bufPtr = bufEnd = buf;
1170 eof = gFalse;
1171}
1172
1173RunLengthStream::~RunLengthStream() {
1174 delete str;
1175}
1176
1177void RunLengthStream::reset() {
1178 str->reset();
1179 bufPtr = bufEnd = buf;
1180 eof = gFalse;
1181}
1182
1183GString *RunLengthStream::getPSFilter(char *indent) {
1184 GString *s;
1185
1186 if (!(s = str->getPSFilter(indent))) {
1187 return NULL;
1188 }
1189 s->append(indent)->append("/RunLengthDecode filter\n");
1190 return s;
1191}
1192
1193GBool RunLengthStream::isBinary(GBool last) {
1194 return str->isBinary(gTrue);
1195}
1196
1197GBool RunLengthStream::fillBuf() {
1198 int c;
1199 int n, i;
1200
1201 if (eof)
1202 return gFalse;
1203 c = str->getChar();
1204 if (c == 0x80 || c == EOF) {
1205 eof = gTrue;
1206 return gFalse;
1207 }
1208 if (c < 0x80) {
1209 n = c + 1;
1210 for (i = 0; i < n; ++i)
1211 buf[i] = (char)str->getChar();
1212 } else {
1213 n = 0x101 - c;
1214 c = str->getChar();
1215 for (i = 0; i < n; ++i)
1216 buf[i] = (char)c;
1217 }
1218 bufPtr = buf;
1219 bufEnd = buf + n;
1220 return gTrue;
1221}
1222
1223//------------------------------------------------------------------------
1224// CCITTFaxStream
1225//------------------------------------------------------------------------
1226
1227CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1228 GBool byteAlignA, int columnsA, int rowsA,
1229 GBool endOfBlockA, GBool blackA):
1230 FilterStream(strA) {
1231 encoding = encodingA;
1232 endOfLine = endOfLineA;
1233 byteAlign = byteAlignA;
1234 columns = columnsA;
1235 rows = rowsA;
1236 endOfBlock = endOfBlockA;
1237 black = blackA;
1238 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1239 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1240
1241 eof = gFalse;
1242 row = 0;
1243 nextLine2D = encoding < 0;
1244 inputBits = 0;
1245 codingLine[0] = 0;
1246 codingLine[1] = refLine[2] = columns;
1247 a0 = 1;
1248
1249 buf = EOF;
1250}
1251
1252CCITTFaxStream::~CCITTFaxStream() {
1253 delete str;
1254 gfree(refLine);
1255 gfree(codingLine);
1256}
1257
1258void CCITTFaxStream::reset() {
1259 int n;
1260
1261 str->reset();
1262 eof = gFalse;
1263 row = 0;
1264 nextLine2D = encoding < 0;
1265 inputBits = 0;
1266 codingLine[0] = 0;
1267 codingLine[1] = refLine[2] = columns;
1268 a0 = 1;
1269 buf = EOF;
1270
1271 // get initial end-of-line marker and 2D encoding tag
1272 if (endOfBlock) {
1273 if (lookBits(12) == 0x001) {
1274 eatBits(12);
1275 }
1276 } else {
1277 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1278 if (n == 11 && lookBits(12) == 0x001) {
1279 eatBits(12);
1280 }
1281 }
1282 if (encoding > 0) {
1283 nextLine2D = !lookBits(1);
1284 eatBits(1);
1285 }
1286}
1287
1288int CCITTFaxStream::lookChar() {
1289 short code1, code2, code3;
1290 int a0New;
1291#if 0
1292 GBool err;
1293#endif
1294 GBool gotEOL;
1295 int ret;
1296 int bits, i;
1297
1298 // if at eof just return EOF
1299 if (eof && codingLine[a0] >= columns) {
1300 return EOF;
1301 }
1302
1303 // read the next row
1304#if 0
1305 err = gFalse;
1306#endif
1307 if (codingLine[a0] >= columns) {
1308
1309 // 2-D encoding
1310 if (nextLine2D) {
1311 for (i = 0; codingLine[i] < columns; ++i)
1312 refLine[i] = codingLine[i];
1313 refLine[i] = refLine[i + 1] = columns;
1314 b1 = 1;
1315 a0New = codingLine[a0 = 0] = 0;
1316 do {
1317 code1 = getTwoDimCode();
1318 switch (code1) {
1319 case twoDimPass:
1320 if (refLine[b1] < columns) {
1321 a0New = refLine[b1 + 1];
1322 b1 += 2;
1323 }
1324 break;
1325 case twoDimHoriz:
1326 if ((a0 & 1) == 0) {
1327 code1 = code2 = 0;
1328 do {
1329 code1 += code3 = getWhiteCode();
1330 } while (code3 >= 64);
1331 do {
1332 code2 += code3 = getBlackCode();
1333 } while (code3 >= 64);
1334 } else {
1335 code1 = code2 = 0;
1336 do {
1337 code1 += code3 = getBlackCode();
1338 } while (code3 >= 64);
1339 do {
1340 code2 += code3 = getWhiteCode();
1341 } while (code3 >= 64);
1342 }
1343 codingLine[a0 + 1] = a0New + code1;
1344 ++a0;
1345 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1346 ++a0;
1347 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1348 b1 += 2;
1349 break;
1350 case twoDimVert0:
1351 a0New = codingLine[++a0] = refLine[b1];
1352 if (refLine[b1] < columns) {
1353 ++b1;
1354 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1355 b1 += 2;
1356 }
1357 break;
1358 case twoDimVertR1:
1359 a0New = codingLine[++a0] = refLine[b1] + 1;
1360 if (refLine[b1] < columns) {
1361 ++b1;
1362 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1363 b1 += 2;
1364 }
1365 break;
1366 case twoDimVertL1:
1367 a0New = codingLine[++a0] = refLine[b1] - 1;
1368 --b1;
1369 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1370 b1 += 2;
1371 break;
1372 case twoDimVertR2:
1373 a0New = codingLine[++a0] = refLine[b1] + 2;
1374 if (refLine[b1] < columns) {
1375 ++b1;
1376 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1377 b1 += 2;
1378 }
1379 break;
1380 case twoDimVertL2:
1381 a0New = codingLine[++a0] = refLine[b1] - 2;
1382 --b1;
1383 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1384 b1 += 2;
1385 break;
1386 case twoDimVertR3:
1387 a0New = codingLine[++a0] = refLine[b1] + 3;
1388 if (refLine[b1] < columns) {
1389 ++b1;
1390 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1391 b1 += 2;
1392 }
1393 break;
1394 case twoDimVertL3:
1395 a0New = codingLine[++a0] = refLine[b1] - 3;
1396 --b1;
1397 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1398 b1 += 2;
1399 break;
1400 case EOF:
1401 eof = gTrue;
1402 codingLine[a0 = 0] = columns;
1403 return EOF;
1404 default:
1405 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1406#if 0
1407 err = gTrue;
1408 break;
1409#else
1410 eof = gTrue;
1411 return EOF;
1412#endif
1413 }
1414 } while (codingLine[a0] < columns);
1415
1416 // 1-D encoding
1417 } else {
1418 codingLine[a0 = 0] = 0;
1419 while (1) {
1420 code1 = 0;
1421 do {
1422 code1 += code3 = getWhiteCode();
1423 } while (code3 >= 64);
1424 codingLine[a0+1] = codingLine[a0] + code1;
1425 ++a0;
1426 if (codingLine[a0] >= columns)
1427 break;
1428 code2 = 0;
1429 do {
1430 code2 += code3 = getBlackCode();
1431 } while (code3 >= 64);
1432 codingLine[a0+1] = codingLine[a0] + code2;
1433 ++a0;
1434 if (codingLine[a0] >= columns)
1435 break;
1436 }
1437 }
1438
1439 if (codingLine[a0] != columns) {
1440 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1441#if 0
1442 err = gTrue;
1443#endif
1444 }
1445
1446 // byte-align the row
1447 if (byteAlign) {
1448 inputBits &= ~7;
1449 }
1450
1451 // check for end-of-line marker, skipping over any extra zero bits
1452 gotEOL = gFalse;
1453 if (!endOfBlock && row == rows - 1) {
1454 eof = gTrue;
1455 } else {
1456 code1 = lookBits(12);
1457 while (code1 == 0) {
1458 eatBits(1);
1459 code1 = lookBits(12);
1460 }
1461 if (code1 == 0x001) {
1462 eatBits(12);
1463 gotEOL = gTrue;
1464 } else if (code1 == EOF) {
1465 eof = gTrue;
1466 }
1467 }
1468
1469 // get 2D encoding tag
1470 if (!eof && encoding > 0) {
1471 nextLine2D = !lookBits(1);
1472 eatBits(1);
1473 }
1474
1475 // check for end-of-block marker
1476 if (endOfBlock && gotEOL) {
1477 code1 = lookBits(12);
1478 if (code1 == 0x001) {
1479 eatBits(12);
1480 if (encoding > 0) {
1481 lookBits(1);
1482 eatBits(1);
1483 }
1484 if (encoding >= 0) {
1485 for (i = 0; i < 4; ++i) {
1486 code1 = lookBits(12);
1487 if (code1 != 0x001) {
1488 error(getPos(), "Bad RTC code in CCITTFax stream");
1489 }
1490 eatBits(12);
1491 if (encoding > 0) {
1492 lookBits(1);
1493 eatBits(1);
1494 }
1495 }
1496 }
1497 eof = gTrue;
1498 }
1499 }
1500
1501#if 0
1502 // This looks for an end-of-line marker after an error, however
1503 // some (most?) CCITT streams in PDF files don't use end-of-line
1504 // markers, and the just-plow-on technique works better in those
1505 // cases.
1506 else if (err) {
1507 do {
1508 if (code1 == EOF) {
1509 eof = gTrue;
1510 return EOF;
1511 }
1512 eatBits(1);
1513 code1 = look13Bits();
1514 } while ((code1 >> 1) != 0x001);
1515 eatBits(12);
1516 codingLine[++a0] = columns;
1517 if (encoding > 0) {
1518 eatBits(1);
1519 nextLine2D = !(code1 & 1);
1520 }
1521 }
1522#endif
1523
1524 a0 = 0;
1525 outputBits = codingLine[1] - codingLine[0];
1526 if (outputBits == 0) {
1527 a0 = 1;
1528 outputBits = codingLine[2] - codingLine[1];
1529 }
1530
1531 ++row;
1532 }
1533
1534 // get a byte
1535 if (outputBits >= 8) {
1536 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1537 if ((outputBits -= 8) == 0) {
1538 ++a0;
1539 if (codingLine[a0] < columns) {
1540 outputBits = codingLine[a0 + 1] - codingLine[a0];
1541 }
1542 }
1543 } else {
1544 bits = 8;
1545 ret = 0;
1546 do {
1547 if (outputBits > bits) {
1548 i = bits;
1549 bits = 0;
1550 if ((a0 & 1) == 0) {
1551 ret |= 0xff >> (8 - i);
1552 }
1553 outputBits -= i;
1554 } else {
1555 i = outputBits;
1556 bits -= outputBits;
1557 if ((a0 & 1) == 0) {
1558 ret |= (0xff >> (8 - i)) << bits;
1559 }
1560 outputBits = 0;
1561 ++a0;
1562 if (codingLine[a0] < columns) {
1563 outputBits = codingLine[a0 + 1] - codingLine[a0];
1564 }
1565 }
1566 } while (bits > 0 && codingLine[a0] < columns);
1567 }
1568 buf = black ? (ret ^ 0xff) : ret;
1569 return buf;
1570}
1571
1572short CCITTFaxStream::getTwoDimCode() {
1573 short code;
1574 CCITTCode *p;
1575 int n;
1576
1577 code = 0; // make gcc happy
1578 if (endOfBlock) {
1579 code = lookBits(7);
1580 p = &twoDimTab1[code];
1581 if (p->bits > 0) {
1582 eatBits(p->bits);
1583 return p->n;
1584 }
1585 } else {
1586 for (n = 1; n <= 7; ++n) {
1587 code = lookBits(n);
1588 if (n < 7) {
1589 code <<= 7 - n;
1590 }
1591 p = &twoDimTab1[code];
1592 if (p->bits == n) {
1593 eatBits(n);
1594 return p->n;
1595 }
1596 }
1597 }
1598 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1599 return EOF;
1600}
1601
1602short CCITTFaxStream::getWhiteCode() {
1603 short code;
1604 CCITTCode *p;
1605 int n;
1606
1607 code = 0; // make gcc happy
1608 if (endOfBlock) {
1609 code = lookBits(12);
1610 if ((code >> 5) == 0) {
1611 p = &whiteTab1[code];
1612 } else {
1613 p = &whiteTab2[code >> 3];
1614 }
1615 if (p->bits > 0) {
1616 eatBits(p->bits);
1617 return p->n;
1618 }
1619 } else {
1620 for (n = 1; n <= 9; ++n) {
1621 code = lookBits(n);
1622 if (n < 9) {
1623 code <<= 9 - n;
1624 }
1625 p = &whiteTab2[code];
1626 if (p->bits == n) {
1627 eatBits(n);
1628 return p->n;
1629 }
1630 }
1631 for (n = 11; n <= 12; ++n) {
1632 code = lookBits(n);
1633 if (n < 12) {
1634 code <<= 12 - n;
1635 }
1636 p = &whiteTab1[code];
1637 if (p->bits == n) {
1638 eatBits(n);
1639 return p->n;
1640 }
1641 }
1642 }
1643 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1644 // eat a bit and return a positive number so that the caller doesn't
1645 // go into an infinite loop
1646 eatBits(1);
1647 return 1;
1648}
1649
1650short CCITTFaxStream::getBlackCode() {
1651 short code;
1652 CCITTCode *p;
1653 int n;
1654
1655 code = 0; // make gcc happy
1656 if (endOfBlock) {
1657 code = lookBits(13);
1658 if ((code >> 7) == 0) {
1659 p = &blackTab1[code];
1660 } else if ((code >> 9) == 0) {
1661 p = &blackTab2[(code >> 1) - 64];
1662 } else {
1663 p = &blackTab3[code >> 7];
1664 }
1665 if (p->bits > 0) {
1666 eatBits(p->bits);
1667 return p->n;
1668 }
1669 } else {
1670 for (n = 2; n <= 6; ++n) {
1671 code = lookBits(n);
1672 if (n < 6) {
1673 code <<= 6 - n;
1674 }
1675 p = &blackTab3[code];
1676 if (p->bits == n) {
1677 eatBits(n);
1678 return p->n;
1679 }
1680 }
1681 for (n = 7; n <= 12; ++n) {
1682 code = lookBits(n);
1683 if (n < 12) {
1684 code <<= 12 - n;
1685 }
1686 if (code >= 64) {
1687 p = &blackTab2[code - 64];
1688 if (p->bits == n) {
1689 eatBits(n);
1690 return p->n;
1691 }
1692 }
1693 }
1694 for (n = 10; n <= 13; ++n) {
1695 code = lookBits(n);
1696 if (n < 13) {
1697 code <<= 13 - n;
1698 }
1699 p = &blackTab1[code];
1700 if (p->bits == n) {
1701 eatBits(n);
1702 return p->n;
1703 }
1704 }
1705 }
1706 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1707 // eat a bit and return a positive number so that the caller doesn't
1708 // go into an infinite loop
1709 eatBits(1);
1710 return 1;
1711}
1712
1713short CCITTFaxStream::lookBits(int n) {
1714 int c;
1715
1716 while (inputBits < n) {
1717 if ((c = str->getChar()) == EOF) {
1718 if (inputBits == 0) {
1719 return EOF;
1720 }
1721 // near the end of the stream, the caller may ask for more bits
1722 // than are available, but there may still be a valid code in
1723 // however many bits are available -- we need to return correct
1724 // data in this case
1725 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1726 }
1727 inputBuf = (inputBuf << 8) + c;
1728 inputBits += 8;
1729 }
1730 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1731}
1732
1733GString *CCITTFaxStream::getPSFilter(char *indent) {
1734 GString *s;
1735 char s1[50];
1736
1737 if (!(s = str->getPSFilter(indent))) {
1738 return NULL;
1739 }
1740 s->append(indent)->append("<< ");
1741 if (encoding != 0) {
1742 sprintf(s1, "/K %d ", encoding);
1743 s->append(s1);
1744 }
1745 if (endOfLine) {
1746 s->append("/EndOfLine true ");
1747 }
1748 if (byteAlign) {
1749 s->append("/EncodedByteAlign true ");
1750 }
1751 sprintf(s1, "/Columns %d ", columns);
1752 s->append(s1);
1753 if (rows != 0) {
1754 sprintf(s1, "/Rows %d ", rows);
1755 s->append(s1);
1756 }
1757 if (!endOfBlock) {
1758 s->append("/EndOfBlock false ");
1759 }
1760 if (black) {
1761 s->append("/BlackIs1 true ");
1762 }
1763 s->append(">> /CCITTFaxDecode filter\n");
1764 return s;
1765}
1766
1767GBool CCITTFaxStream::isBinary(GBool last) {
1768 return str->isBinary(gTrue);
1769}
1770
1771//------------------------------------------------------------------------
1772// DCTStream
1773//------------------------------------------------------------------------
1774
1775// IDCT constants (20.12 fixed point format)
1776#ifndef FP_IDCT
1777 #define dctCos1 4017 // cos(pi/16)
1778 #define dctSin1 799 // sin(pi/16)
1779 #define dctCos3 3406 // cos(3*pi/16)
1780 #define dctSin3 2276 // sin(3*pi/16)
1781 #define dctCos6 1567 // cos(6*pi/16)
1782 #define dctSin6 3784 // sin(6*pi/16)
1783 #define dctSqrt2 5793 // sqrt(2)
1784 #define dctSqrt1d2 2896 // sqrt(2) / 2
1785#endif
1786
1787// IDCT constants
1788#ifdef FP_IDCT
1789 #define dctCos1 0.98078528// cos(pi/16)
1790 #define dctSin1 0.19509032// sin(pi/16)
1791 #define dctCos3 0.83146961// cos(3*pi/16)
1792 #define dctSin3 0.55557023// sin(3*pi/16)
1793 #define dctCos6 0.38268343// cos(6*pi/16)
1794 #define dctSin6 0.92387953// sin(6*pi/16)
1795 #define dctSqrt2 1.41421356// sqrt(2)
1796 #define dctSqrt1d2 0.70710678// sqrt(2) / 2
1797#endif
1798
1799// color conversion parameters (16.16 fixed point format)
1800 #define dctCrToR 91881// 1.4020
1801 #define dctCbToG -22553// -0.3441363
1802 #define dctCrToG -46802// -0.71413636
1803 #define dctCbToB 116130// 1.772
1804
1805// clip [-256,511] --> [0,255]
1806#define dctClipOffset 256
1807static Guchar dctClip[768];
1808static int dctClipInit = 0;
1809
1810// zig zag decode map
1811static int dctZigZag[64] = {
1812 0,
1813 1, 8,
1814 16, 9, 2,
1815 3, 10, 17, 24,
1816 32, 25, 18, 11, 4,
1817 5, 12, 19, 26, 33, 40,
1818 48, 41, 34, 27, 20, 13, 6,
1819 7, 14, 21, 28, 35, 42, 49, 56,
1820 57, 50, 43, 36, 29, 22, 15,
1821 23, 30, 37, 44, 51, 58,
1822 59, 52, 45, 38, 31,
1823 39, 46, 53, 60,
1824 61, 54, 47,
1825 55, 62,
1826 63
1827};
1828
1829DCTStream::DCTStream(Stream *strA):
1830 FilterStream(strA) {
1831 int i, j;
1832
1833 width = height = 0;
1834 mcuWidth = mcuHeight = 0;
1835 numComps = 0;
1836 comp = 0;
1837 x = y = dy = 0;
1838 for (i = 0; i < 4; ++i)
1839 for (j = 0; j < 32; ++j)
1840 rowBuf[i][j] = NULL;
1841
1842 if (!dctClipInit) {
1843 for (i = -256; i < 0; ++i)
1844 dctClip[dctClipOffset + i] = 0;
1845 for (i = 0; i < 256; ++i)
1846 dctClip[dctClipOffset + i] = i;
1847 for (i = 256; i < 512; ++i)
1848 dctClip[dctClipOffset + i] = 255;
1849 dctClipInit = 1;
1850 }
1851}
1852
1853DCTStream::~DCTStream() {
1854 int i, j;
1855
1856 delete str;
1857 for (i = 0; i < numComps; ++i)
1858 for (j = 0; j < mcuHeight; ++j)
1859 gfree(rowBuf[i][j]);
1860}
1861
1862void DCTStream::reset() {
1863 str->reset();
1864 if (!readHeader()) {
1865 y = height;
1866 return;
1867 }
1868 restartMarker = 0xd0;
1869 restart();
1870}
1871
1872int DCTStream::getChar() {
1873 int c;
1874
1875 c = lookChar();
1876 if (c == EOF)
1877 return EOF;
1878 if (++comp == numComps) {
1879 comp = 0;
1880 if (++x == width) {
1881 x = 0;
1882 ++y;
1883 ++dy;
1884 }
1885 }
1886 if (y == height)
1887 readTrailer();
1888 return c;
1889}
1890
1891int DCTStream::lookChar() {
1892 if (y >= height)
1893 return EOF;
1894 if (dy >= mcuHeight) {
1895 if (!readMCURow()) {
1896 y = height;
1897 return EOF;
1898 }
1899 comp = 0;
1900 x = 0;
1901 dy = 0;
1902 }
1903 return rowBuf[comp][dy][x];
1904}
1905
1906void DCTStream::restart() {
1907 int i;
1908
1909 inputBits = 0;
1910 restartCtr = restartInterval;
1911 for (i = 0; i < numComps; ++i)
1912 compInfo[i].prevDC = 0;
1913}
1914
1915GBool DCTStream::readMCURow() {
1916 Guchar data[64];
1917 Guchar *p1, *p2;
1918 int pY, pCb, pCr, pR, pG, pB;
1919 int h, v, horiz, vert, hSub, vSub;
1920 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
1921 int c;
1922
1923 for (x1 = 0; x1 < width; x1 += mcuWidth) {
1924
1925 // deal with restart marker
1926 if (restartInterval > 0 && restartCtr == 0) {
1927 c = readMarker();
1928 if (c != restartMarker) {
1929 error(getPos(), "Bad DCT data: incorrect restart marker");
1930 return gFalse;
1931 }
1932 if (++restartMarker == 0xd8)
1933 restartMarker = 0xd0;
1934 restart();
1935 }
1936
1937 // read one MCU
1938 for (cc = 0; cc < numComps; ++cc) {
1939 h = compInfo[cc].hSample;
1940 v = compInfo[cc].vSample;
1941 horiz = mcuWidth / h;
1942 vert = mcuHeight / v;
1943 hSub = horiz / 8;
1944 vSub = vert / 8;
1945 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
1946 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
1947 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
1948 &acHuffTables[compInfo[cc].acHuffTable],
1949 quantTables[compInfo[cc].quantTable],
1950 &compInfo[cc].prevDC,
1951 data))
1952 return gFalse;
1953 if (hSub == 1 && vSub == 1) {
1954 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
1955 p1 = &rowBuf[cc][y2+y3][x1+x2];
1956 p1[0] = data[i];
1957 p1[1] = data[i+1];
1958 p1[2] = data[i+2];
1959 p1[3] = data[i+3];
1960 p1[4] = data[i+4];
1961 p1[5] = data[i+5];
1962 p1[6] = data[i+6];
1963 p1[7] = data[i+7];
1964 }
1965 } else if (hSub == 2 && vSub == 2) {
1966 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
1967 p1 = &rowBuf[cc][y2+y3][x1+x2];
1968 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
1969 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
1970 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
1971 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
1972 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
1973 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
1974 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
1975 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
1976 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
1977 }
1978 } else {
1979 i = 0;
1980 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
1981 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
1982 for (y5 = 0; y5 < vSub; ++y5)
1983 for (x5 = 0; x5 < hSub; ++x5)
1984 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
1985 ++i;
1986 }
1987 }
1988 }
1989 }
1990 }
1991 }
1992 --restartCtr;
1993
1994 // color space conversion
1995 if (colorXform) {
1996 // convert YCbCr to RGB
1997 if (numComps == 3) {
1998 for (y2 = 0; y2 < mcuHeight; ++y2) {
1999 for (x2 = 0; x2 < mcuWidth; ++x2) {
2000 pY = rowBuf[0][y2][x1+x2];
2001 pCb = rowBuf[1][y2][x1+x2] - 128;
2002 pCr = rowBuf[2][y2][x1+x2] - 128;
2003 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2004 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2005 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2006 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2007 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2008 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2009 }
2010 }
2011 // convert YCbCrK to CMYK (K is passed through unchanged)
2012 } else if (numComps == 4) {
2013 for (y2 = 0; y2 < mcuHeight; ++y2) {
2014 for (x2 = 0; x2 < mcuWidth; ++x2) {
2015 pY = rowBuf[0][y2][x1+x2];
2016 pCb = rowBuf[1][y2][x1+x2] - 128;
2017 pCr = rowBuf[2][y2][x1+x2] - 128;
2018 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2019 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2020 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2021 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2022 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2023 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2024 }
2025 }
2026 }
2027 }
2028 }
2029 return gTrue;
2030}
2031
2032// This IDCT algorithm is taken from:
2033// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2034// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2035// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2036// 988-991.
2037// The stage numbers mentioned in the comments refer to Figure 1 in this
2038// paper.
2039#ifndef FP_IDCT
2040GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2041 DCTHuffTable *acHuffTable,
2042 Guchar quantTable[64], int *prevDC,
2043 Guchar data[64]) {
2044 int tmp1[64];
2045 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2046 int run, size, amp;
2047 int c;
2048 int i, j;
2049
2050 // Huffman decode and dequantize
2051 size = readHuffSym(dcHuffTable);
2052 if (size == 9999)
2053 return gFalse;
2054 if (size > 0) {
2055 amp = readAmp(size);
2056 if (amp == 9999)
2057 return gFalse;
2058 } else {
2059 amp = 0;
2060 }
2061 tmp1[0] = (*prevDC += amp) * quantTable[0];
2062 for (i = 1; i < 64; ++i)
2063 tmp1[i] = 0;
2064 i = 1;
2065 while (i < 64) {
2066 run = 0;
2067 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2068 run += 0x10;
2069 if (c == 9999)
2070 return gFalse;
2071 if (c == 0x00) {
2072 break;
2073 } else {
2074 run += (c >> 4) & 0x0f;
2075 size = c & 0x0f;
2076 amp = readAmp(size);
2077 if (amp == 9999)
2078 return gFalse;
2079 i += run;
2080 j = dctZigZag[i++];
2081 tmp1[j] = amp * quantTable[j];
2082 }
2083 }
2084
2085 // inverse DCT on rows
2086 for (i = 0; i < 64; i += 8) {
2087
2088 // stage 4
2089 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
2090 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
2091 v2 = tmp1[i+2];
2092 v3 = tmp1[i+6];
2093 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
2094 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
2095 v5 = tmp1[i+3] << 4;
2096 v6 = tmp1[i+5] << 4;
2097
2098 // stage 3
2099 t = (v0 - v1+ 1) >> 1;
2100 v0 = (v0 + v1 + 1) >> 1;
2101 v1 = t;
2102 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2103 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2104 v3 = t;
2105 t = (v4 - v6 + 1) >> 1;
2106 v4 = (v4 + v6 + 1) >> 1;
2107 v6 = t;
2108 t = (v7 + v5 + 1) >> 1;
2109 v5 = (v7 - v5 + 1) >> 1;
2110 v7 = t;
2111
2112 // stage 2
2113 t = (v0 - v3 + 1) >> 1;
2114 v0 = (v0 + v3 + 1) >> 1;
2115 v3 = t;
2116 t = (v1 - v2 + 1) >> 1;
2117 v1 = (v1 + v2 + 1) >> 1;
2118 v2 = t;
2119 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2120 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2121 v7 = t;
2122 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2123 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2124 v6 = t;
2125
2126 // stage 1
2127 tmp1[i+0] = v0 + v7;
2128 tmp1[i+7] = v0 - v7;
2129 tmp1[i+1] = v1 + v6;
2130 tmp1[i+6] = v1 - v6;
2131 tmp1[i+2] = v2 + v5;
2132 tmp1[i+5] = v2 - v5;
2133 tmp1[i+3] = v3 + v4;
2134 tmp1[i+4] = v3 - v4;
2135 }
2136
2137 // inverse DCT on columns
2138 for (i = 0; i < 8; ++i) {
2139
2140 // stage 4
2141 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2142 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2143 v2 = tmp1[2*8+i];
2144 v3 = tmp1[6*8+i];
2145 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2146 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2147 v5 = tmp1[3*8+i];
2148 v6 = tmp1[5*8+i];
2149
2150 // stage 3
2151 t = (v0 - v1 + 1) >> 1;
2152 v0 = (v0 + v1 + 1) >> 1;
2153 v1 = t;
2154 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2155 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2156 v3 = t;
2157 t = (v4 - v6 + 1) >> 1;
2158 v4 = (v4 + v6 + 1) >> 1;
2159 v6 = t;
2160 t = (v7 + v5 + 1) >> 1;
2161 v5 = (v7 - v5 + 1) >> 1;
2162 v7 = t;
2163
2164 // stage 2
2165 t = (v0 - v3 + 1) >> 1;
2166 v0 = (v0 + v3 + 1) >> 1;
2167 v3 = t;
2168 t = (v1 - v2 + 1) >> 1;
2169 v1 = (v1 + v2 + 1) >> 1;
2170 v2 = t;
2171 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2172 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2173 v7 = t;
2174 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2175 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2176 v6 = t;
2177
2178 // stage 1
2179 tmp1[0*8+i] = v0 + v7;
2180 tmp1[7*8+i] = v0 - v7;
2181 tmp1[1*8+i] = v1 + v6;
2182 tmp1[6*8+i] = v1 - v6;
2183 tmp1[2*8+i] = v2 + v5;
2184 tmp1[5*8+i] = v2 - v5;
2185 tmp1[3*8+i] = v3 + v4;
2186 tmp1[4*8+i] = v3 - v4;
2187 }
2188
2189 // convert to 8-bit integers
2190 for (i = 0; i < 64; ++i)
2191 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2192
2193 return gTrue;
2194}
2195#endif
2196
2197#ifdef FP_IDCT
2198GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2199 DCTHuffTable *acHuffTable,
2200 Guchar quantTable[64], int *prevDC,
2201 Guchar data[64]) {
2202 fouble tmp1[64];
2203 fouble v0, v1, v2, v3, v4, v5, v6, v7, t;
2204 int run, size, amp;
2205 int c;
2206 int i, j;
2207
2208 // Huffman decode and dequantize
2209 size = readHuffSym(dcHuffTable);
2210 if (size == 9999)
2211 return gFalse;
2212 if (size > 0) {
2213 amp = readAmp(size);
2214 if (amp == 9999)
2215 return gFalse;
2216 } else {
2217 amp = 0;
2218 }
2219 tmp1[0] = (*prevDC += amp) * quantTable[0];
2220 for (i = 1; i < 64; ++i)
2221 tmp1[i] = 0;
2222 i = 1;
2223 while (i < 64) {
2224 run = 0;
2225 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2226 run += 0x10;
2227 if (c == 9999)
2228 return gFalse;
2229 if (c == 0x00) {
2230 break;
2231 } else {
2232 run += (c >> 4) & 0x0f;
2233 size = c & 0x0f;
2234 amp = readAmp(size);
2235 if (amp == 9999)
2236 return gFalse;
2237 i += run;
2238 j = dctZigZag[i++];
2239 tmp1[j] = amp * quantTable[j];
2240 }
2241 }
2242
2243 // inverse DCT on rows
2244 for (i = 0; i < 64; i += 8) {
2245
2246 // stage 4
2247 v0 = dctSqrt2 * tmp1[i+0];
2248 v1 = dctSqrt2 * tmp1[i+4];
2249 v2 = tmp1[i+2];
2250 v3 = tmp1[i+6];
2251 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2252 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2253 v5 = tmp1[i+3];
2254 v6 = tmp1[i+5];
2255
2256 // stage 3
2257 t = 0.5 * (v0 - v1);
2258 v0 = 0.5 * (v0 + v1);
2259 v1 = t;
2260 t = v2 * dctSin6 + v3 * dctCos6;
2261 v2 = v2 * dctCos6 - v3 * dctSin6;
2262 v3 = t;
2263 t = 0.5 * (v4 - v6);
2264 v4 = 0.5 * (v4 + v6);
2265 v6 = t;
2266 t = 0.5 * (v7 + v5);
2267 v5 = 0.5 * (v7 - v5);
2268 v7 = t;
2269
2270 // stage 2
2271 t = 0.5 * (v0 - v3);
2272 v0 = 0.5 * (v0 + v3);
2273 v3 = t;
2274 t = 0.5 * (v1 - v2);
2275 v1 = 0.5 * (v1 + v2);
2276 v2 = t;
2277 t = v4 * dctSin3 + v7 * dctCos3;
2278 v4 = v4 * dctCos3 - v7 * dctSin3;
2279 v7 = t;
2280 t = v5 * dctSin1 + v6 * dctCos1;
2281 v5 = v5 * dctCos1 - v6 * dctSin1;
2282 v6 = t;
2283
2284 // stage 1
2285 tmp1[i+0] = v0 + v7;
2286 tmp1[i+7] = v0 - v7;
2287 tmp1[i+1] = v1 + v6;
2288 tmp1[i+6] = v1 - v6;
2289 tmp1[i+2] = v2 + v5;
2290 tmp1[i+5] = v2 - v5;
2291 tmp1[i+3] = v3 + v4;
2292 tmp1[i+4] = v3 - v4;
2293 }
2294
2295 // inverse DCT on columns
2296 for (i = 0; i < 8; ++i) {
2297
2298 // stage 4
2299 v0 = dctSqrt2 * tmp1[0*8+i];
2300 v1 = dctSqrt2 * tmp1[4*8+i];
2301 v2 = tmp1[2*8+i];
2302 v3 = tmp1[6*8+i];
2303 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2304 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2305 v5 = tmp1[3*8+i];
2306 v6 = tmp1[5*8+i];
2307
2308 // stage 3
2309 t = 0.5 * (v0 - v1);
2310 v0 = 0.5 * (v0 + v1);
2311 v1 = t;
2312 t = v2 * dctSin6 + v3 * dctCos6;
2313 v2 = v2 * dctCos6 - v3 * dctSin6;
2314 v3 = t;
2315 t = 0.5 * (v4 - v6);
2316 v4 = 0.5 * (v4 + v6);
2317 v6 = t;
2318 t = 0.5 * (v7 + v5);
2319 v5 = 0.5 * (v7 - v5);
2320 v7 = t;
2321
2322 // stage 2
2323 t = 0.5 * (v0 - v3);
2324 v0 = 0.5 * (v0 + v3);
2325 v3 = t;
2326 t = 0.5 * (v1 - v2);
2327 v1 = 0.5 * (v1 + v2);
2328 v2 = t;
2329 t = v4 * dctSin3 + v7 * dctCos3;
2330 v4 = v4 * dctCos3 - v7 * dctSin3;
2331 v7 = t;
2332 t = v5 * dctSin1 + v6 * dctCos1;
2333 v5 = v5 * dctCos1 - v6 * dctSin1;
2334 v6 = t;
2335
2336 // stage 1
2337 tmp1[0*8+i] = v0 + v7;
2338 tmp1[7*8+i] = v0 - v7;
2339 tmp1[1*8+i] = v1 + v6;
2340 tmp1[6*8+i] = v1 - v6;
2341 tmp1[2*8+i] = v2 + v5;
2342 tmp1[5*8+i] = v2 - v5;
2343 tmp1[3*8+i] = v3 + v4;
2344 tmp1[4*8+i] = v3 - v4;
2345 }
2346
2347 // convert to 8-bit integers
2348 for (i = 0; i < 64; ++i)
2349 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2350
2351 return gTrue;
2352}
2353#endif
2354
2355int DCTStream::readHuffSym(DCTHuffTable *table) {
2356 Gushort code;
2357 int bit;
2358 int codeBits;
2359
2360 code = 0;
2361 codeBits = 0;
2362 do {
2363 // add a bit to the code
2364 if ((bit = readBit()) == EOF)
2365 return 9999;
2366 code = (code << 1) + bit;
2367 ++codeBits;
2368
2369 // look up code
2370 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2371 code -= table->firstCode[codeBits];
2372 return table->sym[table->firstSym[codeBits] + code];
2373 }
2374 } while (codeBits < 16);
2375
2376 error(getPos(), "Bad Huffman code in DCT stream");
2377 return 9999;
2378}
2379
2380int DCTStream::readAmp(int size) {
2381 int amp, bit;
2382 int bits;
2383
2384 amp = 0;
2385 for (bits = 0; bits < size; ++bits) {
2386 if ((bit = readBit()) == EOF)
2387 return 9999;
2388 amp = (amp << 1) + bit;
2389 }
2390 if (amp < (1 << (size - 1)))
2391 amp -= (1 << size) - 1;
2392 return amp;
2393}
2394
2395int DCTStream::readBit() {
2396 int bit;
2397 int c, c2;
2398
2399 if (inputBits == 0) {
2400 if ((c = str->getChar()) == EOF)
2401 return EOF;
2402 if (c == 0xff) {
2403 do {
2404 c2 = str->getChar();
2405 } while (c2 == 0xff);
2406 if (c2 != 0x00) {
2407 error(getPos(), "Bad DCT data: missing 00 after ff");
2408 return EOF;
2409 }
2410 }
2411 inputBuf = c;
2412 inputBits = 8;
2413 }
2414 bit = (inputBuf >> (inputBits - 1)) & 1;
2415 --inputBits;
2416 return bit;
2417}
2418
2419GBool DCTStream::readHeader() {
2420 GBool doScan;
2421 int minHSample, minVSample;
2422 int bufWidth;
2423 int n;
2424 int c = 0;
2425 int i, j;
2426
2427 width = height = 0;
2428 numComps = 0;
2429 numQuantTables = 0;
2430 numDCHuffTables = 0;
2431 numACHuffTables = 0;
2432 colorXform = 0;
2433 gotAdobeMarker = gFalse;
2434 restartInterval = 0;
2435
2436 // read headers
2437 doScan = gFalse;
2438 while (!doScan) {
2439 c = readMarker();
2440 switch (c) {
2441 case 0xc0: // SOF0
2442 if (!readFrameInfo())
2443 return gFalse;
2444 break;
2445 case 0xc4: // DHT
2446 if (!readHuffmanTables())
2447 return gFalse;
2448 break;
2449 case 0xd8: // SOI
2450 break;
2451 case 0xda: // SOS
2452 if (!readScanInfo())
2453 return gFalse;
2454 doScan = gTrue;
2455 break;
2456 case 0xdb: // DQT
2457 if (!readQuantTables())
2458 return gFalse;
2459 break;
2460 case 0xdd: // DRI
2461 if (!readRestartInterval())
2462 return gFalse;
2463 break;
2464 case 0xee: // APP14
2465 if (!readAdobeMarker())
2466 return gFalse;
2467 break;
2468 case EOF:
2469 error(getPos(), "Bad DCT header");
2470 return gFalse;
2471 default:
2472 // skip APPn / COM / etc.
2473 if (c >= 0xe0) {
2474 n = read16() - 2;
2475 for (i = 0; i < n; ++i)
2476 str->getChar();
2477 } else {
2478 error(getPos(), "Unknown DCT marker <%02x>", c);
2479 return gFalse;
2480 }
2481 break;
2482 }
2483 }
2484
2485 // compute MCU size
2486 mcuWidth = minHSample = compInfo[0].hSample;
2487 mcuHeight = minVSample = compInfo[0].vSample;
2488 for (i = 1; i < numComps; ++i) {
2489 if (compInfo[i].hSample < minHSample)
2490 minHSample = compInfo[i].hSample;
2491 if (compInfo[i].vSample < minVSample)
2492 minVSample = compInfo[i].vSample;
2493 if (compInfo[i].hSample > mcuWidth)
2494 mcuWidth = compInfo[i].hSample;
2495 if (compInfo[i].vSample > mcuHeight)
2496 mcuHeight = compInfo[i].vSample;
2497 }
2498 for (i = 0; i < numComps; ++i) {
2499 compInfo[i].hSample /= minHSample;
2500 compInfo[i].vSample /= minVSample;
2501 }
2502 mcuWidth = (mcuWidth / minHSample) * 8;
2503 mcuHeight = (mcuHeight / minVSample) * 8;
2504
2505 // allocate buffers
2506 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2507 for (i = 0; i < numComps; ++i)
2508 for (j = 0; j < mcuHeight; ++j)
2509 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2510
2511 // figure out color transform
2512 if (!gotAdobeMarker && numComps == 3) {
2513 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2514 colorXform = 1;
2515 }
2516 }
2517
2518 // initialize counters
2519 comp = 0;
2520 x = 0;
2521 y = 0;
2522 dy = mcuHeight;
2523
2524 return gTrue;
2525}
2526
2527GBool DCTStream::readFrameInfo() {
2528 int length;
2529 int prec;
2530 int i;
2531 int c;
2532
2533 length = read16() - 2;
2534 prec = str->getChar();
2535 height = read16();
2536 width = read16();
2537 numComps = str->getChar();
2538 length -= 6;
2539 if (prec != 8) {
2540 error(getPos(), "Bad DCT precision %d", prec);
2541 return gFalse;
2542 }
2543 for (i = 0; i < numComps; ++i) {
2544 compInfo[i].id = str->getChar();
2545 compInfo[i].inScan = gFalse;
2546 c = str->getChar();
2547 compInfo[i].hSample = (c >> 4) & 0x0f;
2548 compInfo[i].vSample = c & 0x0f;
2549 compInfo[i].quantTable = str->getChar();
2550 compInfo[i].dcHuffTable = 0;
2551 compInfo[i].acHuffTable = 0;
2552 }
2553 return gTrue;
2554}
2555
2556GBool DCTStream::readScanInfo() {
2557 int length;
2558 int scanComps, id, c;
2559 int i, j;
2560
2561 length = read16() - 2;
2562 scanComps = str->getChar();
2563 --length;
2564 if (length != 2 * scanComps + 3) {
2565 error(getPos(), "Bad DCT scan info block");
2566 return gFalse;
2567 }
2568 for (i = 0; i < scanComps; ++i) {
2569 id = str->getChar();
2570 for (j = 0; j < numComps; ++j) {
2571 if (id == compInfo[j].id)
2572 break;
2573 }
2574 if (j == numComps) {
2575 error(getPos(), "Bad DCT component ID in scan info block");
2576 return gFalse;
2577 }
2578 compInfo[j].inScan = gTrue;
2579 c = str->getChar();
2580 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2581 compInfo[j].acHuffTable = c & 0x0f;
2582 }
2583 str->getChar();
2584 str->getChar();
2585 str->getChar();
2586 return gTrue;
2587}
2588
2589GBool DCTStream::readQuantTables() {
2590 int length;
2591 int i;
2592 int index;
2593
2594 length = read16() - 2;
2595 while (length > 0) {
2596 index = str->getChar();
2597 if ((index & 0xf0) || index >= 4) {
2598 error(getPos(), "Bad DCT quantization table");
2599 return gFalse;
2600 }
2601 if (index == numQuantTables)
2602 numQuantTables = index + 1;
2603 for (i = 0; i < 64; ++i)
2604 quantTables[index][dctZigZag[i]] = str->getChar();
2605 length -= 65;
2606 }
2607 return gTrue;
2608}
2609
2610GBool DCTStream::readHuffmanTables() {
2611 DCTHuffTable *tbl;
2612 int length;
2613 int index;
2614 Gushort code;
2615 Guchar sym;
2616 int i;
2617 int c;
2618
2619 length = read16() - 2;
2620 while (length > 0) {
2621 index = str->getChar();
2622 --length;
2623 if ((index & 0x0f) >= 4) {
2624 error(getPos(), "Bad DCT Huffman table");
2625 return gFalse;
2626 }
2627 if (index & 0x10) {
2628 index &= 0x0f;
2629 if (index >= numACHuffTables)
2630 numACHuffTables = index+1;
2631 tbl = &acHuffTables[index];
2632 } else {
2633 if (index >= numDCHuffTables)
2634 numDCHuffTables = index+1;
2635 tbl = &dcHuffTables[index];
2636 }
2637 sym = 0;
2638 code = 0;
2639 for (i = 1; i <= 16; ++i) {
2640 c = str->getChar();
2641 tbl->firstSym[i] = sym;
2642 tbl->firstCode[i] = code;
2643 tbl->numCodes[i] = c;
2644 sym += c;
2645 code = (code + c) << 1;
2646 }
2647 length -= 16;
2648 for (i = 0; i < sym; ++i)
2649 tbl->sym[i] = str->getChar();
2650 length -= sym;
2651 }
2652 return gTrue;
2653}
2654
2655GBool DCTStream::readRestartInterval() {
2656 int length;
2657
2658 length = read16();
2659 if (length != 4) {
2660 error(getPos(), "Bad DCT restart interval");
2661 return gFalse;
2662 }
2663 restartInterval = read16();
2664 return gTrue;
2665}
2666
2667GBool DCTStream::readAdobeMarker() {
2668 int length, i;
2669 char buf[12];
2670 int c;
2671
2672 length = read16();
2673 if (length != 14)
2674 goto err;
2675 for (i = 0; i < 12; ++i) {
2676 if ((c = str->getChar()) == EOF)
2677 goto err;
2678 buf[i] = c;
2679 }
2680 if (strncmp(buf, "Adobe", 5))
2681 goto err;
2682 colorXform = buf[11];
2683 gotAdobeMarker = gTrue;
2684 return gTrue;
2685
2686 err:
2687 error(getPos(), "Bad DCT Adobe APP14 marker");
2688 return gFalse;
2689}
2690
2691GBool DCTStream::readTrailer() {
2692 int c;
2693
2694 c = readMarker();
2695 if (c != 0xd9) { // EOI
2696 error(getPos(), "Bad DCT trailer");
2697 return gFalse;
2698 }
2699 return gTrue;
2700}
2701
2702int DCTStream::readMarker() {
2703 int c;
2704
2705 do {
2706 do {
2707 c = str->getChar();
2708 } while (c != 0xff);
2709 do {
2710 c = str->getChar();
2711 } while (c == 0xff);
2712 } while (c == 0x00);
2713 return c;
2714}
2715
2716int DCTStream::read16() {
2717 int c1, c2;
2718
2719 if ((c1 = str->getChar()) == EOF)
2720 return EOF;
2721 if ((c2 = str->getChar()) == EOF)
2722 return EOF;
2723 return (c1 << 8) + c2;
2724}
2725
2726GString *DCTStream::getPSFilter(char *indent) {
2727 GString *s;
2728
2729 if (!(s = str->getPSFilter(indent))) {
2730 return NULL;
2731 }
2732 s->append(indent)->append("<< >> /DCTDecode filter\n");
2733 return s;
2734}
2735
2736GBool DCTStream::isBinary(GBool last) {
2737 return str->isBinary(gTrue);
2738}
2739
2740//------------------------------------------------------------------------
2741// FlateStream
2742//------------------------------------------------------------------------
2743
2744int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2745 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2746};
2747
2748FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2749 {0, 3},
2750 {0, 4},
2751 {0, 5},
2752 {0, 6},
2753 {0, 7},
2754 {0, 8},
2755 {0, 9},
2756 {0, 10},
2757 {1, 11},
2758 {1, 13},
2759 {1, 15},
2760 {1, 17},
2761 {2, 19},
2762 {2, 23},
2763 {2, 27},
2764 {2, 31},
2765 {3, 35},
2766 {3, 43},
2767 {3, 51},
2768 {3, 59},
2769 {4, 67},
2770 {4, 83},
2771 {4, 99},
2772 {4, 115},
2773 {5, 131},
2774 {5, 163},
2775 {5, 195},
2776 {5, 227},
2777 {0, 258}
2778};
2779
2780FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2781 { 0, 1},
2782 { 0, 2},
2783 { 0, 3},
2784 { 0, 4},
2785 { 1, 5},
2786 { 1, 7},
2787 { 2, 9},
2788 { 2, 13},
2789 { 3, 17},
2790 { 3, 25},
2791 { 4, 33},
2792 { 4, 49},
2793 { 5, 65},
2794 { 5, 97},
2795 { 6, 129},
2796 { 6, 193},
2797 { 7, 257},
2798 { 7, 385},
2799 { 8, 513},
2800 { 8, 769},
2801 { 9, 1025},
2802 { 9, 1537},
2803 {10, 2049},
2804 {10, 3073},
2805 {11, 4097},
2806 {11, 6145},
2807 {12, 8193},
2808 {12, 12289},
2809 {13, 16385},
2810 {13, 24577}
2811};
2812
2813FlateStream::FlateStream(Stream *strA, int predictor, int columns,
2814 int colors, int bits):
2815 FilterStream(strA) {
2816 if (predictor != 1) {
2817 pred = new StreamPredictor(this, predictor, columns, colors, bits);
2818 } else {
2819 pred = NULL;
2820 }
2821}
2822
2823FlateStream::~FlateStream() {
2824 if (pred) {
2825 delete pred;
2826 }
2827 delete str;
2828}
2829
2830void FlateStream::reset() {
2831 int cmf, flg;
2832
2833 index = 0;
2834 remain = 0;
2835 codeBuf = 0;
2836 codeSize = 0;
2837 compressedBlock = gFalse;
2838 endOfBlock = gTrue;
2839 eof = gTrue;
2840
2841 str->reset();
2842
2843 // read header
2844 //~ need to look at window size?
2845 endOfBlock = eof = gTrue;
2846 cmf = str->getChar();
2847 flg = str->getChar();
2848 if (cmf == EOF || flg == EOF)
2849 return;
2850 if ((cmf & 0x0f) != 0x08) {
2851 error(getPos(), "Unknown compression method in flate stream");
2852 return;
2853 }
2854 if ((((cmf << 8) + flg) % 31) != 0) {
2855 error(getPos(), "Bad FCHECK in flate stream");
2856 return;
2857 }
2858 if (flg & 0x20) {
2859 error(getPos(), "FDICT bit set in flate stream");
2860 return;
2861 }
2862
2863 eof = gFalse;
2864}
2865
2866int FlateStream::getChar() {
2867 int c;
2868
2869 if (pred) {
2870 return pred->getChar();
2871 }
2872 while (remain == 0) {
2873 if (endOfBlock && eof)
2874 return EOF;
2875 readSome();
2876 }
2877 c = buf[index];
2878 index = (index + 1) & flateMask;
2879 --remain;
2880 return c;
2881}
2882
2883int FlateStream::lookChar() {
2884 int c;
2885
2886 if (pred) {
2887 return pred->lookChar();
2888 }
2889 while (remain == 0) {
2890 if (endOfBlock && eof)
2891 return EOF;
2892 readSome();
2893 }
2894 c = buf[index];
2895 return c;
2896}
2897
2898int FlateStream::getRawChar() {
2899 int c;
2900
2901 while (remain == 0) {
2902 if (endOfBlock && eof)
2903 return EOF;
2904 readSome();
2905 }
2906 c = buf[index];
2907 index = (index + 1) & flateMask;
2908 --remain;
2909 return c;
2910}
2911
2912GString *FlateStream::getPSFilter(char *indent) {
2913 return NULL;
2914}
2915
2916GBool FlateStream::isBinary(GBool last) {
2917 return str->isBinary(gTrue);
2918}
2919
2920void FlateStream::readSome() {
2921 int code1, code2;
2922 int len, dist;
2923 int i, j, k;
2924 int c;
2925
2926 if (endOfBlock) {
2927 if (!startBlock())
2928 return;
2929 }
2930
2931 if (compressedBlock) {
2932 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
2933 goto err;
2934 if (code1 < 256) {
2935 buf[index] = code1;
2936 remain = 1;
2937 } else if (code1 == 256) {
2938 endOfBlock = gTrue;
2939 remain = 0;
2940 } else {
2941 code1 -= 257;
2942 code2 = lengthDecode[code1].bits;
2943 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2944 goto err;
2945 len = lengthDecode[code1].first + code2;
2946 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
2947 goto err;
2948 code2 = distDecode[code1].bits;
2949 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2950 goto err;
2951 dist = distDecode[code1].first + code2;
2952 i = index;
2953 j = (index - dist) & flateMask;
2954 for (k = 0; k < len; ++k) {
2955 buf[i] = buf[j];
2956 i = (i + 1) & flateMask;
2957 j = (j + 1) & flateMask;
2958 }
2959 remain = len;
2960 }
2961
2962 } else {
2963 len = (blockLen < flateWindow) ? blockLen : flateWindow;
2964 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
2965 if ((c = str->getChar()) == EOF) {
2966 endOfBlock = eof = gTrue;
2967 break;
2968 }
2969 buf[j] = c & 0xff;
2970 }
2971 remain = i;
2972 blockLen -= len;
2973 if (blockLen == 0)
2974 endOfBlock = gTrue;
2975 }
2976
2977 return;
2978
2979err:
2980 error(getPos(), "Unexpected end of file in flate stream");
2981 endOfBlock = eof = gTrue;
2982 remain = 0;
2983}
2984
2985GBool FlateStream::startBlock() {
2986 int blockHdr;
2987 int c;
2988 int check;
2989
2990 // read block header
2991 blockHdr = getCodeWord(3);
2992 if (blockHdr & 1)
2993 eof = gTrue;
2994 blockHdr >>= 1;
2995
2996 // uncompressed block
2997 if (blockHdr == 0) {
2998 compressedBlock = gFalse;
2999 if ((c = str->getChar()) == EOF)
3000 goto err;
3001 blockLen = c & 0xff;
3002 if ((c = str->getChar()) == EOF)
3003 goto err;
3004 blockLen |= (c & 0xff) << 8;
3005 if ((c = str->getChar()) == EOF)
3006 goto err;
3007 check = c & 0xff;
3008 if ((c = str->getChar()) == EOF)
3009 goto err;
3010 check |= (c & 0xff) << 8;
3011 if (check != (~blockLen & 0xffff))
3012 error(getPos(), "Bad uncompressed block length in flate stream");
3013 codeBuf = 0;
3014 codeSize = 0;
3015
3016 // compressed block with fixed codes
3017 } else if (blockHdr == 1) {
3018 compressedBlock = gTrue;
3019 loadFixedCodes();
3020
3021 // compressed block with dynamic codes
3022 } else if (blockHdr == 2) {
3023 compressedBlock = gTrue;
3024 if (!readDynamicCodes())
3025 goto err;
3026
3027 // unknown block type
3028 } else {
3029 goto err;
3030 }
3031
3032 endOfBlock = gFalse;
3033 return gTrue;
3034
3035err:
3036 error(getPos(), "Bad block header in flate stream");
3037 endOfBlock = eof = gTrue;
3038 return gFalse;
3039}
3040
3041void FlateStream::loadFixedCodes() {
3042 int i;
3043
3044 // set up code arrays
3045 litCodeTab.codes = allCodes;
3046 distCodeTab.codes = allCodes + flateMaxLitCodes;
3047
3048 // initialize literal code table
3049 for (i = 0; i <= 143; ++i)
3050 litCodeTab.codes[i].len = 8;
3051 for (i = 144; i <= 255; ++i)
3052 litCodeTab.codes[i].len = 9;
3053 for (i = 256; i <= 279; ++i)
3054 litCodeTab.codes[i].len = 7;
3055 for (i = 280; i <= 287; ++i)
3056 litCodeTab.codes[i].len = 8;
3057 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
3058
3059 // initialize distance code table
3060 for (i = 0; i <= 5; ++i) {
3061 distCodeTab.start[i] = 0;
3062 }
3063 for (i = 6; i <= flateMaxHuffman+1; ++i) {
3064 distCodeTab.start[i] = flateMaxDistCodes;
3065 }
3066 for (i = 0; i < flateMaxDistCodes; ++i) {
3067 distCodeTab.codes[i].len = 5;
3068 distCodeTab.codes[i].code = i;
3069 distCodeTab.codes[i].val = i;
3070 }
3071}
3072
3073GBool FlateStream::readDynamicCodes() {
3074 int numCodeLenCodes;
3075 int numLitCodes;
3076 int numDistCodes;
3077 FlateCode codeLenCodes[flateMaxCodeLenCodes];
3078 FlateHuffmanTab codeLenCodeTab;
3079 int len, repeat, code;
3080 int i;
3081
3082 // read lengths
3083 if ((numLitCodes = getCodeWord(5)) == EOF)
3084 goto err;
3085 numLitCodes += 257;
3086 if ((numDistCodes = getCodeWord(5)) == EOF)
3087 goto err;
3088 numDistCodes += 1;
3089 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
3090 goto err;
3091 numCodeLenCodes += 4;
3092 if (numLitCodes > flateMaxLitCodes ||
3093 numDistCodes > flateMaxDistCodes ||
3094 numCodeLenCodes > flateMaxCodeLenCodes)
3095 goto err;
3096
3097 // read code length code table
3098 codeLenCodeTab.codes = codeLenCodes;
3099 for (i = 0; i < flateMaxCodeLenCodes; ++i)
3100 codeLenCodes[i].len = 0;
3101 for (i = 0; i < numCodeLenCodes; ++i) {
3102 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
3103 goto err;
3104 }
3105 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
3106
3107 // set up code arrays
3108 litCodeTab.codes = allCodes;
3109 distCodeTab.codes = allCodes + numLitCodes;
3110
3111 // read literal and distance code tables
3112 len = 0;
3113 repeat = 0;
3114 i = 0;
3115 while (i < numLitCodes + numDistCodes) {
3116 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3117 goto err;
3118 if (code == 16) {
3119 if ((repeat = getCodeWord(2)) == EOF)
3120 goto err;
3121 for (repeat += 3; repeat > 0; --repeat)
3122 allCodes[i++].len = len;
3123 } else if (code == 17) {
3124 if ((repeat = getCodeWord(3)) == EOF)
3125 goto err;
3126 len = 0;
3127 for (repeat += 3; repeat > 0; --repeat)
3128 allCodes[i++].len = 0;
3129 } else if (code == 18) {
3130 if ((repeat = getCodeWord(7)) == EOF)
3131 goto err;
3132 len = 0;
3133 for (repeat += 11; repeat > 0; --repeat)
3134 allCodes[i++].len = 0;
3135 } else {
3136 allCodes[i++].len = len = code;
3137 }
3138 }
3139 compHuffmanCodes(&litCodeTab, numLitCodes);
3140 compHuffmanCodes(&distCodeTab, numDistCodes);
3141
3142 return gTrue;
3143
3144err:
3145 error(getPos(), "Bad dynamic code table in flate stream");
3146 return gFalse;
3147}
3148
3149// On entry, the <tab->codes> array contains the lengths of each code,
3150// stored in code value order. This function computes the code words.
3151// The result is sorted in order of (1) code length and (2) code word.
3152// The length values are no longer valid. The <tab->start> array is
3153// filled with the indexes of the first code of each length.
3154void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3155 int numLengths[flateMaxHuffman+1];
3156 int nextCode[flateMaxHuffman+1];
3157 int nextIndex[flateMaxHuffman+2];
3158 int code;
3159 int i, j;
3160
3161 // count number of codes for each code length
3162 for (i = 0; i <= flateMaxHuffman; ++i)
3163 numLengths[i] = 0;
3164 for (i = 0; i < n; ++i)
3165 ++numLengths[tab->codes[i].len];
3166
3167 // compute first index for each length
3168 tab->start[0] = nextIndex[0] = 0;
3169 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3170 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3171
3172 // compute first code for each length
3173 code = 0;
3174 numLengths[0] = 0;
3175 for (i = 1; i <= flateMaxHuffman; ++i) {
3176 code = (code + numLengths[i-1]) << 1;
3177 nextCode[i] = code;
3178 }
3179
3180 // compute the codes -- this permutes the codes array from value
3181 // order to length/code order
3182 for (i = 0; i < n; ++i) {
3183 j = nextIndex[tab->codes[i].len]++;
3184 if (tab->codes[i].len == 0)
3185 tab->codes[j].code = 0;
3186 else
3187 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3188 tab->codes[j].val = i;
3189 }
3190}
3191
3192int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3193 int len;
3194 int code;
3195 int c;
3196 int i, j;
3197
3198 code = 0;
3199 for (len = 1; len <= flateMaxHuffman; ++len) {
3200
3201 // add a bit to the code
3202 if (codeSize == 0) {
3203 if ((c = str->getChar()) == EOF)
3204 return EOF;
3205 codeBuf = c & 0xff;
3206 codeSize = 8;
3207 }
3208 code = (code << 1) | (codeBuf & 1);
3209 codeBuf >>= 1;
3210 --codeSize;
3211
3212 // look for code
3213 i = tab->start[len];
3214 j = tab->start[len + 1];
3215 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3216 i += code - tab->codes[i].code;
3217 return tab->codes[i].val;
3218 }
3219 }
3220
3221 // not found
3222 error(getPos(), "Bad code (%04x) in flate stream", code);
3223 return EOF;
3224}
3225
3226int FlateStream::getCodeWord(int bits) {
3227 int c;
3228
3229 while (codeSize < bits) {
3230 if ((c = str->getChar()) == EOF)
3231 return EOF;
3232 codeBuf |= (c & 0xff) << codeSize;
3233 codeSize += 8;
3234 }
3235 c = codeBuf & ((1 << bits) - 1);
3236 codeBuf >>= bits;
3237 codeSize -= bits;
3238 return c;
3239}
3240
3241//------------------------------------------------------------------------
3242// EOFStream
3243//------------------------------------------------------------------------
3244
3245EOFStream::EOFStream(Stream *strA):
3246 FilterStream(strA) {
3247}
3248
3249EOFStream::~EOFStream() {
3250 delete str;
3251}
3252
3253//------------------------------------------------------------------------
3254// FixedLengthEncoder
3255//------------------------------------------------------------------------
3256
3257FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3258 FilterStream(strA) {
3259 length = lengthA;
3260 count = 0;
3261}
3262
3263FixedLengthEncoder::~FixedLengthEncoder() {
3264 if (str->isEncoder())
3265 delete str;
3266}
3267
3268void FixedLengthEncoder::reset() {
3269 str->reset();
3270 count = 0;
3271}
3272
3273void FixedLengthEncoder::close() {
3274}
3275
3276int FixedLengthEncoder::getChar() {
3277 if (length >= 0 && count >= length)
3278 return EOF;
3279 ++count;
3280 return str->getChar();
3281}
3282
3283int FixedLengthEncoder::lookChar() {
3284 if (length >= 0 && count >= length)
3285 return EOF;
3286 return str->getChar();
3287}
3288
3289//------------------------------------------------------------------------
3290// ASCII85Encoder
3291//------------------------------------------------------------------------
3292
3293ASCII85Encoder::ASCII85Encoder(Stream *strA):
3294 FilterStream(strA) {
3295 bufPtr = bufEnd = buf;
3296 lineLen = 0;
3297 eof = gFalse;
3298}
3299
3300ASCII85Encoder::~ASCII85Encoder() {
3301 if (str->isEncoder())
3302 delete str;
3303}
3304
3305void ASCII85Encoder::reset() {
3306 str->reset();
3307 bufPtr = bufEnd = buf;
3308 lineLen = 0;
3309 eof = gFalse;
3310}
3311
3312void ASCII85Encoder::close() {
3313}
3314
3315GBool ASCII85Encoder::fillBuf() {
3316 Gulong t;
3317 char buf1[5];
3318 int c;
3319 int n, i;
3320
3321 if (eof)
3322 return gFalse;
3323 t = 0;
3324 for (n = 0; n < 4; ++n) {
3325 if ((c = str->getChar()) == EOF)
3326 break;
3327 t = (t << 8) + c;
3328 }
3329 bufPtr = bufEnd = buf;
3330 if (n > 0) {
3331 if (n == 4 && t == 0) {
3332 *bufEnd++ = 'z';
3333 if (++lineLen == 65) {
3334 *bufEnd++ = '\n';
3335 lineLen = 0;
3336 }
3337 } else {
3338 if (n < 4)
3339 t <<= 8 * (4 - n);
3340 for (i = 4; i >= 0; --i) {
3341 buf1[i] = (char)(t % 85 + 0x21);
3342 t /= 85;
3343 }
3344 for (i = 0; i <= n; ++i) {
3345 *bufEnd++ = buf1[i];
3346 if (++lineLen == 65) {
3347 *bufEnd++ = '\n';
3348 lineLen = 0;
3349 }
3350 }
3351 }
3352 }
3353 if (n < 4) {
3354 *bufEnd++ = '~';
3355 *bufEnd++ = '>';
3356 eof = gTrue;
3357 }
3358 return bufPtr < bufEnd;
3359}
3360
3361//------------------------------------------------------------------------
3362// RunLengthEncoder
3363//------------------------------------------------------------------------
3364
3365RunLengthEncoder::RunLengthEncoder(Stream *strA):
3366 FilterStream(strA) {
3367 bufPtr = bufEnd = nextEnd = buf;
3368 eof = gFalse;
3369}
3370
3371RunLengthEncoder::~RunLengthEncoder() {
3372 if (str->isEncoder())
3373 delete str;
3374}
3375
3376void RunLengthEncoder::reset() {
3377 str->reset();
3378 bufPtr = bufEnd = nextEnd = buf;
3379 eof = gFalse;
3380}
3381
3382void RunLengthEncoder::close() {
3383}
3384
3385//
3386// When fillBuf finishes, buf[] looks like this:
3387// +-----+--------------+-----------------+--
3388// + tag | ... data ... | next 0, 1, or 2 |
3389// +-----+--------------+-----------------+--
3390// ^ ^ ^
3391// bufPtr bufEnd nextEnd
3392//
3393GBool RunLengthEncoder::fillBuf() {
3394 int c, c1, c2;
3395 int n;
3396
3397 // already hit EOF?
3398 if (eof)
3399 return gFalse;
3400
3401 // grab two bytes
3402 if (nextEnd < bufEnd + 1) {
3403 if ((c1 = str->getChar()) == EOF) {
3404 eof = gTrue;
3405 return gFalse;
3406 }
3407 } else {
3408 c1 = bufEnd[0] & 0xff;
3409 }
3410 if (nextEnd < bufEnd + 2) {
3411 if ((c2 = str->getChar()) == EOF) {
3412 eof = gTrue;
3413 buf[0] = 0;
3414 buf[1] = c1;
3415 bufPtr = buf;
3416 bufEnd = &buf[2];
3417 return gTrue;
3418 }
3419 } else {
3420 c2 = bufEnd[1] & 0xff;
3421 }
3422
3423 // check for repeat
3424 c = 0; // make gcc happy
3425 if (c1 == c2) {
3426 n = 2;
3427 while (n < 128 && (c = str->getChar()) == c1)
3428 ++n;
3429 buf[0] = (char)(257 - n);
3430 buf[1] = c1;
3431 bufEnd = &buf[2];
3432 if (c == EOF) {
3433 eof = gTrue;
3434 } else if (n < 128) {
3435 buf[2] = c;
3436 nextEnd = &buf[3];
3437 } else {
3438 nextEnd = bufEnd;
3439 }
3440
3441 // get up to 128 chars
3442 } else {
3443 buf[1] = c1;
3444 buf[2] = c2;
3445 n = 2;
3446 while (n < 128) {
3447 if ((c = str->getChar()) == EOF) {
3448 eof = gTrue;
3449 break;
3450 }
3451 ++n;
3452 buf[n] = c;
3453 if (buf[n] == buf[n-1])
3454 break;
3455 }
3456 if (buf[n] == buf[n-1]) {
3457 buf[0] = (char)(n-2-1);
3458 bufEnd = &buf[n-1];
3459 nextEnd = &buf[n+1];
3460 } else {
3461 buf[0] = (char)(n-1);
3462 bufEnd = nextEnd = &buf[n+1];
3463 }
3464 }
3465 bufPtr = buf;
3466 return gTrue;
3467}