support reading interlaced GIFs
Stefan Schuermans

Stefan Schuermans commited on 2016-12-18 20:29:15
Showing 1 changed files, with 21 additions and 12 deletions.

... ...
@@ -61,7 +61,13 @@ static void BlinkenGifSetPixel(ColorMapObject *pMap, int idx, int transparent,
61 61
 stBlinkenMovie *BlinkenGifLoad(const char *pFilename)
62 62
 {
63 63
   GifFileType *gif;
64
-  int height, width, frameCnt, frameIdx, i, y, x,
64
+  struct sPass { int ofs, stride; };
65
+  static struct sPass const passes_linear[] = { { 0, 1 }, { 0, 0 } };
66
+  static struct sPass const passes_interlaced[] = {
67
+    { 0, 8 }, { 4, 8 }, { 2, 4 }, { 1, 2 }
68
+  };
69
+  struct sPass const *pass;
70
+  int height, width, frameCnt, frameIdx, i, y, x, y1, x1,
65 71
       bg, disposal, delay, transp, idx;
66 72
   ColorMapObject *pGlobalMap, *pMap;
67 73
   SavedImage *pImg;
... ...
@@ -140,9 +146,11 @@ stBlinkenMovie *BlinkenGifLoad(const char *pFilename)
140 146
       // frames with no duration -> only effect on background
141 147
       pFrame = NULL;
142 148
     }
143
-    // FIXME: pDesc->Interlace > 0
144
-    for (y = pDesc->Top, i = 0; y < pDesc->Top + pDesc->Height; ++y) {
145
-      for (x = pDesc->Left; x < pDesc->Left + pDesc->Width; ++x, ++i) {
149
+    for (pass = pDesc->Interlace ? passes_interlaced : passes_linear;
150
+         pass->stride > 0; ++pass) {
151
+      for (y = pass->ofs, y1 = pDesc->Top + pass->ofs, i = 0;
152
+           y < pDesc->Height; y += pass->stride, y1 += pass->stride) {
153
+        for (x = 0, x1 = pDesc->Left; x < pDesc->Width; ++x, ++x1, ++i) {
146 154
           idx = pImg->RasterBits[i];
147 155
           switch (disposal) {
148 156
             // undefined
... ...
@@ -153,21 +161,22 @@ stBlinkenMovie *BlinkenGifLoad(const char *pFilename)
153 161
             case 7:
154 162
             // do not dispose -> draw to frame and update background
155 163
             case 1:
156
-            BlinkenGifSetPixel(pMap, idx, transp, pFrame, y, x);
157
-            BlinkenGifSetPixel(pMap, idx, transp, pBack, y, x);
164
+              BlinkenGifSetPixel(pMap, idx, transp, pFrame, y1, x1);
165
+              BlinkenGifSetPixel(pMap, idx, transp, pBack, y1, x1);
158 166
               break;
159 167
             // restore background -> draw to frame and reset background
160 168
             case 2:
161
-            BlinkenGifSetPixel(pMap, idx, transp, pFrame, y, x);
162
-            BlinkenGifSetPixel(pMap, bg, transp, pBack, y, x);
169
+              BlinkenGifSetPixel(pMap, idx, transp, pFrame, y1, x1);
170
+              BlinkenGifSetPixel(pMap, bg, transp, pBack, y1, x1);
163 171
               break;
164 172
             // restore previous -> draw to frame only
165 173
             case 3:
166
-            BlinkenGifSetPixel(pMap, idx, transp, pFrame, y, x);
174
+              BlinkenGifSetPixel(pMap, idx, transp, pFrame, y1, x1);
167 175
               break;
168
-        }
169
-      }
170
-    }
176
+          } // switch disposal
177
+        } // for x
178
+      } // for y
179
+    } // for pass
171 180
 
172 181
     // append frame to movie
173 182
     if (pFrame) {
174 183