Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Animated GIF files (movies) directly from Fortran code

508 views
Skip to first unread message

Jos Bergervoet

unread,
Aug 2, 2017, 6:09:02 AM8/2/17
to

http://bergervo.home.xs4all.nl/LW3.gif (example output)

Remaining question about reading/writing unformatted files: does it
work on a system where file storage units are not 1 Byte?

Maybe someone can try.. Using gfortran (where unit=1 Byte) it works:

gfortran -ffast-math -O3 bin_io.f90 gif_util.f90 Lienard-Wiechert.f90

Running the executable will create 'LW3.gif'. If OK, it's viewable in
web-browsers (or with 'gifview' or imageview or whatever). Files:

http://bergervo.home.xs4all.nl/Lienard-Wiechert.zip (Fortran code)

[NB: It's not programmed in the best way. There should be 'GIFhandle'
objects to allow writing different GIF animations concurrently!]

--
Jos

Jos Bergervoet

unread,
Aug 2, 2017, 6:15:47 AM8/2/17
to
On 8/2/2017 12:08 PM, Jos Bergervoet wrote:
>
> http://bergervo.home.xs4all.nl/LW3.gif (example output)

Another problem: for some reason Firefox refuses to show it while
IE thinks it's OK!

--
Jos

Jos Bergervoet

unread,
Aug 2, 2017, 6:56:13 AM8/2/17
to
No, that was an upload mix-up. The wrong version of gif_util.f90,
containing on line 289:
call integer_block_write (Fu, 0, 1) ! data sub-block index (always 1)

which is writing a 1-Byte integer with value 0 (even though the
comment correctly states that it should be 1). It's OK now:

call integer_block_write (Fu, 1, 1) ! data sub-block index (always 1)

--
Jos

Arjen Markus

unread,
Aug 2, 2017, 8:11:47 AM8/2/17
to
I tried it with Intel Fortran - that failed on a stack overflow problem (even when I used the SAVE attribute), but reducing the image size solved this problem. The resulting GIF can be viewed with IE, but not with FireFox - that complains about errors in the file.

Now checking with -assume:byterecl to see if something else might be going on.

Regards,

Arjen

Stefano Zaghi

unread,
Aug 2, 2017, 8:12:59 AM8/2/17
to
Dear Jos,

thank you for sharing this program.

Do you think that 4-bytes storage system is a good test?

My best regards.

Arjen Markus

unread,
Aug 2, 2017, 8:14:55 AM8/2/17
to
Well, actually, IE showed a close button-like image without animation, FF complained, but when I used the -assume:byterecl option I got a beautiful animation.

So, my conclusion is that you do need a record unit of one byte.

Regards,

Arjen

Anton Shterenlikht

unread,
Aug 2, 2017, 8:23:41 AM8/2/17
to
I can play this in firefox 54.0.1 on FreeBSD fine.

Anton

Jos Bergervoet

unread,
Aug 2, 2017, 8:50:53 AM8/2/17
to
On 8/2/2017 2:12 PM, Stefano Zaghi wrote:
> Il giorno mercoledì 2 agosto 2017 12:09:02 UTC+2, Jos Bergervoet ha scritto:
>> http://bergervo.home.xs4all.nl/LW3.gif (example output)
>>
>> Remaining question about reading/writing unformatted files: does it
>> work on a system where file storage units are not 1 Byte?
>>
>> Maybe someone can try.. Using gfortran (where unit=1 Byte) it works:
>>
>> gfortran -ffast-math -O3 bin_io.f90 gif_util.f90 Lienard-Wiechert.f90
>>
>> Running the executable will create 'LW3.gif'. If OK, it's viewable in
>> web-browsers (or with 'gifview' or imageview or whatever). Files:
>>
>> http://bergervo.home.xs4all.nl/Lienard-Wiechert.zip (Fortran code)
>>
>> [NB: It's not programmed in the best way. There should be 'GIFhandle'
>> objects to allow writing different GIF animations concurrently!]
...
> thank you for sharing this program.
>
> Do you think that 4-bytes storage system is a good test?

