display pictures sorted by filename

Andreas Schleth schleth_es at web.de
Mon Feb 28 21:00:16 GMT 2022


Hi Georgios,

I had a similar problem with ~10k scanned images from color slides a few
years ago.
To deal with it I used the perl script attached here together with some
custom shell scripts to pack the commandlines for batches of images
together.
The script takes two images and two date-strings. It then tries to find
the number part of the image file names, calculates the number of images
in between and then sets exif and file dates at equal intervals between
the two dates. This allows for sorting in KPA and - if you take smaller
batches - to approximately time the images correctly. Not perfect but
good enough.

Here is a real use case (a simple shell script - just a sequence of
command lines):
"""
exif_date_range k140_01 4.2.6-14:00 k140_30 4.2.6-22:0
exif_date_range k140_31 10.2.6  k140_32
exif_date_range k140_33 15.3.6  k140_36 20.4.6
exif_date_range k140_37 27.4.6 k140_43
exif_date_range k140_44 28.4.6 k140_50
mv new/* .
rmdir new

"""
The images k140_01 to .._30 all were taken on Feb 4th 2006.

You might need to fiddle with the script to get the numbering detection
right.
Also you need the respective perl modules installed (the lines with "use
..."). They usually come with the packages of your distribution.

Happy tagging, Andreas


Am 28.02.22 um 21:15 schrieb g:
>
> Hi,
>
> I find myself needing to order scanned images in time and try to
> assign dates to them. The filenames themselves are reasonably sorted,
> i.e. when I list the filenames alphabetically they are also close to
> ordered in time. The problem is that the files themselves have mtimes
> that are practically randomly ordered and it looks to me that
> kphotoablum uses mtime as the sorting criterion in the absence of exif
> info etc.
> Is there a way for me to tell kphotoalbum to display the selected
> pictures ordered by filename? (For example we can say View|Show oldest
> first or show newest first. Could we not use other criteria for
> ordering selected images?).
>
> As an alternative I was thinking about a small script that would sort
> the files by name, and then assign/touch the mtime attribute,
> incrementing it by an hour or a day for each successive file. Am I
> overthinking this?
>
> A made-up example:
>
> I have   filename scan_19931020.tiff  with mtime 2022-01-22T101112
> and then          scan_19891101.tiff  with mtime 2022-02-22T103344
> and so on.
>
>
> Thank you.
>
> Georgios
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kphotoalbum/attachments/20220228/9f3d9a08/attachment.htm>
-------------- 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