Solved

Manipulating gifsicle

Posted on 2006-07-02
15
536 Views
Last Modified: 2008-02-01
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
Comment
Question by:paulinewin
  • 8
  • 6
15 Comments
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 17028092
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
 

Author Comment

by:paulinewin
ID: 17031806
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
 
LVL 17

Expert Comment

by:mjcoyne
ID: 17039858
gifsicle.exe is not being called anywhere in your system call:

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

Author Comment

by:paulinewin
ID: 17044851
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
 
LVL 17

Expert Comment

by:mjcoyne
ID: 17046860
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
 

Author Comment

by:paulinewin
ID: 17047114
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
 
LVL 17

Expert Comment

by:mjcoyne
ID: 17047996
Does it work from the command line with something like:

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

?
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:paulinewin
ID: 17048157
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
 

Author Comment

by:paulinewin
ID: 17048201
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
 
LVL 17

Expert Comment

by:mjcoyne
ID: 17050733
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
 

Author Comment

by:paulinewin
ID: 17051583
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
 
LVL 17

Accepted Solution

by:
mjcoyne earned 500 total points
ID: 17054819
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
 

Author Comment

by:paulinewin
ID: 17055275
This is more than I expected. Thank you very much!  Could you provide a tutorial site I can practice on?
0
 
LVL 17

Expert Comment

by:mjcoyne
ID: 17056026
"Could you provide a tutorial site I can practice on?"

I'm not sure what you mean...  A place to learn Perl?
0
 

Author Comment

by:paulinewin
ID: 17056227
Yes, please.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
MySQL Web Database 5 107
Perl 101 11 68
Having a problem with ActiveState Perl on 64-bit Windows 7 3 61
Exchange 2010 Transport Rule Regex 28 88
I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now