Given the existing compilers, that seems the most important test!

The way I wrote the file access in bin_io.f90 (which dates back to
about 20 years ago) is by using stream access and *trying* to do
it right for 1, 2, 4, 8, or 16-Bytes as the value for 'filePosUnit'
as determined by lines 42-43.

I believe the last time I had ifort installed it was not without
problems (but I don't have ifort at hand right now).

[And there may be other problems! A single misspelled bit makes the
whole 2MByte file unacceptable to some viewers, but not to others,
see further up-thread..]

--
Jos

Stefano Zaghi

unread,
Aug 2, 2017, 9:57:15 AM8/2/17
to
Dear Jos,

I tested you nice program with Intel 17 and 18 beta in default 4bytes unit storage: the produced gif is not working well. Inspecting it with imagemagick I got

identify LW3.gif
identify: negative or zero image size `LW3.gif' @ error/gif.c/ReadGIFImage/1404.

Trying to dig deeper I got

giffix LW3.gif
GIF87a���

▒▒ "$&(*,.02468:<>@BDFHJLNPRTVXZ\^`bdfhjlnprtvxz|~������������������ժS�B}ڔ�ҤG�%▒�Ϟ;u��Y��̘/]�d��ɒ#E�ّ�ƌ/R��▒�C�
"DX����ۯ?�����LJ���[�o�}�]8׉S�J�EW�s�4w�r9%w�:ŭ3;�!�[o��OnR�&OmZ�FOl`�fOkd�vVjj�vZis��Wh�}��������(��CI�����dfH�$�2�����x����X����8�� ��!����a;V8ar�@���
*89�S����_�u37�ms�6�e36�^~
�|�V�A���L�A��L
/�=��n��d>۱7�����(@�P�z��bth��Jֲ���b�i˂▒Ԗ���@�І"1��<�D'��Y.�����4̦�n�l|�)��5S:ϴ���<�g��!z�Ȟ@~�x��)8MxH&���bd���u����D�

Following unrecoverable error occured:GIF-LIB error: Wrong record type detected.
GIF-LIB undefined error 0.
�\�?I���"؜�6I�n�T���}��A��W�쒛;

The 4bytes form does not work well.

My best regards.


Clive Page

unread,
Aug 2, 2017, 10:33:38 AM8/2/17
to
On 02/08/2017 11:08, Jos Bergervoet wrote:
>
> http://bergervo.home.xs4all.nl/LW3.gif (example output)
>
> Remaining question about reading/writing unformatted files: does it
> work on a system where file storage units are not 1 Byte?

Surely the best way of doing this is to write a stream I/O file, standardised in Fortran for many years and supported by all modern compilers. This is what I did in my code to write a GIF file (ok static not dynamic GIF) as shown here
http://fortranwiki.org/fortran/show/writegif

Then the question of file storage units is irrelevant.

--
Clive Page

Jos Bergervoet

unread,
Aug 2, 2017, 10:58:14 AM8/2/17
to
On 8/2/2017 4:33 PM, Clive Page wrote:
> On 02/08/2017 11:08, Jos Bergervoet wrote:
>>
>> http://bergervo.home.xs4all.nl/LW3.gif (example output)
>>
>> Remaining question about reading/writing unformatted files: does it
>> work on a system where file storage units are not 1 Byte?
>
> Surely the best way of doing this is to write a stream I/O file,
> standardised in Fortran for many years and supported by all modern
> compilers. This is what I did in my code to write a GIF file (ok static
> not dynamic GIF) as shown here
> http://fortranwiki.org/fortran/show/writegif

Yes, it looks familiar!

> Then the question of file storage units is irrelevant.

It only is for positioning in the file, because stream I/O
in that case *also* uses file storage units for the 'pos='
specifier. But you are right, it's irrelevant if:
a) You only write.
b) And do it without any re-positioning or backspacing.

