Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SonyMisc2b makernote tags (tag 9404) #1792

Merged
merged 3 commits into from
Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/templates/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ TABLES = Exif \
Sony1MltCsOld \
Sony1MltCsA100 \
Sony2Fp \
SonyMisc1
SonyMisc1 \
SonyMisc2b

SCHEMA = xmp_dc \
xmp_dwc \
Expand Down
1 change: 1 addition & 0 deletions man/man1/exiv2.1
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ SubImage8 MinoltaCs7D NikonFl1 Olympus Panasonic Son
SubImage9 MinoltaCsNew NikonFl2 Olympus2 PanasonicRaw Sony2Cs2
SubThumb1 MinoltaCsOld NikonFl3 OlympusCs Sony2Fp
Thumbnail NikonIi OlympusEq Sigma SonyMisc1
SonyMisc2b
SonyMinolta
.fi
.sp 1
Expand Down
39 changes: 35 additions & 4 deletions src/makernote_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,11 @@
// *****************************************************************************
namespace {
// Todo: Can be generalized further - get any tag as a string/long/...
//! Get the Value for a tag within a particular group
const Exiv2::Value* getExifValue(Exiv2::Internal::TiffComponent* const pRoot, const uint16_t& tag, const Exiv2::Internal::IfdId& group);
//! Get the model name from tag Exif.Image.Model
std::string getExifModel(Exiv2::Internal::TiffComponent* pRoot);

//! Nikon en/decryption function
void ncrypt(Exiv2::byte* pData, uint32_t size, uint32_t count, uint32_t serial);
} // namespace
Expand Down Expand Up @@ -1201,19 +1204,47 @@ namespace Exiv2 {
}
return 0;
}
int sonyMisc2bSelector(uint16_t /*tag*/, const byte* /*pData*/, uint32_t /*size*/, TiffComponent* const pRoot)
{
// From Exiftool: https://github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/Sony.pm
// > First byte must be 9 or 12 or 13 or 15 or 16 and 4th byte must be 2 (deciphered)
const auto value = getExifValue(pRoot, 0x9404, Exiv2::Internal::sony1Id);
if (!value || value->count() < 4)
return -1;

switch (value->toLong(0)) { // Using encrypted values
case 231: // 231 == 9
case 234: // 234 == 12
case 205: // 205 == 13
case 138: // 138 == 15
case 112: // 112 == 16
return value->toLong(3) == 8 ? 0 : -1; // 8 == 2
default:
break;
}
return -1;
}
} // namespace Internal
} // namespace Exiv2

