Gifs created by ROOT do not replay on libreoffice impress

Dear developers,
on Debian stable and ROOT v5.34-26, I am creating animated gifs with ROOT (infinite replay), and they play correctly in any viewer. However, when I embed them into a Libreoffice Impress 4 presentation, they do not replay (they just run one time).

As I learned in this post, if I open the gif with Gimp and export it again as gif (check “Loop forever”), then they replay correctly in Impress.
forum.openoffice.org/en/forum/v … f=10&t=510

Is there any trick how ROOT could export in the same way as Gimp for being compatible with Impress and avoiding the tedious open-and-resave-with-Gimp?

I attach my macro and the gifs.
test_gifs.zip (31.4 KB)





test_gifs.cpp (671 Bytes)

So it looks like a bug in Libreoffice Impress 4

There is no special trick… I do not know what Gimp does. It needs to be checked.

Yes, it looks like a bug in LibreOffice Impress. I have written a batch export script for Gimp, just in case some user wants to automatize this bypass-procedure, where 500 is the 500 ms delay (50 centiseconds in the macro of my previous post).

gimp -i -b "(let* ( (image (car (file-gif-load 1 \"./test_gifs.gif\" \"./test_gifs.gif\") ) ) ) (file-gif-save 1 image 0 \"./test_batch_gimp.gif\" \"./test_batch_gimp.gif\" 0 1 500 0) )" -b "(gimp-quit 0)"

Btw, I checked how Gimp encodes the loop (which works fine for Impress):
gimp.sourcearchive.com/documenta … ource.html

static void
gif_encode_loop_ext (FILE  *fp,
                     guint  num_loops)
{
  fputc(0x21, fp);
  fputc(0xff, fp);
  fputc(0x0b, fp);
  fputs("NETSCAPE2.0", fp);
  fputc(0x03, fp);
  fputc(0x01, fp);
  put_word(num_loops, fp);
  fputc(0x00, fp);

  /* NOTE: num_loops == 0 means 'loop infinitely' */
}

and how ROOT does it:
root.cern.ch/root/html/src/TASI … x.html#709
and

code.metager.de/source/xref/cern … port.c#989
but I am not able to compare it xD.

May be you can send them a bug report.

It seems to be a bug not only in Libreoffice, but also in Firefox (but not in Chrome). See here, if you open with firefox:

root.cern.ch/phpBB3/download/file.php?id=10268 (root version)

root.cern.ch/phpBB3/download/file.php?id=10269 (gimp version)

I filed the bug in libreoffice: bugs.documentfoundation.org/sho … i?id=90262

I opened root.cern.ch/phpBB3/download/file.php?id=10268

With: Chrome, Firefox, Safari, Opera, Camino on Mac
They are All fine … I see the animation everywhere.

Oh, sorry, you are right. Ok, I just figured out the reason why I was confused.

File
root.cern.ch/phpBB3/download/file.php?id=10268
plays again exactly 50 times, which in reality should be the 50cs delay I wanted between image 4 and image 1. Then it stops.

The other file loops forever.
root.cern.ch/phpBB3/download/file.php?id=10269

The reason is the different behaviour of “NN” for the last subimage, when used in animation. It is described in
root.cern.ch/root/html/src/TASI … x.html#615