So that would mean that writing the GIF files should
actually work on any system using stream access. (I did
of course also replace the direct access from the 90s
version to stream access).

Unclear remains why Arjen Markus reported that single-
Byte access was needed..

--
Jos

dpb

unread,
Aug 2, 2017, 11:26:34 AM8/2/17
to
On 08/02/2017 9:58 AM, Jos Bergervoet wrote:
...

> Unclear remains why Arjen Markus reported that single-
> Byte access was needed..

While I don't know for certain, I'd certainly expect any readers will be
accessing by bytes and there are internal counts based on such which if
are in word units would be in error...

--



Sjouke Burry

unread,
Aug 2, 2017, 2:35:34 PM8/2/17
to
Displays fine here. (ESR 45.9.0)

Clive Page

unread,
Aug 2, 2017, 6:17:18 PM8/2/17
to
On 02/08/2017 15:58, Jos Bergervoet wrote:
>> http://fortranwiki.org/fortran/show/writegif
>
> Yes, it looks familiar!

Well your name appears fairly prominently. I didn't mean to claim that I had more than a minor part in it, or indeed in the read_gif.f90 also available there.


--
Clive Page

urba...@comcast.net

unread,
Aug 3, 2017, 12:46:08 AM8/3/17
to
FYI:

A have used a similar derivative of writegif(3f) called
write_animated_gif(3f) by jacobwilliams. I see that it is now in a
module called FGIF on github.

It was working very successfully for creating animated GIF files
for a document for a Fortran module I started (The module is called
M_pixel(3f). It creates simple pixel arrays containing basic vector
graphics).

=======

PS:

I got pulled off onto other things so I am well aware the M_pixel(3f)
module is in a draft state, but for anyone interested it is included
in a Fortran collection at

http://www.urbanjost.altervista.org/LIBRARY/libjust4/download/tmp/html/download.html

The auto-generated manual I mentioned is at

http://www.urbanjost.altervista.org/LIBRARY/libjust4/download/tmp/html/BOOK_M_pixel.html

(Note that the manual requires Javascript).

I intend to get M_pixel(3f) up to a release-level quality and move it
to github, but not soon. That said, it might still be of interest.

I have only tested with gfortran(1) V5.0.4. If anyone wants to build
the Fortran collection (there is a little C in there too) with other
compilers (must be near-f2003=compliant with a few f2008 features)
I would like to know what compiler issues occur.

Arjen Markus

unread,
Aug 3, 2017, 2:53:53 AM8/3/17
to
On Wednesday, August 2, 2017 at 4:58:14 PM UTC+2, Jos Bergervoet wrote:

>
> Unclear remains why Arjen Markus reported that single-
> Byte access was needed..
>
> --
> Jos

Well, I redid the experiment, this time compiling the sources separately just in case.

My compiler is: Intel Fortran, 64 bits, version 15.0.1.148

If I compile the sources with default options, the resulting GIF file is 94501 bytes in size and displays in IE as a small "close" icon and FF refuses to show anything.

If instead I compile all the sources with -assume:byterecl I get a GIF file that is 375589 bytes in size and it shows a nice animation looking like a setting sun.

I had to reduce the size of the matrix, becaus eof stack overflow. The size I used for the above report was: 3*64 by 3*48 pixels.

If you want, I can send the GIF files for closer inspection.

Regards,

Arjen

Jos Bergervoet

