@@ -59,19 +59,15 @@ namespace Exiv2 {
5959
6060 int RafImage::pixelWidth () const
6161 {
62- Exiv2::ExifData::const_iterator widthIter = exifData_.findKey (Exiv2::ExifKey (" Exif.Photo.PixelXDimension" ));
63- if (widthIter != exifData_.end () && widthIter->count () > 0 ) {
64- return widthIter->toLong ();
65- }
62+ if (pixelWidth_ != 0 ) return pixelWidth_;
63+
6664 return 0 ;
6765 }
6866
6967 int RafImage::pixelHeight () const
7068 {
71- Exiv2::ExifData::const_iterator heightIter = exifData_.findKey (Exiv2::ExifKey (" Exif.Photo.PixelYDimension" ));
72- if (heightIter != exifData_.end () && heightIter->count () > 0 ) {
73- return heightIter->toLong ();
74- }
69+ if (pixelHeight_ != 0 ) return pixelHeight_;
70+
7571 return 0 ;
7672 }
7773
@@ -313,8 +309,64 @@ namespace Exiv2 {
313309
314310 enforce (jpg_img_len >= 12 , kerCorruptedMetadata);
315311
312+ /* Look for the height and width of the raw image in the raf metadata header.
313+ * Raf metadata starts with 4 bytes giving the number of available tags,
314+ * followed by the tags. Each tag starts with two bytes with the tag id and
315+ * two bytes with the tag size, followed by the actual tag data.
316+ * The image width and height have the tag id of 0x0100.
317+ * For more tag ids have a look at e.g. exiftool.
318+ */
319+ byte cfa_header_offset [4 ];
320+ if (io_->read (cfa_header_offset, 4 ) != 4 ) throw Error (kerFailedToReadImageData);
321+ byte cfa_header_length [4 ];
322+ if (io_->read (cfa_header_length, 4 ) != 4 ) throw Error (kerFailedToReadImageData);
323+ uint32_t cfa_hdr_off_u32 = Exiv2::getULong ((const byte *) cfa_header_offset, bigEndian);
324+ uint32_t cfa_hdr_len_u32 = Exiv2::getULong ((const byte *) cfa_header_length, bigEndian);
325+
326+ enforce (Safe::add (cfa_hdr_off_u32, cfa_hdr_len_u32) <= io_->size (), kerCorruptedMetadata);
327+
328+ long cfa_hdr_off = static_cast <long >(cfa_hdr_off_u32);
329+
330+ if (io_->seek (cfa_hdr_off, BasicIo::beg) != 0 ) throw Error (kerFailedToReadImageData);
331+
332+ byte tag_count[4 ];
333+ if (io_->read (tag_count, 4 ) != 4 ) throw Error (kerFailedToReadImageData);
334+ uint32_t count = getULong (tag_count, bigEndian);
335+ // check that the count value is in a sane range
336+ // assume a size of 4 bytes, but raf tags may also be larger
337+ enforce (count < cfa_hdr_len_u32 / 4 , kerCorruptedMetadata);
338+
339+ byte byte_tag[2 ];
340+ byte byte_size[2 ];
341+ uint16_t tag;
342+ uint16_t tag_size;
343+
344+ for (uint32_t i = 0 ; i < count; ++i ) {
345+ if (io_->read (byte_tag, 2 ) != 2 || io_->read (byte_size, 2 ) != 2 ) {
346+ break ;
347+ } else {
348+ tag = getUShort (byte_tag, bigEndian);
349+ tag_size = getUShort (byte_size, bigEndian);
350+ }
351+ if (tag == 0x0100 ) {
352+ byte image_height [2 ];
353+ byte image_width [2 ];
354+ if (io_->read (image_height, 2 ) == 2 ) {
355+ pixelHeight_ = getUShort (image_height, bigEndian);
356+ }
357+ if (io_->read (image_width, 2 ) == 2 ) {
358+ pixelWidth_ = getUShort (image_width, bigEndian);
359+ }
360+ break ;
361+ } else {
362+ if (io_->seek (tag_size, BasicIo::cur) != 0 || io_->eof ()) {
363+ break ;
364+ };
365+ }
366+ } // raf metadata header
367+
316368 DataBuf buf (jpg_img_len - 12 );
317- if (io_->seek (jpg_img_off + 12 ,BasicIo::beg) != 0 ) throw Error (kerFailedToReadImageData);
369+ if (io_->seek (jpg_img_off + 12 , BasicIo::beg) != 0 ) throw Error (kerFailedToReadImageData);
318370 io_->read (buf.pData_ , buf.size_ );
319371 if (io_->error () || io_->eof ()) throw Error (kerFailedToReadImageData);
320372
0 commit comments