1002
# standard RMETA tag directory
1003
my (@tags, @vals, @nums, $valPos);
1004
my $pos = $dirStart + 6;
1014
# decode standard RMETA tag directory
1015
my (@tags, @vals, @nums, $valPos, $numPos);
1016
my $pos = $dirStart + Get16u($dataPt, $dirStart+8);
1017
my $numEntries = Get16u($dataPt, $pos);
1018
$numEntries > 100 and $et->Warn('Bad RMETA entry count'), return 0;
1019
$pos += 10; # start of first RMETA section
1020
# loop through RMETA sections
1005
1021
while ($pos <= $dataLen - 4) {
1006
1022
my $type = Get16u($dataPt, $pos);
1007
1023
my $size = Get16u($dataPt, $pos + 2);
1012
1028
$et->Warn('Corrupted Ricoh RMETA data', 1);
1031
my $dat = substr($$dataPt, $pos, $size);
1033
$et->VPrint(2, "$$et{INDENT}RMETA section type=$type size=$size\n");
1035
my %dumpParms = ( Addr => $$dirInfo{DataPos} + $pos, Prefix => $$et{INDENT} );
1036
$dumpParms{MaxLen} = 96 if $verbose == 3;
1037
Image::ExifTool::HexDump(\$dat, undef, %dumpParms);
1040
if ($type == 1) { # section 1: tag names
1016
1041
# save the tag names
1017
my $tags = substr($$dataPt, $pos, $size);
1018
$tags =~ s/\0+$//; # remove trailing nulls
1019
@tags = split /\0/, $tags;
1020
} elsif ($type eq 2) {
1021
# save the ASCII tag values
1022
my $vals = substr($$dataPt, $pos, $size);
1024
@vals = split /\0/, $vals;
1025
$valPos = $pos; # save position of first ASCII value
1026
} elsif ($type eq 3) {
1027
# save the numerical tag values
1028
my $nums = substr($$dataPt, $pos, $size);
1029
@nums = unpack($byteOrder eq 'MM' ? 'n*' : 'v*', $nums);
1030
} elsif ($type eq 0) {
1031
$pos += 2; # why 2 extra bytes?
1042
@tags = split /\0/, $dat, $numEntries+1;
1043
} elsif ($type == 2 || $type == 18) { # section 2/18: string values (G800 uses type 18)
1044
# save the tag values (assume "ASCII\0" encoding since others never seen)
1045
@vals = split /\0/, $dat, $numEntries+1;
1046
$valPos = $pos; # save position of first string value
1047
} elsif ($type == 3) { # section 3: numerical values
1048
if ($size < $numEntries * 2) {
1049
$et->Warn('Truncated RMETA section 3');
1051
# save the numerical tag values
1052
# (0=empty, 0xffff=text input, otherwise menu item number)
1053
@nums = unpack(($byteOrder eq 'MM' ? 'n' : 'v').$numEntries, $dat);
1054
$numPos = $pos; # save position of numerical values
1056
} elsif ($type != 16) {
1057
$et->Warn("Unrecognized RMETA section (type $type, len $size)");
1035
if (@tags or @vals) {
1036
if (@tags < @vals) {
1037
my ($nt, $nv) = (scalar(@tags), scalar(@vals));
1038
$et->Warn("Fewer tags ($nt) than values ($nv) in Ricoh RMETA", 1);
1040
# find next tag in null-delimited list
1041
# unpack numerical values from block of int16u values
1042
my ($tag, $name, $val);
1043
foreach $tag (@tags) {
1045
$val = '' unless defined $val;
1046
($name = $tag) =~ s/\b([a-z])/\U$1/gs; # make capitalize all words
1047
$name =~ s/ (\w)/\U$1/g; # remove special characters
1048
$name = 'RMETA_Unknown' unless length($name);
1049
my $num = shift @nums;
1050
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
1052
# make sure print conversion is defined
1053
$$tagInfo{PrintConv} = { } unless ref $$tagInfo{PrintConv} eq 'HASH';
1055
# create tagInfo hash
1056
$tagInfo = { Name => $name, PrintConv => { } };
1057
AddTagToTable($tagTablePtr, $tag, $tagInfo);
1059
# use string value directly if no numerical value
1060
$num = $val unless defined $num;
1061
# add conversion for this value (replacing any existing entry)
1062
$tagInfo->{PrintConv}->{$num} = length $val ? $val : $num;
1064
$et->VerboseInfo($tag, $tagInfo,
1065
Table => $tagTablePtr,
1068
DataPos => $$dirInfo{DataPos},
1070
Size => length($val),
1073
$et->FoundTag($tagInfo, $num);
1074
$valPos += length($val) + 1;
1061
return 1 unless @tags or @vals;
1062
$valPos or $valPos = 0; # (just in case there was no value section)
1063
# find next tag in null-delimited list
1064
# unpack numerical values from block of int16u values
1066
for ($i=0; $i<$numEntries; ++$i) {
1067
my $tag = $tags[$i];
1068
my $val = $vals[$i];
1069
$val = '' unless defined $val;
1070
unless (defined $tag and length $tag) {
1071
length $val or ++$valPos, next; # (skip empty entries)
1074
($name = $tag) =~ s/\b([a-z])/\U$1/gs; # capitalize all words
1075
$name =~ s/ (\w)/\U$1/g; # remove special characters
1076
$name = 'RMETA_Unknown' unless length($name);
1077
my $num = $nums[$i];
1078
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
1080
# make sure print conversion is defined
1081
$$tagInfo{PrintConv} = { } unless ref $$tagInfo{PrintConv} eq 'HASH';
1083
# create tagInfo hash
1084
$tagInfo = { Name => $name, PrintConv => { } };
1085
AddTagToTable($tagTablePtr, $tag, $tagInfo);
1087
# use string value directly if no numerical value
1088
$num = $val unless defined $num;
1089
# add conversion for this value (replacing any existing entry)
1090
$tagInfo->{PrintConv}->{$num} = length $val ? $val : $num;
1094
%datParms = ( Start => $valPos, Size => length($val), Format => 'string' );
1096
%datParms = ( Start => $numPos + $i * 2, Size => 2, Format => 'int16u' );
1098
%datParms and $datParms{DataPt} = $dataPt, $datParms{DataPos} = $$dirInfo{DataPos};
1099
$et->VerboseInfo($tag, $tagInfo, Table=>$tagTablePtr, Value=>$num, %datParms);
1101
$et->FoundTag($tagInfo, $num);
1102
$valPos += length($val) + 1;