unread,
Aug 3, 2017, 5:30:11 AM8/3/17
to
Feel free to upload more version with animated GIF movies as well, if
you have the time! (I usually haven't..) My examples merely serve to
show how it can be done.

Nevertheless, I am going to change the write function to allow multiple
GIF movies to be processed (needed for writing movies of E-field and
B-field during the same calculation, or a number of cross-section movies
in a 3D FDTD run.) Now the question is: how?

One possible way is to make a type(GIFhandle), with completely
private components of course, and this usage:

type(GIFhandle) :: Movie1, Movie2 ! auto-initialized
! .. calculate
writeAnimGIF( filNam, PixelsA, Colors, Movie1 ) ! 1st frame
writeAnimGIF( filNam, PixelsB, Colors, Movie2 ) ! 1st frame
! .. calculate
writeAnimGIF( filNam, PixelsA, Colors, Movie1 ) ! next frame
writeAnimGIF( filNam, PixelsB, Colors, Movie2 ) ! next frame
! .. calculate last time
writeAnimGIF( filNam, PixelsA, Colors, Movie1, Finish=.true. )
writeAnimGIF( filNam, PixelsB, Colors, Movie2, Finish=.true. )

Questions:
1) We can overload this behavior on the old name writeGIF, but
should writing a picture have the same name as a movie?

2) We could use object syntax, but is it better?
Movie1 %writeGIF( filNam, Pixels, Colors )

3) Should the argument order be changed? Pixels is always needed
while the others can be made optional, in particular filNam (it
could be checked against the first-time name, if repeatedly
given, but that's not needed). So should Pixel come first?

4) We're managing 'state' here (the core difficulty of programming!)
Instead of encapsulating it in a module (allowing only 1 instance)
we'll now encapsulate it in objects (GIFhandle). Does the advise
to "avoid state" make any sense here? It just seems to be needed..
<http://stackoverflow.com/questions/3722084/does-functional-programming-avoid-state>

--
Jos

Ian Harvey

unread,
Aug 3, 2017, 5:36:47 AM8/3/17
to
It is still relevant. F2008 says...

Every value in a stream file or an unformatted record file
shall occupy an integer number of file storage units.

...

The number of bits in a file storage unit is given by the
constant FILE_STORAGE_SIZE defined in the intrinsic
module ISO_FORTRAN_ENV.

If the number of bits in a file storage unit is not eight, then you are
going to get additional padding when you try and write eight-bit bytes
to a file.

Arjen Markus

unread,
Aug 3, 2017, 8:04:54 AM8/3/17
to
How about:

handle = GIFHandle(filename, colors)
call handle%write(pixels)

as an interface?

You can still use the original API via suitable overloading and a private GIFHandle that is used if none was given.

Regards,

Arjen

Arjen Markus

unread,
Aug 3, 2017, 3:39:39 PM8/3/17
to
I think I know what is going on:
- Intel Fortran (at least the version I have been using) uses a file storage unit of 4 bytes for direct-access files (the minimum size of such a file is 4 bytes)
- It uses a unit of 1 byte, however, for stream-access files (the minimum size is 1 byte)
- inquire(iolength=) uses the 4 bytes unit
- the parameter file_storage_unit is that of stream-access files

The program below reported this with default options:

Minimum size of direct-access file (bytes): 4
Size of stream-access file (bytes): 1
File storage unit (bytes): 1

File storage unit (bits): 8
Character storage unit (bits): 8
IO-length one character (units): 1
IO-length 16 characters (units): 4

but with -assume:byterecl, it reports:

Minimum size of direct-access file (bytes): 1
Size of stream-access file (bytes): 1
File storage unit (bytes): 1

File storage unit (bits): 8
Character storage unit (bits): 8
IO-length one character (units): 1
IO-length 16 characters (units): 16

This would seem an inconsistency with the F2008 standard.

At least using the file storage unit instead of iolength= gives the correct number of bytes.

Regards,

Arjen

----
! chk_storage.f90 --
! Check the storage unit for direct-access and stream-access files
!
program chk_storage
use iso_fortran_env

implicit none

integer :: filesize, charsize
!
! First check the storage size for direct-access files
!
open( 10, file = 'chk_storage.bin', access = 'direct', recl = 1 )
write( 10, rec = 1 ) 'A'
close( 10 )

inquire( file = 'chk_storage.bin', size = filesize )

write( *, '(a,i0)' ) 'Minimum size of direct-access file (bytes): ', filesize

