7373#define TAG_cmt2 0x434D5432 /* *< "CMD2" exifID */
7474#define TAG_cmt3 0x434D5433 /* *< "CMT3" canonID */
7575#define TAG_cmt4 0x434D5434 /* *< "CMT4" gpsID */
76- #define TAG_colr 0x636f6c72 /* *< "colr" */
76+ #define TAG_colr 0x636f6c72 /* *< "colr" Colour information */
7777#define TAG_exif 0x45786966 /* *< "Exif" Used by JXL*/
78- #define TAG_xml 0x786d6c20 /* *< "xml" Used by JXL*/
78+ #define TAG_xml 0x786d6c20 /* *< "xml " Used by JXL*/
79+ #define TAG_thmb 0x54484d42 /* *< "THMB" Canon thumbnail */
80+ #define TAG_prvw 0x50525657 /* *< "PRVW" Canon preview image */
7981
8082// *****************************************************************************
8183// class member definitions
@@ -124,7 +126,7 @@ namespace Exiv2
124126
125127 bool BmffImage::fullBox (uint32_t box)
126128 {
127- return box == TAG_meta || box == TAG_iinf || box == TAG_iloc;
129+ return box == TAG_meta || box == TAG_iinf || box == TAG_iloc || box == TAG_thmb || box == TAG_prvw ;
128130 }
129131
130132 static bool skipBox (uint32_t box)
@@ -264,7 +266,7 @@ namespace Exiv2
264266 enforce (data.size_ - skip >= 4 , Exiv2::kerCorruptedMetadata);
265267 flags = getLong (data.pData_ + skip, endian_); // version/flags
266268 version = static_cast <uint8_t >(flags >> 24 );
267- version &= 0x00ffffff ;
269+ flags &= 0x00ffffff ;
268270 skip += 4 ;
269271 }
270272
@@ -453,7 +455,12 @@ namespace Exiv2
453455 out << " uuidName " << name << std::endl;
454456 bLF = false ;
455457 }
456- if (name == " cano" ) {
458+ if (name == " cano" || name == " canp" ) {
459+ if (name == " canp" ) {
460+ // based on
461+ // https://github.com/lclevy/canon_cr3/blob/7be75d6/parse_cr3.py#L271
462+ io_->seek (8 , BasicIo::cur);
463+ }
457464 while (io_->tell () < box_end) {
458465 io_->seek (boxHandler (out,option,box_end,depth + 1 ), BasicIo::beg);
459466 }
@@ -480,10 +487,20 @@ namespace Exiv2
480487 case TAG_xml:
481488 parseXmp (box_length,io_->tell ());
482489 break ;
490+ case TAG_thmb:
491+ if (version == 0 ) {
492+ parseCr3Preview (data, out, bTrace, skip, skip+2 , skip+4 , skip+12 );
493+ }
494+ break ;
495+ case TAG_prvw:
496+ if (version == 0 ) {
497+ parseCr3Preview (data, out, bTrace, skip+2 , skip+4 , skip+8 , skip+12 );
498+ }
499+ break ;
483500
484501 default : break ; /* do nothing */
485502 }
486- if ( bLF&& bTrace) out << std::endl;
503+ if (bLF && bTrace) out << std::endl;
487504
488505 // return address of next box
489506 return box_end;
@@ -564,6 +581,42 @@ namespace Exiv2
564581 }
565582 }
566583
584+ void BmffImage::parseCr3Preview (DataBuf &data,
585+ std::ostream& out,
586+ bool bTrace,
587+ uint32_t width_offset,
588+ uint32_t height_offset,
589+ uint32_t size_offset,
590+ uint32_t relative_position)
591+ {
592+ // Derived from https://github.com/lclevy/canon_cr3
593+ // Only JPEG (version 0) is currently supported
594+ // (relative_position is identical between versions)
595+ long here = io_->tell ();
596+ enforce (here >= 0 &&
597+ here <= std::numeric_limits<long >::max () - static_cast <long >(relative_position),
598+ kerCorruptedMetadata);
599+ NativePreview nativePreview;
600+ nativePreview.position_ = here + relative_position;
601+ enforce (4 <= data.size_ , kerCorruptedMetadata);
602+ enforce (width_offset <= static_cast <size_t >(data.size_ - 2 ), kerCorruptedMetadata);
603+ nativePreview.width_ = getShort (data.pData_ + width_offset, endian_);
604+ enforce (height_offset <= static_cast <size_t >(data.size_ - 2 ), kerCorruptedMetadata);
605+ nativePreview.height_ = getShort (data.pData_ + height_offset, endian_);
606+ enforce (size_offset <= static_cast <size_t >(data.size_ - 4 ), kerCorruptedMetadata);
607+ nativePreview.size_ = getLong (data.pData_ + size_offset, endian_);
608+ nativePreview.filter_ = " " ;
609+ nativePreview.mimeType_ = " image/jpeg" ;
610+ nativePreviews_.push_back (nativePreview);
611+
612+ if (bTrace) {
613+ out << Internal::stringFormat (" width,height,size = %u,%u,%u" ,
614+ nativePreview.width_ ,
615+ nativePreview.height_ ,
616+ nativePreview.size_ );
617+ }
618+ }
619+
567620 void BmffImage::setComment (const std::string& /* comment*/ )
568621 {
569622 // bmff files are read-only
0 commit comments