Improved Panasonic RW2 decoder: now uses a dedicated PanasonicRaw tag table and reads Exif data from embedded preview image.

v0.27.3
Andreas Huggel 17 years ago
parent 808494f0a1
commit afe8efcc31

@ -52,7 +52,7 @@ TABLES = Exif \
Nikon1 Nikon2 Nikon3 \
Olympus OlympusCs OlympusEq OlympusRd OlympusRd2 \
OlympusIp OlympusFi OlympusFe1 OlympusRi \
Panasonic \
Panasonic PanasonicRaw \
Pentax \
Sigma \
Sony

@ -13,6 +13,13 @@ __index2__
</div>
__Panasonic__
</div>
<h2>Panasonic RAW Tags defined in Exiv2</h2>
<div>
<p>Tags found in IFD0 of Panasonic RAW and RW2 images.</p>
<p>Click on a column header to sort the table.</p>
</div>
__PanasonicRaw__
</div>
<!-- closes content -->
</body>

@ -324,4 +324,38 @@ namespace Exiv2 {
} // PanasonicMakerNote::print0x0023
// Panasonic MakerNote Tag Info
const TagInfo PanasonicMakerNote::tagInfoRaw_[] = {
TagInfo(0x0001, "Version", N_("Version"), N_("Panasonic raw version"), panaRawIfdId, panaRaw, undefined, printExifVersion),
TagInfo(0x0002, "SensorWidth", N_("Sensor Width"), N_("Sensor width"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0003, "SensorHeight", N_("Sensor Height"), N_("Sensor height"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0004, "SensorTopBorder", N_("Sensor Top Border"), N_("Sensor top border"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0005, "SensorLeftBorder", N_("Sensor Left Border"), N_("Sensor left border"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0006, "ImageHeight", N_("Image Height"), N_("Image height"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0007, "ImageWidth", N_("Image Width"), N_("Image width"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0011, "RedBalance", N_("Red Balance"), N_("Red balance (found in Digilux 2 RAW images)"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0012, "BlueBalance", N_("Blue Balance"), N_("Blue balance"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0017, "ISOSpeed", N_("ISO Speed"), N_("ISO speed setting"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0024, "WBRedLevel", N_("WB Red Level"), N_("WB red level"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0025, "WBGreenLevel", N_("WB Green Level"), N_("WB green level"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0026, "WBBlueLevel", N_("WB Blue Level"), N_("WB blue level"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x002e, "PreviewImage", N_("Preview Image"), N_("Preview image"), panaRawIfdId, panaRaw, undefined, printValue),
TagInfo(0x010f, "Make", N_("Manufacturer"), N_("The manufacturer of the recording equipment"), panaRawIfdId, panaRaw, asciiString, printValue),
TagInfo(0x0110, "Model", N_("Model"), N_("The model name or model number of the equipment"), panaRawIfdId, panaRaw, asciiString, printValue),
TagInfo(0x0111, "StripOffsets", N_("Strip Offsets"), N_("Strip offsets"), panaRawIfdId, panaRaw, unsignedLong, printValue),
TagInfo(0x0112, "Orientation", N_("Orientation"), N_("Orientation"), panaRawIfdId, panaRaw, unsignedShort, print0x0112),
TagInfo(0x0116, "RowsPerStrip", N_("Rows Per Strip"), N_("The number of rows per strip"), panaRawIfdId, panaRaw, unsignedShort, printValue),
TagInfo(0x0117, "StripByteCounts", N_("Strip Byte Counts"), N_("Strip byte counts"), panaRawIfdId, panaRaw, unsignedLong, printValue),
TagInfo(0x0118, "RawDataOffset", N_("Raw Data Offset"), N_("Raw data offset"), panaRawIfdId, panaRaw, unsignedLong, printValue),
TagInfo(0x8769, "ExifTag", N_("Exif IFD Pointer"), N_("A pointer to the Exif IFD"), panaRawIfdId, panaRaw, unsignedLong, printValue),
TagInfo(0x8825, "GPSTag", N_("GPS Info IFD Pointer"), N_("A pointer to the GPS Info IFD"), panaRawIfdId, panaRaw, unsignedLong, printValue),
// End of list marker
TagInfo(0xffff, "(UnknownPanasonicRawTag)", "(UnknownPanasonicRawTag)", N_("Unknown PanasonicRaw tag"), panaRawIfdId, panaRaw, invalidTypeId, printValue)
};
const TagInfo* PanasonicMakerNote::tagListRaw()
{
return tagInfoRaw_;
}
} // namespace Exiv2

@ -55,6 +55,8 @@ namespace Exiv2 {
public:
//! Return read-only list of built-in Panasonic tags
static const TagInfo* tagList();
//! Return read-only list of built-in Panasonic RAW image tags (IFD0)
static const TagInfo* tagListRaw();
//! @name Print functions for Panasonic %MakerNote tags
//@{
@ -65,8 +67,10 @@ namespace Exiv2 {
//@}
private:
//! Tag information
//! Makernote tag list
static const TagInfo tagInfo_[];
//! Taglist for IFD0 of Panasonic RAW images
static const TagInfo tagInfoRaw_[];
}; // class PanasonicMakerNote

@ -283,7 +283,7 @@ namespace {
{ "Exif.Olympus.ThumbnailImage", 0 }, // 4
{ "Exif.Olympus2.ThumbnailImage", 0 }, // 5
{ "Exif.Minolta.Thumbnail", 0 }, // 6
{ "Exif.Image.0x002e", 0 } // 7
{ "Exif.PanasonicRaw.PreviewImage", 0 } // 7
};
const LoaderTiff::Param LoaderTiff::param_[] = {

@ -42,6 +42,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "tiffcomposite_int.hpp"
#include "tiffimage_int.hpp"
#include "image.hpp"
#include "preview.hpp"
#include "error.hpp"
#include "futils.hpp"
@ -63,7 +64,8 @@ namespace Exiv2 {
int Rw2Image::pixelWidth() const
{
ExifData::const_iterator imageWidth = exifData_.findKey(Exiv2::ExifKey("Exif.Image.0x0007"));
ExifData::const_iterator imageWidth =
exifData_.findKey(Exiv2::ExifKey("Exif.PanasonicRaw.SensorWidth"));
if (imageWidth != exifData_.end() && imageWidth->count() > 0) {
return imageWidth->toLong();
}
@ -72,7 +74,8 @@ namespace Exiv2 {
int Rw2Image::pixelHeight() const
{
ExifData::const_iterator imageHeight = exifData_.findKey(Exiv2::ExifKey("Exif.Image.0x0006"));
ExifData::const_iterator imageHeight =
exifData_.findKey(Exiv2::ExifKey("Exif.PanasonicRaw.SensorHeight"));
if (imageHeight != exifData_.end() && imageHeight->count() > 0) {
return imageHeight->toLong();
}
@ -118,6 +121,33 @@ namespace Exiv2 {
io_->mmap(),
io_->size());
setByteOrder(bo);
// A lot more metadata is hidden in the embedded preview image
// Todo: This should go into the Rw2Parser, but for that it needs the Image
PreviewManager loader(*this);
PreviewPropertiesList list = loader.getPreviewProperties();
// Todo: What if there are more preview images?
if (list.size() > 1) {
#ifndef SUPPRESS_WARNINGS
std::cerr << "Warning: RW2 image contains more than one preview. None used.\n";
#endif
}
if (list.size() != 1) return;
ExifData exifData;
PreviewImage preview = loader.getPreviewImage(*list.begin());
Image::AutoPtr image = ImageFactory::open(preview.pData(), preview.size());
if (image.get() == 0) {
#ifndef SUPPRESS_WARNINGS
std::cerr << "Warning: Failed to open RW2 preview image.\n";
#endif
return;
}
image->readMetadata();
for (ExifData::const_iterator pos = image->exifData().begin();
pos != image->exifData().end(); ++pos) {
exifData_.add(*pos);
}
} // Rw2Image::readMetadata
void Rw2Image::writeMetadata()
@ -140,7 +170,7 @@ namespace Exiv2 {
xmpData,
pData,
size,
Tag::root,
Tag::pana,
TiffMapping::findDecoder,
&rw2Header);
}

@ -38,7 +38,7 @@ try {
}
IfdId ifdId = ExifTags::ifdIdByIfdItem(item);
if (ExifTags::isMakerIfd(ifdId)) {
if (ExifTags::isExifIfd(ifdId) || ExifTags::isMakerIfd(ifdId)) {
ExifTags::taglist(std::cout, ifdId);
break;
}

@ -132,6 +132,7 @@ namespace Exiv2 {
{ olympusFe9IfdId, "Makernote", "OlympusFe9", OlympusMakerNote::tagListFe },
{ olympusRiIfdId, "Makernote", "OlympusRi", OlympusMakerNote::tagListRi },
{ panasonicIfdId, "Makernote", "Panasonic", PanasonicMakerNote::tagList },
{ panaRawIfdId, "PanaRaw", "PanasonicRaw", PanasonicMakerNote::tagListRaw },
{ pentaxIfdId, "Makernote", "Pentax", PentaxMakerNote::tagList },
{ sigmaIfdId, "Makernote", "Sigma", SigmaMakerNote::tagList },
{ sonyIfdId, "Makernote", "Sony", SonyMakerNote::tagList },
@ -155,6 +156,7 @@ namespace Exiv2 {
{ iopTags, "Interoperability", N_("Interoperability information") },
{ makerTags, "Makernote", N_("Vendor specific information") },
{ dngTags, "DngTags", N_("Adobe DNG tags") },
{ panaRaw, "PanasonicRaw", N_("Panasonic RAW tags") },
{ lastSectionId, "(LastSection)", N_("Last section") }
};
@ -1690,8 +1692,9 @@ namespace Exiv2 {
case subImage1Id:
case subImage2Id:
case subImage3Id:
case subImage4Id: rc = true; break;
default: rc = false; break;
case subImage4Id:
case panaRawIfdId: rc = true; break;
default: rc = false; break;
}
return rc;
} // ExifTags::isExifIfd

@ -66,7 +66,7 @@ namespace Exiv2 {
enum SectionId { sectionIdNotSet,
imgStruct, recOffset, imgCharacter, otherTags, exifFormat,
exifVersion, imgConfig, userInfo, relatedFile, dateTime,
captureCond, gpsTags, iopTags, makerTags, dngTags,
captureCond, gpsTags, iopTags, makerTags, dngTags, panaRaw,
lastSectionId };
// *****************************************************************************

@ -79,6 +79,7 @@ namespace Exiv2 {
{ 8, "SubImage2" },
{ 9, "SubImage3" },
{ 10, "SubImage4" },
{ 64, "PanasonicRaw" },
{ 256, "MakerNote" },
// 257 not needed (olympmn)
{ 258, "Fujifilm" },

@ -77,6 +77,9 @@ namespace Exiv2 {
Todo: what exactly are these and where should they go?
Are they going to be mapped to the second part of an Exif key or are they
the second part of the key?
@note Groups with ids > mn are Makernote groups and get treated slightly
differently.
*/
namespace Group {
const uint16_t none = 0; //!< Dummy group
@ -90,6 +93,7 @@ namespace Exiv2 {
const uint16_t subimg2 = 8; //!< 2nd TIFF SubIFD in IFD0
const uint16_t subimg3 = 9; //!< 3rd TIFF SubIFD in IFD0
const uint16_t subimg4 = 10; //!< 4th TIFF SubIFD in IFD0
const uint16_t panaraw = 64; //!< IFD0 of Panasonic RAW images
const uint16_t mn = 256; //!< Makernote
const uint16_t ignr = 511; //!< Read but do not decode
}
@ -104,6 +108,7 @@ namespace Exiv2 {
const uint32_t root = 0x20000; //!< Special tag: root IFD
const uint32_t next = 0x30000; //!< Special tag: next IFD
const uint32_t all = 0x40000; //!< Special tag: all tags in a group
const uint32_t pana = 0x80000; //!< Special tag: root IFD of Panasonic RAW images
}
/*!

@ -313,7 +313,13 @@ namespace Exiv2 {
{ Tag::root, Group::minocso, Group::minoltamn, 0x0001 },
{ Tag::root, Group::minocsn, Group::minoltamn, 0x0003 },
{ Tag::root, Group::minocs7, Group::minoltamn, 0x0004 },
{ Tag::root, Group::minocs5, Group::minoltamn, 0x0114 }
{ Tag::root, Group::minocs5, Group::minoltamn, 0x0114 },
// ---------------------------------------------------------
// Panasonic RW2 raw images
{ Tag::pana, Group::none, Group::none, Tag::pana },
{ Tag::pana, Group::panaraw, Group::none, Tag::pana },
{ Tag::pana, Group::exif, Group::panaraw, 0x8769 },
{ Tag::pana, Group::gps, Group::panaraw, 0x8825 }
};
/*
@ -572,6 +578,19 @@ namespace Exiv2 {
{ Tag::all, Group::minocs7, newTiffArrayElement<ttUnsignedShort, bigEndian> },
{ Tag::all, Group::minocs5, newTiffArrayElement<ttUnsignedShort, bigEndian> },
// -----------------------------------------------------------------------
// Root directory of Panasonic RAW images
{ Tag::pana, Group::none, newTiffDirectory<Group::panaraw> },
// IFD0 of Panasonic RAW images
{ 0x8769, Group::panaraw, newTiffSubIfd<Group::exif> },
{ 0x8825, Group::panaraw, newTiffSubIfd<Group::gps> },
// { 0x0111, Group::panaraw, newTiffImageData<0x0117, Group::panaraw> },
// { 0x0117, Group::panaraw, newTiffImageSize<0x0111, Group::panaraw> },
{ Tag::next, Group::panaraw, newTiffDirectory<Group::ignr> },
{ Tag::all, Group::panaraw, newTiffEntry },
// -----------------------------------------------------------------------
// Tags which are not de/encoded
{ Tag::next, Group::ignr, newTiffDirectory<Group::ignr> },
{ Tag::all, Group::ignr, newTiffEntry }

@ -149,7 +149,8 @@ namespace Exiv2 {
olympusFe1IfdId, olympusFe2IfdId, olympusFe3IfdId, olympusFe4IfdId,
olympusFe5IfdId, olympusFe6IfdId, olympusFe7IfdId, olympusFe8IfdId,
olympusFe9IfdId, olympusRiIfdId,
panasonicIfdId, pentaxIfdId, sigmaIfdId, sonyIfdId,
panasonicIfdId, panaRawIfdId,
pentaxIfdId, sigmaIfdId, sonyIfdId,
lastIfdId };
//! Container for binary data

Loading…
Cancel
Save