* NB: the image is written as a single strip of data.
*/
setupStartPage(tif, params);
+ if (params.df == DF_JBIG) {
+ int cc = 0, c;
+ bool fin = false;
+ for (; cc < 20; cc++) {
+ c = getModemChar(30000);
+ if (c == EOF || wasTimeout()) {
+ fin = true;
+ break;
+ }
+ if (c == DLE) {
+ c = getModemChar(30000);
+ if (c == EOF || c == ETX || wasTimeout()) {
+ fin = true;
+ break;
+ }
+ }
+ buf[cc] = c;
+ }
+ parseJBIGBIH(buf);
+ flushRawData(tif, 0, (const u_char*) buf, cc);
+ if (!fin) {
+ do {
+ cc = 0;
+ do {
+ c = getModemChar(30000);
+ if (c == EOF || wasTimeout()) {
+ fin = true;
+ break;
+ }
+ if (c == DLE) {
+ c = getModemChar(30000);
+ if (c == EOF || c == ETX || wasTimeout()) {
+ fin = true;
+ break;
+ }
+ }
+ parseJBIGStream(c);
+ buf[cc++] = c;
+ } while (cc < RCVBUFSIZ && !fin);
+ flushRawData(tif, 0, (const u_char*) buf, cc);
+ } while (!fin);
+ clearSDNORMCount();
+ }
+ recvEndPage(tif, params);
+ return (true);
+ }
/*
* NB: There is a potential memory leak here if the
* stack buffer gets expanded, such that memory gets
serverTrace("RECV: %s: write error", TIFFFileName(tif));
}
+void
+FaxModem::clearSDNORMCount()
+{
+ if (parserCount[1]) {
+ copyQualityTrace("Found %d SDNORM Marker Segments in BID", parserCount[1]);
+ parserCount[1] = 0;
+ }
+}
+
+void
+FaxModem::parseJBIGStream(u_char c)
+{
+ /*
+ * parserCount[n]
+ * n = 0, bytes since last marker
+ * n = 1, SDNORM marker counter
+ * n = 2, framelength bypass countdown
+ */
+ parserCount[0]++;
+ if (parserCount[2]) {
+ // just skipping bytes
+ parserCount[2]--;
+ return;
+ }
+ u_long framelength = 0;
+
+ memcpy(parserBuf+1, parserBuf, 15);
+ parserBuf[0] = c;
+
+ if (parserCount[0] >= 2 && parserBuf[1] == 0xFF && parserBuf[0] == 0x04) {
+ clearSDNORMCount();
+ copyQualityTrace("Found ABORT Marker Segment in BID");
+ parserCount[0] = 0;
+ return;
+ }
+ if (parserCount[0] >= 8 && parserBuf[7] == 0xFF && parserBuf[6] == 0x06) {
+ clearSDNORMCount();
+ copyQualityTrace("Found ATMOVE Marker Segment in BID, Yat %d, tx %d, ty %d",
+ 256*256*256*parserBuf[5]+256*256*parserBuf[4]+256*parserBuf[3]+parserBuf[2], parserBuf[1], parserBuf[0]);
+ parserCount[0] = 0;
+ return;
+ }
+ if (parserCount[0] >= 6 && parserBuf[5] == 0xFF && parserBuf[4] == 0x07) {
+ clearSDNORMCount();
+ parserCount[2] = 256*256*256*parserBuf[3]+256*256*parserBuf[2]+256*parserBuf[1]+parserBuf[0];
+ copyQualityTrace("Found COMMENT Marker Segment in BID");
+ parserCount[0] = 0;
+ return;
+ }
+ if (parserCount[0] >= 6 && parserBuf[5] == 0xFF && parserBuf[4] == 0x05) {
+ clearSDNORMCount();
+ framelength = 256*256*256*parserBuf[3];
+ framelength += 256*256*parserBuf[2];
+ framelength += 256*parserBuf[1];
+ framelength += parserBuf[0];
+ copyQualityTrace("Found NEWLEN Marker Segment in BID, Yd = %d", framelength);
+ // T.82: "The new Yd shall never be greater than the original"
+ if (framelength < 65535 && (!recvEOLCount || framelength < recvEOLCount)) recvEOLCount = framelength;
+ parserCount[0] = 0;
+ return;
+ }
+ if (parserCount[0] >= 2 && parserBuf[1] == 0xFF && parserBuf[0] == 0x01) {
+ clearSDNORMCount();
+ copyQualityTrace("Found RESERVE Marker Segment in BID");
+ parserCount[0] = 0;
+ return;
+ }
+ if (parserCount[0] >= 2 && parserBuf[1] == 0xFF && parserBuf[0] == 0x02) {
+ parserCount[1]++; // SDNORM
+ parserCount[0] = 0;
+ return;
+ }
+ if (parserCount[0] >= 2 && parserBuf[1] == 0xFF && parserBuf[0] == 0x03) {
+ clearSDNORMCount();
+ copyQualityTrace("Found SDRST Marker Segment in BID");
+ parserCount[0] = 0;
+ return;
+ }
+ if (parserCount[0] >= 2 && parserBuf[1] == 0xFF && parserBuf[0] != 0x00) { // not STUFF
+ clearSDNORMCount();
+ copyQualityTrace("Found Unknown Marker %#x Segment in BID", parserBuf[0]);
+ parserCount[0] == 0;
+ return;
+ }
+}
+
+void
+FaxModem::parseJBIGBIH(u_char* buf)
+{
+ copyQualityTrace("BIH: Dl %d, D %d, P %d, fill %d", buf[0], buf[1], buf[2], buf[3]);
+ /*
+ * Parse JBIG BIH to get the image length.
+ *
+ * See T.82 6.6.2
+ * These three integers are coded most significant byte first. In
+ * other words, XD is the sum of 256^3 times the fifth byte in BIH, 256^2
+ * times the sixth byte, 256 times the seventh byte, and the eighth byte.
+ */
+ u_long framelength = 0;
+ framelength = 256*256*256*buf[8];
+ framelength += 256*256*buf[9];
+ framelength += 256*buf[10];
+ framelength += buf[11];
+ /*
+ * Senders commonly use 0xFFFF and 0xFFFFFFFF as "maximum Yd". We ignore such large
+ * values because if we use them and no NEWLEN marker is received, then the page
+ * length causes problems for viewers (specifically libtiff).
+ */
+ if (framelength < 65535 && framelength > recvEOLCount) recvEOLCount = framelength;
+ copyQualityTrace("BIH: Xd %d, Yd %d, L0 %d, Mx %d, My %d",
+ 256*256*256*buf[4]+256*256*buf[5]+256*buf[6]+buf[7],
+ framelength,
+ 256*256*256*buf[12]+256*256*buf[13]+256*buf[14]+buf[15],
+ buf[16], buf[17]);
+ copyQualityTrace("BIH: fill %d, HITOLO %d, SEQ %d, ILEAVE %d, SMID %d",
+ (buf[18]&0xF0)>>4, (buf[18]&0x8)>>3, (buf[18]&0x4)>>2, (buf[18]&0x2)>>1, buf[18]&0x1);
+ copyQualityTrace("BIH: fill %d, LRLTWO %d, VLENGTH %d, TPDON %d, TPBON %d, DPON %d, DPPRIV %u, DPLAST %u",
+ (buf[19]&0x80)>>7, (buf[19]&0x40)>>6, (buf[19]&0x20)>>5, (buf[19]&0x10)>>4, (buf[19]&0x8)>>3,
+ (buf[19]&0x4)>>2, (buf[19]&0x2)>>1, buf[19]&0x1);
+}
+
/*
* In ECM mode the ECM module provides the line-counter.
*/
case DF_JBIG:
{
setupStartPage(tif, params);
- copyQualityTrace("BIH: Dl %d, D %d, P %d, fill %d", buf[0], buf[1], buf[2], buf[3]);
- /*
- * Parse JBIG BIH to get the image length.
- *
- * See T.82 6.6.2
- * These three integers are coded most significant byte first. In
- * other words, XD is the sum of 256^3 times the fifth byte in BIH, 256^2
- * times the sixth byte, 256 times the seventh byte, and the eighth byte.
- */
- u_long framelength = 0;
- framelength = 256*256*256*buf[8];
- framelength += 256*256*buf[9];
- framelength += 256*buf[10];
- framelength += buf[11];
- /*
- * Senders commonly use 0xFFFF and 0xFFFFFFFF as "maximum Yd". We ignore such large
- * values because if we use them and no NEWLEN marker is received, then the page
- * length causes problems for viewers (specifically libtiff).
- */
- if (framelength < 65535 && framelength > recvEOLCount) recvEOLCount = framelength;
- copyQualityTrace("BIH: Xd %d, Yd %d, L0 %d, Mx %d, My %d",
- 256*256*256*buf[4]+256*256*buf[5]+256*buf[6]+buf[7],
- framelength,
- 256*256*256*buf[12]+256*256*buf[13]+256*buf[14]+buf[15],
- buf[16], buf[17]);
- copyQualityTrace("BIH: fill %d, HITOLO %d, SEQ %d, ILEAVE %d, SMID %d",
- (buf[18]&0xF0)>>4, (buf[18]&0x8)>>3, (buf[18]&0x4)>>2, (buf[18]&0x2)>>1, buf[18]&0x1);
- copyQualityTrace("BIH: fill %d, LRLTWO %d, VLENGTH %d, TPDON %d, TPBON %d, DPON %d, DPPRIV %u, DPLAST %u",
- (buf[19]&0x80)>>7, (buf[19]&0x40)>>6, (buf[19]&0x20)>>5, (buf[19]&0x10)>>4, (buf[19]&0x8)>>3,
- (buf[19]&0x4)>>2, (buf[19]&0x2)>>1, buf[19]&0x1);
+ parseJBIGBIH(buf);
}
break;
case DF_JBIG:
// search for Marker Segments in JBIG Bi-Level Image Data
{
- u_long framelength = 0;
- u_int sdnormcount = 0, i = 0;
+ parserCount[0] = 0;
+ parserCount[1] = 0;
+ parserCount[2] = 0;
+ memset(parserBuf, 0, 16);
+ u_int i = 0;
if (seq & 1) i += 20; // skip BIH
for (; i < cc; i++) {
- if (i+1 < cc && buf[i] == 0xFF && buf[i+1] == 0x04) {
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
- sdnormcount = 0;
- }
- copyQualityTrace("Found ABORT Marker Segment in BID");
- i += 1;
- continue;
- }
- if (i+7 < cc && buf[i] == 0xFF && buf[i+1] == 0x06) {
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
- sdnormcount = 0;
- }
- copyQualityTrace("Found ATMOVE Marker Segment in BID, Yat %d, tx %d, ty %d",
- 256*256*256*buf[i+2]+256*256*buf[i+3]+256*buf[i+4]+buf[i+5], buf[i+6], buf[i+7]);
- i += 7;
- continue;
- }
- if (i+6 < cc && buf[i] == 0xFF && buf[i+1] == 0x07) {
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
- sdnormcount = 0;
- }
- u_long clength = 256*256*256*buf[i+2]+256*256*buf[i+3]+256*buf[i+4]+buf[i+5];
- if (clength >= cc - i - 5) clength = 0; // bogus comment
- fxStr comment = "";
- for (u_long cpos = 0; i+6+cpos < cc && cpos < clength && cpos < 256; cpos++) {
- if (!isprint(buf[i+6+cpos])) break; // only printables
- comment.append(buf[i+6+cpos]);
- }
- copyQualityTrace("Found COMMENT Marker Segment in BID, \"%s\"", (const char*) comment);
- i = i + clength + 5;
- continue;
- }
- if (i+5 < cc && buf[i] == 0xFF && buf[i+1] == 0x05) {
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
- sdnormcount = 0;
- }
- framelength = 256*256*256*buf[i+2];
- framelength += 256*256*buf[i+3];
- framelength += 256*buf[i+4];
- framelength += buf[i+5];
- copyQualityTrace("Found NEWLEN Marker Segment in BID, Yd = %d", framelength);
- // T.82: "The new Yd shall never be greater than the original"
- if (framelength < 65535 && (!recvEOLCount || framelength < recvEOLCount)) recvEOLCount = framelength;
- i += 5;
- continue;
- }
- if (i+1 < cc && buf[i] == 0xFF && buf[i+1] == 0x01) {
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
- sdnormcount = 0;
- }
- copyQualityTrace("Found RESERVE Marker Segment in BID");
- i += 1;
- continue;
- }
- if (i+1 < cc && buf[i] == 0xFF && buf[i+1] == 0x02) {
- sdnormcount++;
- i += 1;
- continue;
- }
- if (i+1 < cc && buf[i] == 0xFF && buf[i+1] == 0x03) {
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
- sdnormcount = 0;
- }
- copyQualityTrace("Found SDRST Marker Segment in BID");
- i += 1;
- continue;
- }
- if (i+1 < cc && buf[i] == 0xFF && buf[i+1] != 0x00) { // not STUFF
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
- sdnormcount = 0;
- }
- copyQualityTrace("Found Unknown Marker %#x Segment in BID", buf[i+1]);
- i +=1;
- continue;
- }
- }
- if (sdnormcount) {
- copyQualityTrace("Found %d SDNORM Marker Segments in BID", sdnormcount);
+ parseJBIGStream(buf[i]);
}
+ clearSDNORMCount();
}
break;