// *****************************************************************************
// local definitions
namespace {
std::string getExifModel(Exiv2::Internal::TiffComponent* const pRoot)
const Exiv2::Value* getExifValue(Exiv2::Internal::TiffComponent* const pRoot, const uint16_t& tag, const Exiv2::Internal::IfdId& group)
{
Exiv2::Internal::TiffFinder finder(0x0110, Exiv2::Internal::ifd0Id); // Exif.Image.Model
Exiv2::Internal::TiffFinder finder(tag, group);
if (!pRoot)
return nullptr;
pRoot->accept(finder);
auto te = dynamic_cast<Exiv2::Internal::TiffEntryBase*>(finder.result());
if (!te || !te->pValue() || te->pValue()->count() == 0) return std::string();
return te->pValue()->toString();
return (!te || !te->pValue()) ? nullptr : te->pValue();
}

std::string getExifModel(Exiv2::Internal::TiffComponent* const pRoot)
{
// Lookup the Exif.Image.Model tag
const auto value = getExifValue(pRoot, 0x0110, Exiv2::Internal::ifd0Id);
return (!value || value->count() == 0) ? std::string("") : std::string(value->toString());
}

void ncrypt(Exiv2::byte* pData, uint32_t size, uint32_t count, uint32_t serial)
Expand Down
11 changes: 11 additions & 0 deletions src/makernote_int.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,17 @@ namespace Exiv2 {
*/
int sony2FpSelector(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const pRoot);

/*!
@brief Function to select cfg + def of the SonyMisc2b (tag 9404b) complex binary array.

@param tag Tag number of the binary array
@param pData Pointer to the raw array data.
@param size Size of the array data.
@param pRoot Pointer to the root component of the TIFF tree.
@return An index into the array set, -1 if no match was found.
*/
int sonyMisc2bSelector(uint16_t tag, const byte* pData, uint32_t size, TiffComponent* const pRoot);

/*!
@brief Function to select cfg + def of a Nikon complex binary array.

Expand Down
102 changes: 102 additions & 0 deletions src/sonymn_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <iomanip>
#include <cassert>
#include <cstring>
#include <cmath>

// *****************************************************************************
// class member definitions
Expand Down Expand Up @@ -908,6 +909,107 @@ namespace Exiv2 {
return os;
}

//! Lookup table to translate Sony Exposure Program 3 values to readable labels
constexpr TagDetails sonyExposureProgram3[] = {
{ 0, N_("Program AE") },
{ 1, N_("Aperture-priority AE") },
{ 2, N_("Shutter speed priority AE") },
{ 3, N_("Manual") },
{ 4, N_("Auto") },
{ 5, N_("iAuto") },
{ 6, N_("Superior Auto") },
{ 7, N_("iAuto+") },
{ 8, N_("Portrait") },
{ 9, N_("Landscape") },
{ 10, N_("Twilight") },
{ 11, N_("Twilight Portrait") },
{ 12, N_("Sunset") },
{ 14, N_("Action (High speed)") },
{ 16, N_("Sports") },
{ 17, N_("Handheld Night Shot") },
{ 18, N_("Anti Motion Blur") },
{ 19, N_("High Sensitivity") },
{ 21, N_("Beach") },
{ 22, N_("Snow") },
{ 23, N_("Fireworks") },
{ 26, N_("Underwater") },
{ 27, N_("Gourmet") },
{ 28, N_("Pet") },
{ 29, N_("Macro") },
{ 30, N_("Backlight Correction HDR") },
{ 33, N_("Sweep Panorama") },
{ 36, N_("Background Defocus") },
{ 37, N_("Soft Skin") },
{ 42, N_("3D Image") },
{ 43, N_("Cont. Priority AE") },
{ 45, N_("Document") },
{ 46, N_("Party") }
};

//! Sony Tag 9404b SonyMisc2b tags
constexpr TagInfo SonyMakerNote::tagInfoSonyMisc2b_[] = {
{12, "ExposureProgram", N_("Exposure program"),
N_("Exposure program"),
sonyMisc2bId, makerTags, unsignedByte, -1, EXV_PRINT_TAG(sonyExposureProgram3)},
{14, "IntelligentAuto", N_("Intelligent auto"),
N_("Whether intelligent auto was used"),
sonyMisc2bId, makerTags, unsignedByte, -1, printMinoltaSonyBoolValue},
{30, "LensZoomPosition", N_("Lens zoom position"),
N_("Lens zoom position (in %)"),
sonyMisc2bId, makerTags, unsignedShort, -1, printSonyMisc2bLensZoomPosition},
{32, "FocusPosition2", N_("Focus position 2"),
N_("Focus position 2"),
sonyMisc2bId, makerTags, unsignedByte, -1, printSonyMisc2bFocusPosition2},
// End of list marker
{0xffff, "(UnknownSonyMisc2bTag)", "(Unknown SonyMisc2b tag)",
"(Unknown SonyMisc2b tag)",
sonyMisc2bId, makerTags, unsignedByte, -1, printValue}
};

const TagInfo* SonyMakerNote::tagListSonyMisc2b()
{
return tagInfoSonyMisc2b_;
}

std::ostream& SonyMakerNote::printSonyMisc2bLensZoomPosition(std::ostream& os, const Value& value, const ExifData* metadata)
{
if (value.count() != 1)
return os << "(" << value << ")";

auto pos = metadata->findKey(ExifKey("Exif.Image.Model"));
if (pos == metadata->end())
return os << "(" << value << ")";

// Models that do not support this tag
std::string model = pos->toString();
for (auto& m : { "SLT-", "HV", "ILCA-"}) {
if (model.find(m) != std::string::npos)
return os << N_("n/a");
}

os << std::round((value.toLong()/10.24)) << "%";

return os;
}

std::ostream& SonyMakerNote::printSonyMisc2bFocusPosition2(std::ostream& os, const Value& value, const ExifData* metadata)
{
if (value.count() != 1)
return os << "(" << value << ")";

auto pos = metadata->findKey(ExifKey("Exif.Image.Model"));
if (pos == metadata->end())
return os << "(" << value << ")";

// Models that do not support this tag
std::string model = pos->toString();
for (auto& m : { "SLT-", "HV", "ILCA-"}) {
if (model.find(m) != std::string::npos)
return os << N_("n/a");
}

return os << value;
}

//! Sony Tag 2010 Sony2010 (Miscellaneous)
constexpr TagInfo SonyMakerNote::tagInfo2010e_[] = {
Expand Down
7 changes: 7 additions & 0 deletions src/sonymn_int.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ namespace Exiv2 {
static const TagInfo* tagListFp();
//! Return read-only list of built-in Sony Misc1 tags (Tag 9403)
static const TagInfo* tagListSonyMisc1();
//! Return read-only list of built-in Sony Misc2b tags (Tag 9404)
static const TagInfo* tagListSonyMisc2b();

static const TagInfo* tagList2010e();

Expand All @@ -62,6 +64,10 @@ namespace Exiv2 {
static std::ostream& printSony2FpFocusPosition2(std::ostream&, const Value&, const ExifData* metadata);
//! Print Sony temperature values (in degrees Celsius)
static std::ostream& printTemperatureInDegC(std::ostream&, const Value&, const ExifData*);
//! Print SonyMisc2b Lens Zoom Position value
static std::ostream& printSonyMisc2bLensZoomPosition(std::ostream&, const Value&, const ExifData* metadata);
//! Print SonyMisc2b Focus Position 2 value
static std::ostream& printSonyMisc2bFocusPosition2(std::ostream&, const Value&, const ExifData* metadata);
//! Print Sony Camera Model
static std::ostream& print0xb000(std::ostream&, const Value&, const ExifData*);
//! Print Full and Preview Image size
Expand All @@ -74,6 +80,7 @@ namespace Exiv2 {
static const TagInfo tagInfoCs2_[];
static const TagInfo tagInfoFp_[];
static const TagInfo tagInfoSonyMisc1_[];
static const TagInfo tagInfoSonyMisc2b_[];
static const TagInfo tagInfo2010e_[];

}; // class SonyMakerNote
Expand Down
1 change: 1 addition & 0 deletions src/tags_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ namespace Exiv2 {
{ sony2Cs2Id, "Makernote", "Sony2Cs2", SonyMakerNote::tagListCs2 },
{ sony2FpId, "Makernote", "Sony2Fp", SonyMakerNote::tagListFp },
{ sonyMisc1Id, "Makernote", "SonyMisc1", SonyMakerNote::tagListSonyMisc1},
{ sonyMisc2bId, "Makernote", "SonyMisc2b", SonyMakerNote::tagListSonyMisc2b},
{ sony2010eId, "Makernote", "Sony2010e", SonyMakerNote::tagList2010e },
{ lastId, "(Last IFD info)", "(Last IFD item)", nullptr }
};
Expand Down
1 change: 1 addition & 0 deletions src/tags_int.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ namespace Exiv2 {
sony2Cs2Id,
sony2FpId,
sonyMisc1Id,
sonyMisc2bId,
sony2010eId,
sony1MltCs7DId,
sony1MltCsOldId,
Expand Down
33 changes: 33 additions & 0 deletions src/tiffimage_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,29 @@ namespace Exiv2 {
{ 0x05, ttSignedByte , 1 }, // Exif.SonyMisc1.CameraTemperature
};

constexpr ArrayCfg sonyMisc2bCfg = {
sonyMisc2bId, // Group for the elements
littleEndian, // Little endian
ttUnsignedByte, // Type for array entry and size element
sonyTagDecipher, // (uint16_t, const byte*, uint32_t, TiffComponent* const);
false, // No size element
false, // No fillers
false, // Don't concatenate gaps
{ 0, ttUnsignedByte, 1 }
};

constexpr ArrayDef sonyMisc2bDef[] = {
{ 12, ttUnsignedByte , 1 }, // Exif.SonyMisc2b.ExposureProgram
{ 14, ttUnsignedByte , 1 }, // Exif.SonyMisc2b.IntelligentAuto
{ 30, ttUnsignedShort , 1 }, // Exif.SonyMisc2b.LensZoomPosition
{ 32, ttUnsignedByte , 1 }, // Exif.SonyMisc2b.FocusPosition2
};

//! SonyMisc2b configurations and definitions
constexpr ArraySet sonyMisc2bSet[] = {
{ sonyMisc2bCfg, sonyMisc2bDef, EXV_COUNTOF(sonyMisc2bDef) }
};

constexpr ArrayCfg sony2010eCfg = {
sony2010eId, // Group for the elements
invalidByteOrder, // inherit from file. Usually littleEndian
Expand Down Expand Up @@ -1117,6 +1140,7 @@ namespace Exiv2 {
{ Tag::root, sony2010eId, sony1Id, 0x2010 },
{ Tag::root, sony2FpId, sony1Id, 0x9402 },
{ Tag::root, sonyMisc1Id, sony1Id, 0x9403 },
{ Tag::root, sonyMisc2bId, sony1Id, 0x9404 },
{ Tag::root, sony1CsId, sony1Id, 0x0114 },
{ Tag::root, sony1Cs2Id, sony1Id, 0x0114 },
{ Tag::root, sonyMltId, sony1Id, 0xb028 },
Expand All @@ -1128,6 +1152,7 @@ namespace Exiv2 {
{ Tag::root, sony2010eId, sony2Id, 0x2010 },
{ Tag::root, sony2FpId, sony2Id, 0x9402 },
{ Tag::root, sonyMisc1Id, sony2Id, 0x9403 },
{ Tag::root, sonyMisc2bId, sony2Id, 0x9404 },
{ Tag::root, sony2CsId, sony2Id, 0x0114 },
{ Tag::root, sony2Cs2Id, sony2Id, 0x0114 },
{ Tag::root, minoltaId, exifId, 0x927c },
Expand Down Expand Up @@ -1566,6 +1591,10 @@ namespace Exiv2 {
{ Tag::all, sony2FpId, newTiffBinaryElement },
{ 0x9402, sony1Id, EXV_COMPLEX_BINARY_ARRAY(sony2FpSet, sony2FpSelector) },

// Tag 0x9404 SonyMisc2b
{ Tag::all, sonyMisc2bId, newTiffBinaryElement },
{ 0x9404, sony1Id, EXV_COMPLEX_BINARY_ARRAY(sonyMisc2bSet, sonyMisc2bSelector) },

// Tag 0x9403 SonyMisc1
{ Tag::all, sonyMisc1Id, newTiffBinaryElement },
{ 0x9403, sony1Id, EXV_BINARY_ARRAY(sonyMisc1Cfg, sonyMisc1Def) },
Expand All @@ -1591,6 +1620,10 @@ namespace Exiv2 {
{ Tag::all, sonyMisc1Id, newTiffBinaryElement },
{ 0x9403, sony2Id, EXV_BINARY_ARRAY(sonyMisc1Cfg, sonyMisc1Def) },

// Tag 0x9404 SonyMisc2b
{ Tag::all, sonyMisc2bId, newTiffBinaryElement },
{ 0x9404, sony2Id, EXV_COMPLEX_BINARY_ARRAY(sonyMisc2bSet, sonyMisc2bSelector) },

// Sony2 makernote
{ 0x0114, sony2Id, EXV_COMPLEX_BINARY_ARRAY(sony2CsSet, sonyCsSelector) },
{ Tag::next, sony2Id, ignoreTiffComponent },
Expand Down
28 changes: 28 additions & 0 deletions tests/bugfixes/github/test_pr_1792.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-

from system_tests import CaseMeta, path

class SonyMisc2bTestSupported(metaclass=CaseMeta):

filename = path("$data_path/test_issue_1464.exv")
commands = ["$exiv2 -pa --grep SonyMisc2b $filename"]

stdout = ["""Exif.SonyMisc2b.ExposureProgram Byte 1 Shutter speed priority AE
Exif.SonyMisc2b.IntelligentAuto Byte 1 Off
Exif.SonyMisc2b.LensZoomPosition Short 1 100%
Exif.SonyMisc2b.FocusPosition2 Byte 1 0
"""
]
stderr = [""]
retval = [0]

# An example of a Sony camera model that does NOT support SonyMisc2b
class SonyMisc2bTestUnsupported(metaclass=CaseMeta):

filename = path("$data_path/exiv2-pr906.exv")
commands = ["$exiv2 -pa --grep SonyMisc2b $filename"]

stdout = [""""""
]
stderr = [""]
retval = [1]