2003.10.01 21:50 "[Tiff] CCITT Group 4 EOFB code is not supported", by Erik Latoshek

2003.10.01 21:50 "[Tiff] CCITT Group 4 EOFB code is not supported", by Erik Latoshek

TIFF 6 spec:

------

If a TIFF reader encounters EOFB before the expected number of lines has been extracted, it is appropriate to assume that the missing rows consist entirely of white pixels. Cautious readers might produce an unobtrusive warning if such an EOFB is followed by anything other than pad bits.

------

it is not implemeted. in such situation libtiff will issue multiple "EOL" warnings(EOFB is a 2x EOL), and in most cases will get error EOF state on decoding such images.

more to say, even EOL codes in Fax4 decoding procedure are not handled correctly. after retrieving 7 table bits, next 5 bits are not "cleared", and further checks on this 5 bits are not performed.

this is not a theoretical problem as software/hardware system named "Kofax"(i dont know currently what is it, i got images, and it was told they were scanned ;> ) like to produce such images when white scanlines are closing image.

here the cure, maybe it helps(diff from 3.5.7)

--- tif_fax3.c  1 Jul 2003 15:53:17 -0000       1.1.2.1
+++ tif_fax3.c  1 Oct 2003 17:26:49 -0000
@@ -77,6 +77,7 @@
        uint32  data;                   /* current i/o byte/word */
        int     bit;                    /* current i/o bit in byte */
        int     EOLcnt;                 /* count of EOL codes recognized */
+        int     EOFBcnt;                /* count of EOFB codes recognized */
        TIFFFaxFillFunc fill;           /* fill routine */
        uint32* runs;                   /* b&w runs for current/previous row */
        uint32* refruns;                /* runs for reference line */
@@ -121,6 +122,7 @@
     uint32* pa;                                /* place to stuff next run */   \
     uint32* thisrun;                   /* current row's run array */   \
     int EOLcnt;                                /* # EOL codes recognized */    \
+    int EOFBcnt;                       /* # EOFB codes recognized */   \
     const u_char* bitmap = sp->bitmap; /* input data bit reverser */   \
     const TIFFFaxTabEnt* TabEnt
 #define        DECLARE_STATE_2D(tif, sp, mod)                                  \
@@ -134,6 +136,7 @@
     BitAcc = sp->data;                                                 \
     BitsAvail = sp->bit;                                               \
     EOLcnt = sp->EOLcnt;                                               \
+    EOFBcnt = sp->EOFBcnt;                                             \
     cp = (unsigned char*) tif->tif_rawcp;                              \
     ep = cp + tif->tif_rawcc;                                          \
 } while (0)
@@ -144,6 +147,7 @@
     sp->bit = BitsAvail;                                               \
     sp->data = BitAcc;                                                 \
     sp->EOLcnt = EOLcnt;                                               \
+    sp->EOFBcnt = EOFBcnt;                                             \
     tif->tif_rawcc -= (tidata_t) cp - tif->tif_rawcp;                  \
     tif->tif_rawcp = (tidata_t) cp;                                    \
 } while (0)
@@ -161,6 +165,7 @@
        sp->bit = 0;                    /* force initial read */
        sp->data = 0;
        sp->EOLcnt = 0;                 /* force initial scan for EOL */
+       sp->EOFBcnt = 0;
        /*
         * Decoder assumes lsb-to-msb bit order.  Note that we select
         * this here rather than in Fax3SetupState so that viewers can

--- tif_fax3.h  1 Jul 2003 15:53:17 -0000       1.1.2.1
+++ tif_fax3.h  1 Oct 2003 17:27:57 -0000
@@ -286,7 +286,8 @@
     if (RunLength)                                                     \
        SETVAL(0);                                                      \
     if (a0 != lastx) {                                                 \
-       badlength(a0, lastx);                                           \
+        if(!EOFBcnt)                                                    \
+            badlength(a0, lastx);                                      \
        while (a0 > lastx && pa > thisrun)                              \
            a0 -= *--pa;                                                \
        if (a0 < lastx) {                                               \
@@ -384,6 +385,8 @@
  * Expand a row of 2D-encoded data.
  */
 #define EXPAND2D(eoflab) do {                                          \
+    if(EOFBcnt)                                                         \
+        goto eol2d;                                                    \
     while (a0 < lastx) {                                               \
        LOOKUP8(7, TIFFFaxMainTable, eof2d);                            \
        switch (TabEnt->State) {                                        \
@@ -486,8 +489,17 @@
        case S_EOL:                                                     \
            *pa++ = lastx - a0;                                         \
            NeedBits8(5,eof2d);                                         \
-           if (GetBits(5))                                             \
-               unexpected("EOL", a0);                                  \
+            ClrBits(5);                                                 \
+                                                                        \
+            NeedBits8(7, noMoreEol);                                   \
+            TabEnt = TIFFFaxMainTable + GetBits(7);                    \
+            if(TabEnt->State == S_EOL) {                                \
+                ClrBits(5);                                             \
+                EOFBcnt++;                                              \
+                goto eol2d;                                             \
+            }                                                           \
+noMoreEol:                                                              \
+           unexpected("EOL", a0);                                      \
            EOLcnt = 1;                                                 \
            goto eol2d;                                                 \
        default:                                                        \