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 )