2525#include <stdio.h>
2626#include <stdlib.h>
2727#include <stdbool.h>
28+ #include <string.h>
2829#include <X11/Xlib.h>
2930#include <X11/Xatom.h>
3031#include <Imlib2.h>
@@ -220,40 +221,26 @@ int load_pixmap_sample()
220221 return 0 ;
221222}
222223
223- static void render_image (GifFileType * gif , GraphicsControlBlock * gcb , SavedImage * img , DATA32 * canvas , int * color_total )
224+ static void dispose_image (GifFileType * gif , GraphicsControlBlock * gcb ,
225+ SavedImage * img , DATA32 * canvas , DATA32 * old_canvas )
224226{
225- int num ;
226- int off , roff ;
227- GifByteType * raster ;
227+ int off ;
228228 GifImageDesc * desc ;
229229 DATA32 c ;
230230 GifColorType color ;
231- GifByteType color_code ;
232231
233-
234- raster = img -> RasterBits ;
235232 desc = & img -> ImageDesc ;
236233
237- if (desc -> ColorMap )
238- * color_total += (num = desc -> ColorMap -> ColorCount );
239- else
240- num = gif -> SColorMap -> ColorCount ;
241- if (!* color_total ) * color_total = num ;
242-
243- printf ("\tCurrent Colors: %d, Color_Total: %d\n" , num , * color_total );
244- printf ("\tDispose: " );
245-
246234 /* Select background color */
247235 if (gif -> SColorMap && gif -> SColorMap -> ColorCount > gif -> SBackGroundColor ) {
248236 color = gif -> SColorMap -> Colors [gif -> SBackGroundColor ];
249237 }else {
250238 color = (GifColorType ){0 , 0 , 0 };
251239 }
252240
241+ printf ("\tDispose: " );
242+
253243 switch (gcb -> DisposalMode ) {
254- case DISPOSE_PREVIOUS :
255- puts ("PREVIOUS (not implemented yet)" );
256- break ;
257244 case DISPOSE_BACKGROUND :
258245 puts ("BACKGROUND" );
259246 c = GRGBTOD32 (color );
@@ -264,28 +251,66 @@ static void render_image(GifFileType *gif, GraphicsControlBlock *gcb, SavedImage
264251 }
265252 }
266253 break ;
267- case DISPOSAL_UNSPECIFIED : /* Don't dispose */
268- printf ("UNSPECIFIED, falling back to " );
269- case DISPOSE_DO_NOT :
270- puts ("NONE" );
254+ case DISPOSE_PREVIOUS :
255+ puts ("PREVIOUS" );
271256 for (int y = 0 ; y < desc -> Height ; ++ y ) {
272257 off = desc -> Top * gif -> SWidth + y * gif -> SWidth + desc -> Left ;
273258 for (int x = 0 ; x < desc -> Width ; ++ x ) {
274- roff = y * desc -> Width ;
275- color_code = raster [roff + x ];
276- if (desc -> ColorMap && desc -> ColorMap -> ColorCount > color_code )
277- color = desc -> ColorMap -> Colors [color_code ];
278- else if (gif -> SColorMap && gif -> SColorMap -> ColorCount > color_code )
279- color = gif -> SColorMap -> Colors [color_code ];
280- else
281- color = (GifColorType ){0 , 0 , 0 };
282- c = GRGBTOD32 (color );
283- if (gcb -> TransparentColor == -1
284- || gcb -> TransparentColor != color_code )
285- canvas [off + x ] = c ;
259+ canvas [off + x ] = old_canvas [off + x ];
286260 }
287261 }
288262 break ;
263+ case DISPOSAL_UNSPECIFIED : printf ("UNSPECIFIED, falling back to " );
264+ case DISPOSE_DO_NOT : puts ("NONE" );
265+ }
266+ }
267+
268+ static void render_image (GifFileType * gif , GraphicsControlBlock * gcb , SavedImage * img ,
269+ DATA32 * canvas , int * color_total )
270+ {
271+ int num ;
272+ int off , roff ;
273+ GifByteType * raster ;
274+ GifImageDesc * desc ;
275+ DATA32 c ;
276+ GifColorType color ;
277+ GifByteType color_code ;
278+
279+
280+ raster = img -> RasterBits ;
281+ desc = & img -> ImageDesc ;
282+
283+ if (desc -> ColorMap )
284+ * color_total += (num = desc -> ColorMap -> ColorCount );
285+ else
286+ num = gif -> SColorMap -> ColorCount ;
287+ if (!* color_total ) * color_total = num ;
288+
289+ printf ("\tCurrent Colors: %d, Color_Total: %d\n" , num , * color_total );
290+
291+ /* Select background color */
292+ if (gif -> SColorMap && gif -> SColorMap -> ColorCount > gif -> SBackGroundColor ) {
293+ color = gif -> SColorMap -> Colors [gif -> SBackGroundColor ];
294+ }else {
295+ color = (GifColorType ){0 , 0 , 0 };
296+ }
297+
298+ for (int y = 0 ; y < desc -> Height ; ++ y ) {
299+ off = desc -> Top * gif -> SWidth + y * gif -> SWidth + desc -> Left ;
300+ for (int x = 0 ; x < desc -> Width ; ++ x ) {
301+ roff = y * desc -> Width ;
302+ color_code = raster [roff + x ];
303+ if (desc -> ColorMap && desc -> ColorMap -> ColorCount > color_code )
304+ color = desc -> ColorMap -> Colors [color_code ];
305+ else if (gif -> SColorMap && gif -> SColorMap -> ColorCount > color_code )
306+ color = gif -> SColorMap -> Colors [color_code ];
307+ else /* this should not happen */
308+ color = (GifColorType ){0 , 0 , 0 };
309+ c = GRGBTOD32 (color );
310+ if (gcb -> TransparentColor == -1
311+ || gcb -> TransparentColor != color_code )
312+ canvas [off + x ] = c ;
313+ }
289314 }
290315}
291316
@@ -297,7 +322,9 @@ int load_pixmaps_from_image()
297322 int delay ;
298323 const char * err ;
299324 GifFileType * gif = NULL ;
325+ size_t canvas_size ;
300326 DATA32 * canvas = NULL ;
327+ DATA32 * old_canvas = NULL ;
301328 Imlib_Image img , img_scaled ;
302329 Pixmap pmap ;
303330 GraphicsControlBlock gcb ;
@@ -313,21 +340,22 @@ int load_pixmaps_from_image()
313340 Background_anim .frames = malloc (sizeof (struct Background_frame )
314341 * gif -> ImageCount );
315342
316- canvas = malloc (sizeof (DATA32 ) * gif -> SWidth * gif -> SHeight );
343+ canvas_size = sizeof (DATA32 ) * gif -> SWidth * gif -> SHeight ;
344+ canvas = malloc (canvas_size );
345+ old_canvas = malloc (canvas_size );
317346
318347 /* Render each image */
319348 for (int i = 0 ; i < gif -> ImageCount ; ++ i ) {
320349 desc = gif -> SavedImages [i ].ImageDesc ;
321-
322- /* Render image on canvas */
323350 DGifSavedExtensionToGCB (gif , i , & gcb );
324- render_image (gif , & gcb , & gif -> SavedImages [i ], canvas , & color_total );
325-
326- //TODO: detect invald gif values, eg gcb delay
327351 pmap = XCreatePixmap (display , root , root_attr .width ,
328352 root_attr .height , root_attr .depth );
329353 XSync (display , false);
330354
355+ /* Render image on canvas */
356+ render_image (gif , & gcb , & gif -> SavedImages [i ], canvas , & color_total );
357+
358+
331359 /* Render canvas on pixmap with imlib2 */
332360 img = imlib_create_image_using_data (gif -> SWidth ,
333361 gif -> SHeight ,
@@ -350,6 +378,10 @@ int load_pixmaps_from_image()
350378 imlib_context_set_image (img );
351379 imlib_free_image ();
352380
381+ /* Dispose image */
382+ dispose_image (gif , & gcb , & gif -> SavedImages [i ], canvas , old_canvas );
383+ memcpy (old_canvas , canvas , canvas_size );
384+
353385 delay = (gcb .DelayTime ) ? gcb .DelayTime : 1 ; // Min delay time
354386 Background_anim .frames [i ].p = pmap ;
355387 Background_anim .frames [((i == 0 ) ? gif -> ImageCount : i )- 1 ].dur
0 commit comments