#!/usr/bin/perl
#
# exifmunge: manipulate exif metadata inside a jpeg file
#
# Gerald Oskoboiny, 16 Feb 2002
#
# I wrote this because I kept forgetting to rotate images in my camera
# before downloading them, and wanted to change the EXIF orientation
# info stored in the file.
#
# bugs:
# - assumes orientation is stored in byte 55 of the file
#
# source: http://impressive.net/software/photo/source/exifmunge
#
# $Id: exifmunge,v 1.3 2002/08/08 03:58:03 gerald Exp $
#

use strict;

my %opt;		# global hash to keep track of command line options
my $debuggin = 0;

# parse command line arguments
my @files = &parse_args( \%opt, \@ARGV );

# @@ way inefficient; rewrite
foreach my $file (@files) {
    if ( $opt{set_orientation} ) {
	&set_orientation($file, $opt{orientation});
    }
}

exit;


###########################################################################
sub parse_args {
# parse command line arguments
# @@ should use Getopt::Long instead of parsing args manually

    my ($opt_ref,$args_ref) = @_;
    my $opt = %$opt_ref;		# deref
    my @args = @$args_ref;		# deref
    my @files;

    &print_usage unless $args[0] =~ /^-/;	# first arg must be an option

    while (my $arg = shift @args) {
	if (( $arg eq "--orientation" ) || ( $arg eq "-o" )) {
	    $opt{set_orientation} = 1;
	    $opt{orientation} = shift @args;
	    if ( ! length $opt{orientation} ) {
		print STDERR "ignoring --orientation; no orientation specified!?";
		$opt{set_orientation} = 0;
	    }
	}
	elsif ( $arg =~ /^-/ ) {		# unknown option specified?
	    &print_usage;
	}
	else {
	    my $file = $arg;
	    if ( ! -f $file ) {
		print "skipping $arg because $file is not a file\n"
		    if $debuggin;
		next;
	    }
	    push( @files, $file );		# add this file to the list
	}
    }
    return @files;
}

sub print_usage {

    print STDERR "\nusage: $0 --orientation {n} file1 file2 ...\n\n";
    exit -1;

}

sub set_orientation {

    my($file,$orientation) = @_;
    my $oldfile = $file . ".old";
    my $buf;				# buffer to hold bits of $file

    rename( $file, $oldfile );

    open( NEW, "> $file" ) or die "error creating new file $file: $!";
    open( OLD, "< $oldfile" ) or die "error reading from old file $file: $!";

    $buf = join('',(<OLD>));		# read whole file into $buf
    # way inefficient; should use seek/read/write etc instead

    close( OLD ) or die "error closing old file $oldfile: $!";

    my $old_o = substr( $buf, 54, 1 );
    print "old orientation was: ", ord($old_o), "\n";

    print "setting orientation to: ", $orientation, "\n";
    substr( $buf, 54, 1 ) = chr($orientation);

    print NEW $buf;

    close( NEW ) or die "error closing new file $file: $!";

    return;

}

