Image-ExifTool
view release on metacpan or search on metacpan
lib/Image/ExifTool/RIFF.pm view on Meta::CPAN
$$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF';
for ($pos=0; $pos<=$dataLen-20; $pos+=20) {
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
my $buff = substr($$dataPt, $pos);
my @a = unpack('NCCNCNCN', $buff);
my @acc = ($a[3]*($a[2]?-1:1)/1e5, $a[5]*($a[4]?-1:1)/1e5, $a[7]*($a[6]?-1:1)/1e5);
$et->HandleTag($tagTbl, FrameNumber => $a[0]);
$et->HandleTag($tagTbl, Accelerometer => "@acc");
unless ($ee) {
$et->Warn('Use ExtractEmbedded option to extract all accelerometer data', 3);
last;
}
}
delete $$et{SET_GROUP0};
delete $$et{SET_GROUP1};
$$et{DOC_NUM} = 0;
return 0;
}
#------------------------------------------------------------------------------
# Process BikeBro SLLT chunk (GPS information) (ref PH)
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
# Returns: 1 on success
sub ProcessSLLT($$$)
{
my ($et, $dirInfo, $tagTbl) = @_;
my $dataPt = $$dirInfo{DataPt};
my $dataLen = length $$dataPt;
my $ee = $et->Options('ExtractEmbedded');
my $pos;
# example GPS record:
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 00 00 00 17 01 00 00 03 fa 21 ec 00 35 01 6e c0 06 00 08 00 62 10 0b 1b 07 e2 03 0e 57 4e
# frame------ ?? lonDD lonDDDDDDDD latDD latDDDDDDDD alt-- spd-- hr mn sc yr--- mn dy EW NS
$$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF';
for ($pos=0; $pos<=$dataLen-30; $pos+=30) {
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
my $buff = substr($$dataPt, $pos);
my @a = unpack('NCnNnNnnCCCnCCaa', $buff);
# - is $a[1] perhaps GPSStatus? (only seen 1, or perhaps record type 1=GPS, 2=acc?)
my $time = sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', @a[11..13, 8..10]);
$et->HandleTag($tagTbl, FrameNumber => $a[0]);
$et->HandleTag($tagTbl, GPSDateTime => $time);
$et->HandleTag($tagTbl, GPSLatitude => ($a[4] + $a[5]/1e8) * ($a[15] eq 'S' ? -1 : 1));
$et->HandleTag($tagTbl, GPSLongitude => ($a[2] + $a[3]/1e8) * ($a[14] eq 'W' ? -1 : 1));
$et->HandleTag($tagTbl, GPSAltitude => $a[6]);
$et->HandleTag($tagTbl, GPSSpeed => $a[7]);
$et->HandleTag($tagTbl, GPSSpeedRef => 'K');
unless ($ee) {
$et->Warn('Use ExtractEmbedded option to extract timed GPS', 3);
last;
}
}
delete $$et{SET_GROUP0};
delete $$et{SET_GROUP1};
$$et{DOC_NUM} = 0;
return 1;
}
#------------------------------------------------------------------------------
# Process Lucas streaming GPS information (Lucas LK-7900 Ace) (ref PH)
# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
# Returns: 1 on success
sub ProcessLucas($$$)
{
my ($et, $dirInfo, $tagTbl) = @_;
my $dataPt = $$dirInfo{DataPt};
my $dataLen = length $$dataPt;
unless ($et->Options('ExtractEmbedded')) {
$et->Warn('Use ExtractEmbedded option to extract timed GPS', 3);
return 1;
}
my %recLen = ( # record lengths (not including 4-byte ID)
'0GDA' => 24,
'0GPS' => 48,
);
my ($date,$time,$lat,$lon,$alt,$spd,$sat,$dop,$ew,$ns);
$$et{SET_GROUP0} = $$et{SET_GROUP1} = 'RIFF';
while ($$dataPt =~ /(0GDA|0GPS)/g) {
my ($rec, $pos) = ($1, pos $$dataPt);
$pos + $recLen{$rec} > $dataLen and $et->Warn("Truncated $1 record"), last;
$$et{DOC_NUM} = ++$$et{DOC_COUNT};
# records start with int64u sample date/time in ms since 1970
$et->HandleTag($tagTbl, SampleDateTime => Get64u($dataPt, $pos) / 1000);
if ($rec eq '0GPS') {
my $len = Get32u($dataPt, $pos+8);
my $endPos = $pos + $recLen{$rec} + $len;
$endPos > $dataLen and $et->Warn('Truncated 0GPS record'), last;
my $buff = substr($$dataPt, $pos+$recLen{$rec}, $len);
while ($buff =~ /\$(GC|GA),(\d+),/g) {
my $p = pos $buff;
$time = $2;
if ($1 eq 'GC') {
# time date dist ? sat dop alt A
# $GC,052350,180914,0000955,1,08,1.1,0017,,A*45\x0d\x0a\0
if ($buff =~ /\G(\d+),\d*,\d*,(\d+),([-\d.]+),(\d+),\d*,A/g) {
($date,$sat,$dop,$alt) = ($1,$2,$3,$4);
}
} else {
# time A lat lon spd N W
# $GA,052351,A,0949.6626,07635.4439,049,N,E,*4C\x0d\x0a\0
if ($buff =~ /\GA,([\d.]+),([\d.]+),(\d+),([NS]),([EW])/g) {
($lat,$lon,$spd,$ns,$ew) = ($1,$2,$3,$4,$5,$6);
# lat/long are in DDDMM.MMMM format
my $deg = int($lat / 100);
$lat = $deg + ($lat - $deg * 100) / 60;
$deg = int($lon / 100);
$lon = $deg + ($lon - $deg * 100) / 60;
$lat *= -1 if $ns eq 'S';
$lon *= -1 if $ew eq 'W';
}
}
# look ahead to next NMEA-like sentence, and store the fix
# now only if the next sentence is not at the same time
if ($buff !~ /\$(GC|GA),$time,/g) {
pos($$dataPt) = $endPos;
if ($$dataPt !~ /\$(GC|GA),(\d+)/ or $1 ne $time) {
$time =~ s/(\d{2})(\d{2})(\d{2})/$1:$2:$3Z/;
if ($date) {
$date =~ s/(\d{2})(\d{2})(\d{2})/20$3:$2:$1/;
( run in 1.188 second using v1.01-cache-2.11-cpan-39bf76dae61 )