Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 590
  • Last Modified:

Manipulating gifsicle

I need to call to a program, gifsicle.exe.  This is a command line program for manipulating gif image files. It works only in the directory where it is present . It outputs to a file but doesn't allow me to use the mode batch.  I would like to try to extend the capabilities of this program by (1) calling it it from a root directory; (2) batch a number of directories in one call; (3) create an output file as a log of all my calls.

I am new to programming and would like a step-by-step instruction as to how I can complete this.
0
paulinewin
Asked:
paulinewin
  • 8
  • 6
1 Solution
 
Kim RyanIT ConsultantCommented:
Should be fairly simple, try something like this

$image_dir =  '/your/gif/files';
chdir($image_dir);
@gif_files = <*.gif>;  # get all .gif files in current directory

# process each file in the current dir
open(LOG,">log.txt');
foreach $current_image (@gif_files)
{
    system("/path/to/gifsicle $image_dir/$current_image");
    print(LOG "Processed: $current_image\n");
}

close(LOG);
0
 
paulinewinAuthor Commented:
Thank you so much for your quick response!
I've tried implementing the your code but have been getting the following error:
'feature' is not recognized as a operable program or batch file.

#!c:\perl\bin\perl

$image_dir =  'feature/001search';
chdir($image_dir);
@gif_files = <*.gif>;  # get all .gif files in current directory

# process each file in the current dir
open(LOG,'>log.txt');
foreach $current_image (@gif_files)
{
    system("feature/001search $image_dir/$current_image");
    print(LOG "Processed: $current_image\n");
}

close(LOG);
0
 
mjcoyneCommented:
gifsicle.exe is not being called anywhere in your system call:

    system("feature/001search $image_dir/$current_image");
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
paulinewinAuthor Commented:
I'm sorry... here is it:
#!c:\perl\bin\perl

$image_dir =  'feature';
chdir($image_dir);
@gif_files = <*.gif>;  # get all .gif files in current directory

$result = `gifsicle.exe`;

# process each file in the current dir
open(LOG, ">> logfile ") || die("can't open logfile:  $!");
foreach $current_image (@gif_files)
{
    system("feature/001search $image_dir/$current_image");
    print(LOG "Processed: $current_image\n");
}

close(LOG);
0
 
mjcoyneCommented:
You're still not executing gifsicle.exe in your system call:

    system("feature/001search $image_dir/$current_image");

You need to do something like:

    system("path/to/gifsicle/gifsicle.exe $image_dir/$current_image");

so that you're executing the program, and passing it the filename you want it to operate on.

What is an example of a command line that works when you type it from the DOS command line?
0
 
paulinewinAuthor Commented:
Oh, thank you so much!  It is finally seeing the gifs.  But I don't think the executable is working outside the image directory.  I'm getting  "No such file or directory" message.  Is there a way to loop through all the directories with a copy of the executable in each directory?

An example of a DOS command line using the executable standalone is "gifsicle.exe -bII -i *.gif"
0
 
mjcoyneCommented:
Does it work from the command line with something like:

"gifsicle.exe -bII -i /some/path/other/than/gifsicles/*.gif"

?
0
 
paulinewinAuthor Commented:
Thank you again!  It does work as a standalone command but not with the Perl call.  I am getting the following output:

C:\gifsicle\images\feature>perl call.pl gifsicle.exe -bII -i *.gif
C:\gifsicle\images\feature\001search\gifsicle.exe: <stdin>: not a GIF image
C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search1.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search2.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search3.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search4.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search5.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search6.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search7.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search8.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search9.gif: No such file or directory

C:\gifsicle\images\feature\001search\gifsicle.exe: 001search/search10.gif: No such file or directory

logfile.txt gets created sucessfully but not with the DOS output, which I was hoping to capture.  Any help would be greatly appreciated!
0
 
paulinewinAuthor Commented:
I forgot to mention that the executable had to reside in 001search directory to work.  The executable still is not working from the parent diretory.  Thank you again!
0
 
mjcoyneCommented:
I'm working on a solution for you, but I got caught up in a bit of my own work; I'll get back to this as soon as I can.  In the meantime, can you describe to me in more detail what it is you're trying to accomplish?

What manipulations are you trying to perform on the *.gif files?

The command line example you gave doesn't seem to do anything (-bII is just batch mode, and print information).  Is information all you're trying to get from these files?

Is there a reason you've settled on gifsicle?

If I knew better what you were trying to accomplish, there might be an easier way (using File::Find and ImageMagick, for example, or if information about the files is all you need, we might be able to use a Perl -x test or stat or something).
0
 
paulinewinAuthor Commented:
The command line example I've provided was to turn on interlacing for all the gifs.  The reason why gifsicle was chosen was because this is what I'm familiar with, since I'm not technically gifted. I'd like to manipulate the gifs in many ways but mainly create animations from them.

My goal is three fold: (1) My directory structure is pretty convoluted and large.  I'm presently working on an array that loops recursively down the directory structure so that gifsicle.exe can work on the sub sub directories, which is quite a task for me.  I'd like to make changes to all gifs in all directories and it's sub and sub directories. (2) Have a log file that keeps track of all the work that has been performed on the gifs. (3) Use one gifsicle.exe to accomplish my objective and getting it work.

Thank you in advance!
0
 
mjcoyneCommented:
Okay, you might have to tune this up a bit, but it works fairly well.  Basically, place this script in a folder off your root directory (C:\).  Place the gifsicle executable there as well (gifsicle.exe appears to have some issues when run from directories with spaces in their names -- I haven't had time to puzzle this out fully yet).

Anyway, when both gifsicle.exe and gifsicle.pl are in the same directory and there are no spaces to deal with in the path to the program, it works fine.  Curiously, the directory containing the .gif files (and, perhaps, subdirectories containing additional .gif files) *can* have spaces in their names...

To test it, I put gifsicle.exe and gifsicle.pl in the C:\gifsicle\ directory.  I created a directory called "C:\Documents and Settings\Michael Coyne\Desktop\gif_files", which has two subdirectories in it (\gif_files_A and \gif_files_B), each of which contains three .gif files.

gifsicle.pl contains:

#!/usr/bin/perl -w
use strict;
use File::Find;

open(LOG,">log.txt");

find(\&process_file, "C:/Documents and Settings/Username/Desktop/gif_files");

sub process_file {
    if ($_ =~ /\.gif$/) {
        my $input_file = "\"$File::Find::name\"";
        my $prgm_out;
        my $command = "$ENV{PWD}/gifsicle.exe -bII -i $input_file 2>$ENV{PWD}/out.txt";
        system ("$command");
        open (TMP, "$ENV{PWD}/out.txt") or die "Couldn't open $ENV{PWD}/out.txt:$!\n";
        {local $/; $prgm_out = <TMP>;}
        close (TMP);
        unlink ("$ENV{PWD}/out.txt") or die "Couldn't delete $ENV{PWD}/out.txt:$!\n";
        print LOG "Processed $File::Find::name\n$prgm_out\n\n";
    }
}

# end of code

Executing this file from C:\gifsicle (by typing "perl gifsicle.pl" at the command prompt) produces this (in C:\gifsicle\log.txt):

Processed C:\Documents and Settings\Username\Desktop\gif_files/gif_files_A/2_computers.gif
* C:\Documents and Settings\Username\Desktop\gif_files/gif_files_A/2_computers.gif 15 images
  logical screen 107x35
  global color table [8]
  background 0
  end comment Reduced 49% @ www.gifwizard.com Guest: NON-COMMERCIAL USE ONLY
  end comment \r\nThis animation is archived at Animation Library at http://www.animationlibrary.com . \r\nVisit us for over two thousand free animations.
  loop count 1000
  + image #0 107x35 interlaced transparent 0
    disposal background delay 0.01s
  + image #1 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #2 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #3 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #4 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #5 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #6 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #7 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #8 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #9 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #10 103x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #11 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #12 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #13 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s
  + image #14 102x33 at 3,0 interlaced transparent 0
    disposal background delay 0.01s

blah, blah, blah...
...(continues in a similar manner for the other two files in the gif_files_A subdirectory)...

Processed C:\Documents and Settings\Username\Desktop\gif_files/gif_files_B/Alien_computer.gif
* C:\Documents and Settings\Username\Desktop\gif_files/gif_files_B/Alien_computer.gif 4 images
  logical screen 120x99
  global color table [64]
  background 0
  loop forever
  extensions 1
  + image #0 120x99 interlaced transparent 49
    disposal background delay 0.20s
  + image #1 92x99 interlaced transparent 15
    disposal background delay 0.20s
  + image #2 120x99 interlaced transparent 2
    disposal background delay 0.20s
  + image #3 120x99 interlaced transparent 4
    disposal background delay 0.20s

blah, blah, blah...
...(continues in a similar manner for the other two files in the gif_files_B subdirectory)...

# end of log output

So, this tells me that gifsicle.exe is seeing and acting upon the files, regardless of where they are under the initial gif_file directory (i.e. it's seeing all files recursively from C:/Documents and Settings/Username/Desktop/gif_files).

You can (obviously) edit the "base image directory" (currently C:/Documents and Settings/Username/Desktop/gif_files) as you please to point the script (and thus gifsicle) at the right directory to begin processing.  If you'd like to be able to include the target directory on the command line, you can do something like:

#!/usr/bin/perl -w
use strict;
use File::Find;

if (!($ARGV[0])) {
    die "You must tell me where the files are!\n";
}

open(LOG,">log.txt");

find(\&process_file, "$ARGV[0]");

sub process_file {
    if ($_ =~ /\.gif$/) {
        my $input_file = "\"$File::Find::name\"";
        my $prgm_out;
        my $command = "$ENV{PWD}/gifsicle.exe -bII -i $input_file 2>$ENV{PWD}/out.txt";
        system ("$command");
        open (TMP, "$ENV{PWD}/out.txt") or die "Couldn't open $ENV{PWD}/out.txt:$!\n";
        {local $/; $prgm_out = <TMP>;}
        close (TMP);
        unlink ("$ENV{PWD}/out.txt") or die "Couldn't delete $ENV{PWD}/out.txt:$!\n";
        print LOG "Processed $File::Find::name\n$prgm_out\n\n";
    }
}

# end of code

and it'll work, too.  Note that you must surround the path name with quotes if it contains spaces (e.g. to replicate the behavior of the first script, I would type:

perl gifsicle.pl "C:\Documents and Settings\Username\Desktop\gif_files"

at the DOS command line).  You can save yourself some typing if you use the environmental variables set by Windows (e.g. perl gifsicle.pl "%USERPROFILE%\Desktop\gif_files" is the same as the prior command).  The script will process all .gif files in the "base" directory, plus any that are in any subdirectory (or sub-subdirectory, etc).

This script could obviously be improved somewhat (making it so you can pass gifsicle.exe's command line parameters to the script from the DOS command line would be nice, for example), and the fact that the script (well, gifsicle anyhow) misbehaves if run from a pathname with spaces in it still bothers me (gifsicle might require "8.3" pathnames, like c:\docume~1\username\desktop\gifsicle\gifsicle.exe).  I'm just outta time...:).

Hope this helps!
0
 
paulinewinAuthor Commented:
This is more than I expected. Thank you very much!  Could you provide a tutorial site I can practice on?
0
 
mjcoyneCommented:
"Could you provide a tutorial site I can practice on?"

I'm not sure what you mean...  A place to learn Perl?
0
 
paulinewinAuthor Commented:
Yes, please.
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

  • 8
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now