and also mentioned in
[GIF Animation (seems to be an old problem)

This info is missing in
root.cern.ch/root/html/src/TPad.cxx.html#pfuPi
root.cern.ch/root/html/src/TPad.cxx.html#KA8ntE
root.cern.ch/root/html/src/TPad.cxx.html#4347
root.cern.ch/root/html/src/TPad.cxx.html#4430
that was the reason why I was confused.

Could it be added at these points also to the documentation, to clarify it / or say at least “->see WriteImage function for more details”? Otherwise, each user has to search deeply in the code until finding the reason.

root.cern.ch/root/html/src/TASI … x.html#634
uses the last image (i=10) to make it an infinite loop. But the delay between the last image of the loop and the first one is the default one (“0”). Is there a way to say at the same time --> I want a delay of 50 cs and also an infinite loop?

Done

I have a related question:

If I want an infinite loop, I have to write my last frame as

c->Print("test_gifs.gif++");

However, the delay between the last image of the loop and the first one is 0 (or non-existent). See the output of gifsicle when analyzing the image created by ROOT:

$ gifsicle -I test_gifs.gif
* test_gifs.gif 4 images
  logical screen 696x472
  global color table [8]
  background 0
  loop forever
  + image #0 696x472
    delay 0.50s
  + image #1 696x472
    delay 0.50s
  + image #2 696x472
    delay 0.50s
  + image #3 696x472

See also in the gif image the attached result, where the image #3 is just a short “flash”.

Could ROOT include in the future a way of controlling this last-frame-delay? Maybe with a syntak like “++50++”. The bypass I use now, namely to write twice the last frame (once with ++50 and the last with ++) does not seem very clean to me…

Thanks for the attention.


I suggest you post a lira request for that.
may be the delay would be always added at the end ?
No need for a new option exist already.
Note that any implementation you may do is welcome.

Ticket submitted. I have implemented two new options.
sft.its.cern.ch/jira/browse/ROOT-7263

New options specifying the delay of last image are now implemented in ROOT’s master branch (and probably v5.34/31 and v6.03/04), see
root.cern.ch/root/html/src/TASI … html#Hvr1e
root.cern.ch/gitweb?p=root.git; … 45cec2705e
for more details.

They answered the bug report. Apparently, GIFs generated by ROOT have a weird metadata order that does not fulfil exactly the standard. Could you check it?

See https://bugs.documentfoundation.org/show_bug.cgi?id=90262#c8

“The Netscape 2.0 looping block must appear immediately
after the global color table of the logical screen
descriptor.”

That is not the case with this GIF; the Netscape extension appears much later.

Thanks for the investigation, ferhue! @couet will take a look once we’re all back from holiday! Should be in about a week’s time.

@ferhue I just looked the point #8 you mention here. I am a bit confused because the file referred in that point (gifread.cxx) is not part of ROOT… Can you clarify what the problem is ? may be post a macro and some instructions reproducing it ? The Jira report linked to this post is closed since a long time and tells all is fixed.

Run this macro:

//root -l -b -q test_gifs.cpp+

#include "TCanvas.h"
#include "TPaveText.h"
#include "TSystem.h"

void test_gifs()
{
	
	const TString kGifName = "test_gifs.gif";
	const TString kGifSleep = "50";//centiseconds
	gSystem->Unlink(kGifName.Data());//delete existing file
	
	TCanvas* c = new TCanvas();
	TPaveText* t = new TPaveText(0.55,0.65,0.8,0.85,"brNDC");
	
	t->AddText("1");
	t->Draw();
	c->Print(kGifName+"+"+kGifSleep);
	
	t->AddText("2");
	t->Draw();
	c->Print(kGifName+"+"+kGifSleep);
	
	t->AddText("3");
	t->Draw();
	c->Print(kGifName+"+"+kGifSleep);
	
	t->AddText("4");
	t->Draw();
	c->Print(kGifName+"++"+kGifSleep);//Two ++ makes an infinite loop (replay gif)
}

Then insert the generated file test_gifs.gif in a LibreOffice Impress slide. There, you will see that the gif file only loops once instead of infinitely.

This is due to the fact that the .gif file generated by ROOT fixes the number of loop iterations (the Netscape 2.0 block) at a later point than expected by the standard. Thus, Libreoffice sets the number of loops to the default value (1).

On http://giflib.sourceforge.net/whatsinagif/bits_and_bytes.html, it says:

The Netscape 2.0 looping block must appear immediately after the global color table of the logical screen descriptor.

2 Likes

I think that the part of the code that should be moved is graf2d/asimage/src/libAfterImage/export.c, line 1111:

EGifPutExtensionFirst(gif, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0");
EGifPutExtensionLast(gif, 0, GIF_NETSCAPE_EXT_BYTES, &(netscape_ext_bytes[0]));

@ferhue thanks for your input. I started looking at it yesterday and I ended up looking in that file too. Because of some other matters to deal with I did not continue. I will today. I will look at your suggestion.

I tried to move up this part of code but all I get is a wrong gif file and many errors:

ASImage2gif():1199:<test_gifs.gif> 
GIF-LIB error: #Pixels bigger than Width * Height.

The file produced by the example you gave cycles indefinilty in Chrome, Firefox, Safari, Keynote and PowerPoint… So it is working every where expect in LibreOffice Impress… Therefore I would guess the problem is in LibreOffice Impress.