1 //========================================================================
5 // Copyright 1996-2002 Glyph & Cog, LLC
7 //========================================================================
10 #pragma implementation
20 extern "C" int unlink(char *filename);
33 #include "Stream-CCITT.h"
36 static GBool setDJSYSFLAGS = gFalse;
40 #if (__VMS_VER < 70000000)
41 extern "C" int unlink(char *filename);
51 #include "StuffItEngineLib.h"
54 //------------------------------------------------------------------------
55 // Stream (base class)
56 //------------------------------------------------------------------------
65 void Stream::close() {
68 int Stream::getRawChar() {
69 error(-1, "Internal: called getRawChar() on non-predictor stream");
73 char *Stream::getLine(char *buf, int size) {
77 if (lookChar() == EOF)
79 for (i = 0; i < size - 1; ++i) {
81 if (c == EOF || c == '\n')
84 if ((c = lookChar()) == '\n')
94 GString *Stream::getPSFilter(char *indent) {
98 Stream *Stream::addFilters(Object *dict) {
100 Object params, params2;
105 dict->dictLookup("Filter", &obj);
108 dict->dictLookup("F", &obj);
110 dict->dictLookup("DecodeParms", ¶ms);
111 if (params.isNull()) {
113 dict->dictLookup("DP", ¶ms);
116 str = makeFilter(obj.getName(), str, ¶ms);
117 } else if (obj.isArray()) {
118 for (i = 0; i < obj.arrayGetLength(); ++i) {
119 obj.arrayGet(i, &obj2);
120 if (params.isArray())
121 params.arrayGet(i, ¶ms2);
125 str = makeFilter(obj2.getName(), str, ¶ms2);
127 error(getPos(), "Bad filter name");
128 str = new EOFStream(str);
133 } else if (!obj.isNull()) {
134 error(getPos(), "Bad 'Filter' attribute in stream");
142 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
143 int pred; // parameters
148 GBool endOfLine, byteAlign, endOfBlock, black;
152 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
153 str = new ASCIIHexStream(str);
154 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
155 str = new ASCII85Stream(str);
156 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
162 if (params->isDict()) {
163 params->dictLookup("Predictor", &obj);
167 params->dictLookup("Columns", &obj);
169 columns = obj.getInt();
171 params->dictLookup("Colors", &obj);
173 colors = obj.getInt();
175 params->dictLookup("BitsPerComponent", &obj);
179 params->dictLookup("EarlyChange", &obj);
181 early = obj.getInt();
184 str = new LZWStream(str, pred, columns, colors, bits, early);
185 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
186 str = new RunLengthStream(str);
187 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
195 if (params->isDict()) {
196 params->dictLookup("K", &obj);
198 encoding = obj.getInt();
201 params->dictLookup("EndOfLine", &obj);
203 endOfLine = obj.getBool();
206 params->dictLookup("EncodedByteAlign", &obj);
208 byteAlign = obj.getBool();
211 params->dictLookup("Columns", &obj);
213 columns = obj.getInt();
216 params->dictLookup("Rows", &obj);
221 params->dictLookup("EndOfBlock", &obj);
223 endOfBlock = obj.getBool();
226 params->dictLookup("BlackIs1", &obj);
228 black = obj.getBool();
232 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
233 columns, rows, endOfBlock, black);
234 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
235 str = new DCTStream(str);
236 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
241 if (params->isDict()) {
242 params->dictLookup("Predictor", &obj);
246 params->dictLookup("Columns", &obj);
248 columns = obj.getInt();
250 params->dictLookup("Colors", &obj);
252 colors = obj.getInt();
254 params->dictLookup("BitsPerComponent", &obj);
259 str = new FlateStream(str, pred, columns, colors, bits);
261 error(getPos(), "Unknown filter '%s'", name);
262 str = new EOFStream(str);
267 //------------------------------------------------------------------------
269 //------------------------------------------------------------------------
271 BaseStream::BaseStream(Object *dictA) {
273 #ifndef NO_DECRYPTION
278 BaseStream::~BaseStream() {
280 #ifndef NO_DECRYPTION
286 #ifndef NO_DECRYPTION
287 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
288 int objNum, int objGen) {
289 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
293 //------------------------------------------------------------------------
295 //------------------------------------------------------------------------
297 FilterStream::FilterStream(Stream *strA) {
301 FilterStream::~FilterStream() {
304 void FilterStream::close() {
308 void FilterStream::setPos(Guint pos, int dir) {
309 error(-1, "Internal: called setPos() on FilterStream");
312 //------------------------------------------------------------------------
314 //------------------------------------------------------------------------
316 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
324 nVals = width * nComps;
326 imgLineSize = (nVals + 7) & ~7;
330 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
334 ImageStream::~ImageStream() {
338 void ImageStream::reset() {
342 GBool ImageStream::getPixel(Guchar *pix) {
348 if (imgIdx >= nVals) {
350 // read one line of image pixels
352 for (i = 0; i < nVals; i += 8) {
354 imgLine[i+0] = (Guchar)((c >> 7) & 1);
355 imgLine[i+1] = (Guchar)((c >> 6) & 1);
356 imgLine[i+2] = (Guchar)((c >> 5) & 1);
357 imgLine[i+3] = (Guchar)((c >> 4) & 1);
358 imgLine[i+4] = (Guchar)((c >> 3) & 1);
359 imgLine[i+5] = (Guchar)((c >> 2) & 1);
360 imgLine[i+6] = (Guchar)((c >> 1) & 1);
361 imgLine[i+7] = (Guchar)(c & 1);
363 } else if (nBits == 8) {
364 for (i = 0; i < nVals; ++i) {
365 imgLine[i] = str->getChar();
368 bitMask = (1 << nBits) - 1;
371 for (i = 0; i < nVals; ++i) {
373 buf = (buf << 8) | (str->getChar() & 0xff);
376 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
381 // reset to start of line
385 for (i = 0; i < nComps; ++i)
386 pix[i] = imgLine[imgIdx++];
390 void ImageStream::skipLine() {
393 n = (nVals * nBits + 7) >> 3;
394 for (i = 0; i < n; ++i) {
399 //------------------------------------------------------------------------
401 //------------------------------------------------------------------------
403 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
404 int widthA, int nCompsA, int nBitsA) {
406 predictor = predictorA;
411 nVals = width * nComps;
412 pixBytes = (nComps * nBits + 7) >> 3;
413 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
414 predLine = (Guchar *)gmalloc(rowBytes);
415 memset(predLine, 0, rowBytes);
419 StreamPredictor::~StreamPredictor() {
423 int StreamPredictor::lookChar() {
424 if (predIdx >= rowBytes) {
425 if (!getNextLine()) {
429 return predLine[predIdx];
432 int StreamPredictor::getChar() {
433 if (predIdx >= rowBytes) {
434 if (!getNextLine()) {
438 return predLine[predIdx++];
441 GBool StreamPredictor::getNextLine() {
444 int left, up, upLeft, p, pa, pb, pc;
446 Gulong inBuf, outBuf, bitMask;
450 // get PNG optimum predictor number
451 if (predictor == 15) {
452 if ((curPred = str->getRawChar()) == EOF) {
460 // read the raw line, apply PNG (byte) predictor
461 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
462 for (i = pixBytes; i < rowBytes; ++i) {
463 upLeftBuf[3] = upLeftBuf[2];
464 upLeftBuf[2] = upLeftBuf[1];
465 upLeftBuf[1] = upLeftBuf[0];
466 upLeftBuf[0] = predLine[i];
467 if ((c = str->getRawChar()) == EOF) {
472 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
475 predLine[i] = predLine[i] + (Guchar)c;
477 case 13: // PNG average
478 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
481 case 14: // PNG Paeth
482 left = predLine[i - pixBytes];
484 upLeft = upLeftBuf[pixBytes];
485 p = left + up - upLeft;
486 if ((pa = p - left) < 0)
488 if ((pb = p - up) < 0)
490 if ((pc = p - upLeft) < 0)
492 if (pa <= pb && pa <= pc)
493 predLine[i] = left + (Guchar)c;
495 predLine[i] = up + (Guchar)c;
497 predLine[i] = upLeft + (Guchar)c;
500 default: // no predictor or TIFF predictor
501 predLine[i] = (Guchar)c;
506 // apply TIFF (component) predictor
507 //~ this is completely untested
508 if (predictor == 2) {
510 inBuf = predLine[pixBytes - 1];
511 for (i = pixBytes; i < rowBytes; i += 8) {
512 // 1-bit add is just xor
513 inBuf = (inBuf << 8) | predLine[i];
514 predLine[i] ^= inBuf >> nComps;
516 } else if (nBits == 8) {
517 for (i = pixBytes; i < rowBytes; ++i) {
518 predLine[i] += predLine[i - nComps];
521 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
522 bitMask = (1 << nBits) - 1;
524 inBits = outBits = 0;
526 for (i = 0; i < nVals; ++i) {
527 if (inBits < nBits) {
528 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
531 upLeftBuf[3] = upLeftBuf[2];
532 upLeftBuf[2] = upLeftBuf[1];
533 upLeftBuf[1] = upLeftBuf[0];
534 upLeftBuf[0] = (upLeftBuf[nComps] +
535 (inBuf >> (inBits - nBits))) & bitMask;
536 outBuf = (outBuf << nBits) | upLeftBuf[0];
540 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
544 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
549 // reset to start of line
555 //------------------------------------------------------------------------
557 //------------------------------------------------------------------------
559 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
560 Guint lengthA, Object *dictA):
566 bufPtr = bufEnd = buf;
572 FileStream::~FileStream() {
576 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
577 Guint lengthA, Object *dictA) {
578 return new FileStream(f, startA, limitedA, lengthA, dictA);
581 void FileStream::reset() {
583 savePos = (Guint)ftell64(f);
584 fseek64(f, start, SEEK_SET);
586 savePos = (Guint)ftell(f);
587 fseek(f, start, SEEK_SET);
590 bufPtr = bufEnd = buf;
592 #ifndef NO_DECRYPTION
598 void FileStream::close() {
601 fseek64(f, savePos, SEEK_SET);
603 fseek(f, savePos, SEEK_SET);
609 GBool FileStream::fillBuf() {
611 #ifndef NO_DECRYPTION
615 bufPos += bufEnd - buf;
616 bufPtr = bufEnd = buf;
617 if (limited && bufPos >= start + length) {
620 if (limited && bufPos + fileStreamBufSize > start + length) {
621 n = start + length - bufPos;
623 n = fileStreamBufSize;
625 n = fread(buf, 1, n, f);
627 if (bufPtr >= bufEnd) {
630 #ifndef NO_DECRYPTION
632 for (p = buf; p < bufEnd; ++p) {
633 *p = (char)decrypt->decryptByte((Guchar)*p);
640 void FileStream::setPos(Guint pos, int dir) {
645 fseek64(f, pos, SEEK_SET);
647 fseek(f, pos, SEEK_SET);
652 fseek64(f, 0, SEEK_END);
653 size = (Guint)ftell64(f);
655 fseek(f, 0, SEEK_END);
656 size = (Guint)ftell(f);
661 //~ work around a bug in cygwin's implementation of fseek
665 fseek64(f, -(int)pos, SEEK_END);
666 bufPos = (Guint)ftell64(f);
668 fseek(f, -(int)pos, SEEK_END);
669 bufPos = (Guint)ftell(f);
672 bufPtr = bufEnd = buf;
675 void FileStream::moveStart(int delta) {
677 bufPtr = bufEnd = buf;
681 //------------------------------------------------------------------------
683 //------------------------------------------------------------------------
685 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
690 bufEnd = buf + length;
694 MemStream::~MemStream() {
700 Stream *MemStream::makeSubStream(Guint start, GBool limited,
701 Guint lengthA, Object *dictA) {
704 if (!limited || start + lengthA > length) {
705 newLength = length - start;
709 return new MemStream(buf + start, newLength, dictA);
712 void MemStream::reset() {
714 #ifndef NO_DECRYPTION
721 void MemStream::close() {
724 void MemStream::setPos(Guint pos, int dir) {
735 bufPtr = bufEnd - pos;
740 void MemStream::moveStart(int delta) {
745 #ifndef NO_DECRYPTION
746 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
747 int objNum, int objGen) {
751 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
753 newBuf = (char *)gmalloc(bufEnd - buf);
754 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
755 *q = (char)decrypt->decryptByte((Guchar)*p);
757 bufEnd = newBuf + (bufEnd - buf);
758 bufPtr = newBuf + (bufPtr - buf);
765 //------------------------------------------------------------------------
767 //------------------------------------------------------------------------
769 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
774 EmbedStream::~EmbedStream() {
777 Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
778 Guint length, Object *dictA) {
779 error(-1, "Internal: called makeSubStream() on EmbedStream");
783 void EmbedStream::setPos(Guint pos, int dir) {
784 error(-1, "Internal: called setPos() on EmbedStream");
787 Guint EmbedStream::getStart() {
788 error(-1, "Internal: called getStart() on EmbedStream");
792 void EmbedStream::moveStart(int delta) {
793 error(-1, "Internal: called moveStart() on EmbedStream");
796 //------------------------------------------------------------------------
798 //------------------------------------------------------------------------
800 ASCIIHexStream::ASCIIHexStream(Stream *strA):
806 ASCIIHexStream::~ASCIIHexStream() {
810 void ASCIIHexStream::reset() {
816 int ASCIIHexStream::lookChar() {
827 } while (isspace(c1));
835 } while (isspace(c2));
840 if (c1 >= '0' && c1 <= '9') {
842 } else if (c1 >= 'A' && c1 <= 'F') {
843 x = (c1 - 'A' + 10) << 4;
844 } else if (c1 >= 'a' && c1 <= 'f') {
845 x = (c1 - 'a' + 10) << 4;
846 } else if (c1 == EOF) {
850 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
853 if (c2 >= '0' && c2 <= '9') {
855 } else if (c2 >= 'A' && c2 <= 'F') {
857 } else if (c2 >= 'a' && c2 <= 'f') {
859 } else if (c2 == EOF) {
863 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
869 GString *ASCIIHexStream::getPSFilter(char *indent) {
872 if (!(s = str->getPSFilter(indent))) {
875 s->append(indent)->append("/ASCIIHexDecode filter\n");
879 GBool ASCIIHexStream::isBinary(GBool last) {
880 return str->isBinary(gFalse);
883 //------------------------------------------------------------------------
885 //------------------------------------------------------------------------
887 ASCII85Stream::ASCII85Stream(Stream *strA):
893 ASCII85Stream::~ASCII85Stream() {
897 void ASCII85Stream::reset() {
903 int ASCII85Stream::lookChar() {
912 c[0] = str->getChar();
913 } while (c[0] == '\n' || c[0] == '\r');
914 if (c[0] == '~' || c[0] == EOF) {
918 } else if (c[0] == 'z') {
919 b[0] = b[1] = b[2] = b[3] = 0;
922 for (k = 1; k < 5; ++k) {
924 c[k] = str->getChar();
925 } while (c[k] == '\n' || c[k] == '\r');
926 if (c[k] == '~' || c[k] == EOF)
930 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
931 for (++k; k < 5; ++k)
936 for (k = 0; k < 5; ++k)
937 t = t * 85 + (c[k] - 0x21);
938 for (k = 3; k >= 0; --k) {
939 b[k] = (int)(t & 0xff);
947 GString *ASCII85Stream::getPSFilter(char *indent) {
950 if (!(s = str->getPSFilter(indent))) {
953 s->append(indent)->append("/ASCII85Decode filter\n");
957 GBool ASCII85Stream::isBinary(GBool last) {
958 return str->isBinary(gFalse);
961 //------------------------------------------------------------------------
963 //------------------------------------------------------------------------
965 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
966 int bits, int earlyA):
968 if (predictor != 1) {
969 pred = new StreamPredictor(this, predictor, columns, colors, bits);
975 bufPtr = bufEnd = buf;
978 LZWStream::~LZWStream() {
986 unlink(zName->getCString());
995 int LZWStream::getChar() {
997 return pred->getChar();
999 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1002 int LZWStream::lookChar() {
1004 return pred->lookChar();
1006 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
1009 int LZWStream::getRawChar() {
1010 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1013 void LZWStream::reset() {
1017 //----- close old LZW stream
1025 unlink(zName->getCString());
1029 //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
1032 if (!setDJSYSFLAGS) {
1033 setenv("DJSYSFLAGS", "0x0002", 0);
1034 setDJSYSFLAGS = gTrue;
1038 //----- create the .Z file
1039 if (!openTempFile(&zName, &f, "wb", ".Z")) {
1040 error(getPos(), "Couldn't create temporary file for LZW stream");
1046 //----- execute uncompress / gzip
1048 zCmd = new GString("c:\\swftools\\gzip.exe");
1050 zCmd = new GString(uncompressCmd);
1053 zCmd->append(zName);
1056 // first we open the engine up
1057 OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
1058 // if we found it - let's use it!
1059 if (!err && magicCookie) {
1060 // make sure we have the correct version of the Engine
1061 if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
1064 strcpy((char *)pName, zName->getCString());
1065 c2pstr((char *)pName);
1066 FSMakeFSSpec(0, 0, pName, &myFSS);
1067 short ftype = DetermineFileType(magicCookie, &myFSS);
1068 OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
1069 NULL, NULL, kCreateFolderNever,
1070 kDeleteOriginal, kTextConvertSmart);
1073 #elif defined(HAVE_POPEN)
1074 if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
1075 error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
1076 unlink(zName->getCString());
1081 if (!executeCommand(zCmd->getCString())) {
1082 error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
1083 unlink(zName->getCString());
1087 zName->del(zName->getLength() - 2, 2);
1088 if (!(zPipe = fopen(zName->getCString(), "rb"))) {
1089 error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
1090 unlink(zName->getCString());
1094 #endif // HAVE_POPEN
1099 //----- initialize buffer
1100 bufPtr = bufEnd = buf;
1103 void LZWStream::dumpFile(FILE *f) {
1104 int outCodeBits; // size of output code
1105 int outBits; // max output code
1106 int outBuf[8]; // output buffer
1107 int outData; // temporary output buffer
1108 int inCode, outCode; // input and output codes
1109 int nextCode; // next code index
1110 GBool eof; // set when EOF is reached
1111 GBool clear; // set if table needs to be cleared
1112 GBool first; // indicates first code word after clear
1121 // max code length, block mode flag
1139 for (i = 0; i < 8; ++i) {
1140 // check for table overflow
1141 if (nextCode + early > 0x1001) {
1148 if (inCode == EOF) {
1152 } while (first && inCode == 256);
1155 // compute output code
1158 } else if (inCode == 256) {
1161 } else if (inCode == 257) {
1165 outCode = inCode - 1;
1167 outBuf[i] = outCode;
1175 // check input code size
1176 if (nextCode + early == 0x200)
1178 else if (nextCode + early == 0x400) {
1180 } else if (nextCode + early == 0x800) {
1184 // check for eof/clear
1193 // write output block
1197 while (j < i || outBits > 0) {
1198 if (outBits < 8 && j < i) {
1199 outData = outData | (outBuf[j++] << outBits);
1200 outBits += outCodeBits;
1202 fputc(outData & 0xff, f);
1207 // check output code size
1208 if (nextCode - 1 == 512 ||
1209 nextCode - 1 == 1024 ||
1210 nextCode - 1 == 2048 ||
1211 nextCode - 1 == 4096) {
1212 outCodeBits = inCodeBits;
1215 // clear table if necessary
1226 int LZWStream::getCode() {
1230 while (inputBits < inCodeBits) {
1231 if ((c = str->getChar()) == EOF)
1233 inputBuf = (inputBuf << 8) | (c & 0xff);
1236 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1237 inputBits -= inCodeBits;
1241 GBool LZWStream::fillBuf() {
1246 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1253 unlink(zName->getCString());
1261 GString *LZWStream::getPSFilter(char *indent) {
1267 if (!(s = str->getPSFilter(indent))) {
1270 s->append(indent)->append("/LZWDecode filter\n");
1274 GBool LZWStream::isBinary(GBool last) {
1275 return str->isBinary(gTrue);
1278 //------------------------------------------------------------------------
1280 //------------------------------------------------------------------------
1282 RunLengthStream::RunLengthStream(Stream *strA):
1283 FilterStream(strA) {
1284 bufPtr = bufEnd = buf;
1288 RunLengthStream::~RunLengthStream() {
1292 void RunLengthStream::reset() {
1294 bufPtr = bufEnd = buf;
1298 GString *RunLengthStream::getPSFilter(char *indent) {
1301 if (!(s = str->getPSFilter(indent))) {
1304 s->append(indent)->append("/RunLengthDecode filter\n");
1308 GBool RunLengthStream::isBinary(GBool last) {
1309 return str->isBinary(gTrue);
1312 GBool RunLengthStream::fillBuf() {
1319 if (c == 0x80 || c == EOF) {
1325 for (i = 0; i < n; ++i)
1326 buf[i] = (char)str->getChar();
1330 for (i = 0; i < n; ++i)
1338 //------------------------------------------------------------------------
1340 //------------------------------------------------------------------------
1342 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1343 GBool byteAlignA, int columnsA, int rowsA,
1344 GBool endOfBlockA, GBool blackA):
1345 FilterStream(strA) {
1346 encoding = encodingA;
1347 endOfLine = endOfLineA;
1348 byteAlign = byteAlignA;
1351 endOfBlock = endOfBlockA;
1353 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1354 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1358 nextLine2D = encoding < 0;
1361 codingLine[1] = refLine[2] = columns;
1367 CCITTFaxStream::~CCITTFaxStream() {
1373 void CCITTFaxStream::reset() {
1379 nextLine2D = encoding < 0;
1382 codingLine[1] = refLine[2] = columns;
1386 // get initial end-of-line marker and 2D encoding tag
1388 if (lookBits(12) == 0x001) {
1392 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1393 if (n == 11 && lookBits(12) == 0x001) {
1398 nextLine2D = !lookBits(1);
1403 int CCITTFaxStream::lookChar() {
1404 short code1, code2, code3;
1413 // if at eof just return EOF
1414 if (eof && codingLine[a0] >= columns) {
1418 // read the next row
1422 if (codingLine[a0] >= columns) {
1426 for (i = 0; codingLine[i] < columns; ++i)
1427 refLine[i] = codingLine[i];
1428 refLine[i] = refLine[i + 1] = columns;
1430 a0New = codingLine[a0 = 0] = 0;
1432 code1 = getTwoDimCode();
1435 if (refLine[b1] < columns) {
1436 a0New = refLine[b1 + 1];
1441 if ((a0 & 1) == 0) {
1444 code1 += code3 = getWhiteCode();
1445 } while (code3 >= 64);
1447 code2 += code3 = getBlackCode();
1448 } while (code3 >= 64);
1452 code1 += code3 = getBlackCode();
1453 } while (code3 >= 64);
1455 code2 += code3 = getWhiteCode();
1456 } while (code3 >= 64);
1458 codingLine[a0 + 1] = a0New + code1;
1460 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1462 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1466 a0New = codingLine[++a0] = refLine[b1];
1467 if (refLine[b1] < columns) {
1469 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1474 a0New = codingLine[++a0] = refLine[b1] + 1;
1475 if (refLine[b1] < columns) {
1477 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1482 a0New = codingLine[++a0] = refLine[b1] - 1;
1484 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1488 a0New = codingLine[++a0] = refLine[b1] + 2;
1489 if (refLine[b1] < columns) {
1491 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1496 a0New = codingLine[++a0] = refLine[b1] - 2;
1498 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1502 a0New = codingLine[++a0] = refLine[b1] + 3;
1503 if (refLine[b1] < columns) {
1505 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1510 a0New = codingLine[++a0] = refLine[b1] - 3;
1512 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1517 codingLine[a0 = 0] = columns;
1520 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1529 } while (codingLine[a0] < columns);
1533 codingLine[a0 = 0] = 0;
1537 code1 += code3 = getWhiteCode();
1538 } while (code3 >= 64);
1539 codingLine[a0+1] = codingLine[a0] + code1;
1541 if (codingLine[a0] >= columns)
1545 code2 += code3 = getBlackCode();
1546 } while (code3 >= 64);
1547 codingLine[a0+1] = codingLine[a0] + code2;
1549 if (codingLine[a0] >= columns)
1554 if (codingLine[a0] != columns) {
1555 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1561 // byte-align the row
1566 // check for end-of-line marker, skipping over any extra zero bits
1568 if (!endOfBlock && row == rows - 1) {
1571 code1 = lookBits(12);
1572 while (code1 == 0) {
1574 code1 = lookBits(12);
1576 if (code1 == 0x001) {
1579 } else if (code1 == EOF) {
1584 // get 2D encoding tag
1585 if (!eof && encoding > 0) {
1586 nextLine2D = !lookBits(1);
1590 // check for end-of-block marker
1591 if (endOfBlock && gotEOL) {
1592 code1 = lookBits(12);
1593 if (code1 == 0x001) {
1599 if (encoding >= 0) {
1600 for (i = 0; i < 4; ++i) {
1601 code1 = lookBits(12);
1602 if (code1 != 0x001) {
1603 error(getPos(), "Bad RTC code in CCITTFax stream");
1617 // This looks for an end-of-line marker after an error, however
1618 // some (most?) CCITT streams in PDF files don't use end-of-line
1619 // markers, and the just-plow-on technique works better in those
1628 code1 = look13Bits();
1629 } while ((code1 >> 1) != 0x001);
1631 codingLine[++a0] = columns;
1634 nextLine2D = !(code1 & 1);
1640 outputBits = codingLine[1] - codingLine[0];
1641 if (outputBits == 0) {
1643 outputBits = codingLine[2] - codingLine[1];
1650 if (outputBits >= 8) {
1651 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1652 if ((outputBits -= 8) == 0) {
1654 if (codingLine[a0] < columns) {
1655 outputBits = codingLine[a0 + 1] - codingLine[a0];
1662 if (outputBits > bits) {
1665 if ((a0 & 1) == 0) {
1666 ret |= 0xff >> (8 - i);
1672 if ((a0 & 1) == 0) {
1673 ret |= (0xff >> (8 - i)) << bits;
1677 if (codingLine[a0] < columns) {
1678 outputBits = codingLine[a0 + 1] - codingLine[a0];
1681 } while (bits > 0 && codingLine[a0] < columns);
1683 buf = black ? (ret ^ 0xff) : ret;
1687 short CCITTFaxStream::getTwoDimCode() {
1692 code = 0; // make gcc happy
1695 p = &twoDimTab1[code];
1701 for (n = 1; n <= 7; ++n) {
1706 p = &twoDimTab1[code];
1713 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1717 short CCITTFaxStream::getWhiteCode() {
1722 code = 0; // make gcc happy
1724 code = lookBits(12);
1725 if ((code >> 5) == 0) {
1726 p = &whiteTab1[code];
1728 p = &whiteTab2[code >> 3];
1735 for (n = 1; n <= 9; ++n) {
1740 p = &whiteTab2[code];
1746 for (n = 11; n <= 12; ++n) {
1751 p = &whiteTab1[code];
1758 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1759 // eat a bit and return a positive number so that the caller doesn't
1760 // go into an infinite loop
1765 short CCITTFaxStream::getBlackCode() {
1770 code = 0; // make gcc happy
1772 code = lookBits(13);
1773 if ((code >> 7) == 0) {
1774 p = &blackTab1[code];
1775 } else if ((code >> 9) == 0) {
1776 p = &blackTab2[(code >> 1) - 64];
1778 p = &blackTab3[code >> 7];
1785 for (n = 2; n <= 6; ++n) {
1790 p = &blackTab3[code];
1796 for (n = 7; n <= 12; ++n) {
1802 p = &blackTab2[code - 64];
1809 for (n = 10; n <= 13; ++n) {
1814 p = &blackTab1[code];
1821 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1822 // eat a bit and return a positive number so that the caller doesn't
1823 // go into an infinite loop
1828 short CCITTFaxStream::lookBits(int n) {
1831 while (inputBits < n) {
1832 if ((c = str->getChar()) == EOF) {
1833 if (inputBits == 0) {
1836 // near the end of the stream, the caller may ask for more bits
1837 // than are available, but there may still be a valid code in
1838 // however many bits are available -- we need to return correct
1839 // data in this case
1840 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1842 inputBuf = (inputBuf << 8) + c;
1845 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1848 GString *CCITTFaxStream::getPSFilter(char *indent) {
1852 if (!(s = str->getPSFilter(indent))) {
1855 s->append(indent)->append("<< ");
1856 if (encoding != 0) {
1857 sprintf(s1, "/K %d ", encoding);
1861 s->append("/EndOfLine true ");
1864 s->append("/EncodedByteAlign true ");
1866 sprintf(s1, "/Columns %d ", columns);
1869 sprintf(s1, "/Rows %d ", rows);
1873 s->append("/EndOfBlock false ");
1876 s->append("/BlackIs1 true ");
1878 s->append(">> /CCITTFaxDecode filter\n");
1882 GBool CCITTFaxStream::isBinary(GBool last) {
1883 return str->isBinary(gTrue);
1886 //------------------------------------------------------------------------
1888 //------------------------------------------------------------------------
1890 // IDCT constants (20.12 fixed point format)
1892 #define dctCos1 4017 // cos(pi/16)
1893 #define dctSin1 799 // sin(pi/16)
1894 #define dctCos3 3406 // cos(3*pi/16)
1895 #define dctSin3 2276 // sin(3*pi/16)
1896 #define dctCos6 1567 // cos(6*pi/16)
1897 #define dctSin6 3784 // sin(6*pi/16)
1898 #define dctSqrt2 5793 // sqrt(2)
1899 #define dctSqrt1d2 2896 // sqrt(2) / 2
1904 #define dctCos1 0.98078528 // cos(pi/16)
1905 #define dctSin1 0.19509032 // sin(pi/16)
1906 #define dctCos3 0.83146961 // cos(3*pi/16)
1907 #define dctSin3 0.55557023 // sin(3*pi/16)
1908 #define dctCos6 0.38268343 // cos(6*pi/16)
1909 #define dctSin6 0.92387953 // sin(6*pi/16)
1910 #define dctSqrt2 1.41421356 // sqrt(2)
1911 #define dctSqrt1d2 0.70710678 // sqrt(2) / 2
1914 // color conversion parameters (16.16 fixed point format)
1915 #define dctCrToR 91881 // 1.4020
1916 #define dctCbToG -22553 // -0.3441363
1917 #define dctCrToG -46802 // -0.71413636
1918 #define dctCbToB 116130 // 1.772
1920 // clip [-256,511] --> [0,255]
1921 #define dctClipOffset 256
1922 static Guchar dctClip[768];
1923 static int dctClipInit = 0;
1925 // zig zag decode map
1926 static int dctZigZag[64] = {
1932 5, 12, 19, 26, 33, 40,
1933 48, 41, 34, 27, 20, 13, 6,
1934 7, 14, 21, 28, 35, 42, 49, 56,
1935 57, 50, 43, 36, 29, 22, 15,
1936 23, 30, 37, 44, 51, 58,
1944 DCTStream::DCTStream(Stream *strA):
1945 FilterStream(strA) {
1949 mcuWidth = mcuHeight = 0;
1953 for (i = 0; i < 4; ++i)
1954 for (j = 0; j < 32; ++j)
1955 rowBuf[i][j] = NULL;
1958 for (i = -256; i < 0; ++i)
1959 dctClip[dctClipOffset + i] = 0;
1960 for (i = 0; i < 256; ++i)
1961 dctClip[dctClipOffset + i] = i;
1962 for (i = 256; i < 512; ++i)
1963 dctClip[dctClipOffset + i] = 255;
1968 DCTStream::~DCTStream() {
1972 for (i = 0; i < numComps; ++i)
1973 for (j = 0; j < mcuHeight; ++j)
1974 gfree(rowBuf[i][j]);
1977 void DCTStream::reset() {
1979 if (!readHeader()) {
1983 restartMarker = 0xd0;
1987 int DCTStream::getChar() {
1993 if (++comp == numComps) {
2006 int DCTStream::lookChar() {
2009 if (dy >= mcuHeight) {
2010 if (!readMCURow()) {
2018 return rowBuf[comp][dy][x];
2021 void DCTStream::restart() {
2025 restartCtr = restartInterval;
2026 for (i = 0; i < numComps; ++i)
2027 compInfo[i].prevDC = 0;
2030 GBool DCTStream::readMCURow() {
2033 int pY, pCb, pCr, pR, pG, pB;
2034 int h, v, horiz, vert, hSub, vSub;
2035 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2038 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2040 // deal with restart marker
2041 if (restartInterval > 0 && restartCtr == 0) {
2043 if (c != restartMarker) {
2044 error(getPos(), "Bad DCT data: incorrect restart marker");
2047 if (++restartMarker == 0xd8)
2048 restartMarker = 0xd0;
2053 for (cc = 0; cc < numComps; ++cc) {
2054 h = compInfo[cc].hSample;
2055 v = compInfo[cc].vSample;
2056 horiz = mcuWidth / h;
2057 vert = mcuHeight / v;
2060 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2061 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2062 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
2063 &acHuffTables[compInfo[cc].acHuffTable],
2064 quantTables[compInfo[cc].quantTable],
2065 &compInfo[cc].prevDC,
2068 if (hSub == 1 && vSub == 1) {
2069 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2070 p1 = &rowBuf[cc][y2+y3][x1+x2];
2080 } else if (hSub == 2 && vSub == 2) {
2081 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2082 p1 = &rowBuf[cc][y2+y3][x1+x2];
2083 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2084 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
2085 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
2086 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
2087 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
2088 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
2089 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
2090 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
2091 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
2095 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2096 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2097 for (y5 = 0; y5 < vSub; ++y5)
2098 for (x5 = 0; x5 < hSub; ++x5)
2099 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
2109 // color space conversion
2111 // convert YCbCr to RGB
2112 if (numComps == 3) {
2113 for (y2 = 0; y2 < mcuHeight; ++y2) {
2114 for (x2 = 0; x2 < mcuWidth; ++x2) {
2115 pY = rowBuf[0][y2][x1+x2];
2116 pCb = rowBuf[1][y2][x1+x2] - 128;
2117 pCr = rowBuf[2][y2][x1+x2] - 128;
2118 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2119 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2120 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2121 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2122 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2123 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2126 // convert YCbCrK to CMYK (K is passed through unchanged)
2127 } else if (numComps == 4) {
2128 for (y2 = 0; y2 < mcuHeight; ++y2) {
2129 for (x2 = 0; x2 < mcuWidth; ++x2) {
2130 pY = rowBuf[0][y2][x1+x2];
2131 pCb = rowBuf[1][y2][x1+x2] - 128;
2132 pCr = rowBuf[2][y2][x1+x2] - 128;
2133 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2134 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2135 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2136 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2137 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2138 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2147 // This IDCT algorithm is taken from:
2148 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2149 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2150 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2152 // The stage numbers mentioned in the comments refer to Figure 1 in this
2155 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2156 DCTHuffTable *acHuffTable,
2157 Guchar quantTable[64], int *prevDC,
2160 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2165 // Huffman decode and dequantize
2166 size = readHuffSym(dcHuffTable);
2170 amp = readAmp(size);
2176 tmp1[0] = (*prevDC += amp) * quantTable[0];
2177 for (i = 1; i < 64; ++i)
2182 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2189 run += (c >> 4) & 0x0f;
2191 amp = readAmp(size);
2196 tmp1[j] = amp * quantTable[j];
2200 // inverse DCT on rows
2201 for (i = 0; i < 64; i += 8) {
2204 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
2205 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
2208 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
2209 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
2210 v5 = tmp1[i+3] << 4;
2211 v6 = tmp1[i+5] << 4;
2214 t = (v0 - v1+ 1) >> 1;
2215 v0 = (v0 + v1 + 1) >> 1;
2217 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2218 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2220 t = (v4 - v6 + 1) >> 1;
2221 v4 = (v4 + v6 + 1) >> 1;
2223 t = (v7 + v5 + 1) >> 1;
2224 v5 = (v7 - v5 + 1) >> 1;
2228 t = (v0 - v3 + 1) >> 1;
2229 v0 = (v0 + v3 + 1) >> 1;
2231 t = (v1 - v2 + 1) >> 1;
2232 v1 = (v1 + v2 + 1) >> 1;
2234 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2235 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2237 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2238 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2242 tmp1[i+0] = v0 + v7;
2243 tmp1[i+7] = v0 - v7;
2244 tmp1[i+1] = v1 + v6;
2245 tmp1[i+6] = v1 - v6;
2246 tmp1[i+2] = v2 + v5;
2247 tmp1[i+5] = v2 - v5;
2248 tmp1[i+3] = v3 + v4;
2249 tmp1[i+4] = v3 - v4;
2252 // inverse DCT on columns
2253 for (i = 0; i < 8; ++i) {
2256 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2257 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2260 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2261 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2266 t = (v0 - v1 + 1) >> 1;
2267 v0 = (v0 + v1 + 1) >> 1;
2269 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2270 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2272 t = (v4 - v6 + 1) >> 1;
2273 v4 = (v4 + v6 + 1) >> 1;
2275 t = (v7 + v5 + 1) >> 1;
2276 v5 = (v7 - v5 + 1) >> 1;
2280 t = (v0 - v3 + 1) >> 1;
2281 v0 = (v0 + v3 + 1) >> 1;
2283 t = (v1 - v2 + 1) >> 1;
2284 v1 = (v1 + v2 + 1) >> 1;
2286 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2287 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2289 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2290 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2294 tmp1[0*8+i] = v0 + v7;
2295 tmp1[7*8+i] = v0 - v7;
2296 tmp1[1*8+i] = v1 + v6;
2297 tmp1[6*8+i] = v1 - v6;
2298 tmp1[2*8+i] = v2 + v5;
2299 tmp1[5*8+i] = v2 - v5;
2300 tmp1[3*8+i] = v3 + v4;
2301 tmp1[4*8+i] = v3 - v4;
2304 // convert to 8-bit integers
2305 for (i = 0; i < 64; ++i)
2306 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2313 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2314 DCTHuffTable *acHuffTable,
2315 Guchar quantTable[64], int *prevDC,
2318 double v0, v1, v2, v3, v4, v5, v6, v7, t;
2323 // Huffman decode and dequantize
2324 size = readHuffSym(dcHuffTable);
2328 amp = readAmp(size);
2334 tmp1[0] = (*prevDC += amp) * quantTable[0];
2335 for (i = 1; i < 64; ++i)
2340 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2347 run += (c >> 4) & 0x0f;
2349 amp = readAmp(size);
2354 tmp1[j] = amp * quantTable[j];
2358 // inverse DCT on rows
2359 for (i = 0; i < 64; i += 8) {
2362 v0 = dctSqrt2 * tmp1[i+0];
2363 v1 = dctSqrt2 * tmp1[i+4];
2366 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2367 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2372 t = 0.5 * (v0 - v1);
2373 v0 = 0.5 * (v0 + v1);
2375 t = v2 * dctSin6 + v3 * dctCos6;
2376 v2 = v2 * dctCos6 - v3 * dctSin6;
2378 t = 0.5 * (v4 - v6);
2379 v4 = 0.5 * (v4 + v6);
2381 t = 0.5 * (v7 + v5);
2382 v5 = 0.5 * (v7 - v5);
2386 t = 0.5 * (v0 - v3);
2387 v0 = 0.5 * (v0 + v3);
2389 t = 0.5 * (v1 - v2);
2390 v1 = 0.5 * (v1 + v2);
2392 t = v4 * dctSin3 + v7 * dctCos3;
2393 v4 = v4 * dctCos3 - v7 * dctSin3;
2395 t = v5 * dctSin1 + v6 * dctCos1;
2396 v5 = v5 * dctCos1 - v6 * dctSin1;
2400 tmp1[i+0] = v0 + v7;
2401 tmp1[i+7] = v0 - v7;
2402 tmp1[i+1] = v1 + v6;
2403 tmp1[i+6] = v1 - v6;
2404 tmp1[i+2] = v2 + v5;
2405 tmp1[i+5] = v2 - v5;
2406 tmp1[i+3] = v3 + v4;
2407 tmp1[i+4] = v3 - v4;
2410 // inverse DCT on columns
2411 for (i = 0; i < 8; ++i) {
2414 v0 = dctSqrt2 * tmp1[0*8+i];
2415 v1 = dctSqrt2 * tmp1[4*8+i];
2418 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2419 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2424 t = 0.5 * (v0 - v1);
2425 v0 = 0.5 * (v0 + v1);
2427 t = v2 * dctSin6 + v3 * dctCos6;
2428 v2 = v2 * dctCos6 - v3 * dctSin6;
2430 t = 0.5 * (v4 - v6);
2431 v4 = 0.5 * (v4 + v6);
2433 t = 0.5 * (v7 + v5);
2434 v5 = 0.5 * (v7 - v5);
2438 t = 0.5 * (v0 - v3);
2439 v0 = 0.5 * (v0 + v3);
2441 t = 0.5 * (v1 - v2);
2442 v1 = 0.5 * (v1 + v2);
2444 t = v4 * dctSin3 + v7 * dctCos3;
2445 v4 = v4 * dctCos3 - v7 * dctSin3;
2447 t = v5 * dctSin1 + v6 * dctCos1;
2448 v5 = v5 * dctCos1 - v6 * dctSin1;
2452 tmp1[0*8+i] = v0 + v7;
2453 tmp1[7*8+i] = v0 - v7;
2454 tmp1[1*8+i] = v1 + v6;
2455 tmp1[6*8+i] = v1 - v6;
2456 tmp1[2*8+i] = v2 + v5;
2457 tmp1[5*8+i] = v2 - v5;
2458 tmp1[3*8+i] = v3 + v4;
2459 tmp1[4*8+i] = v3 - v4;
2462 // convert to 8-bit integers
2463 for (i = 0; i < 64; ++i)
2464 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2470 int DCTStream::readHuffSym(DCTHuffTable *table) {
2478 // add a bit to the code
2479 if ((bit = readBit()) == EOF)
2481 code = (code << 1) + bit;
2485 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2486 code -= table->firstCode[codeBits];
2487 return table->sym[table->firstSym[codeBits] + code];
2489 } while (codeBits < 16);
2491 error(getPos(), "Bad Huffman code in DCT stream");
2495 int DCTStream::readAmp(int size) {
2500 for (bits = 0; bits < size; ++bits) {
2501 if ((bit = readBit()) == EOF)
2503 amp = (amp << 1) + bit;
2505 if (amp < (1 << (size - 1)))
2506 amp -= (1 << size) - 1;
2510 int DCTStream::readBit() {
2514 if (inputBits == 0) {
2515 if ((c = str->getChar()) == EOF)
2519 c2 = str->getChar();
2520 } while (c2 == 0xff);
2522 error(getPos(), "Bad DCT data: missing 00 after ff");
2529 bit = (inputBuf >> (inputBits - 1)) & 1;
2534 GBool DCTStream::readHeader() {
2536 int minHSample, minVSample;
2545 numDCHuffTables = 0;
2546 numACHuffTables = 0;
2548 gotAdobeMarker = gFalse;
2549 restartInterval = 0;
2557 if (!readFrameInfo())
2561 if (!readHuffmanTables())
2567 if (!readScanInfo())
2572 if (!readQuantTables())
2576 if (!readRestartInterval())
2580 if (!readAdobeMarker())
2584 error(getPos(), "Bad DCT header");
2587 // skip APPn / COM / etc.
2590 for (i = 0; i < n; ++i)
2593 error(getPos(), "Unknown DCT marker <%02x>", c);
2601 mcuWidth = minHSample = compInfo[0].hSample;
2602 mcuHeight = minVSample = compInfo[0].vSample;
2603 for (i = 1; i < numComps; ++i) {
2604 if (compInfo[i].hSample < minHSample)
2605 minHSample = compInfo[i].hSample;
2606 if (compInfo[i].vSample < minVSample)
2607 minVSample = compInfo[i].vSample;
2608 if (compInfo[i].hSample > mcuWidth)
2609 mcuWidth = compInfo[i].hSample;
2610 if (compInfo[i].vSample > mcuHeight)
2611 mcuHeight = compInfo[i].vSample;
2613 for (i = 0; i < numComps; ++i) {
2614 compInfo[i].hSample /= minHSample;
2615 compInfo[i].vSample /= minVSample;
2617 mcuWidth = (mcuWidth / minHSample) * 8;
2618 mcuHeight = (mcuHeight / minVSample) * 8;
2621 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2622 for (i = 0; i < numComps; ++i)
2623 for (j = 0; j < mcuHeight; ++j)
2624 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2626 // figure out color transform
2627 if (!gotAdobeMarker && numComps == 3) {
2628 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2633 // initialize counters
2642 GBool DCTStream::readFrameInfo() {
2648 length = read16() - 2;
2649 prec = str->getChar();
2652 numComps = str->getChar();
2655 error(getPos(), "Bad DCT precision %d", prec);
2658 for (i = 0; i < numComps; ++i) {
2659 compInfo[i].id = str->getChar();
2660 compInfo[i].inScan = gFalse;
2662 compInfo[i].hSample = (c >> 4) & 0x0f;
2663 compInfo[i].vSample = c & 0x0f;
2664 compInfo[i].quantTable = str->getChar();
2665 compInfo[i].dcHuffTable = 0;
2666 compInfo[i].acHuffTable = 0;
2671 GBool DCTStream::readScanInfo() {
2673 int scanComps, id, c;
2676 length = read16() - 2;
2677 scanComps = str->getChar();
2679 if (length != 2 * scanComps + 3) {
2680 error(getPos(), "Bad DCT scan info block");
2683 for (i = 0; i < scanComps; ++i) {
2684 id = str->getChar();
2685 for (j = 0; j < numComps; ++j) {
2686 if (id == compInfo[j].id)
2689 if (j == numComps) {
2690 error(getPos(), "Bad DCT component ID in scan info block");
2693 compInfo[j].inScan = gTrue;
2695 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2696 compInfo[j].acHuffTable = c & 0x0f;
2704 GBool DCTStream::readQuantTables() {
2709 length = read16() - 2;
2710 while (length > 0) {
2711 index = str->getChar();
2712 if ((index & 0xf0) || index >= 4) {
2713 error(getPos(), "Bad DCT quantization table");
2716 if (index == numQuantTables)
2717 numQuantTables = index + 1;
2718 for (i = 0; i < 64; ++i)
2719 quantTables[index][dctZigZag[i]] = str->getChar();
2725 GBool DCTStream::readHuffmanTables() {
2734 length = read16() - 2;
2735 while (length > 0) {
2736 index = str->getChar();
2738 if ((index & 0x0f) >= 4) {
2739 error(getPos(), "Bad DCT Huffman table");
2744 if (index >= numACHuffTables)
2745 numACHuffTables = index+1;
2746 tbl = &acHuffTables[index];
2748 if (index >= numDCHuffTables)
2749 numDCHuffTables = index+1;
2750 tbl = &dcHuffTables[index];
2754 for (i = 1; i <= 16; ++i) {
2756 tbl->firstSym[i] = sym;
2757 tbl->firstCode[i] = code;
2758 tbl->numCodes[i] = c;
2760 code = (code + c) << 1;
2763 for (i = 0; i < sym; ++i)
2764 tbl->sym[i] = str->getChar();
2770 GBool DCTStream::readRestartInterval() {
2775 error(getPos(), "Bad DCT restart interval");
2778 restartInterval = read16();
2782 GBool DCTStream::readAdobeMarker() {
2790 for (i = 0; i < 12; ++i) {
2791 if ((c = str->getChar()) == EOF)
2795 if (strncmp(buf, "Adobe", 5))
2797 colorXform = buf[11];
2798 gotAdobeMarker = gTrue;
2802 error(getPos(), "Bad DCT Adobe APP14 marker");
2806 GBool DCTStream::readTrailer() {
2810 if (c != 0xd9) { // EOI
2811 error(getPos(), "Bad DCT trailer");
2817 int DCTStream::readMarker() {
2823 } while (c != 0xff);
2826 } while (c == 0xff);
2827 } while (c == 0x00);
2831 int DCTStream::read16() {
2834 if ((c1 = str->getChar()) == EOF)
2836 if ((c2 = str->getChar()) == EOF)
2838 return (c1 << 8) + c2;
2841 GString *DCTStream::getPSFilter(char *indent) {
2844 if (!(s = str->getPSFilter(indent))) {
2847 s->append(indent)->append("<< >> /DCTDecode filter\n");
2851 GBool DCTStream::isBinary(GBool last) {
2852 return str->isBinary(gTrue);
2855 //------------------------------------------------------------------------
2857 //------------------------------------------------------------------------
2859 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2860 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2863 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2895 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2928 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
2929 int colors, int bits):
2930 FilterStream(strA) {
2931 if (predictor != 1) {
2932 pred = new StreamPredictor(this, predictor, columns, colors, bits);
2938 FlateStream::~FlateStream() {
2945 void FlateStream::reset() {
2952 compressedBlock = gFalse;
2959 //~ need to look at window size?
2960 endOfBlock = eof = gTrue;
2961 cmf = str->getChar();
2962 flg = str->getChar();
2963 if (cmf == EOF || flg == EOF)
2965 if ((cmf & 0x0f) != 0x08) {
2966 error(getPos(), "Unknown compression method in flate stream");
2969 if ((((cmf << 8) + flg) % 31) != 0) {
2970 error(getPos(), "Bad FCHECK in flate stream");
2974 error(getPos(), "FDICT bit set in flate stream");
2981 int FlateStream::getChar() {
2985 return pred->getChar();
2987 while (remain == 0) {
2988 if (endOfBlock && eof)
2993 index = (index + 1) & flateMask;
2998 int FlateStream::lookChar() {
3002 return pred->lookChar();
3004 while (remain == 0) {
3005 if (endOfBlock && eof)
3013 int FlateStream::getRawChar() {
3016 while (remain == 0) {
3017 if (endOfBlock && eof)
3022 index = (index + 1) & flateMask;
3027 GString *FlateStream::getPSFilter(char *indent) {
3031 GBool FlateStream::isBinary(GBool last) {
3032 return str->isBinary(gTrue);
3035 void FlateStream::readSome() {
3046 if (compressedBlock) {
3047 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3052 } else if (code1 == 256) {
3057 code2 = lengthDecode[code1].bits;
3058 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3060 len = lengthDecode[code1].first + code2;
3061 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3063 code2 = distDecode[code1].bits;
3064 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3066 dist = distDecode[code1].first + code2;
3068 j = (index - dist) & flateMask;
3069 for (k = 0; k < len; ++k) {
3071 i = (i + 1) & flateMask;
3072 j = (j + 1) & flateMask;
3078 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3079 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3080 if ((c = str->getChar()) == EOF) {
3081 endOfBlock = eof = gTrue;
3095 error(getPos(), "Unexpected end of file in flate stream");
3096 endOfBlock = eof = gTrue;
3100 GBool FlateStream::startBlock() {
3105 // read block header
3106 blockHdr = getCodeWord(3);
3111 // uncompressed block
3112 if (blockHdr == 0) {
3113 compressedBlock = gFalse;
3114 if ((c = str->getChar()) == EOF)
3116 blockLen = c & 0xff;
3117 if ((c = str->getChar()) == EOF)
3119 blockLen |= (c & 0xff) << 8;
3120 if ((c = str->getChar()) == EOF)
3123 if ((c = str->getChar()) == EOF)
3125 check |= (c & 0xff) << 8;
3126 if (check != (~blockLen & 0xffff))
3127 error(getPos(), "Bad uncompressed block length in flate stream");
3131 // compressed block with fixed codes
3132 } else if (blockHdr == 1) {
3133 compressedBlock = gTrue;
3136 // compressed block with dynamic codes
3137 } else if (blockHdr == 2) {
3138 compressedBlock = gTrue;
3139 if (!readDynamicCodes())
3142 // unknown block type
3147 endOfBlock = gFalse;
3151 error(getPos(), "Bad block header in flate stream");
3152 endOfBlock = eof = gTrue;
3156 void FlateStream::loadFixedCodes() {
3159 // set up code arrays
3160 litCodeTab.codes = allCodes;
3161 distCodeTab.codes = allCodes + flateMaxLitCodes;
3163 // initialize literal code table
3164 for (i = 0; i <= 143; ++i)
3165 litCodeTab.codes[i].len = 8;
3166 for (i = 144; i <= 255; ++i)
3167 litCodeTab.codes[i].len = 9;
3168 for (i = 256; i <= 279; ++i)
3169 litCodeTab.codes[i].len = 7;
3170 for (i = 280; i <= 287; ++i)
3171 litCodeTab.codes[i].len = 8;
3172 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
3174 // initialize distance code table
3175 for (i = 0; i <= 5; ++i) {
3176 distCodeTab.start[i] = 0;
3178 for (i = 6; i <= flateMaxHuffman+1; ++i) {
3179 distCodeTab.start[i] = flateMaxDistCodes;
3181 for (i = 0; i < flateMaxDistCodes; ++i) {
3182 distCodeTab.codes[i].len = 5;
3183 distCodeTab.codes[i].code = i;
3184 distCodeTab.codes[i].val = i;
3188 GBool FlateStream::readDynamicCodes() {
3189 int numCodeLenCodes;
3192 FlateCode codeLenCodes[flateMaxCodeLenCodes];
3193 FlateHuffmanTab codeLenCodeTab;
3194 int len, repeat, code;
3198 if ((numLitCodes = getCodeWord(5)) == EOF)
3201 if ((numDistCodes = getCodeWord(5)) == EOF)
3204 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
3206 numCodeLenCodes += 4;
3207 if (numLitCodes > flateMaxLitCodes ||
3208 numDistCodes > flateMaxDistCodes ||
3209 numCodeLenCodes > flateMaxCodeLenCodes)
3212 // read code length code table
3213 codeLenCodeTab.codes = codeLenCodes;
3214 for (i = 0; i < flateMaxCodeLenCodes; ++i)
3215 codeLenCodes[i].len = 0;
3216 for (i = 0; i < numCodeLenCodes; ++i) {
3217 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
3220 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
3222 // set up code arrays
3223 litCodeTab.codes = allCodes;
3224 distCodeTab.codes = allCodes + numLitCodes;
3226 // read literal and distance code tables
3230 while (i < numLitCodes + numDistCodes) {
3231 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3234 if ((repeat = getCodeWord(2)) == EOF)
3236 for (repeat += 3; repeat > 0; --repeat)
3237 allCodes[i++].len = len;
3238 } else if (code == 17) {
3239 if ((repeat = getCodeWord(3)) == EOF)
3242 for (repeat += 3; repeat > 0; --repeat)
3243 allCodes[i++].len = 0;
3244 } else if (code == 18) {
3245 if ((repeat = getCodeWord(7)) == EOF)
3248 for (repeat += 11; repeat > 0; --repeat)
3249 allCodes[i++].len = 0;
3251 allCodes[i++].len = len = code;
3254 compHuffmanCodes(&litCodeTab, numLitCodes);
3255 compHuffmanCodes(&distCodeTab, numDistCodes);
3260 error(getPos(), "Bad dynamic code table in flate stream");
3264 // On entry, the <tab->codes> array contains the lengths of each code,
3265 // stored in code value order. This function computes the code words.
3266 // The result is sorted in order of (1) code length and (2) code word.
3267 // The length values are no longer valid. The <tab->start> array is
3268 // filled with the indexes of the first code of each length.
3269 void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3270 int numLengths[flateMaxHuffman+1];
3271 int nextCode[flateMaxHuffman+1];
3272 int nextIndex[flateMaxHuffman+2];
3276 // count number of codes for each code length
3277 for (i = 0; i <= flateMaxHuffman; ++i)
3279 for (i = 0; i < n; ++i)
3280 ++numLengths[tab->codes[i].len];
3282 // compute first index for each length
3283 tab->start[0] = nextIndex[0] = 0;
3284 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3285 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3287 // compute first code for each length
3290 for (i = 1; i <= flateMaxHuffman; ++i) {
3291 code = (code + numLengths[i-1]) << 1;
3295 // compute the codes -- this permutes the codes array from value
3296 // order to length/code order
3297 for (i = 0; i < n; ++i) {
3298 j = nextIndex[tab->codes[i].len]++;
3299 if (tab->codes[i].len == 0)
3300 tab->codes[j].code = 0;
3302 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3303 tab->codes[j].val = i;
3307 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3314 for (len = 1; len <= flateMaxHuffman; ++len) {
3316 // add a bit to the code
3317 if (codeSize == 0) {
3318 if ((c = str->getChar()) == EOF)
3323 code = (code << 1) | (codeBuf & 1);
3328 i = tab->start[len];
3329 j = tab->start[len + 1];
3330 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3331 i += code - tab->codes[i].code;
3332 return tab->codes[i].val;
3337 error(getPos(), "Bad code (%04x) in flate stream", code);
3341 int FlateStream::getCodeWord(int bits) {
3344 while (codeSize < bits) {
3345 if ((c = str->getChar()) == EOF)
3347 codeBuf |= (c & 0xff) << codeSize;
3350 c = codeBuf & ((1 << bits) - 1);
3356 //------------------------------------------------------------------------
3358 //------------------------------------------------------------------------
3360 EOFStream::EOFStream(Stream *strA):
3361 FilterStream(strA) {
3364 EOFStream::~EOFStream() {
3368 //------------------------------------------------------------------------
3369 // FixedLengthEncoder
3370 //------------------------------------------------------------------------
3372 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3373 FilterStream(strA) {
3378 FixedLengthEncoder::~FixedLengthEncoder() {
3379 if (str->isEncoder())
3383 void FixedLengthEncoder::reset() {
3388 void FixedLengthEncoder::close() {
3391 int FixedLengthEncoder::getChar() {
3392 if (length >= 0 && count >= length)
3395 return str->getChar();
3398 int FixedLengthEncoder::lookChar() {
3399 if (length >= 0 && count >= length)
3401 return str->getChar();
3404 //------------------------------------------------------------------------
3406 //------------------------------------------------------------------------
3408 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3409 FilterStream(strA) {
3410 bufPtr = bufEnd = buf;
3415 ASCIIHexEncoder::~ASCIIHexEncoder() {
3416 if (str->isEncoder()) {
3421 void ASCIIHexEncoder::reset() {
3423 bufPtr = bufEnd = buf;
3428 void ASCIIHexEncoder::close() {
3431 GBool ASCIIHexEncoder::fillBuf() {
3432 static char *hex = "0123456789abcdef";
3438 bufPtr = bufEnd = buf;
3439 if ((c = str->getChar()) == EOF) {
3443 if (lineLen >= 64) {
3447 *bufEnd++ = hex[(c >> 4) & 0x0f];
3448 *bufEnd++ = hex[c & 0x0f];
3454 //------------------------------------------------------------------------
3456 //------------------------------------------------------------------------
3458 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3459 FilterStream(strA) {
3460 bufPtr = bufEnd = buf;
3465 ASCII85Encoder::~ASCII85Encoder() {
3466 if (str->isEncoder())
3470 void ASCII85Encoder::reset() {
3472 bufPtr = bufEnd = buf;
3477 void ASCII85Encoder::close() {
3480 GBool ASCII85Encoder::fillBuf() {
3489 for (n = 0; n < 4; ++n) {
3490 if ((c = str->getChar()) == EOF)
3494 bufPtr = bufEnd = buf;
3496 if (n == 4 && t == 0) {
3498 if (++lineLen == 65) {
3505 for (i = 4; i >= 0; --i) {
3506 buf1[i] = (char)(t % 85 + 0x21);
3509 for (i = 0; i <= n; ++i) {
3510 *bufEnd++ = buf1[i];
3511 if (++lineLen == 65) {
3523 return bufPtr < bufEnd;
3526 //------------------------------------------------------------------------
3528 //------------------------------------------------------------------------
3530 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3531 FilterStream(strA) {
3532 bufPtr = bufEnd = nextEnd = buf;
3536 RunLengthEncoder::~RunLengthEncoder() {
3537 if (str->isEncoder())
3541 void RunLengthEncoder::reset() {
3543 bufPtr = bufEnd = nextEnd = buf;
3547 void RunLengthEncoder::close() {
3551 // When fillBuf finishes, buf[] looks like this:
3552 // +-----+--------------+-----------------+--
3553 // + tag | ... data ... | next 0, 1, or 2 |
3554 // +-----+--------------+-----------------+--
3556 // bufPtr bufEnd nextEnd
3558 GBool RunLengthEncoder::fillBuf() {
3567 if (nextEnd < bufEnd + 1) {
3568 if ((c1 = str->getChar()) == EOF) {
3573 c1 = bufEnd[0] & 0xff;
3575 if (nextEnd < bufEnd + 2) {
3576 if ((c2 = str->getChar()) == EOF) {
3585 c2 = bufEnd[1] & 0xff;
3589 c = 0; // make gcc happy
3592 while (n < 128 && (c = str->getChar()) == c1)
3594 buf[0] = (char)(257 - n);
3599 } else if (n < 128) {
3606 // get up to 128 chars
3612 if ((c = str->getChar()) == EOF) {
3618 if (buf[n] == buf[n-1])
3621 if (buf[n] == buf[n-1]) {
3622 buf[0] = (char)(n-2-1);
3624 nextEnd = &buf[n+1];
3626 buf[0] = (char)(n-1);
3627 bufEnd = nextEnd = &buf[n+1];