Il suffit de lancer ce script depuis le répertoire gal de SPGM.

S'il y a besoin de modifier les paramètres de configuration pour un répertoire donné et ses sous-répertoires, il est possible de le faire dans un fichier appelé .conf dans le répertoire en question (voir tout en bas). Ça ne fonctionne que pour des scalaires, pas pour des tableaux; donc c'est pas possible de modifier les différentes tailles, par exemple... sauf si quelqu'un me file un patch :-p.

create_thb.pl

#! /usr/bin/perl
#
# by Julien Wajsberg <flash@minet.net>
#
# January 2005
# GPLv2

use strict;
use warnings;

use Image::Magick;
use Image::EXIF;
use File::Find ();

#### conf ####

my $default_conf = {
	thumbnail_prefix =>  "_thb_",
	internal_pattern => qr/^_/,
	thumbnail_geometry_landscape => "160x120",
	thumbnail_geometry_portrait => "160x120",
	resizes_landscape => [ qw/800x600 1024x768/ ],
	resizes_portrait => [ qw/600x800 768x1024/ ],
	quality => 80,
};

my $conf_filename = ".conf";

my $conf = $default_conf;

##############

my @transprogram = qw/exiftran -ai/;

$| = 1;
my $image = new Image::Magick;

# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

sub wanted;

File::Find::find({
	wanted => \&wanted,
	preprocess => \&preprocess,
	postprocess => \&postprocess,
	}, '.');
exit;

##############################
#
# "wanted" function for "find"
# 
sub wanted {
    doaction($_) unless -d;
}

###############################
#
# "preprocess" function for "find"
#
sub preprocess {
	print "*** Entering $File::Find::dir\n";

	# read config file for this directory
	if (-r $conf_filename) {
		open CONF, $conf_filename;
		while (<CONF>) {
			my ($key, $value) = /^\s*(\w+)\s*=\s*(\w+)$/;
			next unless $key and $value;
			$conf->{$key} = $value;
		}
		close CONF;
	}

	my @entries;

	while ($_ = shift) {
		next if /$conf->{internal_pattern}/;
		push @entries, $_ if /^.*\.jpg\z/is;
		push @entries, $_ if -d;
	}

	return @entries;
}

###############################
#
# "postprocess" function for "find"
#
sub postprocess {
	# reset conf
	$conf = $default_conf;
}

###################################
#
# this function is called by wanted
# 
# 1st arg : shortname of the file
# 
sub doaction($) {
	my $shortname = shift;
	my $x;
	my $thumbnail = $conf->{thumbnail_prefix} . $shortname;
	my $resizes;
	my $thumbnail_geometry;

	print $shortname, " :\n";

	# rotating if necessary
	if (need_rotation($shortname)) {
		print "  rotating";
		$x = dorotate($shortname);
		if ($x) {
			warn " : $x" if $x;
			print "  -> something strange happened, let's skip this file !\n";
			return;
		}
		print ".\n";
	} else {
		print "  already correctly oriented.\n";
	}

	# pinging the file, to get the dimensions
	my ($width, $height) = $image->Ping($shortname);

	# orientation : landscape or portrait
	if ($width < $height) {
		$resizes = $conf->{resizes_portrait};
		$thumbnail_geometry = $conf->{thumbnail_geometry_portrait};
	} else {
		$resizes = $conf->{resizes_landscape};
		$thumbnail_geometry = $conf->{thumbnail_geometry_landscape};
	}

	if (all_resizes_done($shortname, $resizes)) {
		print "  nothing left to do.\n";
		return;
	}
	
	# reading the file
	print "  reading";
	$x = $image->Read($shortname);
	if (defined $x and "$x") {
		warn " : $x";
		print "  -> something strange happened, let's skip this file !\n";
		return;
	}
	print ".\n";

	# thumbnail generation
	my $clone = $image->Clone();
	if (! ref $clone) {
		warn " : $clone";
		print "  -> something strange happened, let's skip this file !\n";
		return;
	}

	print '  thumbnail : resizing to ', $thumbnail_geometry;
	$x = doresize($clone, $thumbnail_geometry, $thumbnail);
	if (defined $x and "$x") {
		warn " : $x";
		print "  -> something strange happened, let's skip this file !\n";
		return;
	}
	
	# various geometries generations
	foreach my $geometry (@$resizes) {
		my $clone = $image->Clone();
		my $outputfile = '_' . $geometry . '_' . $shortname;
		print "  resizing to $geometry";

		$x = doresize($clone, $geometry, $outputfile);
		if (defined $x and "$x") {
			warn " : $x";
			print "  -> something strange happened, let's skip this file !\n";
			return;
		}
	}

	@$image = ();
}

#############################################
#
# resizes an image
# 
# 1st arg : imagemagick object
# 2nd arg : destination geometry
# 3rd arg : name of the file to write
# returns an error string if an error happens
# 
sub doresize($$$) {
	my ($image, $geometry, $outputfile) = @_;
	
	do { print " -> $outputfile already exists.\n"; return; } if (-f $outputfile);
	my ($destwidth, $destheight) = split /x/, $geometry;
	do { print " -> original image too small.\n"; return; }
		unless ($image->Get('width') > $destwidth or $image->Get('height') > $destheight);

	my $x = $image->Resize(geometry => $geometry);
	return "$x" if (defined $x and "$x");

	print ", writing file $outputfile";
	$x = $image->Write(filename => $outputfile, quality => $conf->{quality});
	return "$x" if (defined $x and "$x");
	print ".\n";
	return;
}

#################################################
#
# losslessly rotates an image using @transprogram
# 
# 1st arg : image filename
# 
sub dorotate($) {
	my $filename = shift;

	system "@transprogram $filename 1> /dev/null 2>&1";
	
	if ($? == -1) {
		return "failed to execute: $!";
	} elsif ($? & 127) {
		return sprintf ("child died with signal %d, %s coredump\n",
			   ($? & 127),  ($? & 128) ? 'with' : 'without');
	} else {
		my $value = $? >> 8;
		return "child exited with value $value" if ($value);
	}
	return;
}

#################################################
#
# looks for already existing resized files
#
# 1st arg : image filename
# 2nd arg : resizes array
#
sub all_resizes_done ($$) {
	my ($name, $resizes) = @_;

	# looking for the thumbnail
	my $thumbnail = $conf->{thumbnail_prefix} . $name;
	return 0 if ( ! -f $thumbnail);

	# looking for other versions
	foreach my $geometry (@$resizes) {
		my $version = '_' . $geometry . '_' . $name;
		return 0 if ( ! -f $version);
	}

	return 1;
}

#################################################
#
# returns true if the filename need to be rotated
#
# 1st arg : image filename
#
sub need_rotation ($) {
	my $filename = shift;
	my $exif = new Image::EXIF($filename);
	
	my $info = $exif->get_image_info();
	return 0 if  or ($info->{'Image Orientation'} eq 'Top, Left-Hand'));
	return 1;
}

Exemple de fichier .conf utilisé pour La Sélection

thumbnail_geometry_portrait = 384x512
thumbnail_geometry_landscape = 640x480
quality = 90