#!/usr/bin/perl
##### Time-stamp: "2005-08-19 00:44:54 ADT"
#
# add_gif_comment    v1.0
#
#  This program adds a comment block to specified GIFs.
#  If you specify (on the command line) exactly one file whose name
#  ends in ".txt", the contents of that file will be used as the
#  comment to be added to each GIF.  Otherwise the contents of STDIN
#  will be used.
#
# Example usage:
#   date -u | add_gif_comment.pl foo*.gif
#   add_gif_comment.pl copyright.txt *.gif
#   echo "I made this!" | add_gif_comment.pl thing1.gif
#
# Note:
#  This program performs no charset conversion or endline translations
#  on the content to be put into the comment block.  The GIF89
#  standard has no recommendations about character sets or enline
#  formats.
#
# See also:  "list_gif_comments" and "Daktari GIF", also by me.
#
# Author:
#  Sean M. Burke, sburke@cpan.org, http://interglacial.com/~sburke/
#  Copyright 1997- by Sean M. Burke.
#
# Note:  I've not tried this with non-text data on STDIN.
#
# Revision notes:
#  v1.0, 1997-08-04.
#
# Availability & Copying:
#
# add_gif_comment is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2, or
# (at your option) any later version.
#
# add_gif_comment is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# To see a copy of the GNU General Public License, see
# http://interglacial.com/~sburke/gnu_release.html, or write to the
# Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
######################################################################

$silent = 0;

@txts = grep(/\.txt$/i, @ARGV);
@ARGV = grep(!/\.txt$/i, @ARGV);

unless(@ARGV) {
  print "Usage:  add_gif_comment [f1.gif f2.gif ... fN.gif]\n",
        "If one of the files specified ends in \".txt\", its contents\n",
        "will be used as the comment for all the gifs.\n",
        "If no .txt file is specified, text supplied on STDIN will be used.\n\n";
  exit;
}

if(@txts == 0) {
  binmode(STDIN); # presumably not necessary, but who knows
  $message = join('', <STDIN>);
} elsif (@txts == 1) {
  die "Can't open $txts[0]" unless open(TXT, "< $txts[0]");
  $message = join('', <TXT>);
  close(TXT);
  print "Using the contents of $txts[0] as the GIF comment\n";
} else {
  print "You specified too many .txt files.\n",
        "Specify only one, or give input on STDIN\n".
  exit;
}

foreach $file (@ARGV) {
 my $message = $message;
 unless( length($message) ) {
   warn "No message to write.\n";
   next;
 }

 die "Can't open $file" unless open(GIF, "+<$file");
 binmode(GIF);

 seek(GIF, 0, 0);
 read(GIF, $sig, 5);
 unless ($sig =~ /^GIF\d\d/) {
  close(GIF);
  warn "$file is not a GIF.  Skipping.\n";
  next;
 }

 seek(GIF, -1, 2);
 read(GIF, $last, 1);
 unless ($last eq "\x3b") {
  close(GIF);
  warn "$file does not end with a GIF terminator!  Skipping.\n";
  next;
 }

 #OK, write the comment then
 seek(GIF, -1, 2);
 print GIF "\x21\xFE"; # introduce the comment block

 print "Writing a ", length($message), "-byte comment into $file\n"
   unless $silent;
 while(length($message) > 0) {
   if (length($message) > 255) {
     $chunk = substr($message,0,255);
     substr($message,0,255) = '';
   } else {
     $chunk = $message;
     $message = '';
   }
   print GIF (pack('C', length($chunk)), $chunk);
 }

 print GIF "\x00\x3b"; # end of block data, then the gif trailer.
 close(GIF);
}

print "Done.\n" unless $silent;
exit;
