#!/usr/bin/perl # Mass Rotate - Gtk2-perl program to losslessly rotate JPEGs en masse # Version 0.1 # Copyright 2003-2004 John Thompson , # Alexy Khrabrov # This program 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 of the License, or # (at your option) any later version. # # This program 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Changelog # # 0.1 - Initial version # 0.2 - Icons use strict; use Gtk2 -init; ### Stuff you might need to edit: # Name / location of jpegtran. my $jpegtran = "jpegtran"; # Scale images down so they're no bigger than this resolution. # Affects display only, doesn't rescale images on disk. my ($maxw,$maxh) = (800,600); ### Shouldn't need to edit anything below here my @images; if (@ARGV[0] eq '-f') { use File::Find; find({ wanted => \&wanted , no_chdir => 1}, '.'); sub wanted { if (-f && /.jpe?g/i) { push (@images,$_); } } @images = sort @images; } else { @images = @ARGV; } die "No images specified, or none found. Use -f to search.\n" unless scalar(@images); my $imnum = 0; my ($m,$rotdeg,$pixbuf,$spixbuf); # create widgets my $window = Gtk2::Window->new ( "toplevel" ); my $image; my $prevbut = Gtk2::Button->new(); $image = Gtk2::Image->new_from_stock ('gtk-go-back', 'button'); $prevbut->add ($image); my $nextbut = Gtk2::Button->new; $image = Gtk2::Image->new_from_stock ('gtk-go-forward', 'button'); $nextbut->add ($image); my $quitbut = Gtk2::Button->new; $image = Gtk2::Image->new_from_stock ('gtk-quit', 'button'); $quitbut->add ($image); my $savebut = Gtk2::Button->new; $image = Gtk2::Image->new_from_stock ('gtk-save', 'button'); $savebut->add ($image); my $rotlbut = Gtk2::Button->new; $image = Gtk2::Image->new_from_stock ('gtk-undo', 'button'); $rotlbut->add ($image); my $rotrbut = Gtk2::Button->new; $image = Gtk2::Image->new_from_stock ('gtk-redo', 'button'); $rotrbut->add ($image); my $imgbox = Gtk2::Frame->new; my $image = Gtk2::Image->new; my $hbox = Gtk2::HBox->new (1,1); my $vbox = Gtk2::VBox->new (0,1); $imgbox->add ($image); # Show image, etc. render_image(); # callback registration $window->signal_connect( "delete_event", \&quit ); $quitbut->signal_connect( "clicked", \&quit ); $nextbut->signal_connect( "clicked", \&next_pic); $prevbut->signal_connect( "clicked", \&prev_pic); $savebut->signal_connect( "clicked", \&save_pic); $rotlbut->signal_connect( "clicked", \&rot_left); $rotrbut->signal_connect( "clicked", \&rot_right); # set window attributes and show it $hbox->pack_start($prevbut,1,1,0); $hbox->pack_start($nextbut,1,1,0); $hbox->pack_start($rotlbut,1,1,0); $hbox->pack_start($rotrbut,1,1,0); $hbox->pack_start($savebut,1,1,0); $hbox->pack_start($quitbut,1,1,0); $vbox->pack_start($hbox,0,0,0); $vbox->pack_start($imgbox,0,0,0); $window->add($vbox); $window->show_all(); # Gtk2 event loop Gtk2->main; # Shouldn't ever get here exit(0); sub quit { del_temp(); Gtk2->main_quit; return undef; } sub render_image { my $iname = $images[$imnum]; if ($rotdeg != 0) { $iname .= ".mrtmp.$rotdeg"; } eval { $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($iname) }; if ($@) { my $parent = shift; my $dialog = Gtk2::MessageDialog->new ($parent, 'destroy-with-parent', 'error', 'close', "Error loading $iname - $@"); $dialog->signal_connect (response => sub { $_[0]->destroy; }); $dialog->show; return; } my $wid = $pixbuf->get_width; my $hei = $pixbuf->get_height; if ($wid > $maxw) { my $t = ($wid / $maxw); $wid = $wid / $t; $hei = $hei / $t; } if ($hei > $maxh) { my $t = ($hei / $maxh); $wid = $wid / $t; $hei = $hei / $t; } $spixbuf = $pixbuf->scale_simple($wid,$hei,'bilinear'); $image->set_from_pixbuf ($spixbuf); $window->set_title("$iname"); } sub next_pic { del_temp(); $imnum++; if ($imnum > (scalar(@images) - 1)) { $imnum = 0; } render_image(); } sub prev_pic { del_temp(); $imnum--; if ($imnum < 0) { $imnum = scalar(@images) - 1; } render_image(); } sub del_temp { $rotdeg = 0; for my $i (90,180,270) { my $t = "$images[$imnum].mrtmp.$i"; if (-f $t) { unlink $t or die "unable to delete $t - $!\n"; } } } sub rot_left { $rotdeg -= 90; if ($rotdeg < 0) { $rotdeg = 270; } rotate() unless ($rotdeg == 0); render_image(); } sub rot_right { $rotdeg += 90; if ($rotdeg > 359) { $rotdeg = 0; } rotate() unless ($rotdeg == 0); render_image(); } sub save_pic { rename($images[$imnum] . ".mrtmp.$rotdeg",$images[$imnum]); del_temp(); } sub rotate { my $of = $images[$imnum] . ".mrtmp.$rotdeg"; return if (-f $of); system($jpegtran,"-outfile",$of,"-rotate",$rotdeg,$images[$imnum]); }