Thursday, July 27, 2006

Sort digital images.

Last time I posted, I was whining about some guy posting a private TiVo demo on youtube,com. I feel bad about that, and if you read this, I am really sorry!

One of the many reasons for me regretting that post has to do with me asking myself what I really do contribute to people making MythTV boxes out there. In the last couple of months, this has not been much. So, here is something that I find really heplful:

I have a digital camera, a Canon A70. Like all digital cameras, it does both images and videos. Images are easy to handle since there are standard EXIF tags that you can extract and use when, for instance, you would like to sort your images by date and time when they were taken. There is even an excellent program called JHEAD that enables you to rename your files by the EXIF tags. So, an image taken at 12:45:23 on the 15 of November 2002 may easilly be renamed to 2002-11-15_12:45:23.jpg. Neat for sorting and you will never overwrite images because they are called the same.

Movies, however, are different. AFAICT, there is no standard for this information. Also, there are no tools that I have found that lets you rename AVI files created in the same format as the JPEG files discussed above. So, a while back, I created one! :-) It uses mplayer for information extraction, and will probably only work with Canon cameras (or just the A70 camera, I don't know), however, it is easilly adaptable to other cameras that provides this information in the AVI header. Here is the script:
(PLEASE NOTE I TAKE NO RESPONSIBILITY FOR THIS SCRIPT OR ANY DAMAGE DONE BY IT. USE IT AT YOUR OWN RISK! YOU HAVE BEEN WARNED!)


#!/usr/bin/perl

use strict;
use warnings;

package main;
#This is the line you may have to change in order to extract the correct information from
#other cameras
my $inpattern = 'Digitization Time: (\w\w\w) (\w\w\w) (\d\d) (\d\d:\d\d:\d\d) (\d\d\d\d)';

my %months = ( 'Jan' => '01',
'Feb' => '02',
'Mar' => '03',
'Apr' => '04',
'May' => '05',
'Jun' => '06',
'Jul' => '07',
'Aug' => '08',
'Sep' => '09',
'Oct' => '10',
'Nov' => '11',
'Dec' => '12');

my $file;
my $prefix;
my $output;


my $nofiles = $#ARGV;

foreach $file ( @ARGV ) {

$output='';
$prefix = '';

if($nofiles > 0){

$output .= $file." ";
}
open IN, "mplayer -vo null -novideo -nosound -v 1 $file 2>&1 |" or die "Error: $!";

while(){
m/$inpattern/ and $output .= "$5-$months{$2}-$3_$4\n";

}

print $output;

}

1;





This script will provide you with the date and time info in a YYYY-MM-DD_hh:mm:ss format. If you supply the name of more than one files, the name of the file will be given first on every line and the date second.

Ok, what do we do with this script? You may do whatever you like, but I use it for sorting images and videos ;-) This is my soluton to the sorting problem:
(PLEASE NOTE I TAKE NO RESPONSIBILITY FOR THIS SCRIPT OR ANY DAMAGE DONE BY IT. USE IT AT YOUR OWN RISK! YOU HAVE BEEN WARNED!)


#!/usr/bin/perl

use strict;
use warnings;




#jhead -n%Y-%m-%d_%H:%M:%S *.jpg

package main;

my $JHEAD = '/usr/bin/jhead';
my $AVIDIGITIME = '/home/zak/src/perl/avidigtime/avidigtime.pl';

#my $dir = '/home/zak/temp/test';
my $dir = '';
if( length(@ARGV) > 0){

$dir = $ARGV[0];
} else {
print length(@ARGV);
print STDERR "Usage: albumsort.pl directory\n";
exit(1);
}

open IN, " (find $dir -name \"*.jpg\" ; find $dir -name \"*.JPG\")|sort|" or die "Find JPG: $!";

my $file = '';
my $debug = '';

while(){

chomp;
$file = $_;
system("$JHEAD -exonly -n%Y-%m-%d_%H:%M:%S $file") ;



}
close IN;


open IN, " (find $dir -name \"*.avi\" ; find $dir -name \"*.AVI\")|sort|xargs $AVIDIGITIME|" or die "Find avi: $!";

$file = '';
my @outputdir;
my $outdir;
my @div;
my $infile;
my $outfile;

while(){

chomp;
$file = $_;
@div = split;
$infile = shift(@div);
$outfile = shift(@div);
#Skapa namnet på utfilen
@outputdir = split(/\//,$file);

my $temp = pop(@outputdir);
$outdir = join("/",@outputdir);

system("mv $infile $outdir/$outfile.avi && echo \"$infile --> $outdir/$outfile.avi\"" ) ;



}
close IN;

#SORT IMAGES AND MOVIES
open IN, " (find $dir -name \"*.jpg\" ; find $dir -name \"*.avi\")|" or die "File sort: $!";

while(){

chomp;

if( m/.*(\d\d\d\d-\d\d-\d\d)_\d\d:\d\d:\d\d.*/ ){

my $date = $1;
-e $dir.'/'.$date or mkdir $dir.'/'.$date;
system("mv $_ $dir/$date/ 2>&1 > /dev/null");
}
}

close IN;

#Remove empty libraries

system("find $dir -maxdepth 1 -mindepth 1 -type d |egrep -v \'.*/....-..-..\$\'| xargs rm -R ");

1;








You use it by running "albumsort.pl directory". It will sort everything in that directory into sub-directories named by the YYYY-MM-DD format, and remove sub-directories that does not match that pattern. Please note that it will acctually rename, move and remove files, so BE SURE YOU ARE WORKING WITH A COPY OF YOUR IMAGES!

Enjoy!

0 Comments:

Post a Comment

<< Home