!
! Remove the file
!
open( 10, file = 'chk_storage.bin', access = 'direct', recl = 1 )
close( 10, status = 'delete' )

!
! Then check the storage size for stream-access files
!
open( 10, file = 'chk_storage.bin', access = 'stream' )
write( 10 ) 'A'
close( 10 )

inquire( file = 'chk_storage.bin', size = filesize )
write( *, '(a,i0)' ) 'Size of stream-access file (bytes): ', filesize

!
! Remove the file
!
open( 10, file = 'chk_storage.bin', access = 'stream' )
close( 10, status = 'delete' )

!
! Report the advertised storage unit
!
write( *, '(a,i0)' ) 'File storage unit (bytes): ', file_storage_size / character_storage_size
write( *, '(/,a,i0)' ) 'File storage unit (bits): ', file_storage_size
write( *, '(a,i0)' ) 'Character storage unit (bits): ', character_storage_size

!
! Alternatively use the inquire(iolength=) feature
!
inquire(iolength=charsize) 'A'
write( *, '(a,i0)' ) 'IO-length one character (units): ', charsize

inquire(iolength=charsize) '0123456789ABCDEF'
write( *, '(a,i0)' ) 'IO-length 16 characters (units): ', charsize

end program chk_storage

Ian Harvey

unread,
Aug 3, 2017, 4:19:03 PM8/3/17
to
...
The first behaviour is inconsistent, but if you want consistency with
the standard with that compiler, you need to specify the
-standard-semantics option, which also specifies -assume:byterecl.

Arjen Markus

unread,
Aug 4, 2017, 2:24:58 AM8/4/17
to
On Thursday, August 3, 2017 at 10:19:03 PM UTC+2, Ian Harvey wrote:

> ...
> The first behaviour is inconsistent, but if you want consistency with
> the standard with that compiler, you need to specify the
> -standard-semantics option, which also specifies -assume:byterecl.

Ah, so it is a documented feature. Good to know.

Regards,

Arjen

Jos Bergervoet

unread,
Aug 4, 2017, 5:47:45 AM8/4/17
to
On 8/3/2017 8:53 AM, Arjen Markus wrote:
> On Wednesday, August 2, 2017 at 4:58:14 PM UTC+2, Jos Bergervoet wrote:
..
> I had to reduce the size of the matrix, becaus eof stack overflow. The size I used for the above report was: 3*64 by 3*48 pixels.

Which nicely illustrates *another* pitfall in platform-independence..
It is a bit strange that such small numbers are needed. Actually, if
I increase the size 25 times (which gives about 8 Megapixels), then
it's still OK for Lahey's lf95, Andy's g95, and Gnu's gfortran.

[And Firefox still shows the file, which is now 27 MByte, because the
compression rate goes up from 20 times to 50 times for the larger
images, compared with *.bmp]

--
Jos

Arjen Markus

unread,
Aug 4, 2017, 7:51:08 AM8/4/17
to
Right, I am not sure why this is occurring, the matrices do not seem excessively large.

Regards,

Arjen

kees.r...@ecocurves.nl

unread,
Nov 21, 2017, 4:20:40 PM11/21/17
to
Op woensdag 2 augustus 2017 12:09:02 UTC+2 schreef Jos Bergervoet:
Hallo Jos,
I am looking for a long time for a way to write movies. So I am happy to find your code in gif_util. Perhaps this is usefull:

I ran the Lienard-Wiechert example on Intel Fortran with 1 byte word length. With check for floating point overflow I got an error in function E_Lienard_Wiechert(t,x,z) since absr12 may become zero. If I force E=1.0 in these cases (just a choice) then I find that this happens just two times during the run (during computing frame 24 and 34) and the movie looks great.

Alternatively, I can leave out the floating point check and the movie looks great as well. But a few times NaN values of n are produced and go into the movie (?), perhaps with machine or compiler dependent results.

Thanks once more for your gif_util. Regards,

Kees


0 new messages