#!/usr/bin/perl # # # # Generate Google Maps XML from GPS tagged JPG # # Mike Whitton # 6/6/06 # # # # Part of this work was inspired by Tim Vidas (http://www.iceburnslair.com/mapper/) # # use Image::ExifTool; use File::Basename; use Date::Manip qw(ParseDate UnixDate DateCalc); use Image::Magick; use File::Copy; use Math::Trig; $xmlfile = "./marker1.xml"; open(XML,">$xmlfile"); print XML "\n"; $imageloc = '/home/user/pics'; $webpicbase = '/usr/apache/htdocs/new/pics'; $halfpi = (atan2(1,1) * 4)/180; $r = 6378; #radius of earth in kilometers %tabstore = (); $tabid = 1; $mintabdist = 0.019; # tabbed within 19m open(PICS,"find $imageloc -iname '*jpg' -type f|grep -v thumb|"); while () { my $lat; my $lng; my $latref = 1; my $lngref = 1; my $deg; my $min; my $sec; my $date; my $epochdate; my $garbage; my $nogps = 0; my $realdate; my $orien; my $buff; my $rotatepic = 0; my $rotatedeg; my $filename = $_; my $exifhan = new Image::ExifTool; $exifhan->Options(Binary => 1, IgnoreMinorErrors => 1); my $exif = $exifhan->ImageInfo($filename,'GPSAltitude','GPSLongitude','GPSLatitude','GPSDateTime','GPSAltitude','GPSDateStamp','GPSTimeStamp','GPSSatellites','ThumbnailLength','ThumbnailOffset','GPSLatitudeRef','GPSLongitudeRef','LensID','FocalLength','Lens','ISOSetting','ExposureTime','FNumber','ExifImageWidth','ExifImageLength','ImageSize','Orientation'); if ($$exif{'GPSSatellites'} < 1) { print "\n\nNo GPS Data in $filename \n"; $nogps = 1; } if ($nogps != 1) { my ($base,$path,$type) = fileparse($filename,'\..*'); my $thumbbase = $path . $base; if ($$exif{'GPSLatitudeRef'} eq "South") { $latref = -1; } ($deg,$garbage,$min,$sec)=split(/ /,$$exif{'GPSLatitude'}); $$exif{'GPSLatitude'} = sprintf("%.4f",$latref * ($deg + $min/60 + $sec/3600)); if ($$exif{'GPSLongitudeRef'} eq "West") { $lngref = -1; } ($deg,$garbage,$min,$sec)=split(/ /,$$exif{'GPSLongitude'}); $$exif{'GPSLongitude'} = sprintf("%.4f",$lngref * ($deg + $min/60 + $sec/3600)); my $tzfind = `./tzfind.pl -lat=$$exif{'GPSLatitude'} -lon=$$exif{'GPSLongitude'}`; my ($distance, $gmtoffset, $tzname) = split(/ /,$tzfind); $tabstore{$filename}{'latdec'} = $$exif{'GPSLatitude'}; $tabstore{$filename}{'londec'} = $$exif{'GPSLongitude'}; $tabupdate = 0; $smallerexists = 0; $smalldist = 10000; foreach (keys %tabstore) { my $newtabid = $tabid; if ($filename eq $_) { if (!$tabstore{$filename}{'tabid'}) { $tabstore{$filename}{'tabid'} = $newtabid; } $tabupdate = 1; next; } my $sourcelat = $tabstore{$_}{'latdec'}; my $sourcelon = $tabstore{$_}{'londec'}; my $curlat = $tabstore{$filename}{'latdec'}; my $curlon = $tabstore{$filename}{'londec'}; my $dist = &dist_find($sourcelat, $sourcelon, $curlat, $curlon, $halfpi, $r); if ($dist < $smalldist) { $smalldist = $dist; $smallerexists = 0; $smalltabfilename = $_; } if ($smalldist < $mintabdist && $smallerexists != 1) { $tabstore{$filename}{'tabid'} = $tabstore{$smalltabfilename}{'tabid'}; $smallerexists = 1; } elsif ($smallerexists != 1) { $tabstore{$filename}{'tabid'} = $newtabid++; } } if ($smallerexists != 1 && $tabupdate == 1) { $tabid++; } $$exif{'GPSDateStamp'} =~ s/:/\//ig; my ($hour, $minute, $second) = split(/:/,$$exif{'GPSTimeStamp'}); if (length($hour) == 1) { $hour = "0" . $hour; } if (length($minute) == 1) { $minute = "0" . $minute; } if (length($second) == 1) { $second = "0" . $second; } $$exif{'GPSTimeStamp'} = $hour . ":" . $minute . ":" . $second; my $predate = $$exif{'GPSTimeStamp'} . ", " . $$exif{'GPSDateStamp'}; $date = ParseDate($predate); $epochdate = &UnixDate($date,"%s") + $gmtoffset; $realdate = &DateCalc("Jan 1, 1970 00:00:00 GMT",$epochdate); $realdate = &UnixDate($realdate, "%i:%M%p on %A, %B %E, %Y"); $horzval = "Horizontal (normal)"; my ($exiforien, $exifdeg) = split(/ /,$$exif{'Orientation'}); if ($exiforien eq "Horizontal") { $orien = "Horizontal"; } else { $orien = "Vertical"; $rotatepic = 1; $rotatedeg = $exifdeg; } my $thumbfile = $thumbbase . "-thumb.jpg"; open(THUMBREAD, $filename); open(THUMBWRITE, ">$thumbfile"); binmode(THUMBREAD); binmode(THUMBWRITE); seek(THUMBREAD, $$exif{'ThumbnailOffset'}, 0); read(THUMBREAD, $buff, $$exif{'ThumbnailLength'}); print THUMBWRITE $buff; close(THUMBREAD); close(THUMBWRITE); $pcfilename = $filename; chomp($filename); if ($rotatepic == 1) { my $image = Image::Magick->new; $image->Read($thumbfile); $image->Rotate(degrees=>$rotatedeg); $image->Write($thumbfile); my $imagebig = Image::Magick->new; $imagebig->Read($filename); $imagebig->Rotate(degrees=>$rotatedeg); $imagebig->Write($filename); $exifhan->SetNewValue(Orientation => $horzval); $exifhan->WriteInfo($filename); } print "\n" . $filename . "\n"; foreach (keys %$exif) { my $val = $$exif{$_}; print $_ . " = " . $val . "\n"; } print "Orientation = " . $orien . "\n"; print "EpochDate = " . $epochdate . "\n"; print "RealDate = " . $realdate . "\n"; print "Distance = " . $distance . "km\n"; print "GMTOffset = " . $gmtoffset/3600 . "\n"; print "TabID = " . $tabstore{$pcfilename}{'tabid'} . "\n"; print "TZName = " . $tzname . "\n"; print "\n"; my $picbase = $webpicbase . "/" . $tzname . "/"; if (-d $picbase) { $destfile = $picbase . "/" . $base . $type; move($filename, $picbase); move($thumbfile, $picbase); } else { `mkdir -p $picbase`; $destfile = $picbase . "/" . $base . $type; move($filename, $picbase); move($thumbfile, $picbase); } chomp($type); $thumbpic = "./new/pics/" . $tzname . "/" . $base . "-thumb.jpg"; $fullpic = "./new/pics/" . $tzname . "/" . $base . $type; print XML "\n"; } } print XML "<\/markers>"; close(XML); # # $tablat, $tablon = stored in tab file lat/lon in decimal [0,1] # $newlat, $newlon = new location we want to find in decimal [2,3] # $halfpi, $r = half of pi and r [4,5] # convert from decimal to radians then apply distance formula # sub dist_find { $a1 = $_[0] * $_[4]; $b1 = $_[1] * $_[4]; $a2 = $_[2] * $_[4]; $b2 = $_[3] * $_[4]; $dist = acos(cos($a1)*cos($b1)*cos($a2)*cos($b2) + cos($a1)*sin($b1)*cos($a2)*sin($b2) + sin($a1)*sin($a2)) * $_[5]; if ($dist < 0.0001) { $dist = 0.0001; } return $dist; }