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