Skip to content

Commit 1125dcb

Browse files
authored
Merge pull request #999 from Exiv2/mergify/bp/master/pr-988
New PR to replace fix981_canonAutoFocus2 which will be closed. (bp #988)
2 parents c9ac162 + 1712a7b commit 1125dcb

File tree

12 files changed

+220
-3
lines changed

12 files changed

+220
-3
lines changed

src/canonmn_int.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,23 @@ namespace Exiv2 {
406406
{ 2, N_("Adobe RGB") }
407407
};
408408

409+
extern const TagDetails canonAFAreaMode[] = {
410+
{ 0, N_("Off (Manual Focus)") },
411+
{ 1, N_("AF Point Expansion (surround)")},
412+
{ 2, N_("Single-point AF") },
413+
{ 4, N_("Multi-point AF") },
414+
{ 5, N_("Face Detect AF") },
415+
{ 6, N_("Face + Tracking") },
416+
{ 7, N_("Zone AF") },
417+
{ 8, N_("AF Point Expansion (4 point)") },
418+
{ 9, N_("Spot AF") },
419+
{ 10, N_("AF Point Expansion (8 point)") },
420+
{ 11, N_("Flexizone Multi (49 point)") },
421+
{ 12, N_("Flexizone Multi (9 point)") },
422+
{ 13, N_("Flexizone Single") },
423+
{ 14, N_("Large Zone AF") },
424+
};
425+
409426
// Canon MakerNote Tag Info
410427
const TagInfo CanonMakerNote::tagInfo_[] = {
411428
TagInfo(0x0000, "0x0000", "0x0000", N_("Unknown"), canonId, makerTags, unsignedShort, -1, printValue),
@@ -442,6 +459,21 @@ namespace Exiv2 {
442459
TagInfo(0x00c1, "0x00c1", "0x00c1", N_("Unknown"), canonId, makerTags, unsignedShort, -1, printValue),
443460
TagInfo(0x00d0, "VRDOffset", N_("VRD Offset"), N_("VRD offset"), canonId, makerTags, unsignedLong, -1, printValue),
444461
TagInfo(0x00e0, "SensorInfo", N_("Sensor Info"), N_("Sensor info"), canonId, makerTags, unsignedShort, -1, printValue),
462+
TagInfo(0x2600, "AFInfoSize", N_("AF InfoSize"), N_("AF InfoSize"), canonId, makerTags, signedShort, -1, printValue),
463+
TagInfo(0x2601, "AFAreaMode", N_("AF Area Mode"), N_("AF Area Mode"), canonId, makerTags, signedShort, -1, EXV_PRINT_TAG(canonAFAreaMode)),
464+
TagInfo(0x2602, "AFNumPoints", N_("AF NumPoints"), N_("AF NumPoints"), canonId, makerTags, signedShort, -1, printValue),
465+
TagInfo(0x2603, "AFValidPoints", N_("AF ValidPoints"), N_("AF ValidPoints"), canonId, makerTags, signedShort, -1, printValue),
466+
TagInfo(0x2604, "AFCanonImageWidth", N_("AF ImageWidth"), N_("AF ImageWidth"), canonId, makerTags, signedShort, -1, printValue),
467+
TagInfo(0x2605, "AFCanonImageHeight", N_("AF ImageHeight"), N_("AF ImageHeight"), canonId, makerTags, signedShort, -1, printValue),
468+
TagInfo(0x2606, "AFImageWidth", N_("AF Width"), N_("AF Width"), canonId, makerTags, signedShort, -1, printValue),
469+
TagInfo(0x2607, "AFImageHeight", N_("AF Height"), N_("AF Height"), canonId, makerTags, signedShort, -1, printValue),
470+
TagInfo(0x2608, "AFAreaWidths", N_("AF Area Widths"), N_("AF Area Widths"), canonId, makerTags, signedShort, -1, printValue),
471+
TagInfo(0x2609, "AFAreaHeights", N_("AF Area Heights"), N_("AF Area Heights"), canonId, makerTags, signedShort, -1, printValue),
472+
TagInfo(0x260a, "AFXPositions", N_("AF X Positions"), N_("AF X Positions"), canonId, makerTags, signedShort, -1, printValue),
473+
TagInfo(0x260b, "AFYPositions", N_("AF Y Positions"), N_("AF Y Positions"), canonId, makerTags, signedShort, -1, printValue),
474+
TagInfo(0x260c, "AFPointsInFocus", N_("AF Points in Focus"), N_("AF Points in Focus"), canonId, makerTags, signedShort, -1,printBitmask),
475+
TagInfo(0x260d, "AFPointsSelected", N_("AF Points Selected"), N_("AF Points Selected"), canonId, makerTags, signedShort, -1, printBitmask),
476+
TagInfo(0x260e, "AFPrimaryPoint", N_("AF Primary Point"), N_("AF Primary Point"), canonId, makerTags, signedShort, -1, printBitmask),
445477
TagInfo(0x4001, "ColorData", N_("Color Data"), N_("Color data"), canonId, makerTags, unsignedShort, -1, printValue),
446478
// End of list marker
447479
TagInfo(0xffff, "(UnknownCanonMakerNoteTag)", "(UnknownCanonMakerNoteTag)", N_("Unknown CanonMakerNote tag"), canonId, makerTags, asciiString, -1, printValue)

src/exif.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,23 @@ namespace Exiv2 {
651651
"Exif.Image.StripByteCounts",
652652
"Exif.Image.JPEGInterchangeFormat",
653653
"Exif.Image.JPEGInterchangeFormatLength",
654-
"Exif.Image.SubIFDs"
654+
"Exif.Image.SubIFDs",
655+
// Issue 981. Never allow manufactured data to be written
656+
"Exif.Canon.AFInfoSize",
657+
"Exif.Canon.AFAreaMode",
658+
"Exif.Canon.AFNumPoints",
659+
"Exif.Canon.AFValidPoints",
660+
"Exif.Canon.AFCanonImageWidth",
661+
"Exif.Canon.AFCanonImageHeight",
662+
"Exif.Canon.AFImageWidth",
663+
"Exif.Canon.AFImageHeight",
664+
"Exif.Canon.AFAreaWidths",
665+
"Exif.Canon.AFAreaHeights",
666+
"Exif.Canon.AFXPositions",
667+
"Exif.Canon.AFYPositions",
668+
"Exif.Canon.AFPointsInFocus",
669+
"Exif.Canon.AFPointsSelected",
670+
"Exif.Canon.AFPrimaryPoint",
655671
};
656672
for (unsigned int i = 0; i < EXV_COUNTOF(filteredIfd0Tags); ++i) {
657673
ExifData::iterator pos = ed.findKey(ExifKey(filteredIfd0Tags[i]));

src/tags_int.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1944,7 +1944,7 @@ namespace Exiv2 {
19441944
TagInfo(0xb002, "MPFImageList", N_("MPFImageList"),
19451945
N_("MPF Image List"),
19461946
mpfId, mpfTags, asciiString, 0, printValue),
1947-
TagInfo(0xb003, "MPFImageUIDList", N_("MPFImageUIDList "),
1947+
TagInfo(0xb003, "MPFImageUIDList", N_("MPFImageUIDList "),
19481948
N_("MPF Image UID List"),
19491949
mpfId, mpfTags, unsignedLong, 1, printValue),
19501950
TagInfo(0xb004, "MPFTotalFrames", N_("MPFTotalFrames"),
@@ -2164,6 +2164,32 @@ namespace Exiv2 {
21642164
return os << value;
21652165
}
21662166

2167+
std::ostream& printBitmask(std::ostream& os, const Value& value, const ExifData* metadata)
2168+
{
2169+
if (value.typeId() == Exiv2::unsignedShort || value.typeId() == Exiv2::signedShort)
2170+
{
2171+
uint16_t bit = 0;
2172+
uint16_t comma = 0;
2173+
for (uint16_t i = 0; i < value.count(); i++ ) { // for each element in value array
2174+
uint16_t bits = static_cast<uint16_t>(value.toLong(i));
2175+
for (uint16_t b = 0; b < 16; ++b) { // for every bit
2176+
if (bits & (1 << b)) {
2177+
if ( comma++ ) {
2178+
os << ",";
2179+
}
2180+
os << bit;
2181+
}
2182+
bit++ ;
2183+
}
2184+
}
2185+
// if no bits are set, print "(none)"
2186+
if ( !comma ) os << N_("(none)");
2187+
} else {
2188+
printValue(os,value,metadata);
2189+
}
2190+
return os;
2191+
}
2192+
21672193
float fnumber(float apertureValue)
21682194
{
21692195
return std::exp(std::log(2.0f) * apertureValue / 2.f);

src/tags_int.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,8 @@ namespace Exiv2 {
440440
std::ostream& printXmpVersion(std::ostream& os, const Value& value, const ExifData*);
441441
//! Print a date following the format YYYY-MM-DDTHH:MM:SSZ
442442
std::ostream& printXmpDate(std::ostream& os, const Value& value, const ExifData*);
443+
//! Print a bitmask as (none) | n | n,m... where: (none) = no bits set | n = bit n from left (0=left-most) | n,m.. = multiple bits "
444+
std::ostream& printBitmask(std::ostream& os, const Value& value, const ExifData*);
443445
//@}
444446

445447
//! Calculate F number from an APEX aperture value

src/tiffimage_int.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1514,7 +1514,8 @@ namespace Exiv2 {
15141514
{ "*", Tag::all, ignoreId, 0, 0 }, // Do not decode tags with group == ignoreId
15151515
{ "*", 0x02bc, ifd0Id, &TiffDecoder::decodeXmp, 0 /*done before the tree is traversed*/ },
15161516
{ "*", 0x83bb, ifd0Id, &TiffDecoder::decodeIptc, 0 /*done before the tree is traversed*/ },
1517-
{ "*", 0x8649, ifd0Id, &TiffDecoder::decodeIptc, 0 /*done before the tree is traversed*/ }
1517+
{ "*", 0x8649, ifd0Id, &TiffDecoder::decodeIptc, 0 /*done before the tree is traversed*/ },
1518+
{ "*", 0x0026, canonId, &TiffDecoder::decodeCanonAFInfo, 0 /* Exiv2.Canon.AFInfo is read-only */ },
15181519
};
15191520

15201521
DecoderFct TiffMapping::findDecoder(const std::string& make,

src/tiffvisitor_int.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <iomanip>
4646
#include <cassert>
4747
#include <limits>
48+
#include <ostream>
4849

4950
// *****************************************************************************
5051
namespace {
@@ -462,6 +463,78 @@ namespace Exiv2 {
462463
}
463464
} // TiffMetadataDecoder::decodeIptc
464465

466+
static const TagInfo* findTag(const TagInfo* pList,uint16_t tag)
467+
{
468+
while ( pList->tag_ != 0xffff && pList->tag_ != tag ) pList++;
469+
return pList->tag_ != 0xffff ? pList : NULL;
470+
}
471+
472+
void TiffDecoder::decodeCanonAFInfo(const TiffEntryBase* object) {
473+
// report Exif.Canon.AFInfo as usual
474+
TiffDecoder::decodeStdTiffEntry(object);
475+
if ( object->pValue()->count() < 3 || object->pValue()->typeId() != unsignedShort ) return; // insufficient data
476+
477+
// create vector of signedShorts from unsignedShorts in Exif.Canon.AFInfo
478+
std::vector<int16_t> ints;
479+
std::vector<uint16_t> uint;
480+
for (int i = 0; i < object->pValue()->count(); i++) {
481+
ints.push_back((int16_t) object->pValue()->toLong(i));
482+
uint.push_back((uint16_t) object->pValue()->toLong(i));
483+
}
484+
// Check this is AFInfo2 (ints[0] = bytes in object)
485+
if ( ints[0] != object->pValue()->count()*2 ) return ;
486+
487+
std::string familyGroup(std::string("Exif.") + groupName(object->group()) + ".");
488+
489+
const uint16_t nPoints = uint.at(2);
490+
const uint16_t nMasks = (nPoints+15)/(sizeof(uint16_t) * 8);
491+
int nStart = 0;
492+
493+
struct {
494+
uint16_t tag ;
495+
uint16_t size ;
496+
bool bSigned;
497+
} records[] = {
498+
{ 0x2600 , 1 , true }, // AFInfoSize
499+
{ 0x2601 , 1 , true }, // AFAreaMode
500+
{ 0x2602 , 1 , true }, // AFNumPoints
501+
{ 0x2603 , 1 , true }, // AFValidPoints
502+
{ 0x2604 , 1 , true }, // AFCanonImageWidth
503+
{ 0x2605 , 1 , true }, // AFCanonImageHeight
504+
{ 0x2606 , 1 , true }, // AFImageWidth"
505+
{ 0x2607 , 1 , true }, // AFImageHeight
506+
{ 0x2608 , nPoints , true }, // AFAreaWidths
507+
{ 0x2609 , nPoints , true }, // AFAreaHeights
508+
{ 0x260a , nPoints , true }, // AFXPositions
509+
{ 0x260b , nPoints , true }, // AFYPositions
510+
{ 0x260c , nMasks , false }, // AFPointsInFocus
511+
{ 0x260d , nMasks , false }, // AFPointsSelected
512+
{ 0x260e , nMasks , false }, // AFPrimaryPoint
513+
{ 0xffff , 0 , true } // end marker
514+
};
515+
// check we have enough data!
516+
uint16_t count = 0;
517+
for ( uint16_t i = 0; records[i].tag != 0xffff ; i++) count += records[i].size ;
518+
if ( count > ints.size() ) return ;
519+
520+
for ( uint16_t i = 0; records[i].tag != 0xffff ; i++) {
521+
const TagInfo* pTags = ExifTags::tagList("Canon") ;
522+
const TagInfo* pTag = findTag(pTags,records[i].tag);
523+
if ( pTag ) {
524+
auto v = Exiv2::Value::create(records[i].bSigned?Exiv2::signedShort:Exiv2::unsignedShort);
525+
std::ostringstream s;
526+
if ( records[i].bSigned ) {
527+
for ( int16_t k = 0 ; k < records[i].size ; k++ ) s << " " << ints.at(nStart++);
528+
} else {
529+
for ( int16_t k = 0 ; k < records[i].size ; k++ ) s << " " << uint.at(nStart++);
530+
}
531+
532+
v->read(s.str());
533+
exifData_[familyGroup + pTag->name_] = *v;
534+
}
535+
}
536+
}
537+
465538
void TiffDecoder::decodeTiffEntry(const TiffEntryBase* object)
466539
{
467540
assert(object != 0);

src/tiffvisitor_int.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ namespace Exiv2 {
331331
void decodeIptc(const TiffEntryBase* object);
332332
//! Decode XMP packet from an XMLPacket tag
333333
void decodeXmp(const TiffEntryBase* object);
334+
//! Decode Exif.Canon.AFInfo
335+
void decodeCanonAFInfo(const TiffEntryBase* object);
334336
//@}
335337

336338
private:

test/data/test_issue_981a.exv

13.8 KB
Binary file not shown.

test/data/test_issue_981b.exv

17.7 KB
Binary file not shown.

test/data/test_issue_981c.exv

58.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)