package Imager::Album; use strict; use Storable (); # Avoid imports use File::Basename; use File::Spec; use vars qw($VERSION @suf); @suf = qw( jpeg jpg tiff tif gif png ppm pgm pbm png ); $VERSION = '0.06'; # # Methods # sub new { my $class = shift; my %opts = @_; my $self = {}; bless $self,$class; $self->{'preview_opts'} = {xpixels => 100, qtype=>'preview'}; $self->{'commands'} = [ ['Rotate cw', \&rotate_image_cw], ['Rotate ccw', \&rotate_image_ccw], ['Export', sub { shift; $self->{'gui'}->export_gallery(@_); } ], ['Captions', sub { shift; $self->{'gui'}->label(@_); } ], ['Store', sub { shift; $self->store(); }], ['Remove', sub { shift; $self->{'gui'}->remove_images(@_); }], ['Quit', sub { shift; $self->{'gui'}->shutdown(); }], ]; my $dir = exists $opts{'working_dir'} ? $opts{'working_dir'} : undef; $self->set_working_dir($dir); $self->{'seq'} = 1; if (-f $self->{'dir'}."/store") { $self->{'images'} = Storable::retrieve($self->{'dir'}."/store"); $self->{'ordering'} = Storable::retrieve($self->{'dir'}."/ordering"); # $self->{'ordering'} = [keys %{$self->{images}}]; print "@{$self->{ordering}}\n"; for (keys %{$self->{'images'}}) { $self->{'seq'}=$_+1 if $_ >= $self->{'seq'}; } } else { $self->{'images'} = {}; $self->{'orering'} = []; } return $self; } sub store { my $self = shift; my %imcopy = %{$self->{'images'}}; for (keys %imcopy) { delete $imcopy{$_}->{'gdk_preview'}; } Storable::nstore(\%imcopy, $self->{'dir'}."/store"); Storable::nstore($self->{'ordering'}, $self->{'dir'}."/ordering"); print "stored current status in directory: ".$self->{'dir'}."\n"; } sub set_working_dir { my $self = shift; my $base = shift || $ENV{HOME}."/.Imager__Album_$$"; if (!-d $base) { mkdir($base,0777) or die "Couldn't create working dir '$base': $!\n"; } if (!-d "$base/preview") { mkdir("$base/preview",0777) or die "Couldn't create working dir '$base/preview': $!\n"; } $self->{'dir'} = $base; } sub add_image { my $self = shift; my $fname = shift; my $num = $self->{'seq'}++; my ($name, $path, $suffix) = fileparse($fname, @suf); my %hash; return undef unless -f $fname; $hash{path} = $fname; $hash{name} = $name; $hash{caption} = $name; $hash{rotated} = 0; $hash{valid} = 0; push(@{$self->{'ordering'}}, $num); $self->{'images'}->{$num} = \%hash; } sub get_image { my ($self, $imageno) = @_; return $self->{'images'}->{$imageno}; } sub get_preview_path { my ($self, $imageno) = @_; my $path = File::Spec->catfile($self->{'dir'}, 'preview', $imageno.".png"); return $path; } # Find which images need to have previews # updated and call update_preview on those. sub update_previews { my $self = shift; my %images = %{$self->{'images'}}; my @process = grep { !$images{$_}->{valid} } keys %images; my $imageno; my $c = 1; for $imageno (@process) { print "Updating preview $c/".@process."\n"; $c++; $self->update_preview($imageno); } } # Update an images preview file sub update_preview { my $self = shift; my $imageno = shift; my %opts = %{$self->{'preview_opts'}}; my $image = $self->{'images'}->{$imageno}; my $file = $image->{'path'}; my $img = Imager->new(); if (!$img->read(file=>$file)) { print "ERROR $file: ".$img->errstr; return (); } my $prev = $img->scale(%opts); if ($image->{'rotated'}) { $prev = $prev->rotate(degrees=>$image->{'rotated'}*90); } my $dir = $self->{'dir'}; $prev->write(file=>"$dir/preview/$imageno.png") or die $!; $image->{'valid'} = 1; } sub rotate_image_cw { my ($self, @imagenos) = @_; my @images = map { $self->{'images'}->{$_} } @imagenos; for (@images) { $_->{'rotated'}++; $_->{'valid'} = 0; } } sub rotate_image_ccw { my ($self, @imagenos) = @_; my @images = map { $self->{'images'}->{$_} } @imagenos; for (@images) { $_->{'rotated'}--; $_->{'valid'} = 0; } } sub change_order { my ($self, $from, $to) = @_; my $aref = $self->{'ordering'}; my $tmp = splice(@{$aref}, $from, 1); splice(@{$aref}, $to, 0, $tmp); } # Give ids sub remove_images { my ($self, @imagenos) = @_; delete $self->{'images'}->{$_} for @imagenos; my $imageno; for $imageno (@imagenos) { my @order = @{$self->{'ordering'}}; for (0..@order-1) { if ($imageno == $order[$_]) { splice(@{$self->{'ordering'}}, $_, 1); } } @order = @{$self->{'ordering'}}; } } sub export { my ($self, $destdir, $albumname) = @_; my @images = @{$self->{'ordering'}}; print "Exporting images: @images\n"; my %opts1 = (xpixels => 688, ypixels => 688, type=>'min'); my %opts2 = (xpixels => 200, ypixels => 200, type=>'min'); mkdir($destdir, 0777) or die "$!\n"; my $imageno; my $cnt = 0; for $imageno (@images) { print "Processing image $cnt/".@images."\n"; $cnt++; my $ihash = $self->{'images'}->{$imageno}; my $img = Imager->new(); $img->read(file=>$ihash->{'path'}) or die $img->errstr; my %sopts1 = %opts1; my %sopts2 = %opts2; if ($ihash->{'rotated'} % 2) { my $t = $sopts1{'xpixels'}; $sopts1{'xpixels'} = $sopts1{'ypixels'}; $sopts1{'ypixels'} = $t; $t = $sopts2{'xpixels'}; $sopts2{'xpixels'} = $sopts2{'ypixels'}; $sopts2{'ypixels'} = $t; } $img = $img->scale(%sopts1); if ($ihash->{'rotated'}) { $img = $img->rotate(degrees=>$ihash->{'rotated'}*90); } $img->write(file=>"$destdir/$imageno.jpg") or die $img->errstr; $img = $img->scale(%sopts2); $img->write(file=>"$destdir/${imageno}_h.jpg") or die $img->errstr; } local *FHIDX; open(FHIDX, ">$destdir/index.html") or die "Cannot open >$destdir/index.html : $!\n"; print FHIDX "