Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:sbrabec
perl-Image-ExifTool-minolta_A1-byte-exact.openSUSE_Leap_15.2_Update
exiftool-minolta_A1-byte-exact-copy.v11.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File exiftool-minolta_A1-byte-exact-copy.v11.patch of Package perl-Image-ExifTool-minolta_A1-byte-exact.openSUSE_Leap_15.2_Update
exiftool-minolta_A1-byte-exact-copy.v11.patch This patch allows to make byte exact copies of the Minolta Dimage A1 camera original from a copy edited by exiftool >= 7.34. This version is ported for Image-ExifTool-9.70. If you set environment variable MINOLTA_BYTE_EXACT=4 and then remove all tags you added, you will get a copy, that is equal to the original file as it came from the camera. Note: Patch still needs testing for images with edited ExifIFD/UserComment. Author: Stanislav Brabec <utx@penguin.cz> Variable MINOLTA_BYTE_EXACT meanings: 0 or undefined: default exiftool behavior 1: organize tags exactly as camera does 4: 1 + pad items exactly as camera does Notes: - To get byte-exact copy of original, you have to strip custom tags and revert existing tags manually, as levels 2 and 3 are not yet implemented. - For exiftool >= 7.34 you can get byte exact copy of original even from files, that were written by with the default exiftool behavior. - exiftool <= 7.34 has an one obsolete pad byte in the MakerNotes, which causes a different result after reverting of all tags. History: 2008-08-08: v1: initial version for Image-ExifTool-7.37 2009-11-23: v2: ported to Image-ExifTool-7.82 2010-07-11: v3: ported to Image-ExifTool-8.15 2010-08-27: v4: fixed byte exact padding with embedded ICC profile 2010-11-01: v5: fixed exact padding for exif size % 512 equal to 392 (support for negative padding) 2011-03-13: v6: ported to Image-ExifTool-8.40 2012-06-06: v7: fixed byte exact padding with Adobe RGB images without embedded ICC profile 2012-09-23: v8: ported to Image-ExifTool-8.65 (v8 was broken) 2013-03-24: v9: ported to Image-ExifTool-9.01 2014-12-08: v10: ported to Image-ExifTool-9.70 2015-03-21: v11: fixed compilation error Index: Image-ExifTool-10.80/lib/Image/ExifTool/WriteExif.pl =================================================================== --- Image-ExifTool-10.80.orig/lib/Image/ExifTool/WriteExif.pl +++ Image-ExifTool-10.80/lib/Image/ExifTool/WriteExif.pl @@ -461,6 +461,25 @@ sub WriteExif($$$) # set encoding for strings $strEnc = $et->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF'; +# Variable MINOLTA_BYTE_EXACT meanings: +# 0 or undefined: default exiftool behavior +# 1: organize tags exactly as camera does +# 2: 1 + write only tags generated by the camera (not yet implemented) +# 3: 2 + revert tag to values that camera can generate (not yet implemented) +# 4: 3 + pad items exactly as camera does +# Notes: +# - To get byte-exact copy of original, you have to strip custom tags and +# revert existing tags manually, as levels 2 and 3 are not yet +# implemented. +# - For exiftool >= 7.34 you can get byte exact copy of original even +# from files, that were written by with the default exiftool behavior. + my $minolta_byte_exact; + if (defined($ENV{MINOLTA_BYTE_EXACT})) { + $minolta_byte_exact = int($ENV{MINOLTA_BYTE_EXACT}); + } else { + $minolta_byte_exact = 0; + } + # allow multiple IFD's in IFD0-IFD1-IFD2... chain $$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi}; $inMakerNotes = 1 if $$tagTablePtr{GROUPS}{0} eq 'MakerNotes'; @@ -612,6 +631,7 @@ sub WriteExif($$$) } my $dirBuff = ''; # buffer for directory data my $valBuff = ''; # buffer for value data + my $offsetValBuff = 0; # current offset to $valBuff my @valFixups; # list of fixups for offsets in valBuff # fixup for offsets in dirBuff my $dirFixup = new Image::ExifTool::Fixup; @@ -623,6 +643,23 @@ sub WriteExif($$$) my ($offList, $offHash, $ignoreCount, $fixCount); my $oldID = -1; my $newID = -1; + my $sizeUserComment = 0; + + if (($minolta_byte_exact > 0) and ($dirName eq 'ExifIFD')) { + $index = 0; + EntryUserComment: + for (;$index < $numEntries;++$index) { + $entry = $dirStart + 2 + 12 * $index; + $oldID = Get16u($dataPt, $entry); + $readCount = Get32u($dataPt, $entry+4); + # UserComment + if ($oldID == 37510) { + $sizeUserComment=$readCount; + } + } + $index = 0; + $oldID = -1; + } # patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts) if ($inMakerNotes and $$et{Model} eq 'Canon EOS 40D') { @@ -1814,10 +1851,42 @@ NoOverwrite: next if $isNew > my $entryBased; if ($$dirInfo{EntryBased} or ($newInfo and $$newInfo{EntryBased})) { $entryBased = 1; - $offsetVal = Set32u(length($valBuff) - length($dirBuff)); + $offsetValBuff = length($valBuff) - length($dirBuff); } else { - $offsetVal = Set32u(length $valBuff); + if (($minolta_byte_exact > 0) and ($dirName eq 'ExifIFD')) { + CASE:{ + # DateTimeOriginal + $newID == 36867 and do{$offsetValBuff = 0; last CASE;}; + # CreateDate + $newID == 36868 and do{$offsetValBuff = 20; last CASE;}; + # ExposureTime + $newID == 33434 and do{$offsetValBuff = 40; last CASE;}; + # FNumber + $newID == 33437 and do{$offsetValBuff = 48; last CASE;}; + # ExposureCompensation + $newID == 37380 and do{$offsetValBuff = 56; last CASE;}; + # MaxApertureValue + $newID == 37381 and do{$offsetValBuff = 64; last CASE;}; + # FocalLength + $newID == 37386 and do{$offsetValBuff = 72; last CASE;}; + # DigitalZoomRatio + $newID == 41988 and do{$offsetValBuff = 80; last CASE;}; + # BrightnessValue + $newID == 37379 and do{$offsetValBuff = 88; last CASE;}; + # SubjectLocation + $newID == 37396 and do{$offsetValBuff = 96; last CASE;}; + # These two have defined position as well, but editing UserComment, MakerNoteMinolta will change. + # As MakerNote is processed first, we must add UserComment size + # UserComment + $newID == 37510 and do{$offsetValBuff = 104; last CASE;}; + # MakerNote 37500 + $newID == 37500 and do{$offsetValBuff = 104 + $sizeUserComment; last CASE;}; + # Unknown entries + do{$offsetValBuff = length $valBuff;}; + } + } else {$offsetValBuff = length $valBuff;}; } + $offsetVal = Set32u($offsetValBuff); my ($dataTag, $putFirst); ($dataTag, $putFirst) = @$newInfo{'DataTag','PutFirst'} if $newInfo; if ($dataTag) { @@ -1846,7 +1915,11 @@ NoOverwrite: next if $isNew > $offsetVal = Set32u(length $$hdrPtr); $$hdrPtr .= $$newValuePt; } else { - $valBuff .= $$newValuePt; # add value data to buffer + # pad $valBuff if value starts after current buffer end (in byte exact mode) + if ($offsetValBuff > length $valBuff) { + $valBuff .= "\0" x ($offsetValBuff - length $valBuff); + } + (substr $valBuff, $offsetValBuff, length $$newValuePt) = $$newValuePt; # add value data to buffer # must save a fixup pointer for every pointer in the directory if ($entryBased) { $entryBasedFixup or $entryBasedFixup = new Image::ExifTool::Fixup; @@ -2002,6 +2075,10 @@ NoOverwrite: next if $isNew > my $valFixup; foreach $valFixup (@valFixups) { $$valFixup{Start} += $valPos; + if (($minolta_byte_exact > 0) and ($dirName eq 'ExifIFD')) { + # Fix MakerNotes fixups to refer to a known fixed position + $valFixup->{Start} += $sizeUserComment; + } $fixup->AddFixup($valFixup); } # stop if no next IFD pointer @@ -2404,9 +2481,10 @@ NoOverwrite: next if $isNew > my $pt = \$$previewInfo{Data}; # image data or 'LOAD_PREVIEW' flag # now that we know the size of the EXIF data, first test to see if our new image fits # inside the EXIF segment (remember about the TIFF and EXIF headers: 8+6 bytes) - if (($$pt ne 'LOAD_PREVIEW' and length($$pt) + length($newData) + 14 <= 0xfffd and + if (($minolta_byte_exact == 0) and + (($$pt ne 'LOAD_PREVIEW' and length($$pt) + length($newData) + 14 <= 0xfffd and not $$previewInfo{IsTrailer}) or - $$previewInfo{IsShort}) # must fit in this segment if using short pointers + $$previewInfo{IsShort})) # must fit in this segment if using short pointers { # It fits! (or must exist in EXIF segment), so fixup the # PreviewImage pointers and stuff the preview image in here @@ -2457,6 +2535,23 @@ NoOverwrite: next if $isNew > # set changed if ForceWrite tag was set to "EXIF" ++$$et{CHANGED} if defined $newData and length $newData and $$et{FORCE_WRITE}{EXIF}; + if (($minolta_byte_exact > 3) and ($dirName eq 'IFD1')) { + my $padSize; + # is ICC profile included? + # In this time we have no better hint than file extension: + # FIXME: Use of RAF would be better. + if ($$et{FILE_EXT} eq "JPE") { + $padSize = 510 - ((length($newData) + 119) % 512); + } else { + $padSize = 511 - ((length($newData) + 94) % 512); + } + if ($padSize == -1) { + $newData = substr($newData, 0, length($newData) - 1); + } else { + $newData .= "\0" x $padSize; + } + } + return $newData; # return our directory data }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor