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