[KPhotoAlbum] Plugins>Images>Adjust Time & Date

Andreas Schleth schleth_es at web.de
Fri Sep 6 20:15:02 BST 2019


Hi Neil & Joan,

I had a quick look at photini, which was new to me: this is an importer,
probably similar to the one digicam and some others are offering. Looks
interesting, although I do not change the default file names (yet).
Anyway, it is always interesting to find a new tool (thanks Joan!) to
add to the box of tricks.

For a large batch of slide scans (in my case I scanned around 10k slides
during a period of 18 months) photini is maybe not the best tool, as you
have to touch each image (or each group) by itself. If you touch a whole
group at once, several images might get the same date/time and you get
no sequence.

So, please find attached my skripting solution (bash/perl). These
scripts are based on the assumption, that all files have consecutive
numbers and some kind of prefix in the filename. Such as: "K034.jpg
K035.jpg ...".

For each folder with images you need to write a short shell script
("set") with the command lines to call the worker script
("exif_date_range"). You also could type in these commands ...

Using the script will set the time and date of most images to quite
arbitrary times of the day. However, in most cases you do not know the
exact date / time when the shot was taken. So, what counts (for me), is
the correct sequence of the images, when sorted by date. And the
approximate date.

Cheers, Andreas

-------------- next part --------------
exif_date_range k001_01 16.12.80	k001_05 19.12.80
exif_date_range k001_06 24.12.80 k001_10		
exif_date_range k001_11 24.1.81	k001_17 25.1.81
exif_date_range k001_18 1.2.81	k001_26 25.2.81
exif_date_range k001_27 8.4.81	k001_46 14.4.81
exif_date_range k001_47 15.4.81	k001_50 15.4.81-14:0
mv new/* .
rmdir new
-------------- next part --------------
#!/usr/bin/perl -w
#  Copyright (C) 2011-2019 Andreas Schleth
#
#  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.
#
use Image::ExifTool;
use Time::Local;        # - efficiently compute time from local and GMT time
#    $time = timelocal($sec,$min,$hour,$mday,$mon,$year);
use strict;
my $debug=3;
# date: jjjj:mm:dd hh:mm:ss
my $usage = "\nusage: exif_date_range [img1] [date1] [img2] [date2]\n".
    	    "\tdate: dd.mm.[yy]yy[-hh:mm] \n".
	    "Set all dates in all *.jpg-files in the given range equally spaced to dates in date range.\n".
	    "Also updates the file creation date.\nResultfiles are in subdirectory 'new'\n\n";
#
#  get parameters
#
my $img1 = shift || die $usage;
my $dat1 = shift || die $usage;
my $img2 = shift;
my $dat2 = shift;
my $nimg = 0;
my ($base,$field);
#  same day 
$dat2 = $dat1 unless($dat2);
#  1 pic
unless($img2) {
	$img1 =~ s/.jpg$//i;
	$img2 = $img1;
	$dat2 = $dat1;
	$nimg = 1;
} else {
	#
	#  find image range
	#
	my $len = length($img2) > length($img1) ? length($img2) : length($img1);
	if($debug) {
		print "Image 1, Date 1: $img1, $dat1\n";
		print "Image 2, Date 2: $img2, $dat2\n";
		print "Stringlength   : $len\n";
		die("Stop $debug\n") if($debug == 1);
	}
	my $i=0;
	while($i < $len && substr($img1,$i,1) eq substr($img2,$i,1)) {
		$i++;
	}
	#
	#  find number part
	# 
	$base = substr($img1,0,$i);
	print "Image base name: $base\n";
	$img1 =~ s/.jpg$//i;
	$img1 =~ s/^$base//i;
	$img2 =~ s/.jpg$//i;
	$img2 =~ s/^$base//i;
	$field = length($img1);
	print "numberfield $field\n";
	$img1 *= 1.;
	$img2 *= 1.;
	print "Number range: $img1 ... $img2\n";
	$nimg = $img2 - $img1 + 1;
}
#
#  prepare for exiftool attack
#
mkdir "new" unless(-d "new");
my $exifTool = new Image::ExifTool;
$exifTool->Options(Unknown => 1);
my @TAGS = qw(CreateDate DateTimeOriginal ModifyDate);
if($debug) {
	print "No of images: $nimg\n";
	die("Stop $debug\n") if($debug == 2);
}
#
#  Find date/time-range and doit, babe!
#
my ($date,$time1,$time2);
if($nimg > 1) {
	$time1 = &parse_timestring($dat1,1);
	$time2 = &parse_timestring($dat2,2);
	my $deltatime = ($time2 - $time1)/($nimg-1);
	my $dd = int($deltatime/(3600*24));
	my $dh = int(($deltatime - $dd*3600*24)/3600);
	my $dm = int(($deltatime - $dd*3600*24 - $dh*3600)/6)/10;
	print "Delta days: $dd  delta hours: $dh  delta minutes: $dm\n";
	my $dtime = -$deltatime;
	for(my $i=$img1; $i<=$img2; $i++) {
		$dtime += $deltatime;
		$date = &construct_time_date($time1 + $dtime);
		print "$base ... $i:\t$date\n";
		my $fn="$i";
		while(length($fn) < $field) {
			$fn = "0$fn";
		}
		#  simply try both variants
		my $fnc = $base.$fn.'.jpg';
		&change_date($fnc,$date) if(-f $fnc);	
		$fnc 	= $base.$fn.'.JPG';
		&change_date($fnc,$date) if(-f $fnc);	
	}
} else {
	$date = &construct_time_date( &parse_timestring($dat1,0) );
	#  simply try both variants
	my $fn 	= $img1.'.jpg';
	&change_date($fn,$date) if(-f $fn);	
	$fn 	= $img1.'.JPG';
	&change_date($fn,$date) if(-f $fn);	
}

sub construct_time_date {
#
#  return a meaningful time-date-string from time value (1 parameter)
#
	my $time = shift || return "-0-";
	#  0    1    2     3     4    5     6     7     8
        my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time);
	##print "# $i :: ",join("-",($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)),"\n";
	$sec = "00$sec";
	$sec =~ s/.*(..)$/$1/;
	$min = "00$min";
	$min =~ s/.*(..)$/$1/;
	$hour= "00$hour";
	$hour=~ s/.*(..)$/$1/;
	$mday= "00$mday";
	$mday=~ s/.*(..)$/$1/;
	$mon++;
	$mon = "00$mon";
	$mon =~ s/.*(..)$/$1/;
	$year += 1900;
	return "$year:$mon:$mday $hour:$min:$sec";
}

sub parse_timestring {
#
#  split date-input into meaningful bits and produce time value
#
#  parameters:
#	1.	date-string
#	2.	0 || 1 || 2 = only || begin || end of period
#
	my $dat = shift || return 0;
	my $period = shift;
	my ($ddat,$tdat) = split(/-/,$dat);
	my ($h,$i)=(12,0);
	if($period) {
		if($period == 1) {
			($h,$i)=(0,1);
		} else {
			($h,$i)=(23,59);
		}
	}
	($h,$i) = split(/:/,$tdat) if($tdat);
	my ($d,$m,$y) = split(/\./,$ddat);
	return timelocal(0,$i,$h,$d,$m-1,$y);
}

sub change_date {
#
#  change date settings to a certain date
#
#  parameters:
#	1.	$src  = filename of image
#	2.	$date = new date
#
	my $src = shift || return 0;
		print "... $src ..."; 
  	my $date = shift || return 0;
  	$src =~ s/\ /\\ /g;
  	my $no = 0;
	foreach my $t (@TAGS) {
 		unless($exifTool->SetNewValue($t, $date)) {
    			print "   setting for $t failed!\n";
	            	$no = 1;
        	}
  	}
  	unless ($no) {
     		my $f = "new/$src";
		if(-f $f) {
			print "  overwrite!!";
			unlink($f);
		}
     		if($exifTool->WriteInfo($src,$f)) {
		        print "   successfully rewritten!\n";
			my $s = `exiftool -DateTimeOriginal -d %Y%m%d%H%M.%S $f`;
			chomp $s;
			my $t = `exiftool -DateTimeOriginal -d %Y $f`;
			chomp $t;
			$t =~ s/^.*:\s//;
			if($t < 1970) {
				print STDERR "date prior to epoch ($f)\n";
				$s = "197001011200.00";
			} 
			$s =~ s/^.*:\s*//;
			`touch -t $s $f`;
			print "$f:\t$s\n\t",`ls -l $f`;
     		} else {
			print "   rewrite failed\n";
		}
  	}
}


More information about the Kphotoalbum mailing list