Image-ExifTool
view release on metacpan or search on metacpan
lib/Image/ExifTool/Sony.pm view on Meta::CPAN
Format => 'string',
ValueConv => 'Image::ExifTool::Exif::ExifDate($val)',
},
0xe000 => { Name => 'Sony_rtmd_0xe000', Format => 'int8u', %hidUnk }, # (16 bytes)
0xe300 => { Name => 'Sony_rtmd_0xe300', Format => 'int8u', %hidUnk }, # seen: 0,1
0xe301 => { Name => 'Sony_rtmd_0xe301', Format => 'int32u', %hidUnk }, # seen: 100,1600,12800 - ISO
0xe302 => { Name => 'Sony_rtmd_0xe302', Format => 'int8u', %hidUnk }, # seen: 1
0xe303 => { #forum12218
Name => 'WhiteBalance',
Format => 'int8u',
PrintConv => {
1 => 'Incandescent',
2 => 'Fluorescent',
4 => 'Daylight',
5 => 'Cloudy',
6 => 'Custom', # ("Shade" uses this value too)
255 => 'Preset',
},
},
0xe304 => {
Name => 'DateTime',
Groups => { 2 => 'Time' },
Format => 'undef',
ValueConv => 'my @a=unpack("x1H4H2H2H2H2H2",$val); "$a[0]:$a[1]:$a[2] $a[3]:$a[4]:$a[5]"',
PrintConv => '$self->ConvertDateTime($val)',
},
0xe435 => { Name => 'Sony_rtmd_0xe435', Format => 'int32u', %hidUnk }, # seen: 2000
0xe437 => { Name => 'Sony_rtmd_0xe437', Format => 'int32s', %hidUnk }, # seen: -3800 to -3400
0xe43b => {
Name => 'PitchRollYaw',
Format => 'int16s',
RawConv => 'substr($val, 8)',
},
0xe445 => { Name => 'Sony_rtmd_0xe445', Format => 'int32u', %hidUnk }, # seen: 2000
0xe44b => {
Name => 'Accelerometer', # (NC)
Format => 'int16s',
RawConv => 'substr($val, 8)',
},
# f010 - 2048 bytes
# f020 - 543 bytes
);
# Composite Sony tags
%Image::ExifTool::Sony::Composite = (
GROUPS => { 2 => 'Camera' },
FocusDistance => {
Require => {
0 => 'Sony:FocusPosition',
1 => 'FocalLength',
},
Notes => 'distance in metres = FocusPosition * FocalLength / 1000',
ValueConv => '$val >= 128 ? "inf" : $val * $val[1] / 1000',
PrintConv => '$val eq "inf" ? $val : "$val m"',
},
FocusDistance2 => {
# For DSLR-A550 and newer, NEX/ILCE/SLT/ILCA (only A65V/A77V are missing ...):
# seen FocusPosition2 with values from 80 - 255 (and 21 for Touit 12mm...)
# Formula from minolta.pm (WBInfoA100 - 0x49bb) gives mostly correct/acceptable distance indications.
# (https://exiftool.org/forum/index.php/topic,3688.0.html)
# if this value is the 35mm equivalent magnification, then the formula could
# be (1.5 * 2**($val/16-5)+1) * FocalLength, but this tends to underestimate
# distance by about 18% (ref 20) (255=inf)
# modified 16-10-2014 based on A99V measurements: use FocalLengthIn35mmFormat and leave out the "1.5*" factor.
Require => {
0 => 'Sony:FocusPosition2',
1 => 'FocalLengthIn35mmFormat',
},
# (NOTE: This calculation may be wrong. "Focus Distance 2 is the result of an erroneous
# user supplied formula to exiftool. It does use data embedded in the raw file,
# but it is not the data. The actual embedded data seems to be proportional to
# magnification not a focus distance. The camera needs to calculate magnification
# for translation stabilization.", ref https://www.fredmiranda.com/forum/topic/1858744/0)
ValueConv => q{
return undef unless $val;
return 'inf' if $val >= 255;
return (2**($val/16-5) + 1) * $val[1] / 1000;
},
PrintConv => '$val eq "inf" ? $val : sprintf("%.4g m", $val)',
},
GPSDateTime => {
Description => 'GPS Date/Time',
Groups => { 2 => 'Time' },
SubDoc => 1, # generate for all sub-documents
Require => {
0 => 'Sony:GPSDateStamp',
1 => 'Sony:GPSTimeStamp',
},
ValueConv => '"$val[0] $val[1]Z"',
PrintConv => '$self->ConvertDateTime($val)',
},
GPSLatitude => {
SubDoc => 1, # generate for all sub-documents
Groups => { 2 => 'Location' },
Require => {
0 => 'Sony:GPSLatitude',
1 => 'Sony:GPSLatitudeRef',
},
ValueConv => '$val[1] =~ /^S/i ? -$val[0] : $val[0]',
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
},
GPSLongitude => {
SubDoc => 1, # generate for all sub-documents
Groups => { 2 => 'Location' },
Require => {
0 => 'Sony:GPSLongitude',
1 => 'Sony:GPSLongitudeRef',
},
ValueConv => '$val[1] =~ /^W/i ? -$val[0] : $val[0]',
PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
},
HiddenData => {
Require => {
# (Note: This pointer is fragile in JPEG images, and won't be updated
# when the file is written unless the EXIF information is also written, but
# an incorrect offset is fixed by subsequently writing EXIF with ExifTool)
0 => 'Sony:HiddenDataOffset',
1 => 'Sony:HiddenDataLength',
},
Notes => q{
hidden data in some Sony JPG and ARW images, extracted only if specifically
requested
},
RawConv => q{
my $hdOff = $val[0];
my $reqTag = $$self{REQ_TAG_LOOKUP}{hiddendata};
my $hDump = $self->Options('HtmlDump');
return undef unless $reqTag or $self->Options('Validate') or $hDump;
my $dataPt = Image::ExifTool::Sony::ReadHiddenData($self, $hdOff, $val[1]);
if ($dataPt and $hDump) {
lib/Image/ExifTool/Sony.pm view on Meta::CPAN
if ($entry{0x201} and $$et{A100PreviewStart} and
$entry{0x202} and $$et{A100PreviewLength})
{
Set32u($$et{A100PreviewStart}, $dataPt, $entry{0x201} + 8);
Set32u($$et{A100PreviewLength}, $dataPt, $entry{0x202} + 8);
}
# write TIFF IFD structure
my $outfile = $$dirInfo{OutFile};
my $header = GetByteOrder() . Set16u(0x2a) . Set32u(8);
Write($outfile, $header, $$dataPt) or return 'Error writing';
# copy over image data
if (ref $imageData) {
$et->CopyImageData($imageData, $outfile) or return 'Error copying image data';
}
# write MRW data if necessary
if ($$et{MRWDirData}) {
Write($outfile, "\0" x $pad) if $pad; # write padding if necessary
Write($outfile, $$et{MRWDirData});
delete $$et{MRWDirData};
# set TIFF_END to copy over the MRW image data
$$et{TIFF_END} = $dataOffset if $dataOffset;
}
return undef;
}
#------------------------------------------------------------------------------
# Decrypt/Encrypt Sony data (ref 1) (reversible encryption)
# Inputs: 0) data reference, 1) start offset, 2) data length, 3) decryption key
# Returns: nothing (original data buffer is updated with decrypted data)
# Notes: data length should be a multiple of 4
sub Decrypt($$$$)
{
my ($dataPt, $start, $len, $key) = @_;
my ($i, $j, @pad);
my $words = int ($len / 4);
for ($i=0; $i<4; ++$i) {
my $lo = ($key & 0xffff) * 0x0edd + 1;
my $hi = ($key >> 16) * 0x0edd + ($key & 0xffff) * 0x02e9 + ($lo >> 16);
$pad[$i] = $key = (($hi & 0xffff) << 16) + ($lo & 0xffff);
}
$pad[3] = ($pad[3] << 1 | ($pad[0]^$pad[2]) >> 31) & 0xffffffff;
for ($i=4; $i<0x7f; ++$i) {
$pad[$i] = (($pad[$i-4]^$pad[$i-2]) << 1 |
($pad[$i-3]^$pad[$i-1]) >> 31) & 0xffffffff;
}
my @data = unpack("x$start N$words", $$dataPt);
for ($i=0x7f,$j=0; $j<$words; ++$i,++$j) {
$data[$j] ^= $pad[$i & 0x7f] = $pad[($i+1) & 0x7f] ^ $pad[($i+65) & 0x7f];
}
substr($$dataPt, $start, $words*4) = pack('N*', @data);
}
#------------------------------------------------------------------------------
# Decipher/encipher Sony tag 0x2010, 0x900b, 0x9050 and 0x940x data (ref PH)
# Inputs: 0) data reference, 1) true to encipher the data
sub Decipher($;$)
{
my ($dataPt, $encipher) = @_;
# This is a simple substitution cipher, so use a hardcoded translation table for speed.
# The formula is: $c = ($b*$b*$b) % 249, where $c is the enciphered data byte
# (note that bytes with values 249-255 are not translated, and 0-1, 82-84,
# 165-167 and 248 have the same enciphered value)
if ($encipher) { # encipher
$$dataPt =~ tr/\x02-\xf7/\x08\x1b\x40\x7d\xd8\x5e\x0e\xe7\x04V\xea\xcd\x05\x8ap\xb6i\x88\x200\xbe\xd7\x81\xbb\x92\x0c\x28\xecl\xa0\x95Q\xd3\x2f\x5dj\x5c9\x07\xc5\x87L\x1a\xf0\xe2\xef\x24y\x02\xb7\xac\xe0\x60\x2bG\xba\x91\xcbu\x8e\x233\xc4\xe3...
} else { # decipher
$$dataPt =~ tr/\x08\x1b\x40\x7d\xd8\x5e\x0e\xe7\x04V\xea\xcd\x05\x8ap\xb6i\x88\x200\xbe\xd7\x81\xbb\x92\x0c\x28\xecl\xa0\x95Q\xd3\x2f\x5dj\x5c9\x07\xc5\x87L\x1a\xf0\xe2\xef\x24y\x02\xb7\xac\xe0\x60\x2bG\xba\x91\xcbu\x8e\x233\xc4\xe3\x96\xdc\x...
}
}
#------------------------------------------------------------------------------
# Process Sony 0x94xx cipherdata directory
# Inputs: 0) ExifTool object ref, 1) directory information ref, 2) tag table ref
# Returns: 1 on success
# Notes:
# 1) dirInfo may contain VarFormatData (reference to empty list) to return
# details about any variable-length-format tags in the table (used when writing)
# 2) A bug in ExifTool 9.04-9.10 could have double-enciphered these blocks
sub ProcessEnciphered($$$)
{
my ($et, $dirInfo, $tagTablePtr) = @_;
my $dataPt = $$dirInfo{DataPt};
my $dirStart = $$dirInfo{DirStart} || 0;
my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
my $data = substr($$dataPt, $dirStart, $dirLen);
my %dirInfo = (
%$dirInfo,
DataPt => \$data,
DataPos => $$dirInfo{DataPos} + $dirStart,
DirStart => 0,
);
Decipher(\$data);
if ($$et{DoubleCipher}) {
Decipher(\$data);
$et->Warn('Some Sony metadata is double-enciphered. Write any tag to fix',1);
}
if ($et->Options('Verbose') > 2) {
my $tagInfo = $$dirInfo{TagInfo} || { Name => 'data' };
my $str = $$et{DoubleCipher} ? 'ouble-d' : '';
$et->VerboseDir("D${str}eciphered $$tagInfo{Name}");
$et->VerboseDump(\$data,
Prefix => $$et{INDENT} . ' ',
DataPos => $$dirInfo{DirStart} + $$dirInfo{DataPos} + ($$dirInfo{Base} || 0),
);
}
return $et->ProcessBinaryData(\%dirInfo, $tagTablePtr);
}
#------------------------------------------------------------------------------
# Write Sony 0x94xx cipherdata directory
# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
# Returns: cipherdata block or undefined on error
sub WriteEnciphered($$$)
{
my ($et, $dirInfo, $tagTablePtr) = @_;
$et or return 1;
my $dataPt = $$dirInfo{DataPt};
my $dirStart = $$dirInfo{DirStart} || 0;
my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
my $data = substr($$dataPt, $dirStart, $dirLen);
my $changed = $$et{CHANGED};
( run in 0.398 second using v1.01-cache-2.11-cpan-39bf76dae61 )