w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Stream.cc
Go to the documentation of this file.
1 //========================================================================
2 //
3 // Stream.cc
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8 
9 #include <aconf.h>
10 
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stddef.h>
18 #include <limits.h>
19 #ifdef _WIN32
20 #include <io.h>
21 #else
22 #include <unistd.h>
23 #endif
24 #include <string.h>
25 #include <ctype.h>
26 #include "gmem.h"
27 #include "gmempp.h"
28 #include "gfile.h"
29 #if MULTITHREADED
30 #include "GMutex.h"
31 #endif
32 #include "config.h"
33 #include "Error.h"
34 #include "Object.h"
35 #include "Lexer.h"
36 #include "GfxState.h"
37 #include "Stream.h"
38 #include "JBIG2Stream.h"
39 #include "JPXStream.h"
40 #include "Stream-CCITT.h"
41 
42 #ifdef __DJGPP__
43 static GBool setDJSYSFLAGS = gFalse;
44 #endif
45 
46 #ifdef VMS
47 #ifdef __GNUC__
48 #define SEEK_SET 0
49 #define SEEK_CUR 1
50 #define SEEK_END 2
51 #endif
52 #endif
53 
54 //------------------------------------------------------------------------
55 // Stream (base class)
56 //------------------------------------------------------------------------
57 
59 }
60 
62 }
63 
64 void Stream::close() {
65 }
66 
68  error(errInternal, -1, "Called getRawChar() on non-predictor stream");
69  return EOF;
70 }
71 
72 int Stream::getBlock(char *buf, int size) {
73  int n, c;
74 
75  n = 0;
76  while (n < size) {
77  if ((c = getChar()) == EOF) {
78  break;
79  }
80  buf[n++] = (char)c;
81  }
82  return n;
83 }
84 
85 char *Stream::getLine(char *buf, int size) {
86  int i;
87  int c;
88 
89  if (lookChar() == EOF || size < 0)
90  return NULL;
91  for (i = 0; i < size - 1; ++i) {
92  c = getChar();
93  if (c == EOF || c == '\n')
94  break;
95  if (c == '\r') {
96  if ((c = lookChar()) == '\n')
97  getChar();
98  break;
99  }
100  buf[i] = (char)c;
101  }
102  buf[i] = '\0';
103  return buf;
104 }
105 
107  char buf[4096];
108  Guint count, i, j;
109 
110  count = 0;
111  while (count < n) {
112  if ((i = n - count) > sizeof(buf)) {
113  i = (Guint)sizeof(buf);
114  }
115  j = (Guint)getBlock(buf, (int)i);
116  count += j;
117  if (j != i) {
118  break;
119  }
120  }
121  return count;
122 }
123 
124 GString *Stream::getPSFilter(int psLevel, const char *indent,
125  GBool okToReadStream) {
126  return new GString();
127 }
128 
129 Stream *Stream::addFilters(Object *dict, int recursion) {
130  Object obj, obj2;
131  Object params, params2;
132  Stream *str;
133  int i;
134 
135  str = this;
136  dict->dictLookup("Filter", &obj, recursion);
137  if (obj.isNull()) {
138  obj.free();
139  dict->dictLookup("F", &obj, recursion);
140  }
141  dict->dictLookup("DecodeParms", &params, recursion);
142  if (params.isNull()) {
143  params.free();
144  dict->dictLookup("DP", &params, recursion);
145  }
146  if (obj.isName()) {
147  str = makeFilter(obj.getName(), str, &params, recursion);
148  } else if (obj.isArray()) {
149  for (i = 0; i < obj.arrayGetLength(); ++i) {
150  obj.arrayGet(i, &obj2, recursion);
151  if (params.isArray())
152  params.arrayGet(i, &params2, recursion);
153  else
154  params2.initNull();
155  if (obj2.isName()) {
156  str = makeFilter(obj2.getName(), str, &params2, recursion);
157  } else {
158  error(errSyntaxError, getPos(), "Bad filter name");
159  str = new EOFStream(str);
160  }
161  obj2.free();
162  params2.free();
163  }
164  } else if (!obj.isNull()) {
165  error(errSyntaxError, getPos(), "Bad 'Filter' attribute in stream");
166  }
167  obj.free();
168  params.free();
169 
170  return str;
171 }
172 
174  int recursion) {
175  int pred; // parameters
176  int colors;
177  int bits;
178  int early;
179  int encoding;
180  GBool endOfLine, byteAlign, endOfBlock, black;
181  int columns, rows;
182  int colorXform;
183  Object globals, obj;
184 
185  if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
186  str = new ASCIIHexStream(str);
187  } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
188  str = new ASCII85Stream(str);
189  } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
190  pred = 1;
191  columns = 1;
192  colors = 1;
193  bits = 8;
194  early = 1;
195  if (params->isDict()) {
196  params->dictLookup("Predictor", &obj, recursion);
197  if (obj.isInt())
198  pred = obj.getInt();
199  obj.free();
200  params->dictLookup("Columns", &obj, recursion);
201  if (obj.isInt())
202  columns = obj.getInt();
203  obj.free();
204  params->dictLookup("Colors", &obj, recursion);
205  if (obj.isInt())
206  colors = obj.getInt();
207  obj.free();
208  params->dictLookup("BitsPerComponent", &obj, recursion);
209  if (obj.isInt())
210  bits = obj.getInt();
211  obj.free();
212  params->dictLookup("EarlyChange", &obj, recursion);
213  if (obj.isInt())
214  early = obj.getInt();
215  obj.free();
216  }
217  str = new LZWStream(str, pred, columns, colors, bits, early);
218  } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
219  str = new RunLengthStream(str);
220  } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
221  encoding = 0;
222  endOfLine = gFalse;
223  byteAlign = gFalse;
224  columns = 1728;
225  rows = 0;
226  endOfBlock = gTrue;
227  black = gFalse;
228  if (params->isDict()) {
229  params->dictLookup("K", &obj, recursion);
230  if (obj.isInt()) {
231  encoding = obj.getInt();
232  }
233  obj.free();
234  params->dictLookup("EndOfLine", &obj, recursion);
235  if (obj.isBool()) {
236  endOfLine = obj.getBool();
237  }
238  obj.free();
239  params->dictLookup("EncodedByteAlign", &obj, recursion);
240  if (obj.isBool()) {
241  byteAlign = obj.getBool();
242  }
243  obj.free();
244  params->dictLookup("Columns", &obj, recursion);
245  if (obj.isInt()) {
246  columns = obj.getInt();
247  }
248  obj.free();
249  params->dictLookup("Rows", &obj, recursion);
250  if (obj.isInt()) {
251  rows = obj.getInt();
252  }
253  obj.free();
254  params->dictLookup("EndOfBlock", &obj, recursion);
255  if (obj.isBool()) {
256  endOfBlock = obj.getBool();
257  }
258  obj.free();
259  params->dictLookup("BlackIs1", &obj, recursion);
260  if (obj.isBool()) {
261  black = obj.getBool();
262  }
263  obj.free();
264  }
265  str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
266  columns, rows, endOfBlock, black);
267  } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
268  colorXform = -1;
269  if (params->isDict()) {
270  if (params->dictLookup("ColorTransform", &obj, recursion)->isInt()) {
271  colorXform = obj.getInt();
272  }
273  obj.free();
274  }
275  str = new DCTStream(str, colorXform);
276  } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
277  pred = 1;
278  columns = 1;
279  colors = 1;
280  bits = 8;
281  if (params->isDict()) {
282  params->dictLookup("Predictor", &obj, recursion);
283  if (obj.isInt())
284  pred = obj.getInt();
285  obj.free();
286  params->dictLookup("Columns", &obj, recursion);
287  if (obj.isInt())
288  columns = obj.getInt();
289  obj.free();
290  params->dictLookup("Colors", &obj, recursion);
291  if (obj.isInt())
292  colors = obj.getInt();
293  obj.free();
294  params->dictLookup("BitsPerComponent", &obj, recursion);
295  if (obj.isInt())
296  bits = obj.getInt();
297  obj.free();
298  }
299  str = new FlateStream(str, pred, columns, colors, bits);
300  } else if (!strcmp(name, "JBIG2Decode")) {
301  if (params->isDict()) {
302  params->dictLookup("JBIG2Globals", &globals, recursion);
303  }
304  str = new JBIG2Stream(str, &globals);
305  globals.free();
306  } else if (!strcmp(name, "JPXDecode")) {
307  str = new JPXStream(str);
308  } else {
309  error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
310  str = new EOFStream(str);
311  }
312  return str;
313 }
314 
315 //------------------------------------------------------------------------
316 // BaseStream
317 //------------------------------------------------------------------------
318 
320  dict = *dictA;
321 }
322 
324  dict.free();
325 }
326 
327 //------------------------------------------------------------------------
328 // FilterStream
329 //------------------------------------------------------------------------
330 
332  str = strA;
333 }
334 
336 }
337 
339  str->close();
340 }
341 
343  error(errInternal, -1, "Called setPos() on FilterStream");
344 }
345 
346 //------------------------------------------------------------------------
347 // ImageStream
348 //------------------------------------------------------------------------
349 
350 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
351  int imgLineSize;
352 
353  str = strA;
354  width = widthA;
355  nComps = nCompsA;
356  nBits = nBitsA;
357 
358  nVals = width * nComps;
359  inputLineSize = (nVals * nBits + 7) >> 3;
360  if (width > INT_MAX / nComps ||
361  nVals > (INT_MAX - 7) / nBits) {
362  // force a call to gmallocn(-1,...), which will throw an exception
363  inputLineSize = -1;
364  }
365  inputLine = (char *)gmallocn(inputLineSize, sizeof(char));
366  if (nBits == 8) {
367  imgLine = (Guchar *)inputLine;
368  } else {
369  if (nBits == 1) {
370  imgLineSize = (nVals + 7) & ~7;
371  } else {
372  imgLineSize = nVals;
373  }
374  imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
375  }
376  imgIdx = nVals;
377 }
378 
380  if (imgLine != (Guchar *)inputLine) {
381  gfree(imgLine);
382  }
383  gfree(inputLine);
384 }
385 
387  str->reset();
388 }
389 
391  str->close();
392 }
393 
395  int i;
396 
397  if (imgIdx >= nVals) {
398  if (!getLine()) {
399  return gFalse;
400  }
401  imgIdx = 0;
402  }
403  for (i = 0; i < nComps; ++i) {
404  pix[i] = imgLine[imgIdx++];
405  }
406  return gTrue;
407 }
408 
410  Gulong buf, bitMask;
411  int bits;
412  int c;
413  int i;
414  char *p;
415 
417  return NULL;
418  }
419  if (nBits == 1) {
420  p = inputLine;
421  for (i = 0; i < nVals; i += 8) {
422  c = *p++;
423  imgLine[i+0] = (Guchar)((c >> 7) & 1);
424  imgLine[i+1] = (Guchar)((c >> 6) & 1);
425  imgLine[i+2] = (Guchar)((c >> 5) & 1);
426  imgLine[i+3] = (Guchar)((c >> 4) & 1);
427  imgLine[i+4] = (Guchar)((c >> 3) & 1);
428  imgLine[i+5] = (Guchar)((c >> 2) & 1);
429  imgLine[i+6] = (Guchar)((c >> 1) & 1);
430  imgLine[i+7] = (Guchar)(c & 1);
431  }
432  } else if (nBits == 8) {
433  // special case: imgLine == inputLine
434  } else if (nBits == 16) {
435  for (i = 0; i < nVals; ++i) {
436  imgLine[i] = (Guchar)inputLine[2*i];
437  }
438  } else {
439  bitMask = (1 << nBits) - 1;
440  buf = 0;
441  bits = 0;
442  p = inputLine;
443  for (i = 0; i < nVals; ++i) {
444  if (bits < nBits) {
445  buf = (buf << 8) | (*p++ & 0xff);
446  bits += 8;
447  }
448  imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
449  bits -= nBits;
450  }
451  }
452  return imgLine;
453 }
454 
457 }
458 
459 
460 //------------------------------------------------------------------------
461 // StreamPredictor
462 //------------------------------------------------------------------------
463 
465  int widthA, int nCompsA, int nBitsA) {
466  str = strA;
467  predictor = predictorA;
468  width = widthA;
469  nComps = nCompsA;
470  nBits = nBitsA;
471  predLine = NULL;
472  ok = gFalse;
473 
474  nVals = width * nComps;
475  pixBytes = (nComps * nBits + 7) >> 3;
476  rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
477  if (width <= 0 || nComps <= 0 || nBits <= 0 ||
479  nBits > 16 ||
480  width >= INT_MAX / nComps || // check for overflow in nVals
481  nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes
482  return;
483  }
485 
486  reset();
487 
488  ok = gTrue;
489 }
490 
492  gfree(predLine);
493 }
494 
496  memset(predLine, 0, rowBytes);
497  predIdx = rowBytes;
498 }
499 
501  if (predIdx >= rowBytes) {
502  if (!getNextLine()) {
503  return EOF;
504  }
505  }
506  return predLine[predIdx];
507 }
508 
510  if (predIdx >= rowBytes) {
511  if (!getNextLine()) {
512  return EOF;
513  }
514  }
515  return predLine[predIdx++];
516 }
517 
518 int StreamPredictor::getBlock(char *blk, int size) {
519  int n, m;
520 
521  n = 0;
522  while (n < size) {
523  if (predIdx >= rowBytes) {
524  if (!getNextLine()) {
525  break;
526  }
527  }
528  m = rowBytes - predIdx;
529  if (m > size - n) {
530  m = size - n;
531  }
532  memcpy(blk + n, predLine + predIdx, m);
533  predIdx += m;
534  n += m;
535  }
536  return n;
537 }
538 
540  int curPred;
541  Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
542  int left, up, upLeft, p, pa, pb, pc;
543  int c;
544  Gulong inBuf, outBuf, bitMask;
545  int inBits, outBits;
546  int i, j, k, kk;
547 
548  // get PNG optimum predictor number
549  if (predictor >= 10) {
550  if ((curPred = str->getRawChar()) == EOF) {
551  return gFalse;
552  }
553  curPred += 10;
554  } else {
555  curPred = predictor;
556  }
557 
558  // read the raw line, apply PNG (byte) predictor
559  memset(upLeftBuf, 0, pixBytes + 1);
560  for (i = pixBytes; i < rowBytes; ++i) {
561  for (j = pixBytes; j > 0; --j) {
562  upLeftBuf[j] = upLeftBuf[j-1];
563  }
564  upLeftBuf[0] = predLine[i];
565  if ((c = str->getRawChar()) == EOF) {
566  if (i > pixBytes) {
567  // this ought to return false, but some (broken) PDF files
568  // contain truncated image data, and Adobe apparently reads the
569  // last partial line
570  break;
571  }
572  return gFalse;
573  }
574  switch (curPred) {
575  case 11: // PNG sub
576  predLine[i] = (Guchar)(predLine[i - pixBytes] + c);
577  break;
578  case 12: // PNG up
579  predLine[i] = (Guchar)(predLine[i] + c);
580  break;
581  case 13: // PNG average
582  predLine[i] = (Guchar)(((predLine[i - pixBytes] + predLine[i]) >> 1) + c);
583  break;
584  case 14: // PNG Paeth
585  left = predLine[i - pixBytes];
586  up = predLine[i];
587  upLeft = upLeftBuf[pixBytes];
588  p = left + up - upLeft;
589  if ((pa = p - left) < 0)
590  pa = -pa;
591  if ((pb = p - up) < 0)
592  pb = -pb;
593  if ((pc = p - upLeft) < 0)
594  pc = -pc;
595  if (pa <= pb && pa <= pc)
596  predLine[i] = (Guchar)(left + c);
597  else if (pb <= pc)
598  predLine[i] = (Guchar)(up + c);
599  else
600  predLine[i] = (Guchar)(upLeft + c);
601  break;
602  case 10: // PNG none
603  default: // no predictor or TIFF predictor
604  predLine[i] = (Guchar)c;
605  break;
606  }
607  }
608 
609  // apply TIFF (component) predictor
610  if (predictor == 2) {
611  if (nBits == 8) {
612  for (i = pixBytes; i < rowBytes; ++i) {
613  predLine[i] = (Guchar)(predLine[i] + predLine[i - nComps]);
614  }
615  } else if (nBits == 16) {
616  for (i = pixBytes; i < rowBytes; i += 2) {
617  c = ((predLine[i] + predLine[i - 2*nComps]) << 8) +
618  predLine[i + 1] + predLine[i + 1 - 2*nComps];
619  predLine[i] = (Guchar)(c >> 8);
620  predLine[i+1] = (Guchar)(c & 0xff);
621  }
622  } else {
623  memset(upLeftBuf, 0, nComps);
624  bitMask = (1 << nBits) - 1;
625  inBuf = outBuf = 0;
626  inBits = outBits = 0;
627  j = k = pixBytes;
628  for (i = 0; i < width; ++i) {
629  for (kk = 0; kk < nComps; ++kk) {
630  if (inBits < nBits) {
631  inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
632  inBits += 8;
633  }
634  upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] +
635  (inBuf >> (inBits - nBits))) & bitMask);
636  inBits -= nBits;
637  outBuf = (outBuf << nBits) | upLeftBuf[kk];
638  outBits += nBits;
639  if (outBits >= 8) {
640  predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
641  outBits -= 8;
642  }
643  }
644  }
645  if (outBits > 0) {
646  predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
647  (inBuf & ((1 << (8 - outBits)) - 1)));
648  }
649  }
650  }
651 
652  // reset to start of line
653  predIdx = pixBytes;
654 
655  return gTrue;
656 }
657 
658 //------------------------------------------------------------------------
659 // SharedFile
660 //------------------------------------------------------------------------
661 
662 class SharedFile {
663 public:
664 
665  SharedFile(FILE *fA);
666  SharedFile *copy();
667  void free();
668  int readBlock(char *buf, GFileOffset pos, int size);
670 
671 private:
672 
673  ~SharedFile();
674 
675  FILE *f;
676  int refCnt;
677 #if MULTITHREADED
678  GMutex mutex;
679 #endif
680 };
681 
683  f = fA;
684  refCnt = 1;
685 #if MULTITHREADED
686  gInitMutex(&mutex);
687 #endif
688 }
689 
691 #if MULTITHREADED
692  gDestroyMutex(&mutex);
693 #endif
694 }
695 
697 #if MULTITHREADED
698  gLockMutex(&mutex);
699 #endif
700  ++refCnt;
701 #if MULTITHREADED
702  gUnlockMutex(&mutex);
703 #endif
704  return this;
705 }
706 
708  int newCount;
709 
710 #if MULTITHREADED
711  gLockMutex(&mutex);
712 #endif
713  newCount = --refCnt;
714 #if MULTITHREADED
715  gUnlockMutex(&mutex);
716 #endif
717  if (newCount == 0) {
718  delete this;
719  }
720 }
721 
723  int n;
724 
725 #if MULTITHREADED
726  gLockMutex(&mutex);
727 #endif
728  gfseek(f, pos, SEEK_SET);
729  n = (int)fread(buf, 1, size, f);
730 #if MULTITHREADED
731  gUnlockMutex(&mutex);
732 #endif
733  return n;
734 }
735 
738 
739 #if MULTITHREADED
740  gLockMutex(&mutex);
741 #endif
742  gfseek(f, 0, SEEK_END);
743  size = gftell(f);
744 #if MULTITHREADED
745  gUnlockMutex(&mutex);
746 #endif
747  return size;
748 }
749 
750 //------------------------------------------------------------------------
751 // FileStream
752 //------------------------------------------------------------------------
753 
755  GFileOffset lengthA, Object *dictA):
756  BaseStream(dictA) {
757  f = new SharedFile(fA);
758  start = startA;
759  limited = limitedA;
760  length = lengthA;
761  bufPtr = bufEnd = buf;
762  bufPos = start;
763 }
764 
766  GFileOffset lengthA, Object *dictA):
767  BaseStream(dictA) {
768  f = fA->copy();
769  start = startA;
770  limited = limitedA;
771  length = lengthA;
772  bufPtr = bufEnd = buf;
773  bufPos = start;
774 }
775 
777  f->free();
778 }
779 
781  Object dictA;
782 
783  dict.copy(&dictA);
784  return new FileStream(f, start, limited, length, &dictA);
785 }
786 
788  GFileOffset lengthA, Object *dictA) {
789  return new FileStream(f, startA, limitedA, lengthA, dictA);
790 }
791 
793  bufPtr = bufEnd = buf;
794  bufPos = start;
795 }
796 
797 int FileStream::getBlock(char *blk, int size) {
798  int n, m;
799 
800  n = 0;
801  while (n < size) {
802  if (bufPtr >= bufEnd) {
803  if (!fillBuf()) {
804  break;
805  }
806  }
807  m = (int)(bufEnd - bufPtr);
808  if (m > size - n) {
809  m = size - n;
810  }
811  memcpy(blk + n, bufPtr, m);
812  bufPtr += m;
813  n += m;
814  }
815  return n;
816 }
817 
819  int n;
820 
821  bufPos += (int)(bufEnd - buf);
822  bufPtr = bufEnd = buf;
823  if (limited && bufPos >= start + length) {
824  return gFalse;
825  }
827  n = (int)(start + length - bufPos);
828  } else {
830  }
831  n = f->readBlock(buf, bufPos, n);
832  bufEnd = buf + n;
833  if (bufPtr >= bufEnd) {
834  return gFalse;
835  }
836  return gTrue;
837 }
838 
841 
842  if (dir >= 0) {
843  bufPos = pos;
844  } else {
845  size = f->getSize();
846  if (pos <= size) {
847  bufPos = size - pos;
848  } else {
849  bufPos = 0;
850  }
851  }
852  bufPtr = bufEnd = buf;
853 }
854 
856  start += delta;
857  bufPtr = bufEnd = buf;
858  bufPos = start;
859 }
860 
861 //------------------------------------------------------------------------
862 // MemStream
863 //------------------------------------------------------------------------
864 
865 MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
866  BaseStream(dictA) {
867  buf = bufA;
868  start = startA;
869  length = lengthA;
870  bufEnd = buf + start + length;
871  bufPtr = buf + start;
872  needFree = gFalse;
873 }
874 
876  if (needFree) {
877  gfree(buf);
878  }
879 }
880 
882  Object dictA;
883 
884  dict.copy(&dictA);
885  return new MemStream(buf, start, length, &dictA);
886 }
887 
889  GFileOffset lengthA, Object *dictA) {
890  MemStream *subStr;
891  Guint newStart, newLength;
892 
893  if (startA < start) {
894  newStart = start;
895  } else if (startA > start + length) {
896  newStart = start + (int)length;
897  } else {
898  newStart = (int)startA;
899  }
900  if (!limited || newStart + lengthA > start + length) {
901  newLength = start + length - newStart;
902  } else {
903  newLength = (Guint)lengthA;
904  }
905  subStr = new MemStream(buf, newStart, newLength, dictA);
906  return subStr;
907 }
908 
910  bufPtr = buf + start;
911 }
912 
914 }
915 
916 int MemStream::getBlock(char *blk, int size) {
917  int n;
918 
919  if (size <= 0) {
920  return 0;
921  }
922  if (bufEnd - bufPtr < size) {
923  n = (int)(bufEnd - bufPtr);
924  } else {
925  n = size;
926  }
927  memcpy(blk, bufPtr, n);
928  bufPtr += n;
929  return n;
930 }
931 
933  Guint i;
934 
935  if (dir >= 0) {
936  i = (Guint)pos;
937  } else {
938  i = (Guint)(start + length - pos);
939  }
940  if (i < start) {
941  i = start;
942  } else if (i > start + length) {
943  i = start + length;
944  }
945  bufPtr = buf + i;
946 }
947 
949  start += delta;
950  length -= delta;
951  bufPtr = buf + start;
952 }
953 
954 //------------------------------------------------------------------------
955 // EmbedStream
956 //------------------------------------------------------------------------
957 
959  GBool limitedA, GFileOffset lengthA):
960  BaseStream(dictA) {
961  str = strA;
962  limited = limitedA;
963  length = lengthA;
964 }
965 
967 }
968 
970  Object dictA;
971 
972  dict.copy(&dictA);
973  return new EmbedStream(str, &dictA, limited, length);
974 }
975 
977  GFileOffset lengthA, Object *dictA) {
978  error(errInternal, -1, "Called makeSubStream() on EmbedStream");
979  return NULL;
980 }
981 
983  if (limited && !length) {
984  return EOF;
985  }
986  --length;
987  return str->getChar();
988 }
989 
991  if (limited && !length) {
992  return EOF;
993  }
994  return str->lookChar();
995 }
996 
997 int EmbedStream::getBlock(char *blk, int size) {
998  if (size <= 0) {
999  return 0;
1000  }
1001  if (limited && length < (Guint)size) {
1002  size = (int)length;
1003  }
1004  length -= size;
1005  return str->getBlock(blk, size);
1006 }
1007 
1009  error(errInternal, -1, "Called setPos() on EmbedStream");
1010 }
1011 
1013  error(errInternal, -1, "Called getStart() on EmbedStream");
1014  return 0;
1015 }
1016 
1018  error(errInternal, -1, "Called moveStart() on EmbedStream");
1019 }
1020 
1021 //------------------------------------------------------------------------
1022 // ASCIIHexStream
1023 //------------------------------------------------------------------------
1024 
1026  FilterStream(strA) {
1027  buf = EOF;
1028  eof = gFalse;
1029 }
1030 
1032  delete str;
1033 }
1034 
1036  return new ASCIIHexStream(str->copy());
1037 }
1038 
1040  str->reset();
1041  buf = EOF;
1042  eof = gFalse;
1043 }
1044 
1046  int c1, c2, x;
1047 
1048  if (buf != EOF)
1049  return buf;
1050  if (eof) {
1051  buf = EOF;
1052  return EOF;
1053  }
1054  do {
1055  c1 = str->getChar();
1056  } while (isspace(c1));
1057  if (c1 == '>') {
1058  eof = gTrue;
1059  buf = EOF;
1060  return buf;
1061  }
1062  do {
1063  c2 = str->getChar();
1064  } while (isspace(c2));
1065  if (c2 == '>') {
1066  eof = gTrue;
1067  c2 = '0';
1068  }
1069  if (c1 >= '0' && c1 <= '9') {
1070  x = (c1 - '0') << 4;
1071  } else if (c1 >= 'A' && c1 <= 'F') {
1072  x = (c1 - 'A' + 10) << 4;
1073  } else if (c1 >= 'a' && c1 <= 'f') {
1074  x = (c1 - 'a' + 10) << 4;
1075  } else if (c1 == EOF) {
1076  eof = gTrue;
1077  x = 0;
1078  } else {
1080  "Illegal character <{0:02x}> in ASCIIHex stream", c1);
1081  x = 0;
1082  }
1083  if (c2 >= '0' && c2 <= '9') {
1084  x += c2 - '0';
1085  } else if (c2 >= 'A' && c2 <= 'F') {
1086  x += c2 - 'A' + 10;
1087  } else if (c2 >= 'a' && c2 <= 'f') {
1088  x += c2 - 'a' + 10;
1089  } else if (c2 == EOF) {
1090  eof = gTrue;
1091  x = 0;
1092  } else {
1094  "Illegal character <{0:02x}> in ASCIIHex stream", c2);
1095  }
1096  buf = x & 0xff;
1097  return buf;
1098 }
1099 
1100 GString *ASCIIHexStream::getPSFilter(int psLevel, const char *indent,
1101  GBool okToReadStream) {
1102  GString *s;
1103 
1104  if (psLevel < 2) {
1105  return NULL;
1106  }
1107  if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
1108  return NULL;
1109  }
1110  s->append(indent)->append("/ASCIIHexDecode filter\n");
1111  return s;
1112 }
1113 
1115  return str->isBinary(gFalse);
1116 }
1117 
1118 //------------------------------------------------------------------------
1119 // ASCII85Stream
1120 //------------------------------------------------------------------------
1121 
1123  FilterStream(strA) {
1124  index = n = 0;
1125  eof = gFalse;
1126 }
1127 
1129  delete str;
1130 }
1131 
1133  return new ASCII85Stream(str->copy());
1134 }
1135 
1137  str->reset();
1138  index = n = 0;
1139  eof = gFalse;
1140 }
1141 
1143  int k;
1144  Gulong t;
1145 
1146  if (index >= n) {
1147  if (eof)
1148  return EOF;
1149  index = 0;
1150  do {
1151  c[0] = str->getChar();
1152  } while (Lexer::isSpace(c[0]));
1153  if (c[0] == '~' || c[0] == EOF) {
1154  eof = gTrue;
1155  n = 0;
1156  return EOF;
1157  } else if (c[0] == 'z') {
1158  b[0] = b[1] = b[2] = b[3] = 0;
1159  n = 4;
1160  } else {
1161  for (k = 1; k < 5; ++k) {
1162  do {
1163  c[k] = str->getChar();
1164  } while (Lexer::isSpace(c[k]));
1165  if (c[k] == '~' || c[k] == EOF)
1166  break;
1167  }
1168  n = k - 1;
1169  if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
1170  for (++k; k < 5; ++k)
1171  c[k] = 0x21 + 84;
1172  eof = gTrue;
1173  }
1174  t = 0;
1175  for (k = 0; k < 5; ++k)
1176  t = t * 85 + (c[k] - 0x21);
1177  for (k = 3; k >= 0; --k) {
1178  b[k] = (int)(t & 0xff);
1179  t >>= 8;
1180  }
1181  }
1182  }
1183  return b[index];
1184 }
1185 
1186 GString *ASCII85Stream::getPSFilter(int psLevel, const char *indent,
1187  GBool okToReadStream) {
1188  GString *s;
1189 
1190  if (psLevel < 2) {
1191  return NULL;
1192  }
1193  if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
1194  return NULL;
1195  }
1196  s->append(indent)->append("/ASCII85Decode filter\n");
1197  return s;
1198 }
1199 
1201  return str->isBinary(gFalse);
1202 }
1203 
1204 //------------------------------------------------------------------------
1205 // LZWStream
1206 //------------------------------------------------------------------------
1207 
1208 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
1209  int bits, int earlyA):
1210  FilterStream(strA) {
1211  if (predictor != 1) {
1212  pred = new StreamPredictor(this, predictor, columns, colors, bits);
1213  if (!pred->isOk()) {
1214  delete pred;
1215  pred = NULL;
1216  }
1217  } else {
1218  pred = NULL;
1219  }
1220  early = earlyA;
1221  eof = gFalse;
1222  inputBits = 0;
1223  clearTable();
1224 }
1225 
1227  if (pred) {
1228  delete pred;
1229  }
1230  delete str;
1231 }
1232 
1234  if (pred) {
1235  return new LZWStream(str->copy(), pred->getPredictor(),
1236  pred->getWidth(), pred->getNComps(),
1237  pred->getNBits(), early);
1238  } else {
1239  return new LZWStream(str->copy(), 1, 0, 0, 0, early);
1240  }
1241 }
1242 
1244  if (pred) {
1245  return pred->getChar();
1246  }
1247  if (eof) {
1248  return EOF;
1249  }
1250  if (seqIndex >= seqLength) {
1251  if (!processNextCode()) {
1252  return EOF;
1253  }
1254  }
1255  return seqBuf[seqIndex++];
1256 }
1257 
1259  if (pred) {
1260  return pred->lookChar();
1261  }
1262  if (eof) {
1263  return EOF;
1264  }
1265  if (seqIndex >= seqLength) {
1266  if (!processNextCode()) {
1267  return EOF;
1268  }
1269  }
1270  return seqBuf[seqIndex];
1271 }
1272 
1274  if (eof) {
1275  return EOF;
1276  }
1277  if (seqIndex >= seqLength) {
1278  if (!processNextCode()) {
1279  return EOF;
1280  }
1281  }
1282  return seqBuf[seqIndex++];
1283 }
1284 
1285 int LZWStream::getBlock(char *blk, int size) {
1286  int n, m;
1287 
1288  if (pred) {
1289  return pred->getBlock(blk, size);
1290  }
1291  if (eof) {
1292  return 0;
1293  }
1294  n = 0;
1295  while (n < size) {
1296  if (seqIndex >= seqLength) {
1297  if (!processNextCode()) {
1298  break;
1299  }
1300  }
1301  m = seqLength - seqIndex;
1302  if (m > size - n) {
1303  m = size - n;
1304  }
1305  memcpy(blk + n, seqBuf + seqIndex, m);
1306  seqIndex += m;
1307  n += m;
1308  }
1309  return n;
1310 }
1311 
1313  str->reset();
1314  if (pred) {
1315  pred->reset();
1316  }
1317  eof = gFalse;
1318  inputBits = 0;
1319  clearTable();
1320  totalIn = totalOut = 0;
1321 }
1322 
1324  int code;
1325  int nextLength;
1326  int i, j;
1327 
1328  // check for EOF
1329  if (eof) {
1330  return gFalse;
1331  }
1332 
1333  // check for eod and clear-table codes
1334  start:
1335  code = getCode();
1336  if (code == EOF || code == 257) {
1337  eof = gTrue;
1338  return gFalse;
1339  }
1340  if (code == 256) {
1341  clearTable();
1342  goto start;
1343  }
1344  if (nextCode >= 4097) {
1346  "Bad LZW stream - expected clear-table code");
1347  clearTable();
1348  }
1349 
1350  // process the next code
1351  nextLength = seqLength + 1;
1352  if (code < 256) {
1353  seqBuf[0] = (Guchar)code;
1354  seqLength = 1;
1355  } else if (code < nextCode) {
1356  seqLength = table[code].length;
1357  for (i = seqLength - 1, j = code; i > 0; --i) {
1358  seqBuf[i] = table[j].tail;
1359  j = table[j].head;
1360  }
1361  seqBuf[0] = (Guchar)j;
1362  } else if (code == nextCode) {
1364  ++seqLength;
1365  } else {
1366  error(errSyntaxError, getPos(), "Bad LZW stream - unexpected code");
1367  eof = gTrue;
1368  return gFalse;
1369  }
1370  newChar = seqBuf[0];
1371  if (first) {
1372  first = gFalse;
1373  } else {
1374  table[nextCode].length = nextLength;
1375  table[nextCode].head = prevCode;
1376  table[nextCode].tail = (Guchar)newChar;
1377  ++nextCode;
1378  if (nextCode + early == 512)
1379  nextBits = 10;
1380  else if (nextCode + early == 1024)
1381  nextBits = 11;
1382  else if (nextCode + early == 2048)
1383  nextBits = 12;
1384  }
1385  prevCode = code;
1386  totalOut += seqLength;
1387 
1388  // check for a 'decompression bomb'
1389  if (totalOut > 50000000 && totalIn < totalOut / 250) {
1390  error(errSyntaxError, getPos(), "Decompression bomb in flate stream");
1391  eof = gTrue;
1392  return gFalse;
1393  }
1394 
1395  // reset buffer
1396  seqIndex = 0;
1397 
1398  return gTrue;
1399 }
1400 
1402  nextCode = 258;
1403  nextBits = 9;
1404  seqIndex = seqLength = 0;
1405  first = gTrue;
1406 }
1407 
1409  int c;
1410  int code;
1411 
1412  while (inputBits < nextBits) {
1413  if ((c = str->getChar()) == EOF)
1414  return EOF;
1415  inputBuf = (inputBuf << 8) | (c & 0xff);
1416  inputBits += 8;
1417  ++totalIn;
1418  }
1419  code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1420  inputBits -= nextBits;
1421  return code;
1422 }
1423 
1424 GString *LZWStream::getPSFilter(int psLevel, const char *indent,
1425  GBool okToReadStream) {
1426  GString *s;
1427 
1428  if (psLevel < 2 || pred) {
1429  return NULL;
1430  }
1431  if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
1432  return NULL;
1433  }
1434  s->append(indent)->append("<< ");
1435  if (!early) {
1436  s->append("/EarlyChange 0 ");
1437  }
1438  s->append(">> /LZWDecode filter\n");
1439  return s;
1440 }
1441 
1443  return str->isBinary(gTrue);
1444 }
1445 
1446 //------------------------------------------------------------------------
1447 // RunLengthStream
1448 //------------------------------------------------------------------------
1449 
1451  FilterStream(strA) {
1452  bufPtr = bufEnd = buf;
1453  eof = gFalse;
1454 }
1455 
1457  delete str;
1458 }
1459 
1461  return new RunLengthStream(str->copy());
1462 }
1463 
1465  str->reset();
1466  bufPtr = bufEnd = buf;
1467  eof = gFalse;
1468 }
1469 
1470 int RunLengthStream::getBlock(char *blk, int size) {
1471  int n, m;
1472 
1473  n = 0;
1474  while (n < size) {
1475  if (bufPtr >= bufEnd) {
1476  if (!fillBuf()) {
1477  break;
1478  }
1479  }
1480  m = (int)(bufEnd - bufPtr);
1481  if (m > size - n) {
1482  m = size - n;
1483  }
1484  memcpy(blk + n, bufPtr, m);
1485  bufPtr += m;
1486  n += m;
1487  }
1488  return n;
1489 }
1490 
1491 GString *RunLengthStream::getPSFilter(int psLevel, const char *indent,
1492  GBool okToReadStream) {
1493  GString *s;
1494 
1495  if (psLevel < 2) {
1496  return NULL;
1497  }
1498  if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
1499  return NULL;
1500  }
1501  s->append(indent)->append("/RunLengthDecode filter\n");
1502  return s;
1503 }
1504 
1506  return str->isBinary(gTrue);
1507 }
1508 
1510  int c;
1511  int n, i;
1512 
1513  if (eof)
1514  return gFalse;
1515  c = str->getChar();
1516  if (c == 0x80 || c == EOF) {
1517  eof = gTrue;
1518  return gFalse;
1519  }
1520  if (c < 0x80) {
1521  n = c + 1;
1522  for (i = 0; i < n; ++i)
1523  buf[i] = (char)str->getChar();
1524  } else {
1525  n = 0x101 - c;
1526  c = str->getChar();
1527  for (i = 0; i < n; ++i)
1528  buf[i] = (char)c;
1529  }
1530  bufPtr = buf;
1531  bufEnd = buf + n;
1532  return gTrue;
1533 }
1534 
1535 //------------------------------------------------------------------------
1536 // CCITTFaxStream
1537 //------------------------------------------------------------------------
1538 
1539 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1540  GBool byteAlignA, int columnsA, int rowsA,
1541  GBool endOfBlockA, GBool blackA):
1542  FilterStream(strA) {
1543  encoding = encodingA;
1544  endOfLine = endOfLineA;
1545  byteAlign = byteAlignA;
1546  columns = columnsA;
1547  if (columns < 1) {
1548  columns = 1;
1549  } else if (columns > INT_MAX - 3) {
1550  columns = INT_MAX - 3;
1551  }
1552  rows = rowsA;
1553  endOfBlock = endOfBlockA;
1554  black = blackA;
1555  blackXOR = black ? 0xff : 0x00;
1556  // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
1557  // ---> max codingLine size = columns + 1
1558  // refLine has two extra guard entries at the end
1559  // ---> max refLine size = columns + 3
1560  codingLine = (int *)gmallocn(columns + 1, sizeof(int));
1561  refLine = (int *)gmallocn(columns + 3, sizeof(int));
1562 
1563  eof = gFalse;
1564  row = 0;
1565  nextLine2D = encoding < 0;
1566  inputBits = 0;
1567  codingLine[0] = columns;
1568  nextCol = columns;
1569  a0i = 0;
1570  err = gFalse;
1571  nErrors = 0;
1572 }
1573 
1575  delete str;
1576  gfree(refLine);
1577  gfree(codingLine);
1578 }
1579 
1581  return new CCITTFaxStream(str->copy(), encoding, endOfLine,
1583 }
1584 
1586  int code1;
1587 
1588  str->reset();
1589  eof = gFalse;
1590  row = 0;
1591  nextLine2D = encoding < 0;
1592  inputBits = 0;
1593  codingLine[0] = columns;
1594  nextCol = columns;
1595  a0i = 0;
1596 
1597  // skip any initial zero bits and end-of-line marker, and get the 2D
1598  // encoding tag
1599  while ((code1 = lookBits(12)) == 0) {
1600  eatBits(1);
1601  }
1602  if (code1 == 0x001) {
1603  eatBits(12);
1604  endOfLine = gTrue;
1605  }
1606  if (encoding > 0) {
1607  nextLine2D = !lookBits(1);
1608  eatBits(1);
1609  }
1610 }
1611 
1613  int c, bitsNeeded, bitsAvail, bitsUsed;
1614 
1615  if (nextCol >= columns) {
1616  if (eof) {
1617  return EOF;
1618  }
1619  if (!readRow()) {
1620  return EOF;
1621  }
1622  }
1623  bitsAvail = codingLine[a0i] - nextCol;
1624  if (bitsAvail > 8) {
1625  c = (a0i & 1) ? 0x00 : 0xff;
1626  } else {
1627  c = 0;
1628  bitsNeeded = 8;
1629  do {
1630  bitsUsed = (bitsAvail < bitsNeeded) ? bitsAvail : bitsNeeded;
1631  c <<= bitsUsed;
1632  if (!(a0i & 1)) {
1633  c |= 0xff >> (8 - bitsUsed);
1634  }
1635  bitsAvail -= bitsUsed;
1636  bitsNeeded -= bitsUsed;
1637  if (bitsAvail == 0) {
1638  if (codingLine[a0i] >= columns) {
1639  c <<= bitsNeeded;
1640  break;
1641  }
1642  ++a0i;
1643  bitsAvail = codingLine[a0i] - codingLine[a0i - 1];
1644  }
1645  } while (bitsNeeded > 0);
1646  }
1647  nextCol += 8;
1648  c ^= blackXOR;
1649  return c;
1650 }
1651 
1653  int c, bitsNeeded, bitsAvail, bitsUsed, i;
1654 
1655  if (nextCol >= columns) {
1656  if (eof) {
1657  return EOF;
1658  }
1659  if (!readRow()) {
1660  return EOF;
1661  }
1662  }
1663  bitsAvail = codingLine[a0i] - nextCol;
1664  if (bitsAvail >= 8) {
1665  c = (a0i & 1) ? 0x00 : 0xff;
1666  } else {
1667  i = a0i;
1668  c = 0;
1669  bitsNeeded = 8;
1670  do {
1671  bitsUsed = (bitsAvail < bitsNeeded) ? bitsAvail : bitsNeeded;
1672  c <<= bitsUsed;
1673  if (!(i & 1)) {
1674  c |= 0xff >> (8 - bitsUsed);
1675  }
1676  bitsAvail -= bitsUsed;
1677  bitsNeeded -= bitsUsed;
1678  if (bitsAvail == 0) {
1679  if (codingLine[i] >= columns) {
1680  c <<= bitsNeeded;
1681  break;
1682  }
1683  ++i;
1684  bitsAvail = codingLine[i] - codingLine[i - 1];
1685  }
1686  } while (bitsNeeded > 0);
1687  }
1688  c ^= blackXOR;
1689  return c;
1690 }
1691 
1692 int CCITTFaxStream::getBlock(char *blk, int size) {
1693  int bytesRead, bitsAvail, bitsNeeded, bitsUsed, byte, c;
1694 
1695  bytesRead = 0;
1696  while (bytesRead < size) {
1697  if (nextCol >= columns) {
1698  if (eof) {
1699  break;
1700  }
1701  if (!readRow()) {
1702  break;
1703  }
1704  }
1705  bitsAvail = codingLine[a0i] - nextCol;
1706  byte = (a0i & 1) ? 0x00 : 0xff;
1707  if (bitsAvail > 8) {
1708  c = byte;
1709  bitsAvail -= 8;
1710  } else {
1711  c = 0;
1712  bitsNeeded = 8;
1713  do {
1714  bitsUsed = (bitsAvail < bitsNeeded) ? bitsAvail : bitsNeeded;
1715  c <<= bitsUsed;
1716  c |= byte >> (8 - bitsUsed);
1717  bitsAvail -= bitsUsed;
1718  bitsNeeded -= bitsUsed;
1719  if (bitsAvail == 0) {
1720  if (codingLine[a0i] >= columns) {
1721  c <<= bitsNeeded;
1722  break;
1723  }
1724  ++a0i;
1725  bitsAvail = codingLine[a0i] - codingLine[a0i - 1];
1726  byte ^= 0xff;
1727  }
1728  } while (bitsNeeded > 0);
1729  }
1730  nextCol += 8;
1731  blk[bytesRead++] = (char)(c ^ blackXOR);
1732  }
1733  return bytesRead;
1734 }
1735 
1736 inline void CCITTFaxStream::addPixels(int a1, int blackPixels) {
1737  if (a1 > codingLine[a0i]) {
1738  if (a1 > columns) {
1740  "CCITTFax row is wrong length ({0:d})", a1);
1741  err = gTrue;
1742  ++nErrors;
1743  a1 = columns;
1744  }
1745  if ((a0i & 1) ^ blackPixels) {
1746  ++a0i;
1747  }
1748  codingLine[a0i] = a1;
1749  }
1750 }
1751 
1752 inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) {
1753  if (a1 > codingLine[a0i]) {
1754  if (a1 > columns) {
1756  "CCITTFax row is wrong length ({0:d})", a1);
1757  err = gTrue;
1758  ++nErrors;
1759  a1 = columns;
1760  }
1761  if ((a0i & 1) ^ blackPixels) {
1762  ++a0i;
1763  }
1764  codingLine[a0i] = a1;
1765  } else if (a1 < codingLine[a0i]) {
1766  if (a1 < 0) {
1767  error(errSyntaxError, getPos(), "Invalid CCITTFax code");
1768  err = gTrue;
1769  ++nErrors;
1770  a1 = 0;
1771  }
1772  while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
1773  --a0i;
1774  }
1775  codingLine[a0i] = a1;
1776  }
1777 }
1778 
1780  int code1, code2, code3;
1781  int b1i, blackPixels, i;
1782  GBool gotEOL;
1783 
1784  // if at eof just return EOF
1785  if (eof) {
1786  return gFalse;
1787  }
1788 
1789  err = gFalse;
1790 
1791  // 2-D encoding
1792  if (nextLine2D) {
1793  for (i = 0; codingLine[i] < columns; ++i) {
1794  refLine[i] = codingLine[i];
1795  }
1796  refLine[i++] = columns;
1797  refLine[i++] = columns;
1798  refLine[i] = columns;
1799  codingLine[0] = 0;
1800  a0i = 0;
1801  b1i = 0;
1802  blackPixels = 0;
1803  // invariant:
1804  // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
1805  // <= columns
1806  // exception at left edge:
1807  // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
1808  // exception at right edge:
1809  // refLine[b1i] = refLine[b1i+1] = columns is possible
1810  while (codingLine[a0i] < columns) {
1811  code1 = getTwoDimCode();
1812  switch (code1) {
1813  case twoDimPass:
1814  addPixels(refLine[b1i + 1], blackPixels);
1815  if (refLine[b1i + 1] < columns) {
1816  b1i += 2;
1817  }
1818  break;
1819  case twoDimHoriz:
1820  code1 = code2 = 0;
1821  if (blackPixels) {
1822  do {
1823  code1 += code3 = getBlackCode();
1824  } while (code3 >= 64);
1825  do {
1826  code2 += code3 = getWhiteCode();
1827  } while (code3 >= 64);
1828  } else {
1829  do {
1830  code1 += code3 = getWhiteCode();
1831  } while (code3 >= 64);
1832  do {
1833  code2 += code3 = getBlackCode();
1834  } while (code3 >= 64);
1835  }
1836  addPixels(codingLine[a0i] + code1, blackPixels);
1837  if (codingLine[a0i] < columns) {
1838  addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
1839  }
1840  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1841  b1i += 2;
1842  }
1843  break;
1844  case twoDimVertR3:
1845  addPixels(refLine[b1i] + 3, blackPixels);
1846  blackPixels ^= 1;
1847  if (codingLine[a0i] < columns) {
1848  ++b1i;
1849  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1850  b1i += 2;
1851  }
1852  }
1853  break;
1854  case twoDimVertR2:
1855  addPixels(refLine[b1i] + 2, blackPixels);
1856  blackPixels ^= 1;
1857  if (codingLine[a0i] < columns) {
1858  ++b1i;
1859  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1860  b1i += 2;
1861  }
1862  }
1863  break;
1864  case twoDimVertR1:
1865  addPixels(refLine[b1i] + 1, blackPixels);
1866  blackPixels ^= 1;
1867  if (codingLine[a0i] < columns) {
1868  ++b1i;
1869  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1870  b1i += 2;
1871  }
1872  }
1873  break;
1874  case twoDimVert0:
1875  addPixels(refLine[b1i], blackPixels);
1876  blackPixels ^= 1;
1877  if (codingLine[a0i] < columns) {
1878  ++b1i;
1879  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1880  b1i += 2;
1881  }
1882  }
1883  break;
1884  case twoDimVertL3:
1885  addPixelsNeg(refLine[b1i] - 3, blackPixels);
1886  blackPixels ^= 1;
1887  if (codingLine[a0i] < columns) {
1888  if (b1i > 0) {
1889  --b1i;
1890  } else {
1891  ++b1i;
1892  }
1893  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1894  b1i += 2;
1895  }
1896  }
1897  break;
1898  case twoDimVertL2:
1899  addPixelsNeg(refLine[b1i] - 2, blackPixels);
1900  blackPixels ^= 1;
1901  if (codingLine[a0i] < columns) {
1902  if (b1i > 0) {
1903  --b1i;
1904  } else {
1905  ++b1i;
1906  }
1907  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1908  b1i += 2;
1909  }
1910  }
1911  break;
1912  case twoDimVertL1:
1913  addPixelsNeg(refLine[b1i] - 1, blackPixels);
1914  blackPixels ^= 1;
1915  if (codingLine[a0i] < columns) {
1916  if (b1i > 0) {
1917  --b1i;
1918  } else {
1919  ++b1i;
1920  }
1921  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1922  b1i += 2;
1923  }
1924  }
1925  break;
1926  case EOF:
1927  addPixels(columns, 0);
1928  err = gTrue;
1929  break;
1930  default:
1932  "Bad 2D code {0:04x} in CCITTFax stream", code1);
1933  addPixels(columns, 0);
1934  err = gTrue;
1935  ++nErrors;
1936  break;
1937  }
1938  }
1939 
1940  // 1-D encoding
1941  } else {
1942  codingLine[0] = 0;
1943  a0i = 0;
1944  blackPixels = 0;
1945  while (codingLine[a0i] < columns) {
1946  code1 = 0;
1947  if (blackPixels) {
1948  do {
1949  code1 += code3 = getBlackCode();
1950  } while (code3 >= 64);
1951  } else {
1952  do {
1953  code1 += code3 = getWhiteCode();
1954  } while (code3 >= 64);
1955  }
1956  addPixels(codingLine[a0i] + code1, blackPixels);
1957  blackPixels ^= 1;
1958  }
1959  }
1960 
1961  // check for end-of-line marker, skipping over any extra zero bits
1962  // (if EncodedByteAlign is true and EndOfLine is false, there can
1963  // be "false" EOL markers -- i.e., if the last n unused bits in
1964  // row i are set to zero, and the first 11-n bits in row i+1
1965  // happen to be zero -- so we don't look for EOL markers in this
1966  // case)
1967  gotEOL = gFalse;
1968  if (!endOfBlock && row == rows - 1) {
1969  eof = gTrue;
1970  } else if (endOfLine || !byteAlign) {
1971  code1 = lookBits(12);
1972  if (endOfLine) {
1973  while (code1 != EOF && code1 != 0x001) {
1974  eatBits(1);
1975  code1 = lookBits(12);
1976  }
1977  } else {
1978  while (code1 == 0) {
1979  eatBits(1);
1980  code1 = lookBits(12);
1981  }
1982  }
1983  if (code1 == 0x001) {
1984  eatBits(12);
1985  gotEOL = gTrue;
1986  }
1987  }
1988 
1989  // byte-align the row
1990  // (Adobe apparently doesn't do byte alignment after EOL markers
1991  // -- I've seen CCITT image data streams in two different formats,
1992  // both with the byteAlign flag set:
1993  // 1. xx:x0:01:yy:yy
1994  // 2. xx:00:1y:yy:yy
1995  // where xx is the previous line, yy is the next line, and colons
1996  // separate bytes.)
1997  if (byteAlign && !gotEOL) {
1998  inputBits &= ~7;
1999  }
2000 
2001  // check for end of stream
2002  if (lookBits(1) == EOF) {
2003  eof = gTrue;
2004  }
2005 
2006  // get 2D encoding tag
2007  if (!eof && encoding > 0) {
2008  nextLine2D = !lookBits(1);
2009  eatBits(1);
2010  }
2011 
2012  // check for end-of-block marker
2013  if (endOfBlock && !endOfLine && byteAlign) {
2014  // in this case, we didn't check for an EOL code above, so we
2015  // need to check here
2016  code1 = lookBits(24);
2017  if (code1 == 0x001001) {
2018  eatBits(12);
2019  gotEOL = gTrue;
2020  }
2021  }
2022  if (endOfBlock && gotEOL) {
2023  code1 = lookBits(12);
2024  if (code1 == 0x001) {
2025  eatBits(12);
2026  if (encoding > 0) {
2027  lookBits(1);
2028  eatBits(1);
2029  }
2030  if (encoding > 0) {
2031  for (i = 0; i < 4; ++i) {
2032  code1 = lookBits(12);
2033  if (code1 != 0x001) {
2035  "Bad RTC code in CCITTFax stream");
2036  ++nErrors;
2037  }
2038  eatBits(12);
2039  if (encoding > 0) {
2040  lookBits(1);
2041  eatBits(1);
2042  }
2043  }
2044  }
2045  eof = gTrue;
2046  }
2047 
2048  // look for an end-of-line marker after an error -- we only do
2049  // this if we know the stream contains end-of-line markers because
2050  // the "just plow on" technique tends to work better otherwise
2051  } else if (err && endOfLine) {
2052  while (1) {
2053  code1 = lookBits(13);
2054  if (code1 == EOF) {
2055  eof = gTrue;
2056  return gFalse;
2057  }
2058  if ((code1 >> 1) == 0x001) {
2059  break;
2060  }
2061  eatBits(1);
2062  }
2063  eatBits(12);
2064  if (encoding > 0) {
2065  eatBits(1);
2066  nextLine2D = !(code1 & 1);
2067  }
2068  }
2069 
2070  // corrupt CCITTFax streams can generate huge data expansion -- we
2071  // avoid that case by aborting decode after 1000 errors
2072  if (nErrors > 1000) {
2073  error(errSyntaxError, getPos(), "Too many errors in CCITTFaxStream - aborting decode");
2074  eof = gTrue;
2075  return gFalse;
2076  }
2077 
2078  // set up for output
2079  nextCol = 0;
2080  a0i = (codingLine[0] > 0) ? 0 : 1;
2081 
2082  ++row;
2083 
2084  return gTrue;
2085 }
2086 
2088  int code;
2089  CCITTCode *p;
2090  int n;
2091 
2092  code = 0; // make gcc happy
2093  if (endOfBlock) {
2094  if ((code = lookBits(7)) != EOF) {
2095  p = &twoDimTab1[code];
2096  if (p->bits > 0) {
2097  eatBits(p->bits);
2098  return p->n;
2099  }
2100  }
2101  } else {
2102  for (n = 1; n <= 7; ++n) {
2103  if ((code = lookBits(n)) == EOF) {
2104  break;
2105  }
2106  if (n < 7) {
2107  code <<= 7 - n;
2108  }
2109  p = &twoDimTab1[code];
2110  if (p->bits == n) {
2111  eatBits(n);
2112  return p->n;
2113  }
2114  }
2115  }
2117  "Bad two dim code ({0:04x}) in CCITTFax stream", code);
2118  ++nErrors;
2119  return EOF;
2120 }
2121 
2123  short code;
2124  CCITTCode *p;
2125  int n;
2126 
2127  code = 0; // make gcc happy
2128  if (endOfBlock) {
2129  code = lookBits(12);
2130  if (code == EOF) {
2131  return 1;
2132  }
2133  if ((code >> 5) == 0) {
2134  p = &whiteTab1[code];
2135  } else {
2136  p = &whiteTab2[code >> 3];
2137  }
2138  if (p->bits > 0) {
2139  eatBits(p->bits);
2140  return p->n;
2141  }
2142  } else {
2143  for (n = 1; n <= 9; ++n) {
2144  code = lookBits(n);
2145  if (code == EOF) {
2146  return 1;
2147  }
2148  if (n < 9) {
2149  code = (short)(code << (9 - n));
2150  }
2151  p = &whiteTab2[code];
2152  if (p->bits == n) {
2153  eatBits(n);
2154  return p->n;
2155  }
2156  }
2157  for (n = 11; n <= 12; ++n) {
2158  code = lookBits(n);
2159  if (code == EOF) {
2160  return 1;
2161  }
2162  if (n < 12) {
2163  code = (short)(code << (12 - n));
2164  }
2165  p = &whiteTab1[code];
2166  if (p->bits == n) {
2167  eatBits(n);
2168  return p->n;
2169  }
2170  }
2171  }
2173  "Bad white code ({0:04x}) in CCITTFax stream", code);
2174  ++nErrors;
2175  // eat a bit and return a positive number so that the caller doesn't
2176  // go into an infinite loop
2177  eatBits(1);
2178  return 1;
2179 }
2180 
2182  short code;
2183  CCITTCode *p;
2184  int n;
2185 
2186  code = 0; // make gcc happy
2187  if (endOfBlock) {
2188  code = lookBits(13);
2189  if (code == EOF) {
2190  return 1;
2191  }
2192  if ((code >> 7) == 0) {
2193  p = &blackTab1[code];
2194  } else if ((code >> 9) == 0 && (code >> 7) != 0) {
2195  p = &blackTab2[(code >> 1) - 64];
2196  } else {
2197  p = &blackTab3[code >> 7];
2198  }
2199  if (p->bits > 0) {
2200  eatBits(p->bits);
2201  return p->n;
2202  }
2203  } else {
2204  for (n = 2; n <= 6; ++n) {
2205  code = lookBits(n);
2206  if (code == EOF) {
2207  return 1;
2208  }
2209  if (n < 6) {
2210  code = (short)(code << (6 - n));
2211  }
2212  p = &blackTab3[code];
2213  if (p->bits == n) {
2214  eatBits(n);
2215  return p->n;
2216  }
2217  }
2218  for (n = 7; n <= 12; ++n) {
2219  code = lookBits(n);
2220  if (code == EOF) {
2221  return 1;
2222  }
2223  if (n < 12) {
2224  code = (short)(code << (12 - n));
2225  }
2226  if (code >= 64) {
2227  p = &blackTab2[code - 64];
2228  if (p->bits == n) {
2229  eatBits(n);
2230  return p->n;
2231  }
2232  }
2233  }
2234  for (n = 10; n <= 13; ++n) {
2235  code = lookBits(n);
2236  if (code == EOF) {
2237  return 1;
2238  }
2239  if (n < 13) {
2240  code = (short)(code << (13 - n));
2241  }
2242  p = &blackTab1[code];
2243  if (p->bits == n) {
2244  eatBits(n);
2245  return p->n;
2246  }
2247  }
2248  }
2250  "Bad black code ({0:04x}) in CCITTFax stream", code);
2251  ++nErrors;
2252  // eat a bit and return a positive number so that the caller doesn't
2253  // go into an infinite loop
2254  eatBits(1);
2255  return 1;
2256 }
2257 
2259  int c;
2260 
2261  while (inputBits < n) {
2262  if ((c = str->getChar()) == EOF) {
2263  if (inputBits == 0) {
2264  return EOF;
2265  }
2266  // near the end of the stream, the caller may ask for more bits
2267  // than are available, but there may still be a valid code in
2268  // however many bits are available -- we need to return correct
2269  // data in this case
2270  return (short)((inputBuf << (n - inputBits)) & (0xffffffff >> (32 - n)));
2271  }
2272  inputBuf = (inputBuf << 8) + c;
2273  inputBits += 8;
2274  }
2275  return (short)((inputBuf >> (inputBits - n)) & (0xffffffff >> (32 - n)));
2276 }
2277 
2278 GString *CCITTFaxStream::getPSFilter(int psLevel, const char *indent,
2279  GBool okToReadStream) {
2280  GString *s;
2281 
2282  if (psLevel < 2) {
2283  return NULL;
2284  }
2285  if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
2286  return NULL;
2287  }
2288  s->append(indent)->append("<< ");
2289  if (encoding != 0) {
2290  s->appendf("/K {0:d} ", encoding);
2291  }
2292  if (endOfLine) {
2293  s->append("/EndOfLine true ");
2294  }
2295  if (byteAlign) {
2296  s->append("/EncodedByteAlign true ");
2297  }
2298  s->appendf("/Columns {0:d} ", columns);
2299  if (rows != 0) {
2300  s->appendf("/Rows {0:d} ", rows);
2301  }
2302  if (!endOfBlock) {
2303  s->append("/EndOfBlock false ");
2304  }
2305  if (black) {
2306  s->append("/BlackIs1 true ");
2307  }
2308  s->append(">> /CCITTFaxDecode filter\n");
2309  return s;
2310 }
2311 
2313  return str->isBinary(gTrue);
2314 }
2315 
2316 //------------------------------------------------------------------------
2317 // DCTStream
2318 //------------------------------------------------------------------------
2319 
2320 #if HAVE_JPEGLIB
2321 
2322 DCTStream::DCTStream(Stream *strA, GBool colorXformA):
2323  FilterStream(strA) {
2324  colorXform = colorXformA;
2325  lineBuf = NULL;
2326  inlineImage = str->isEmbedStream();
2327 }
2328 
2330  delete str;
2331 }
2332 
2334  return new DCTStream(str->copy(), colorXform);
2335 }
2336 
2337 void DCTStream::reset() {
2338  int i;
2339 
2340  lineBuf = NULL;
2341  error = gFalse;
2342 
2343  str->reset();
2344 
2345  // initialize the libjpeg decompression object
2346  decomp.err = jpeg_std_error(&errorMgr.err);
2347  errorMgr.err.error_exit = &errorExit;
2348  errorMgr.err.output_message = &errorMessage;
2349  if (setjmp(errorMgr.setjmpBuf)) {
2350  error = gTrue;
2351  return;
2352  }
2354 
2355  // set up the data source manager
2356  sourceMgr.src.next_input_byte = NULL;
2357  sourceMgr.src.bytes_in_buffer = 0;
2358  sourceMgr.src.init_source = &initSourceCbk;
2359  sourceMgr.src.fill_input_buffer = &fillInputBufferCbk;
2360  sourceMgr.src.skip_input_data = &skipInputDataCbk;
2361  sourceMgr.src.resync_to_restart = &jpeg_resync_to_restart;
2362  sourceMgr.src.term_source = &termSourceCbk;
2363  sourceMgr.str = this;
2364  decomp.src = &sourceMgr.src;
2365 
2366  // read the header
2369 
2370  // set up the color transform
2371  if (!decomp.saw_Adobe_marker && colorXform >= 0) {
2372  if (decomp.num_components == 3) {
2373  decomp.jpeg_color_space = colorXform ? JCS_YCbCr : JCS_RGB;
2374  decomp.out_color_space = JCS_RGB;
2375  decomp.out_color_components = 3;
2376  } else if (decomp.num_components == 4) {
2377  decomp.jpeg_color_space = colorXform ? JCS_YCCK : JCS_CMYK;
2378  decomp.out_color_space = JCS_CMYK;
2379  decomp.out_color_components = 4;
2380  }
2381  }
2382 
2383  // allocate a line buffer
2384  if ((lineBufHeight = decomp.rec_outbuf_height) > 4) {
2385  lineBufHeight = 4;
2386  }
2387  lineBuf = (char *)gmallocn(lineBufHeight * decomp.out_color_components,
2388  decomp.output_width);
2389  for (i = 0; i < lineBufHeight; ++i) {
2390  lineBufRows[i] = lineBuf +
2391  i * decomp.out_color_components * decomp.output_width;
2392  }
2393  bufPtr = bufEnd = lineBuf;
2394 
2395  // start up the decompression process
2397 }
2398 
2400  //~ this is unimplemented
2401  return gTrue;
2402 }
2403 
2404 void DCTStream::close() {
2405  // we don't call jpeg_finish_decompress() here because it will report
2406  // an error if the full image wasn't read
2407  if (setjmp(errorMgr.setjmpBuf)) {
2408  goto skip;
2409  }
2411  skip:
2412  gfree(lineBuf);
2414 }
2415 
2416 int DCTStream::getChar() {
2417  if (error) {
2418  return EOF;
2419  }
2420  if (bufPtr == bufEnd) {
2421  if (!fillBuf()) {
2422  return EOF;
2423  }
2424  }
2425  return *bufPtr++ & 0xff;
2426 }
2427 
2428 int DCTStream::lookChar() {
2429  if (error) {
2430  return EOF;
2431  }
2432  if (bufPtr == bufEnd) {
2433  if (!fillBuf()) {
2434  return EOF;
2435  }
2436  }
2437  return *bufPtr & 0xff;
2438 }
2439 
2440 int DCTStream::getBlock(char *blk, int size) {
2441  int nRead, nAvail, n;
2442 
2443  if (error) {
2444  return 0;
2445  }
2446  nRead = 0;
2447  while (nRead < size) {
2448  if (bufPtr == bufEnd) {
2449  if (!fillBuf()) {
2450  break;
2451  }
2452  }
2453  nAvail = bufEnd - bufPtr;
2454  n = (nAvail < size - nRead) ? nAvail : size - nRead;
2455  memcpy(blk + nRead, bufPtr, n);
2456  bufPtr += n;
2457  nRead += n;
2458  }
2459  return nRead;
2460 }
2461 
2462 GBool DCTStream::fillBuf() {
2463  int nLines;
2464 
2465  if (setjmp(errorMgr.setjmpBuf)) {
2466  error = gTrue;
2467  return gFalse;
2468  }
2469  nLines = jpeg_read_scanlines(&decomp, (JSAMPARRAY)lineBufRows,
2470  lineBufHeight);
2471  bufPtr = lineBuf;
2472  bufEnd = lineBuf +
2473  nLines * decomp.out_color_components * decomp.output_width;
2474  return nLines > 0;
2475 }
2476 
2477 void DCTStream::errorExit(j_common_ptr d) {
2478  DCTErrorMgr *errMgr = (DCTErrorMgr *)d->err;
2479  longjmp(errMgr->setjmpBuf, 1);
2480 }
2481 
2483 #if 0 // for debugging
2484  char buf[JMSG_LENGTH_MAX];
2485 
2486  (*d->err->format_message)(d, buf);
2487  fprintf(stderr, "%s\n", buf);
2488 #endif
2489 }
2490 
2491 void DCTStream::initSourceCbk(j_decompress_ptr d) {
2492  DCTSourceMgr *sourceMgr = (DCTSourceMgr *)d->src;
2493 
2494  sourceMgr->src.next_input_byte = NULL;
2495  sourceMgr->src.bytes_in_buffer = 0;
2496 }
2497 
2498 boolean DCTStream::fillInputBufferCbk(j_decompress_ptr d) {
2499  DCTSourceMgr *sourceMgr = (DCTSourceMgr *)d->src;
2500  int c, n;
2501 
2502  // for inline images, we need to read one byte at a time so we don't
2503  // read past the end of the input data
2504  if (sourceMgr->str->inlineImage) {
2505  c = sourceMgr->str->str->getChar();
2506  if (c == EOF) {
2507  sourceMgr->buf[0] = (char)0xff;
2508  sourceMgr->buf[1] = (char)JPEG_EOI;
2509  sourceMgr->src.bytes_in_buffer = 2;
2510  } else {
2511  sourceMgr->buf[0] = (char)c;
2512  sourceMgr->src.bytes_in_buffer = 1;
2513  }
2514  } else {
2515  n = sourceMgr->str->str->getBlock(sourceMgr->buf, dctStreamBufSize);
2516  if (n > 0) {
2517  sourceMgr->src.bytes_in_buffer = (size_t)n;
2518  } else {
2519  sourceMgr->buf[0] = (char)0xff;
2520  sourceMgr->buf[1] = (char)JPEG_EOI;
2521  sourceMgr->src.bytes_in_buffer = 2;
2522  }
2523  }
2524  sourceMgr->src.next_input_byte = (JOCTET *)sourceMgr->buf;
2525  return TRUE;
2526 }
2527 
2528 void DCTStream::skipInputDataCbk(j_decompress_ptr d, long numBytes) {
2529  DCTSourceMgr *sourceMgr = (DCTSourceMgr *)d->src;
2530 
2531  if (numBytes > 0) {
2532  if ((long)sourceMgr->src.bytes_in_buffer < numBytes) {
2533  sourceMgr->str->str->discardChars(
2534  (Guint)(numBytes - sourceMgr->src.bytes_in_buffer));
2535  sourceMgr->src.bytes_in_buffer = 0;
2536  } else {
2537  sourceMgr->src.bytes_in_buffer -= numBytes;
2538  sourceMgr->src.next_input_byte += numBytes;
2539  }
2540  }
2541 }
2542 
2543 void DCTStream::termSourceCbk(j_decompress_ptr d) {
2544 }
2545 
2546 #else // HAVE_JPEGLIB
2547 
2548 #define idctScaleA 1024
2549 #define idctScaleB 1138
2550 #define idctScaleC 1730
2551 #define idctScaleD 1609
2552 #define idctScaleE 1264
2553 #define idctScaleF 1922
2554 #define idctScaleG 1788
2555 #define idctScaleH 2923
2556 #define idctScaleI 2718
2557 #define idctScaleJ 2528
2558 
2559 static int idctScaleMat[64] = {
2568 };
2569 
2570 // color conversion parameters (16.16 fixed point format)
2571 #define dctCrToR 91881 // 1.4020
2572 #define dctCbToG -22553 // -0.3441363
2573 #define dctCrToG -46802 // -0.71413636
2574 #define dctCbToB 116130 // 1.772
2575 
2576 // The dctClip function clips signed integers to the [0,255] range.
2577 // To handle valid DCT inputs, this must support an input range of at
2578 // least [-256,511]. Invalid DCT inputs (e.g., from damaged PDF
2579 // files) can result in arbitrary values, so we want to mask those
2580 // out. We round the input range size up to a power of 2 (so we can
2581 // use a bit mask), which gives us an input range of [-384,639]. The
2582 // end result is:
2583 // input output
2584 // ---------- ------
2585 // <-384 X invalid inputs -> output is "don't care"
2586 // -384..-257 0 invalid inputs, clipped
2587 // -256..-1 0 valid inputs, need to be clipped
2588 // 0..255 0..255
2589 // 256..511 255 valid inputs, need to be clipped
2590 // 512..639 255 invalid inputs, clipped
2591 // >=512 X invalid inputs -> output is "don't care"
2592 
2593 #define dctClipOffset 384
2594 #define dctClipMask 1023
2595 static Guchar dctClipData[1024];
2596 
2597 static inline void dctClipInit() {
2598  static int initDone = 0;
2599  int i;
2600  if (!initDone) {
2601  for (i = -384; i < 0; ++i) {
2602  dctClipData[dctClipOffset + i] = 0;
2603  }
2604  for (i = 0; i < 256; ++i) {
2606  }
2607  for (i = 256; i < 639; ++i) {
2608  dctClipData[dctClipOffset + i] = 255;
2609  }
2610  initDone = 1;
2611  }
2612 }
2613 
2614 static inline Guchar dctClip(int x) {
2615  return dctClipData[(dctClipOffset + x) & dctClipMask];
2616 }
2617 
2618 // zig zag decode map
2619 static int dctZigZag[64] = {
2620  0,
2621  1, 8,
2622  16, 9, 2,
2623  3, 10, 17, 24,
2624  32, 25, 18, 11, 4,
2625  5, 12, 19, 26, 33, 40,
2626  48, 41, 34, 27, 20, 13, 6,
2627  7, 14, 21, 28, 35, 42, 49, 56,
2628  57, 50, 43, 36, 29, 22, 15,
2629  23, 30, 37, 44, 51, 58,
2630  59, 52, 45, 38, 31,
2631  39, 46, 53, 60,
2632  61, 54, 47,
2633  55, 62,
2634  63
2635 };
2636 
2637 DCTStream::DCTStream(Stream *strA, GBool colorXformA):
2638  FilterStream(strA) {
2639  int i;
2640 
2641  colorXform = colorXformA;
2643  width = height = 0;
2644  mcuWidth = mcuHeight = 0;
2645  numComps = 0;
2646  comp = 0;
2647  x = y = 0;
2648  for (i = 0; i < 4; ++i) {
2649  frameBuf[i] = NULL;
2650  }
2651  rowBuf = NULL;
2652  memset(dcHuffTables, 0, sizeof(dcHuffTables));
2653  memset(acHuffTables, 0, sizeof(acHuffTables));
2654 
2655  dctClipInit();
2656 }
2657 
2659  close();
2660  delete str;
2661 }
2662 
2664  return new DCTStream(str->copy(), colorXform);
2665 }
2666 
2668  int i;
2669 
2670  str->reset();
2671 
2673  width = height = 0;
2674  numComps = 0;
2675  numQuantTables = 0;
2676  numDCHuffTables = 0;
2677  numACHuffTables = 0;
2680  restartInterval = 0;
2681 
2682  if (!readHeader(gTrue)) {
2683  // force an EOF condition
2684  progressive = gTrue;
2685  y = height;
2686  return;
2687  }
2688 
2689  // compute MCU size
2690  if (numComps == 1) {
2691  compInfo[0].hSample = compInfo[0].vSample = 1;
2692  }
2693  mcuWidth = compInfo[0].hSample;
2694  mcuHeight = compInfo[0].vSample;
2695  for (i = 1; i < numComps; ++i) {
2696  if (compInfo[i].hSample > mcuWidth) {
2698  }
2699  if (compInfo[i].vSample > mcuHeight) {
2701  }
2702  }
2703  mcuWidth *= 8;
2704  mcuHeight *= 8;
2705 
2706  // figure out color transform
2707  if (colorXform == -1) {
2708  if (numComps == 3) {
2709  if (gotJFIFMarker) {
2710  colorXform = 1;
2711  } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
2712  compInfo[2].id == 66) { // ASCII "RGB"
2713  colorXform = 0;
2714  } else {
2715  colorXform = 1;
2716  }
2717  } else {
2718  colorXform = 0;
2719  }
2720  }
2721 
2722  if (progressive || !interleaved) {
2723 
2724  // allocate a buffer for the whole image
2725  bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2726  bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
2727  if (bufWidth <= 0 || bufHeight <= 0 ||
2728  bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
2729  error(errSyntaxError, getPos(), "Invalid image size in DCT stream");
2730  y = height;
2731  return;
2732  }
2733  for (i = 0; i < numComps; ++i) {
2734  frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
2735  memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
2736  }
2737 
2738  // read the image data
2739  do {
2740  restartMarker = 0xd0;
2741  restart();
2742  readScan();
2743  } while (readHeader(gFalse));
2744 
2745  // decode
2746  decodeImage();
2747 
2748  // initialize counters
2749  comp = 0;
2750  x = 0;
2751  y = 0;
2752 
2753  } else {
2754 
2755  if (scanInfo.numComps != numComps) {
2756  error(errSyntaxError, getPos(), "Invalid scan in sequential DCT stream");
2757  y = height;
2758  return;
2759  }
2760 
2761  // allocate a buffer for one row of MCUs
2762  bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2765 
2766  // initialize counters
2767  y = -mcuHeight;
2768 
2769  restartMarker = 0xd0;
2770  restart();
2771  }
2772 }
2773 
2775  GBool headerOk;
2776 
2777  str->reset();
2778 
2780  width = height = 0;
2781  numComps = 0;
2782  numQuantTables = 0;
2783  numDCHuffTables = 0;
2784  numACHuffTables = 0;
2787  restartInterval = 0;
2788 
2789  headerOk = readHeader(gTrue);
2790 
2792 
2793  return headerOk && !progressive && interleaved;
2794 }
2795 
2797  int i;
2798 
2799  for (i = 0; i < 4; ++i) {
2800  gfree(frameBuf[i]);
2801  frameBuf[i] = NULL;
2802  }
2803  gfree(rowBuf);
2804  rowBuf = NULL;
2806 }
2807 
2809  int c;
2810 
2811  if (progressive || !interleaved) {
2812  if (y >= height) {
2813  return EOF;
2814  }
2815  c = frameBuf[comp][y * bufWidth + x];
2816  if (++comp == numComps) {
2817  comp = 0;
2818  if (++x == width) {
2819  x = 0;
2820  ++y;
2821  }
2822  }
2823  } else {
2824  if (rowBufPtr == rowBufEnd) {
2825  if (y + mcuHeight >= height) {
2826  return EOF;
2827  }
2828  y += mcuHeight;
2829  if (!readMCURow()) {
2830  y = height;
2831  return EOF;
2832  }
2833  }
2834  c = *rowBufPtr++;
2835  }
2836  return c;
2837 }
2838 
2840  if (progressive || !interleaved) {
2841  if (y >= height) {
2842  return EOF;
2843  }
2844  return frameBuf[comp][y * bufWidth + x];
2845  } else {
2846  if (rowBufPtr == rowBufEnd) {
2847  if (y + mcuHeight >= height) {
2848  return EOF;
2849  }
2850  if (!readMCURow()) {
2851  y = height;
2852  return EOF;
2853  }
2854  }
2855  return *rowBufPtr;
2856  }
2857 }
2858 
2859 int DCTStream::getBlock(char *blk, int size) {
2860  int nRead, nAvail, n;
2861 
2862  if (progressive || !interleaved) {
2863  if (y >= height) {
2864  return 0;
2865  }
2866  for (nRead = 0; nRead < size; ++nRead) {
2867  blk[nRead] = (char)frameBuf[comp][y * bufWidth + x];
2868  if (++comp == numComps) {
2869  comp = 0;
2870  if (++x == width) {
2871  x = 0;
2872  ++y;
2873  if (y >= height) {
2874  ++nRead;
2875  break;
2876  }
2877  }
2878  }
2879  }
2880  } else {
2881  nRead = 0;
2882  while (nRead < size) {
2883  if (rowBufPtr == rowBufEnd) {
2884  if (y + mcuHeight >= height) {
2885  break;
2886  }
2887  y += mcuHeight;
2888  if (!readMCURow()) {
2889  y = height;
2890  break;
2891  }
2892  }
2893  nAvail = (int)(rowBufEnd - rowBufPtr);
2894  n = (nAvail < size - nRead) ? nAvail : size - nRead;
2895  memcpy(blk + nRead, rowBufPtr, n);
2896  rowBufPtr += n;
2897  nRead += n;
2898  }
2899  }
2900  return nRead;
2901 }
2902 
2904  int i;
2905 
2906  inputBits = 0;
2908  for (i = 0; i < numComps; ++i) {
2909  compInfo[i].prevDC = 0;
2910  }
2911  eobRun = 0;
2912 }
2913 
2914 // Read one row of MCUs from a sequential JPEG stream.
2916  int data1[64];
2917  Guchar data2[64];
2918  Guchar *p1, *p2;
2919  int pY, pCb, pCr, pR, pG, pB;
2920  int h, v, horiz, vert, hSub, vSub;
2921  int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2922  int c;
2923 
2924  for (cc = 0; cc < numComps; ++cc) {
2925  if (scanInfo.dcHuffTable[cc] >= numDCHuffTables ||
2928  "Bad DCT data: invalid Huffman table index");
2929  return gFalse;
2930  }
2931  if (compInfo[cc].quantTable > numQuantTables) {
2933  "Bad DCT data: invalid quant table index");
2934  return gFalse;
2935  }
2936  }
2937 
2938  for (x1 = 0; x1 < width; x1 += mcuWidth) {
2939 
2940  // deal with restart marker
2941  if (restartInterval > 0 && restartCtr == 0) {
2942  c = readMarker();
2943  if (c != restartMarker) {
2945  "Bad DCT data: incorrect restart marker");
2946  return gFalse;
2947  }
2948  if (++restartMarker == 0xd8)
2949  restartMarker = 0xd0;
2950  restart();
2951  }
2952 
2953  // read one MCU
2954  for (cc = 0; cc < numComps; ++cc) {
2955  h = compInfo[cc].hSample;
2956  v = compInfo[cc].vSample;
2957  horiz = mcuWidth / h;
2958  vert = mcuHeight / v;
2959  hSub = horiz / 8;
2960  vSub = vert / 8;
2961  for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2962  for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2965  &compInfo[cc].prevDC,
2966  data1)) {
2967  return gFalse;
2968  }
2969  transformDataUnit(quantTables[compInfo[cc].quantTable],
2970  data1, data2);
2971  if (hSub == 1 && vSub == 1 && x1+x2+8 <= width) {
2972  for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2973  p1 = &rowBuf[((y2+y3) * width + (x1+x2)) * numComps + cc];
2974  p1[0] = data2[i];
2975  p1[ numComps] = data2[i+1];
2976  p1[2*numComps] = data2[i+2];
2977  p1[3*numComps] = data2[i+3];
2978  p1[4*numComps] = data2[i+4];
2979  p1[5*numComps] = data2[i+5];
2980  p1[6*numComps] = data2[i+6];
2981  p1[7*numComps] = data2[i+7];
2982  }
2983  } else if (hSub == 2 && vSub == 2 && x1+x2+16 <= width) {
2984  for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2985  p1 = &rowBuf[((y2+y3) * width + (x1+x2)) * numComps + cc];
2986  p2 = p1 + width * numComps;
2987  p1[0] = p1[numComps] =
2988  p2[0] = p2[numComps] = data2[i];
2989  p1[2*numComps] = p1[3*numComps] =
2990  p2[2*numComps] = p2[3*numComps] = data2[i+1];
2991  p1[4*numComps] = p1[5*numComps] =
2992  p2[4*numComps] = p2[5*numComps] = data2[i+2];
2993  p1[6*numComps] = p1[7*numComps] =
2994  p2[6*numComps] = p2[7*numComps] = data2[i+3];
2995  p1[8*numComps] = p1[9*numComps] =
2996  p2[8*numComps] = p2[9*numComps] = data2[i+4];
2997  p1[10*numComps] = p1[11*numComps] =
2998  p2[10*numComps] = p2[11*numComps] = data2[i+5];
2999  p1[12*numComps] = p1[13*numComps] =
3000  p2[12*numComps] = p2[13*numComps] = data2[i+6];
3001  p1[14*numComps] = p1[15*numComps] =
3002  p2[14*numComps] = p2[15*numComps] = data2[i+7];
3003  }
3004  } else {
3005  p1 = &rowBuf[(y2 * width + (x1+x2)) * numComps + cc];
3006  i = 0;
3007  for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
3008  for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
3009  for (y5 = 0; y5 < vSub; ++y5) {
3010  for (x5 = 0; x5 < hSub && x1+x2+x4+x5 < width; ++x5) {
3011  p1[((y4+y5) * width + (x4+x5)) * numComps] = data2[i];
3012  }
3013  }
3014  ++i;
3015  }
3016  }
3017  }
3018  }
3019  }
3020  }
3021  --restartCtr;
3022  }
3023 
3024  // color space conversion
3025  if (colorXform) {
3026  // convert YCbCr to RGB
3027  if (numComps == 3) {
3028  for (i = 0, p1 = rowBuf; i < width * mcuHeight; ++i, p1 += 3) {
3029  pY = p1[0];
3030  pCb = p1[1] - 128;
3031  pCr = p1[2] - 128;
3032  pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3033  p1[0] = dctClip(pR);
3034  pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
3035  p1[1] = dctClip(pG);
3036  pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3037  p1[2] = dctClip(pB);
3038  }
3039  // convert YCbCrK to CMYK (K is passed through unchanged)
3040  } else if (numComps == 4) {
3041  for (i = 0, p1 = rowBuf; i < width * mcuHeight; ++i, p1 += 4) {
3042  pY = p1[0];
3043  pCb = p1[1] - 128;
3044  pCr = p1[2] - 128;
3045  pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3046  p1[0] = (Guchar)(255 - dctClip(pR));
3047  pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
3048  p1[1] = (Guchar)(255 - dctClip(pG));
3049  pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3050  p1[2] = (Guchar)(255 - dctClip(pB));
3051  }
3052  }
3053  }
3054 
3055  rowBufPtr = rowBuf;
3056  if (y + mcuHeight <= height) {
3058  } else {
3059  rowBufEnd = rowBuf + numComps * width * (height - y);
3060  }
3061 
3062  return gTrue;
3063 }
3064 
3065 // Read one scan from a progressive or non-interleaved JPEG stream.
3067  int data[64];
3068  int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
3069  int h, v, horiz, vert, vSub;
3070  int *p1;
3071  int c;
3072 
3073  for (cc = 0; cc < numComps; ++cc) {
3074  if (scanInfo.comp[cc] &&
3076  ((!progressive || scanInfo.lastCoeff > 0) &&
3079  "Bad DCT data: invalid Huffman table index");
3080  return;
3081  }
3082  if (compInfo[cc].quantTable > numQuantTables) {
3084  "Bad DCT data: invalid quant table index");
3085  return;
3086  }
3087  }
3088 
3089  if (scanInfo.numComps == 1) {
3090  for (cc = 0; cc < numComps; ++cc) {
3091  if (scanInfo.comp[cc]) {
3092  break;
3093  }
3094  }
3095  dx1 = mcuWidth / compInfo[cc].hSample;
3096  dy1 = mcuHeight / compInfo[cc].vSample;
3097  } else {
3098  dx1 = mcuWidth;
3099  dy1 = mcuHeight;
3100  }
3101 
3102  for (y1 = 0; y1 < height; y1 += dy1) {
3103  for (x1 = 0; x1 < width; x1 += dx1) {
3104 
3105  // deal with restart marker
3106  if (restartInterval > 0 && restartCtr == 0) {
3107  c = readMarker();
3108  if (c != restartMarker) {
3110  "Bad DCT data: incorrect restart marker");
3111  return;
3112  }
3113  if (++restartMarker == 0xd8) {
3114  restartMarker = 0xd0;
3115  }
3116  restart();
3117  }
3118 
3119  // read one MCU
3120  for (cc = 0; cc < numComps; ++cc) {
3121  if (!scanInfo.comp[cc]) {
3122  continue;
3123  }
3124 
3125  h = compInfo[cc].hSample;
3126  v = compInfo[cc].vSample;
3127  horiz = mcuWidth / h;
3128  vert = mcuHeight / v;
3129  vSub = vert / 8;
3130  for (y2 = 0; y2 < dy1; y2 += vert) {
3131  for (x2 = 0; x2 < dx1; x2 += horiz) {
3132 
3133  // pull out the current values
3134  p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3135  for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3136  data[i] = p1[0];
3137  data[i+1] = p1[1];
3138  data[i+2] = p1[2];
3139  data[i+3] = p1[3];
3140  data[i+4] = p1[4];
3141  data[i+5] = p1[5];
3142  data[i+6] = p1[6];
3143  data[i+7] = p1[7];
3144  p1 += bufWidth * vSub;
3145  }
3146 
3147  // read one data unit
3148  if (progressive) {
3152  &compInfo[cc].prevDC,
3153  data)) {
3154  return;
3155  }
3156  } else {
3159  &compInfo[cc].prevDC,
3160  data)) {
3161  return;
3162  }
3163  }
3164 
3165  // add the data unit into frameBuf
3166  p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3167  for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3168  p1[0] = data[i];
3169  p1[1] = data[i+1];
3170  p1[2] = data[i+2];
3171  p1[3] = data[i+3];
3172  p1[4] = data[i+4];
3173  p1[5] = data[i+5];
3174  p1[6] = data[i+6];
3175  p1[7] = data[i+7];
3176  p1 += bufWidth * vSub;
3177  }
3178  }
3179  }
3180  }
3181  --restartCtr;
3182  }
3183  }
3184 }
3185 
3186 // Read one data unit from a sequential JPEG stream.
3188  DCTHuffTable *acHuffTable,
3189  int *prevDC, int data[64]) {
3190  int run, size, amp;
3191  int c;
3192  int i, j;
3193 
3194  if ((size = readHuffSym(dcHuffTable)) == 9999) {
3195  return gFalse;
3196  }
3197  if (size > 0) {
3198  if ((amp = readAmp(size)) == 9999) {
3199  return gFalse;
3200  }
3201  } else {
3202  amp = 0;
3203  }
3204  data[0] = *prevDC += amp;
3205  for (i = 1; i < 64; ++i) {
3206  data[i] = 0;
3207  }
3208  i = 1;
3209  while (i < 64) {
3210  run = 0;
3211  while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
3212  run += 0x10;
3213  }
3214  if (c == 9999) {
3215  return gFalse;
3216  }
3217  if (c == 0x00) {
3218  break;
3219  } else {
3220  run += (c >> 4) & 0x0f;
3221  size = c & 0x0f;
3222  amp = readAmp(size);
3223  if (amp == 9999) {
3224  return gFalse;
3225  }
3226  i += run;
3227  if (i < 64) {
3228  j = dctZigZag[i++];
3229  data[j] = amp;
3230  }
3231  }
3232  }
3233  return gTrue;
3234 }
3235 
3236 // Read one data unit from a progressive JPEG stream.
3238  DCTHuffTable *acHuffTable,
3239  int *prevDC, int data[64]) {
3240  int run, size, amp, bit, c;
3241  int i, j, k;
3242 
3243  // get the DC coefficient
3244  i = scanInfo.firstCoeff;
3245  if (i == 0) {
3246  if (scanInfo.ah == 0) {
3247  if ((size = readHuffSym(dcHuffTable)) == 9999) {
3248  return gFalse;
3249  }
3250  if (size > 0) {
3251  if ((amp = readAmp(size)) == 9999) {
3252  return gFalse;
3253  }
3254  } else {
3255  amp = 0;
3256  }
3257  data[0] += (*prevDC += amp) << scanInfo.al;
3258  } else {
3259  if ((bit = readBit()) == 9999) {
3260  return gFalse;
3261  }
3262  if (bit) {
3263  data[0] += 1 << scanInfo.al;
3264  }
3265  }
3266  ++i;
3267  }
3268  if (scanInfo.lastCoeff == 0) {
3269  return gTrue;
3270  }
3271 
3272  // check for an EOB run
3273  if (eobRun > 0) {
3274  while (i <= scanInfo.lastCoeff) {
3275  j = dctZigZag[i++];
3276  if (data[j] != 0) {
3277  if ((bit = readBit()) == EOF) {
3278  return gFalse;
3279  }
3280  if (bit) {
3281  if (data[j] >= 0) {
3282  data[j] += 1 << scanInfo.al;
3283  } else {
3284  data[j] -= 1 << scanInfo.al;
3285  }
3286  }
3287  }
3288  }
3289  --eobRun;
3290  return gTrue;
3291  }
3292 
3293  // read the AC coefficients
3294  while (i <= scanInfo.lastCoeff) {
3295  if ((c = readHuffSym(acHuffTable)) == 9999) {
3296  return gFalse;
3297  }
3298 
3299  // ZRL
3300  if (c == 0xf0) {
3301  k = 0;
3302  while (k < 16 && i <= scanInfo.lastCoeff) {
3303  j = dctZigZag[i++];
3304  if (data[j] == 0) {
3305  ++k;
3306  } else {
3307  if ((bit = readBit()) == EOF) {
3308  return gFalse;
3309  }
3310  if (bit) {
3311  if (data[j] >= 0) {
3312  data[j] += 1 << scanInfo.al;
3313  } else {
3314  data[j] -= 1 << scanInfo.al;
3315  }
3316  }
3317  }
3318  }
3319 
3320  // EOB run
3321  } else if ((c & 0x0f) == 0x00) {
3322  j = c >> 4;
3323  eobRun = 0;
3324  for (k = 0; k < j; ++k) {
3325  if ((bit = readBit()) == EOF) {
3326  return gFalse;
3327  }
3328  eobRun = (eobRun << 1) | bit;
3329  }
3330  eobRun += 1 << j;
3331  while (i <= scanInfo.lastCoeff) {
3332  j = dctZigZag[i++];
3333  if (data[j] != 0) {
3334  if ((bit = readBit()) == EOF) {
3335  return gFalse;
3336  }
3337  if (bit) {
3338  if (data[j] >= 0) {
3339  data[j] += 1 << scanInfo.al;
3340  } else {
3341  data[j] -= 1 << scanInfo.al;
3342  }
3343  }
3344  }
3345  }
3346  --eobRun;
3347  break;
3348 
3349  // zero run and one AC coefficient
3350  } else {
3351  run = (c >> 4) & 0x0f;
3352  size = c & 0x0f;
3353  if ((amp = readAmp(size)) == 9999) {
3354  return gFalse;
3355  }
3356  j = 0; // make gcc happy
3357  for (k = 0; k <= run && i <= scanInfo.lastCoeff; ++k) {
3358  j = dctZigZag[i++];
3359  while (data[j] != 0 && i <= scanInfo.lastCoeff) {
3360  if ((bit = readBit()) == EOF) {
3361  return gFalse;
3362  }
3363  if (bit) {
3364  if (data[j] >= 0) {
3365  data[j] += 1 << scanInfo.al;
3366  } else {
3367  data[j] -= 1 << scanInfo.al;
3368  }
3369  }
3370  j = dctZigZag[i++];
3371  }
3372  }
3373  data[j] = amp << scanInfo.al;
3374  }
3375  }
3376 
3377  return gTrue;
3378 }
3379 
3380 // Decode a progressive JPEG image.
3382  int dataIn[64];
3383  Guchar dataOut[64];
3384  Gushort *quantTable;
3385  int pY, pCb, pCr, pR, pG, pB;
3386  int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
3387  int h, v, horiz, vert, hSub, vSub;
3388  int *p0, *p1, *p2;
3389 
3390  for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
3391  for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
3392  for (cc = 0; cc < numComps; ++cc) {
3393  quantTable = quantTables[compInfo[cc].quantTable];
3394  h = compInfo[cc].hSample;
3395  v = compInfo[cc].vSample;
3396  horiz = mcuWidth / h;
3397  vert = mcuHeight / v;
3398  hSub = horiz / 8;
3399  vSub = vert / 8;
3400  for (y2 = 0; y2 < mcuHeight; y2 += vert) {
3401  for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
3402 
3403  // pull out the coded data unit
3404  p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3405  for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3406  dataIn[i] = p1[0];
3407  dataIn[i+1] = p1[1];
3408  dataIn[i+2] = p1[2];
3409  dataIn[i+3] = p1[3];
3410  dataIn[i+4] = p1[4];
3411  dataIn[i+5] = p1[5];
3412  dataIn[i+6] = p1[6];
3413  dataIn[i+7] = p1[7];
3414  p1 += bufWidth * vSub;
3415  }
3416 
3417  // transform
3418  transformDataUnit(quantTable, dataIn, dataOut);
3419 
3420  // store back into frameBuf, doing replication for
3421  // subsampled components
3422  p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3423  if (hSub == 1 && vSub == 1) {
3424  for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3425  p1[0] = dataOut[i] & 0xff;
3426  p1[1] = dataOut[i+1] & 0xff;
3427  p1[2] = dataOut[i+2] & 0xff;
3428  p1[3] = dataOut[i+3] & 0xff;
3429  p1[4] = dataOut[i+4] & 0xff;
3430  p1[5] = dataOut[i+5] & 0xff;
3431  p1[6] = dataOut[i+6] & 0xff;
3432  p1[7] = dataOut[i+7] & 0xff;
3433  p1 += bufWidth;
3434  }
3435  } else if (hSub == 2 && vSub == 2) {
3436  p2 = p1 + bufWidth;
3437  for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
3438  p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
3439  p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
3440  p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
3441  p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
3442  p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
3443  p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
3444  p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
3445  p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
3446  p1 += bufWidth * 2;
3447  p2 += bufWidth * 2;
3448  }
3449  } else {
3450  i = 0;
3451  for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
3452  for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
3453  p2 = p1 + x4;
3454  for (y5 = 0; y5 < vSub; ++y5) {
3455  for (x5 = 0; x5 < hSub; ++x5) {
3456  p2[x5] = dataOut[i] & 0xff;
3457  }
3458  p2 += bufWidth;
3459  }
3460  ++i;
3461  }
3462  p1 += bufWidth * vSub;
3463  }
3464  }
3465  }
3466  }
3467  }
3468 
3469  // color space conversion
3470  if (colorXform) {
3471  // convert YCbCr to RGB
3472  if (numComps == 3) {
3473  for (y2 = 0; y2 < mcuHeight; ++y2) {
3474  p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
3475  p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
3476  p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
3477  for (x2 = 0; x2 < mcuWidth; ++x2) {
3478  pY = *p0;
3479  pCb = *p1 - 128;
3480  pCr = *p2 - 128;
3481  pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3482  *p0++ = dctClip(pR);
3483  pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
3484  32768) >> 16;
3485  *p1++ = dctClip(pG);
3486  pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3487  *p2++ = dctClip(pB);
3488  }
3489  }
3490  // convert YCbCrK to CMYK (K is passed through unchanged)
3491  } else if (numComps == 4) {
3492  for (y2 = 0; y2 < mcuHeight; ++y2) {
3493  p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
3494  p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
3495  p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
3496  for (x2 = 0; x2 < mcuWidth; ++x2) {
3497  pY = *p0;
3498  pCb = *p1 - 128;
3499  pCr = *p2 - 128;
3500  pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3501  *p0++ = 255 - dctClip(pR);
3502  pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
3503  32768) >> 16;
3504  *p1++ = 255 - dctClip(pG);
3505  pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3506  *p2++ = 255 - dctClip(pB);
3507  }
3508  }
3509  }
3510  }
3511  }
3512  }
3513 }
3514 
3515 // Transform one data unit -- this performs the dequantization and
3516 // IDCT steps. This IDCT algorithm is taken from:
3517 // Y. A. Reznik, A. T. Hinds, L. Yu, Z. Ni, and C-X. Zhang,
3518 // "Efficient fixed-point approximations of the 8x8 inverse discrete
3519 // cosine transform" (invited paper), Proc. SPIE Vol. 6696, Sep. 24,
3520 // 2007.
3521 // which is based on:
3522 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
3523 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
3524 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
3525 // 988-991.
3526 // The stage numbers mentioned in the comments refer to Figure 1 in the
3527 // Loeffler paper.
3529  int dataIn[64], Guchar dataOut[64]) {
3530  int v0, v1, v2, v3, v4, v5, v6, v7;
3531  int t0, t1, t2, t3, t4, t5, t6, t7;
3532  int *p, *scale;
3533  Gushort *q;
3534  int i;
3535 
3536  // dequant; inverse DCT on rows
3537  for (i = 0; i < 64; i += 8) {
3538  p = dataIn + i;
3539  q = quantTable + i;
3540  scale = idctScaleMat + i;
3541 
3542  // check for all-zero AC coefficients
3543  if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
3544  p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
3545  t0 = p[0] * q[0] * scale[0];
3546  if (i == 0) {
3547  t0 += 1 << 12; // rounding bias
3548  }
3549  p[0] = t0;
3550  p[1] = t0;
3551  p[2] = t0;
3552  p[3] = t0;
3553  p[4] = t0;
3554  p[5] = t0;
3555  p[6] = t0;
3556  p[7] = t0;
3557  continue;
3558  }
3559 
3560  // stage 4
3561  v0 = p[0] * q[0] * scale[0];
3562  if (i == 0) {
3563  v0 += 1 << 12; // rounding bias
3564  }
3565  v1 = p[4] * q[4] * scale[4];
3566  v2 = p[2] * q[2] * scale[2];
3567  v3 = p[6] * q[6] * scale[6];
3568  t0 = p[1] * q[1] * scale[1];
3569  t1 = p[7] * q[7] * scale[7];
3570  v4 = t0 - t1;
3571  v7 = t0 + t1;
3572  v5 = p[3] * q[3] * scale[3];
3573  v6 = p[5] * q[5] * scale[5];
3574 
3575  // stage 3
3576  t0 = v0 - v1;
3577  v0 = v0 + v1;
3578  v1 = t0;
3579  t0 = v2 + (v2 >> 5);
3580  t1 = t0 >> 2;
3581  t2 = t1 + (v2 >> 4); // 41/128 * v2
3582  t3 = t0 - t1; // 99/128 * v2
3583  t4 = v3 + (v3 >> 5);
3584  t5 = t4 >> 2;
3585  t6 = t5 + (v3 >> 4); // 41/128 * v3
3586  t7 = t4 - t5; // 99/128 * v3
3587  v2 = t2 - t7;
3588  v3 = t3 + t6;
3589  t0 = v4 - v6;
3590  v4 = v4 + v6;
3591  v6 = t0;
3592  t0 = v7 + v5;
3593  v5 = v7 - v5;
3594  v7 = t0;
3595 
3596  // stage 2
3597  t0 = v0 - v3;
3598  v0 = v0 + v3;
3599  v3 = t0;
3600  t0 = v1 - v2;
3601  v1 = v1 + v2;
3602  v2 = t0;
3603  t0 = (v4 >> 9) - v4;
3604  t1 = v4 >> 1; // 1/2 * v4
3605  t2 = (t0 >> 2) - t0; // 1533/2048 * v4
3606  t3 = (v7 >> 9) - v7;
3607  t4 = v7 >> 1; // 1/2 * v7
3608  t5 = (t3 >> 2) - t3; // 1533/2048 * v7
3609  v4 = t2 - t4;
3610  v7 = t1 + t5;
3611  t0 = (v5 >> 3) - (v5 >> 7);
3612  t1 = t0 - (v5 >> 11);
3613  t2 = t0 + (t1 >> 1); // 719/4096 * v5
3614  t3 = v5 - t0; // 113/256 * v5
3615  t4 = (v6 >> 3) - (v6 >> 7);
3616  t5 = t4 - (v6 >> 11);
3617  t6 = t4 + (t5 >> 1); // 719/4096 * v6
3618  t7 = v6 - t4; // 113/256 * v6
3619  v5 = t3 - t6;
3620  v6 = t2 + t7;
3621 
3622  // stage 1
3623  p[0] = v0 + v7;
3624  p[7] = v0 - v7;
3625  p[1] = v1 + v6;
3626  p[6] = v1 - v6;
3627  p[2] = v2 + v5;
3628  p[5] = v2 - v5;
3629  p[3] = v3 + v4;
3630  p[4] = v3 - v4;
3631  }
3632 
3633  // inverse DCT on columns
3634  for (i = 0; i < 8; ++i) {
3635  p = dataIn + i;
3636 
3637  // check for all-zero AC coefficients
3638  if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
3639  p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
3640  t0 = p[0*8];
3641  p[1*8] = t0;
3642  p[2*8] = t0;
3643  p[3*8] = t0;
3644  p[4*8] = t0;
3645  p[5*8] = t0;
3646  p[6*8] = t0;
3647  p[7*8] = t0;
3648  continue;
3649  }
3650 
3651  // stage 4
3652  v0 = p[0*8];
3653  v1 = p[4*8];
3654  v2 = p[2*8];
3655  v3 = p[6*8];
3656  t0 = p[1*8];
3657  t1 = p[7*8];
3658  v4 = t0 - t1;
3659  v7 = t0 + t1;
3660  v5 = p[3*8];
3661  v6 = p[5*8];
3662 
3663  // stage 3
3664  t0 = v0 - v1;
3665  v0 = v0 + v1;
3666  v1 = t0;
3667  t0 = v2 + (v2 >> 5);
3668  t1 = t0 >> 2;
3669  t2 = t1 + (v2 >> 4); // 41/128 * v2
3670  t3 = t0 - t1; // 99/128 * v2
3671  t4 = v3 + (v3 >> 5);
3672  t5 = t4 >> 2;
3673  t6 = t5 + (v3 >> 4); // 41/128 * v3
3674  t7 = t4 - t5; // 99/128 * v3
3675  v2 = t2 - t7;
3676  v3 = t3 + t6;
3677  t0 = v4 - v6;
3678  v4 = v4 + v6;
3679  v6 = t0;
3680  t0 = v7 + v5;
3681  v5 = v7 - v5;
3682  v7 = t0;
3683 
3684  // stage 2
3685  t0 = v0 - v3;
3686  v0 = v0 + v3;
3687  v3 = t0;
3688  t0 = v1 - v2;
3689  v1 = v1 + v2;
3690  v2 = t0;
3691  t0 = (v4 >> 9) - v4;
3692  t1 = v4 >> 1; // 1/2 * v4
3693  t2 = (t0 >> 2) - t0; // 1533/2048 * v4
3694  t3 = (v7 >> 9) - v7;
3695  t4 = v7 >> 1; // 1/2 * v7
3696  t5 = (t3 >> 2) - t3; // 1533/2048 * v7
3697  v4 = t2 - t4;
3698  v7 = t1 + t5;
3699  t0 = (v5 >> 3) - (v5 >> 7);
3700  t1 = t0 - (v5 >> 11);
3701  t2 = t0 + (t1 >> 1); // 719/4096 * v5
3702  t3 = v5 - t0; // 113/256 * v5
3703  t4 = (v6 >> 3) - (v6 >> 7);
3704  t5 = t4 - (v6 >> 11);
3705  t6 = t4 + (t5 >> 1); // 719/4096 * v6
3706  t7 = v6 - t4; // 113/256 * v6
3707  v5 = t3 - t6;
3708  v6 = t2 + t7;
3709 
3710  // stage 1
3711  p[0*8] = v0 + v7;
3712  p[7*8] = v0 - v7;
3713  p[1*8] = v1 + v6;
3714  p[6*8] = v1 - v6;
3715  p[2*8] = v2 + v5;
3716  p[5*8] = v2 - v5;
3717  p[3*8] = v3 + v4;
3718  p[4*8] = v3 - v4;
3719  }
3720 
3721  // convert to 8-bit integers
3722  for (i = 0; i < 64; ++i) {
3723  dataOut[i] = dctClip(128 + (dataIn[i] >> 13));
3724  }
3725 }
3726 
3728  Gushort code;
3729  int bit;
3730  int codeBits;
3731 
3732  code = 0;
3733  codeBits = 0;
3734  do {
3735  // add a bit to the code
3736  if ((bit = readBit()) == EOF) {
3737  return 9999;
3738  }
3739  code = (Gushort)((code << 1) + bit);
3740  ++codeBits;
3741 
3742  // look up code
3743  if (code < table->firstCode[codeBits]) {
3744  break;
3745  }
3746  if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
3747  code = (Gushort)(code - table->firstCode[codeBits]);
3748  return table->sym[table->firstSym[codeBits] + code];
3749  }
3750  } while (codeBits < 16);
3751 
3752  error(errSyntaxError, getPos(), "Bad Huffman code in DCT stream");
3753  return 9999;
3754 }
3755 
3757  int amp, bit;
3758  int bits;
3759 
3760  amp = 0;
3761  for (bits = 0; bits < size; ++bits) {
3762  if ((bit = readBit()) == EOF)
3763  return 9999;
3764  amp = (amp << 1) + bit;
3765  }
3766  if (amp < (1 << (size - 1)))
3767  amp -= (1 << size) - 1;
3768  return amp;
3769 }
3770 
3772  int bit;
3773  int c, c2;
3774 
3775  if (inputBits == 0) {
3776  if ((c = str->getChar()) == EOF)
3777  return EOF;
3778  if (c == 0xff) {
3779  do {
3780  c2 = str->getChar();
3781  } while (c2 == 0xff);
3782  if (c2 != 0x00) {
3783  error(errSyntaxError, getPos(), "Bad DCT data: missing 00 after ff");
3784  return EOF;
3785  }
3786  }
3787  inputBuf = c;
3788  inputBits = 8;
3789  }
3790  bit = (inputBuf >> (inputBits - 1)) & 1;
3791  --inputBits;
3792  return bit;
3793 }
3794 
3796  GBool doScan;
3797  int n, i;
3798  int c = 0;
3799 
3800  // read headers
3801  doScan = gFalse;
3802  while (!doScan) {
3803  c = readMarker();
3804  switch (c) {
3805  case 0xc0: // SOF0 (sequential)
3806  case 0xc1: // SOF1 (extended sequential)
3807  if (!frame) {
3809  "Invalid DCT marker in scan <{0:02x}>", c);
3810  return gFalse;
3811  }
3812  if (!readBaselineSOF()) {
3813  return gFalse;
3814  }
3815  break;
3816  case 0xc2: // SOF2 (progressive)
3817  if (!frame) {
3819  "Invalid DCT marker in scan <{0:02x}>", c);
3820  return gFalse;
3821  }
3822  if (!readProgressiveSOF()) {
3823  return gFalse;
3824  }
3825  break;
3826  case 0xc4: // DHT
3827  if (!readHuffmanTables()) {
3828  return gFalse;
3829  }
3830  break;
3831  case 0xd8: // SOI
3832  if (!frame) {
3834  "Invalid DCT marker in scan <{0:02x}>", c);
3835  return gFalse;
3836  }
3837  break;
3838  case 0xd9: // EOI
3839  return gFalse;
3840  case 0xda: // SOS
3841  if (!readScanInfo()) {
3842  return gFalse;
3843  }
3844  doScan = gTrue;
3845  break;
3846  case 0xdb: // DQT
3847  if (!readQuantTables()) {
3848  return gFalse;
3849  }
3850  break;
3851  case 0xdd: // DRI
3852  if (!readRestartInterval()) {
3853  return gFalse;
3854  }
3855  break;
3856  case 0xe0: // APP0
3857  if (!frame) {
3859  "Invalid DCT marker in scan <{0:02x}>", c);
3860  return gFalse;
3861  }
3862  if (!readJFIFMarker()) {
3863  return gFalse;
3864  }
3865  break;
3866  case 0xee: // APP14
3867  if (!frame) {
3869  "Invalid DCT marker in scan <{0:02x}>", c);
3870  return gFalse;
3871  }
3872  if (!readAdobeMarker()) {
3873  return gFalse;
3874  }
3875  break;
3876  case EOF:
3877  error(errSyntaxError, getPos(), "Bad DCT header");
3878  return gFalse;
3879  default:
3880  // skip APPn / COM / etc.
3881  if (c >= 0xe0) {
3882  n = read16() - 2;
3883  str->discardChars(n);
3884  } else {
3885  error(errSyntaxError, getPos(), "Unknown DCT marker <{0:02x}>", c);
3886  return gFalse;
3887  }
3888  break;
3889  }
3890  }
3891 
3892  for (i = 0; i < numComps; ++i) {
3893  if (compInfo[i].quantTable >= numQuantTables) {
3894  error(errSyntaxError, getPos(), "Invalid DCT quant table selector");
3895  return gFalse;
3896  }
3897  }
3898 
3899  return gTrue;
3900 }
3901 
3903  int prec;
3904  int i;
3905  int c;
3906 
3907  read16(); // length
3908  prec = str->getChar();
3909  height = read16();
3910  width = read16();
3911  numComps = str->getChar();
3912  if (numComps <= 0 || numComps > 4) {
3913  error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
3914  numComps = 0;
3915  return gFalse;
3916  }
3917  if (prec != 8) {
3918  error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
3919  return gFalse;
3920  }
3921  for (i = 0; i < numComps; ++i) {
3922  compInfo[i].id = str->getChar();
3923  c = str->getChar();
3924  compInfo[i].hSample = (c >> 4) & 0x0f;
3925  compInfo[i].vSample = c & 0x0f;
3927  // a sampling factor of 3 is allowed by the spec, but requires
3928  // messy upsampling, and appears not to be used in practice
3929  if (!(compInfo[i].hSample == 1 ||
3930  compInfo[i].hSample == 2 ||
3931  compInfo[i].hSample == 4) ||
3932  !(compInfo[i].vSample == 1 ||
3933  compInfo[i].vSample == 2 ||
3934  compInfo[i].vSample == 4)) {
3935  error(errSyntaxError, getPos(), "Bad DCT sampling factor");
3936  return gFalse;
3937  }
3938  if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
3939  error(errSyntaxError, getPos(), "Bad DCT quant table selector");
3940  return gFalse;
3941  }
3942  }
3943  progressive = gFalse;
3944  return gTrue;
3945 }
3946 
3948  int prec;
3949  int i;
3950  int c;
3951 
3952  read16(); // length
3953  prec = str->getChar();
3954  height = read16();
3955  width = read16();
3956  numComps = str->getChar();
3957  if (numComps <= 0 || numComps > 4) {
3958  error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
3959  numComps = 0;
3960  return gFalse;
3961  }
3962  if (prec != 8) {
3963  error(errSyntaxError, getPos(), "Bad DCT precision {0:d}", prec);
3964  return gFalse;
3965  }
3966  for (i = 0; i < numComps; ++i) {
3967  compInfo[i].id = str->getChar();
3968  c = str->getChar();
3969  compInfo[i].hSample = (c >> 4) & 0x0f;
3970  compInfo[i].vSample = c & 0x0f;
3972  // a sampling factor of 3 is allowed by the spec, but requires
3973  // messy upsampling, and appears not to be used in practice
3974  if (!(compInfo[i].hSample == 1 ||
3975  compInfo[i].hSample == 2 ||
3976  compInfo[i].hSample == 4) ||
3977  !(compInfo[i].vSample == 1 ||
3978  compInfo[i].vSample == 2 ||
3979  compInfo[i].vSample == 4)) {
3980  error(errSyntaxError, getPos(), "Bad DCT sampling factor");
3981  return gFalse;
3982  }
3983  if (compInfo[i].quantTable < 0 || compInfo[i].quantTable > 3) {
3984  error(errSyntaxError, getPos(), "Bad DCT quant table selector");
3985  return gFalse;
3986  }
3987  }
3988  progressive = gTrue;
3989  return gTrue;
3990 }
3991 
3993  int length;
3994  int id, c;
3995  int i, j;
3996 
3997  length = read16() - 2;
3999  if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
4000  error(errSyntaxError, getPos(), "Bad number of components in DCT stream");
4001  scanInfo.numComps = 0;
4002  return gFalse;
4003  }
4004  --length;
4005  if (length != 2 * scanInfo.numComps + 3) {
4006  error(errSyntaxError, getPos(), "Bad DCT scan info block");
4007  return gFalse;
4008  }
4010  for (j = 0; j < numComps; ++j) {
4011  scanInfo.comp[j] = gFalse;
4012  }
4013  for (i = 0; i < scanInfo.numComps; ++i) {
4014  id = str->getChar();
4015  // some (broken) DCT streams reuse ID numbers, but at least they
4016  // keep the components in order, so we check compInfo[i] first to
4017  // work around the problem
4018  if (id == compInfo[i].id) {
4019  j = i;
4020  } else {
4021  for (j = 0; j < numComps; ++j) {
4022  if (id == compInfo[j].id) {
4023  break;
4024  }
4025  }
4026  if (j == numComps) {
4028  "Bad DCT component ID in scan info block");
4029  return gFalse;
4030  }
4031  }
4032  if (scanInfo.comp[j]) {
4034  "Invalid DCT component ID in scan info block");
4035  return gFalse;
4036  }
4037  scanInfo.comp[j] = gTrue;
4038  c = str->getChar();
4039  scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
4040  scanInfo.acHuffTable[j] = c & 0x0f;
4041  }
4044  if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
4047  "Bad DCT coefficient numbers in scan info block");
4048  return gFalse;
4049  }
4050  c = str->getChar();
4051  scanInfo.ah = (c >> 4) & 0x0f;
4052  scanInfo.al = c & 0x0f;
4053  return gTrue;
4054 }
4055 
4057  int length, prec, i, index;
4058 
4059  length = read16() - 2;
4060  while (length > 0) {
4061  index = str->getChar();
4062  prec = (index >> 4) & 0x0f;
4063  index &= 0x0f;
4064  if (prec > 1 || index >= 4) {
4065  error(errSyntaxError, getPos(), "Bad DCT quantization table");
4066  return gFalse;
4067  }
4068  if (index >= numQuantTables) {
4069  numQuantTables = index + 1;
4070  }
4071  for (i = 0; i < 64; ++i) {
4072  if (prec) {
4074  } else {
4076  }
4077  }
4078  if (prec) {
4079  length -= 129;
4080  } else {
4081  length -= 65;
4082  }
4083  }
4084  return gTrue;
4085 }
4086 
4088  DCTHuffTable *tbl;
4089  int length;
4090  int index;
4091  Gushort code;
4092  Guchar sym;
4093  int i;
4094  int c;
4095 
4096  length = read16() - 2;
4097  while (length > 0) {
4098  index = str->getChar();
4099  --length;
4100  if ((index & 0x0f) >= 4) {
4101  error(errSyntaxError, getPos(), "Bad DCT Huffman table");
4102  return gFalse;
4103  }
4104  if (index & 0x10) {
4105  index &= 0x0f;
4106  if (index >= numACHuffTables)
4107  numACHuffTables = index+1;
4108  tbl = &acHuffTables[index];
4109  } else {
4110  index &= 0x0f;
4111  if (index >= numDCHuffTables)
4112  numDCHuffTables = index+1;
4113  tbl = &dcHuffTables[index];
4114  }
4115  sym = 0;
4116  code = 0;
4117  for (i = 1; i <= 16; ++i) {
4118  c = str->getChar();
4119  tbl->firstSym[i] = sym;
4120  tbl->firstCode[i] = code;
4121  tbl->numCodes[i] = (Gushort)c;
4122  sym = (Guchar)(sym + c);
4123  code = (Gushort)((code + c) << 1);
4124  }
4125  length -= 16;
4126  for (i = 0; i < sym; ++i)
4127  tbl->sym[i] = (Guchar)str->getChar();
4128  length -= sym;
4129  }
4130  return gTrue;
4131 }
4132 
4134  int length;
4135 
4136  length = read16();
4137  if (length != 4) {
4138  error(errSyntaxError, getPos(), "Bad DCT restart interval");
4139  return gFalse;
4140  }
4141  restartInterval = read16();
4142  return gTrue;
4143 }
4144 
4146  int length, i;
4147  char buf[5];
4148  int c;
4149 
4150  length = read16();
4151  length -= 2;
4152  if (length >= 5) {
4153  for (i = 0; i < 5; ++i) {
4154  if ((c = str->getChar()) == EOF) {
4155  error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
4156  return gFalse;
4157  }
4158  buf[i] = (char)c;
4159  }
4160  length -= 5;
4161  if (!memcmp(buf, "JFIF\0", 5)) {
4162  gotJFIFMarker = gTrue;
4163  }
4164  }
4165  while (length > 0) {
4166  if (str->getChar() == EOF) {
4167  error(errSyntaxError, getPos(), "Bad DCT APP0 marker");
4168  return gFalse;
4169  }
4170  --length;
4171  }
4172  return gTrue;
4173 }
4174 
4176  int length, i;
4177  char buf[12];
4178  int c;
4179 
4180  length = read16();
4181  if (length < 14) {
4182  goto err;
4183  }
4184  for (i = 0; i < 12; ++i) {
4185  if ((c = str->getChar()) == EOF) {
4186  goto err;
4187  }
4188  buf[i] = (char)c;
4189  }
4190  if (!strncmp(buf, "Adobe", 5)) {
4191  colorXform = buf[11];
4193  }
4194  for (i = 14; i < length; ++i) {
4195  if (str->getChar() == EOF) {
4196  goto err;
4197  }
4198  }
4199  return gTrue;
4200 
4201  err:
4202  error(errSyntaxError, getPos(), "Bad DCT Adobe APP14 marker");
4203  return gFalse;
4204 }
4205 
4207  int c;
4208 
4209  c = readMarker();
4210  if (c != 0xd9) { // EOI
4211  error(errSyntaxError, getPos(), "Bad DCT trailer");
4212  return gFalse;
4213  }
4214  return gTrue;
4215 }
4216 
4218  int c;
4219 
4220  do {
4221  do {
4222  c = str->getChar();
4223  } while (c != 0xff && c != EOF);
4224  do {
4225  c = str->getChar();
4226  } while (c == 0xff);
4227  } while (c == 0x00);
4228  return c;
4229 }
4230 
4232  int c1, c2;
4233 
4234  if ((c1 = str->getChar()) == EOF)
4235  return EOF;
4236  if ((c2 = str->getChar()) == EOF)
4237  return EOF;
4238  return (c1 << 8) + c2;
4239 }
4240 
4241 #endif // HAVE_JPEGLIB
4242 
4243 GString *DCTStream::getPSFilter(int psLevel, const char *indent,
4244  GBool okToReadStream) {
4245  GString *s;
4246 
4247  if (psLevel < 2) {
4248  return NULL;
4249  }
4250  if (!(s = str->getPSFilter(psLevel, indent, okToReadStream))) {
4251  return NULL;
4252  }
4253  if (okToReadStream && !checkSequentialInterleaved()) {
4254  // PostScript does not allow progressive or interleaved JPEG
4255  delete s;
4256  return NULL;
4257  }
4258  s->append(indent)->append("<< >> /DCTDecode filter\n");
4259  return s;
4260 }
4261 
4263  return str->isBinary(gTrue);
4264 }
4265 
4266 //------------------------------------------------------------------------
4267 // FlateStream
4268 //------------------------------------------------------------------------
4269 
4271  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
4272 };
4273 
4275  {0, 3},
4276  {0, 4},
4277  {0, 5},
4278  {0, 6},
4279  {0, 7},
4280  {0, 8},
4281  {0, 9},
4282  {0, 10},
4283  {1, 11},
4284  {1, 13},
4285  {1, 15},
4286  {1, 17},
4287  {2, 19},
4288  {2, 23},
4289  {2, 27},
4290  {2, 31},
4291  {3, 35},
4292  {3, 43},
4293  {3, 51},
4294  {3, 59},
4295  {4, 67},
4296  {4, 83},
4297  {4, 99},
4298  {4, 115},
4299  {5, 131},
4300  {5, 163},
4301  {5, 195},
4302  {5, 227},
4303  {0, 258},
4304  {0, 258},
4305  {0, 258}
4306 };
4307 
4309  { 0, 1},
4310  { 0, 2},
4311  { 0, 3},
4312  { 0, 4},
4313  { 1, 5},
4314  { 1, 7},
4315  { 2, 9},
4316  { 2, 13},
4317  { 3, 17},
4318  { 3, 25},
4319  { 4, 33},
4320  { 4, 49},
4321  { 5, 65},
4322  { 5, 97},
4323  { 6, 129},
4324  { 6, 193},
4325  { 7, 257},
4326  { 7, 385},
4327  { 8, 513},
4328  { 8, 769},
4329  { 9, 1025},
4330  { 9, 1537},
4331  {10, 2049},
4332  {10, 3073},
4333  {11, 4097},
4334  {11, 6145},
4335  {12, 8193},
4336  {12, 12289},
4337  {13, 16385},
4338  {13, 24577}
4339 };
4340 
4342  {7, 0x0100},
4343  {8, 0x0050},
4344  {8, 0x0010},
4345  {8, 0x0118},
4346  {7, 0x0110},
4347  {8, 0x0070},
4348  {8, 0x0030},
4349  {9, 0x00c0},
4350  {7, 0x0108},
4351  {8, 0x0060},
4352  {8, 0x0020},
4353  {9, 0x00a0},
4354  {8, 0x0000},
4355  {8, 0x0080},
4356  {8, 0x0040},
4357  {9, 0x00e0},
4358  {7, 0x0104},
4359  {8, 0x0058},
4360  {8, 0x0018},
4361  {9, 0x0090},
4362  {7, 0x0114},
4363  {8, 0x0078},
4364  {8, 0x0038},
4365  {9, 0x00d0},
4366  {7, 0x010c},
4367  {8, 0x0068},
4368  {8, 0x0028},
4369  {9, 0x00b0},
4370  {8, 0x0008},
4371  {8, 0x0088},
4372  {8, 0x0048},
4373  {9, 0x00f0},
4374  {7, 0x0102},
4375  {8, 0x0054},
4376  {8, 0x0014},
4377  {8, 0x011c},
4378  {7, 0x0112},
4379  {8, 0x0074},
4380  {8, 0x0034},
4381  {9, 0x00c8},
4382  {7, 0x010a},
4383  {8, 0x0064},
4384  {8, 0x0024},
4385  {9, 0x00a8},
4386  {8, 0x0004},
4387  {8, 0x0084},
4388  {8, 0x0044},
4389  {9, 0x00e8},
4390  {7, 0x0106},
4391  {8, 0x005c},
4392  {8, 0x001c},
4393  {9, 0x0098},
4394  {7, 0x0116},
4395  {8, 0x007c},
4396  {8, 0x003c},
4397  {9, 0x00d8},
4398  {7, 0x010e},
4399  {8, 0x006c},
4400  {8, 0x002c},
4401  {9, 0x00b8},
4402  {8, 0x000c},
4403  {8, 0x008c},
4404  {8, 0x004c},
4405  {9, 0x00f8},
4406  {7, 0x0101},
4407  {8, 0x0052},
4408  {8, 0x0012},
4409  {8, 0x011a},
4410  {7, 0x0111},
4411  {8, 0x0072},
4412  {8, 0x0032},
4413  {9, 0x00c4},
4414  {7, 0x0109},
4415  {8, 0x0062},
4416  {8, 0x0022},
4417  {9, 0x00a4},
4418  {8, 0x0002},
4419  {8, 0x0082},
4420  {8, 0x0042},
4421  {9, 0x00e4},
4422  {7, 0x0105},
4423  {8, 0x005a},
4424  {8, 0x001a},
4425  {9, 0x0094},
4426  {7, 0x0115},
4427  {8, 0x007a},
4428  {8, 0x003a},
4429  {9, 0x00d4},
4430  {7, 0x010d},
4431  {8, 0x006a},
4432  {8, 0x002a},
4433  {9, 0x00b4},
4434  {8, 0x000a},
4435  {8, 0x008a},
4436  {8, 0x004a},
4437  {9, 0x00f4},
4438  {7, 0x0103},
4439  {8, 0x0056},
4440  {8, 0x0016},
4441  {8, 0x011e},
4442  {7, 0x0113},
4443  {8, 0x0076},
4444  {8, 0x0036},
4445  {9, 0x00cc},
4446  {7, 0x010b},
4447  {8, 0x0066},
4448  {8, 0x0026},
4449  {9, 0x00ac},
4450  {8, 0x0006},
4451  {8, 0x0086},
4452  {8, 0x0046},
4453  {9, 0x00ec},
4454  {7, 0x0107},
4455  {8, 0x005e},
4456  {8, 0x001e},
4457  {9, 0x009c},
4458  {7, 0x0117},
4459  {8, 0x007e},
4460  {8, 0x003e},
4461  {9, 0x00dc},
4462  {7, 0x010f},
4463  {8, 0x006e},
4464  {8, 0x002e},
4465  {9, 0x00bc},
4466  {8, 0x000e},
4467  {8, 0x008e},
4468  {8, 0x004e},
4469  {9, 0x00fc},
4470  {7, 0x0100},
4471  {8, 0x0051},
4472  {8, 0x0011},
4473  {8, 0x0119},
4474  {7, 0x0110},
4475  {8, 0x0071},
4476  {8, 0x0031},
4477  {9, 0x00c2},
4478  {7, 0x0108},
4479  {8, 0x0061},
4480  {8, 0x0021},
4481  {9, 0x00a2},
4482  {8, 0x0001},
4483  {8, 0x0081},
4484  {8, 0x0041},
4485  {9, 0x00e2},
4486  {7, 0x0104},
4487  {8, 0x0059},
4488  {8, 0x0019},
4489  {9, 0x0092},
4490  {7, 0x0114},
4491  {8, 0x0079},
4492  {8, 0x0039},
4493  {9, 0x00d2},
4494  {7, 0x010c},
4495  {8, 0x0069},
4496  {8, 0x0029},
4497  {9, 0x00b2},
4498  {8, 0x0009},
4499  {8, 0x0089},
4500  {8, 0x0049},
4501  {9, 0x00f2},
4502  {7, 0x0102},
4503  {8, 0x0055},
4504  {8, 0x0015},
4505  {8, 0x011d},
4506  {7, 0x0112},
4507  {8, 0x0075},
4508  {8, 0x0035},
4509  {9, 0x00ca},
4510  {7, 0x010a},
4511  {8, 0x0065},
4512  {8, 0x0025},
4513  {9, 0x00aa},
4514  {8, 0x0005},
4515  {8, 0x0085},
4516  {8, 0x0045},
4517  {9, 0x00ea},
4518  {7, 0x0106},
4519  {8, 0x005d},
4520  {8, 0x001d},
4521  {9, 0x009a},
4522  {7, 0x0116},
4523  {8, 0x007d},
4524  {8, 0x003d},
4525  {9, 0x00da},
4526  {7, 0x010e},
4527  {8, 0x006d},
4528  {8, 0x002d},
4529  {9, 0x00ba},
4530  {8, 0x000d},
4531  {8, 0x008d},
4532  {8, 0x004d},
4533  {9, 0x00fa},
4534  {7, 0x0101},
4535  {8, 0x0053},
4536  {8, 0x0013},
4537  {8, 0x011b},
4538  {7, 0x0111},
4539  {8, 0x0073},
4540  {8, 0x0033},
4541  {9, 0x00c6},
4542  {7, 0x0109},
4543  {8, 0x0063},
4544  {8, 0x0023},
4545  {9, 0x00a6},
4546  {8, 0x0003},
4547  {8, 0x0083},
4548  {8, 0x0043},
4549  {9, 0x00e6},
4550  {7, 0x0105},
4551  {8, 0x005b},
4552  {8, 0x001b},
4553  {9, 0x0096},
4554  {7, 0x0115},
4555  {8, 0x007b},
4556  {8, 0x003b},
4557  {9, 0x00d6},
4558  {7, 0x010d},
4559  {8, 0x006b},
4560  {8, 0x002b},
4561  {9, 0x00b6},
4562  {8, 0x000b},
4563  {8, 0x008b},
4564  {8, 0x004b},
4565  {9, 0x00f6},
4566  {7, 0x0103},
4567  {8, 0x0057},
4568  {8, 0x0017},
4569  {8, 0x011f},
4570  {7, 0x0113},
4571  {8, 0x0077},
4572  {8, 0x0037},
4573  {9, 0x00ce},
4574  {7, 0x010b},
4575  {8, 0x0067},
4576  {8, 0x0027},
4577  {9, 0x00ae},
4578  {8, 0x0007},
4579  {8, 0x0087},
4580  {8, 0x0047},
4581  {9, 0x00ee},
4582  {7, 0x0107},
4583  {8, 0x005f},
4584  {8, 0x001f},
4585  {9, 0x009e},
4586  {7, 0x0117},
4587  {8, 0x007f},
4588  {8, 0x003f},
4589  {9, 0x00de},
4590  {7, 0x010f},
4591  {8, 0x006f},
4592  {8, 0x002f},
4593  {9, 0x00be},
4594  {8, 0x000f},
4595  {8, 0x008f},
4596  {8, 0x004f},
4597  {9, 0x00fe},
4598  {7, 0x0100},
4599  {8, 0x0050},
4600  {8, 0x0010},
4601  {8, 0x0118},
4602  {7, 0x0110},
4603  {8, 0x0070},
4604  {8, 0x0030},
4605  {9, 0x00c1},
4606  {7, 0x0108},
4607  {8, 0x0060},
4608  {8, 0x0020},
4609  {9, 0x00a1},
4610  {8, 0x0000},
4611  {8, 0x0080},
4612  {8, 0x0040},
4613  {9, 0x00e1},
4614  {7, 0x0104},
4615  {8, 0x0058},
4616  {8, 0x0018},
4617  {9, 0x0091},
4618  {7, 0x0114},
4619  {8, 0x0078},
4620  {8, 0x0038},
4621  {9, 0x00d1},
4622  {7, 0x010c},
4623  {8, 0x0068},
4624  {8, 0x0028},
4625  {9, 0x00b1},
4626  {8, 0x0008},
4627  {8, 0x0088},
4628  {8, 0x0048},
4629  {9, 0x00f1},
4630  {7, 0x0102},
4631  {8, 0x0054},
4632  {8, 0x0014},
4633  {8, 0x011c},
4634  {7, 0x0112},
4635  {8, 0x0074},
4636  {8, 0x0034},
4637  {9, 0x00c9},
4638  {7, 0x010a},
4639  {8, 0x0064},
4640  {8, 0x0024},
4641  {9, 0x00a9},
4642  {8, 0x0004},
4643  {8, 0x0084},
4644  {8, 0x0044},
4645  {9, 0x00e9},
4646  {7, 0x0106},
4647  {8, 0x005c},
4648  {8, 0x001c},
4649  {9, 0x0099},
4650  {7, 0x0116},
4651  {8, 0x007c},
4652  {8, 0x003c},
4653  {9, 0x00d9},
4654  {7, 0x010e},
4655  {8, 0x006c},
4656  {8, 0x002c},
4657  {9, 0x00b9},
4658  {8, 0x000c},
4659  {8, 0x008c},
4660  {8, 0x004c},
4661  {9, 0x00f9},
4662  {7, 0x0101},
4663  {8, 0x0052},
4664  {8, 0x0012},
4665  {8, 0x011a},
4666  {7, 0x0111},
4667  {8, 0x0072},
4668  {8, 0x0032},
4669  {9, 0x00c5},
4670  {7, 0x0109},
4671  {8, 0x0062},
4672  {8, 0x0022},
4673  {9, 0x00a5},
4674  {8, 0x0002},
4675  {8, 0x0082},
4676  {8, 0x0042},
4677  {9, 0x00e5},
4678  {7, 0x0105},
4679  {8, 0x005a},
4680  {8, 0x001a},
4681  {9, 0x0095},
4682  {7, 0x0115},
4683  {8, 0x007a},
4684  {8, 0x003a},
4685  {9, 0x00d5},
4686  {7, 0x010d},
4687  {8, 0x006a},
4688  {8, 0x002a},
4689  {9, 0x00b5},
4690  {8, 0x000a},
4691  {8, 0x008a},
4692  {8, 0x004a},
4693  {9, 0x00f5},
4694  {7, 0x0103},
4695  {8, 0x0056},
4696  {8, 0x0016},
4697  {8, 0x011e},
4698  {7, 0x0113},
4699  {8, 0x0076},
4700  {8, 0x0036},
4701  {9, 0x00cd},
4702  {7, 0x010b},
4703  {8, 0x0066},
4704  {8, 0x0026},
4705  {9, 0x00ad},
4706  {8, 0x0006},
4707  {8, 0x0086},
4708  {8, 0x0046},
4709  {9, 0x00ed},
4710  {7, 0x0107},
4711  {8, 0x005e},
4712  {8, 0x001e},
4713  {9, 0x009d},
4714  {7, 0x0117},
4715  {8, 0x007e},
4716  {8, 0x003e},
4717  {9, 0x00dd},
4718  {7, 0x010f},
4719  {8, 0x006e},
4720  {8, 0x002e},
4721  {9, 0x00bd},
4722  {8, 0x000e},
4723  {8, 0x008e},
4724  {8, 0x004e},
4725  {9, 0x00fd},
4726  {7, 0x0100},
4727  {8, 0x0051},
4728  {8, 0x0011},
4729  {8, 0x0119},
4730  {7, 0x0110},
4731  {8, 0x0071},
4732  {8, 0x0031},
4733  {9, 0x00c3},
4734  {7, 0x0108},
4735  {8, 0x0061},
4736  {8, 0x0021},
4737  {9, 0x00a3},
4738  {8, 0x0001},
4739  {8, 0x0081},
4740  {8, 0x0041},
4741  {9, 0x00e3},
4742  {7, 0x0104},
4743  {8, 0x0059},
4744  {8, 0x0019},
4745  {9, 0x0093},
4746  {7, 0x0114},
4747  {8, 0x0079},
4748  {8, 0x0039},
4749  {9, 0x00d3},
4750  {7, 0x010c},
4751  {8, 0x0069},
4752  {8, 0x0029},
4753  {9, 0x00b3},
4754  {8, 0x0009},
4755  {8, 0x0089},
4756  {8, 0x0049},
4757  {9, 0x00f3},
4758  {7, 0x0102},
4759  {8, 0x0055},
4760  {8, 0x0015},
4761  {8, 0x011d},
4762  {7, 0x0112},
4763  {8, 0x0075},
4764  {8, 0x0035},
4765  {9, 0x00cb},
4766  {7, 0x010a},
4767  {8, 0x0065},
4768  {8, 0x0025},
4769  {9, 0x00ab},
4770  {8, 0x0005},
4771  {8, 0x0085},
4772  {8, 0x0045},
4773  {9, 0x00eb},
4774  {7, 0x0106},
4775  {8, 0x005d},
4776  {8, 0x001d},
4777  {9, 0x009b},
4778  {7, 0x0116},
4779  {8, 0x007d},
4780  {8, 0x003d},
4781  {9, 0x00db},
4782  {7, 0x010e},
4783  {8, 0x006d},
4784  {8, 0x002d},
4785  {9, 0x00bb},
4786  {8, 0x000d},
4787  {8, 0x008d},
4788  {8, 0x004d},
4789  {9, 0x00fb},
4790  {7, 0x0101},
4791  {8, 0x0053},
4792  {8, 0x0013},
4793  {8, 0x011b},
4794  {7, 0x0111},
4795  {8, 0x0073},
4796  {8, 0x0033},
4797  {9, 0x00c7},
4798  {7, 0x0109},
4799  {8, 0x0063},
4800  {8, 0x0023},
4801  {9, 0x00a7},
4802  {8, 0x0003},
4803  {8, 0x0083},
4804  {8, 0x0043},
4805  {9, 0x00e7},
4806  {7, 0x0105},
4807  {8, 0x005b},
4808  {8, 0x001b},
4809  {9, 0x0097},
4810  {7, 0x0115},
4811  {8, 0x007b},
4812  {8, 0x003b},
4813  {9, 0x00d7},
4814  {7, 0x010d},
4815  {8, 0x006b},
4816  {8, 0x002b},
4817  {9, 0x00b7},
4818  {8, 0x000b},
4819  {8, 0x008b},
4820  {8, 0x004b},
4821  {9, 0x00f7},
4822  {7, 0x0103},
4823  {8, 0x0057},
4824  {8, 0x0017},
4825  {8, 0x011f},
4826  {7, 0x0113},
4827  {8, 0x0077},
4828  {8, 0x0037},
4829  {9, 0x00cf},
4830  {7, 0x010b},
4831  {8, 0x0067},
4832  {8, 0x0027},
4833  {9, 0x00af},
4834  {8, 0x0007},
4835  {8, 0x0087},
4836  {8, 0x0047},
4837  {9, 0x00ef},
4838  {7, 0x0107},
4839  {8, 0x005f},
4840  {8, 0x001f},
4841  {9, 0x009f},
4842  {7, 0x0117},
4843  {8, 0x007f},
4844  {8, 0x003f},
4845  {9, 0x00df},
4846  {7, 0x010f},
4847  {8, 0x006f},
4848  {8, 0x002f},
4849  {9, 0x00bf},
4850  {8, 0x000f},
4851  {8, 0x008f},
4852  {8, 0x004f},
4853  {9, 0x00ff}
4854 };
4855 
4858 };
4859 
4861  {5, 0x0000},
4862  {5, 0x0010},
4863  {5, 0x0008},
4864  {5, 0x0018},