#800: Added and unified support for multiple IRB types (8BIM, AgHg, DCSR, PHUT) in JPEG and PSD images

v0.27.3
vog 14 years ago
parent 2a7fa8b157
commit 72013d4147

@ -86,10 +86,21 @@ namespace Exiv2 {
const char JpegBase::xmpId_[] = "http://ns.adobe.com/xap/1.0/\0"; const char JpegBase::xmpId_[] = "http://ns.adobe.com/xap/1.0/\0";
const char Photoshop::ps3Id_[] = "Photoshop 3.0\0"; const char Photoshop::ps3Id_[] = "Photoshop 3.0\0";
const char Photoshop::bimId_[] = "8BIM"; const char* Photoshop::irbId_[] = {"8BIM", "AgHg", "DCSR", "PHUT"};
const uint16_t Photoshop::iptc_ = 0x0404; const uint16_t Photoshop::iptc_ = 0x0404;
const uint16_t Photoshop::preview_ = 0x040c; const uint16_t Photoshop::preview_ = 0x040c;
bool Photoshop::isIrb(const byte* pPsData,
long sizePsData)
{
if (sizePsData < 4) return false;
for (size_t i = 0; i < (sizeof irbId_) / (sizeof *irbId_); i++) {
assert(strlen(irbId_[i]) == 4);
if (memcmp(pPsData, irbId_[i], 4) == 0) return true;
}
return false;
}
bool Photoshop::valid(const byte* pPsData, bool Photoshop::valid(const byte* pPsData,
long sizePsData) long sizePsData)
{ {
@ -126,8 +137,7 @@ namespace Exiv2 {
std::cerr << "Photoshop::locateIrb: "; std::cerr << "Photoshop::locateIrb: ";
#endif #endif
// Data should follow Photoshop format, if not exit // Data should follow Photoshop format, if not exit
while ( position <= sizePsData - 12 while (position <= sizePsData - 12 && isIrb(pPsData + position, 4)) {
&& memcmp(pPsData + position, Photoshop::bimId_, 4) == 0) {
const byte *hrd = pPsData + position; const byte *hrd = pPsData + position;
position += 4; position += 4;
uint16_t type = getUShort(pPsData + position, bigEndian); uint16_t type = getUShort(pPsData + position, bigEndian);
@ -237,7 +247,7 @@ namespace Exiv2 {
DataBuf rawIptc = IptcParser::encode(iptcData); DataBuf rawIptc = IptcParser::encode(iptcData);
if (rawIptc.size_ > 0) { if (rawIptc.size_ > 0) {
byte tmpBuf[12]; byte tmpBuf[12];
std::memcpy(tmpBuf, Photoshop::bimId_, 4); std::memcpy(tmpBuf, Photoshop::irbId_[0], 4);
us2Data(tmpBuf + 4, iptc_, bigEndian); us2Data(tmpBuf + 4, iptc_, bigEndian);
tmpBuf[6] = 0; tmpBuf[6] = 0;
tmpBuf[7] = 0; tmpBuf[7] = 0;

@ -64,10 +64,20 @@ namespace Exiv2 {
struct EXIV2API Photoshop { struct EXIV2API Photoshop {
// Todo: Public for now // Todo: Public for now
static const char ps3Id_[]; //!< %Photoshop marker static const char ps3Id_[]; //!< %Photoshop marker
static const char bimId_[]; //!< %Photoshop marker static const char* irbId_[]; //!< %Photoshop IRB markers
static const uint16_t iptc_; //!< %Photoshop IPTC marker static const uint16_t iptc_; //!< %Photoshop IPTC marker
static const uint16_t preview_; //!< %Photoshop preview marker static const uint16_t preview_; //!< %Photoshop preview marker
/*!
@brief Checks an IRB
@param pPsData Existing IRB buffer
@param sizePsData Size of the IRB buffer
@return true if the IRB marker is known and the buffer is big enough to check this;<BR>
false otherwise
*/
static bool isIrb(const byte* pPsData,
long sizePsData);
/*! /*!
@brief Validates all IRBs @brief Validates all IRBs

@ -39,6 +39,7 @@ EXIV2_RCSID("@(#) $Id$")
# include "exv_conf.h" # include "exv_conf.h"
#endif #endif
#include "psdimage.hpp" #include "psdimage.hpp"
#include "jpgimage.hpp"
#include "image.hpp" #include "image.hpp"
#include "basicio.hpp" #include "basicio.hpp"
#include "error.hpp" #include "error.hpp"
@ -56,11 +57,9 @@ EXIV2_RCSID("@(#) $Id$")
// Extend this helper to a proper class with all required functionality, // Extend this helper to a proper class with all required functionality,
// then move it here or into a separate file? // then move it here or into a separate file?
const uint32_t kPhotoshopResourceType = 0x3842494d; // '8BIM'
//! @cond IGNORE //! @cond IGNORE
struct PhotoshopResourceBlock { struct PhotoshopResourceBlock {
uint32_t resourceType; // always kPhotoshopResourceType uint32_t resourceType; // one of the markers in Photoshop::irbId_[]
uint16_t resourceId; uint16_t resourceId;
unsigned char resourceName[2]; // Pascal string (length byte + characters), padded to an even size -- this assumes the empty string unsigned char resourceName[2]; // Pascal string (length byte + characters), padded to an even size -- this assumes the empty string
uint32_t resourceDataSize; uint32_t resourceDataSize;
@ -215,14 +214,11 @@ namespace Exiv2 {
throw Error(3, "Photoshop"); throw Error(3, "Photoshop");
} }
// read resource type and ID if (!Photoshop::isIrb(buf, 4))
uint32_t resourceType = getULong(buf, bigEndian);
uint16_t resourceId = getUShort(buf + 4, bigEndian);
if (resourceType != kPhotoshopResourceType)
{ {
break; // bad resource type break; // bad resource type
} }
uint16_t resourceId = getUShort(buf + 4, bigEndian);
uint32_t resourceNameLength = buf[6] & ~1; uint32_t resourceNameLength = buf[6] & ~1;
// skip the resource name, plus any padding // skip the resource name, plus any padding
@ -447,7 +443,8 @@ namespace Exiv2 {
// read resource type and ID // read resource type and ID
uint32_t resourceType = getULong(buf, bigEndian); uint32_t resourceType = getULong(buf, bigEndian);
if (resourceType != kPhotoshopResourceType) { if (!Photoshop::isIrb(buf, 4))
{
throw Error(3, "Photoshop"); // bad resource type throw Error(3, "Photoshop"); // bad resource type
} }
uint16_t resourceId = getUShort(buf + 4, bigEndian); uint16_t resourceId = getUShort(buf + 4, bigEndian);
@ -493,11 +490,12 @@ namespace Exiv2 {
&& resourceId != kPhotoshopResourceID_ExifInfo && resourceId != kPhotoshopResourceID_ExifInfo
&& resourceId != kPhotoshopResourceID_XMPPacket) { && resourceId != kPhotoshopResourceID_XMPPacket) {
#ifdef DEBUG #ifdef DEBUG
std::cerr << std::hex << "copy : resourceType: " << resourceType << "\n";
std::cerr << std::hex << "copy : resourceId: " << resourceId << "\n"; std::cerr << std::hex << "copy : resourceId: " << resourceId << "\n";
std::cerr << std::dec; std::cerr << std::dec;
#endif #endif
// Copy resource block to new PSD file // Copy resource block to new PSD file
ul2Data(buf, kPhotoshopResourceType, bigEndian); ul2Data(buf, resourceType, bigEndian);
if (outIo.write(buf, 4) != 4) throw Error(21); if (outIo.write(buf, 4) != 4) throw Error(21);
us2Data(buf, resourceId, bigEndian); us2Data(buf, resourceId, bigEndian);
if (outIo.write(buf, 2) != 2) throw Error(21); if (outIo.write(buf, 2) != 2) throw Error(21);
@ -577,8 +575,7 @@ namespace Exiv2 {
std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_IPTC_NAA << "\n"; std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_IPTC_NAA << "\n";
std::cerr << std::dec << "Writing IPTC_NAA: size: " << rawIptc.size_ << "\n"; std::cerr << std::dec << "Writing IPTC_NAA: size: " << rawIptc.size_ << "\n";
#endif #endif
ul2Data(buf, kPhotoshopResourceType, bigEndian); if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4) throw Error(21);
if (out.write(buf, 4) != 4) throw Error(21);
us2Data(buf, kPhotoshopResourceID_IPTC_NAA, bigEndian); us2Data(buf, kPhotoshopResourceID_IPTC_NAA, bigEndian);
if (out.write(buf, 2) != 2) throw Error(21); if (out.write(buf, 2) != 2) throw Error(21);
us2Data(buf, 0, bigEndian); // NULL resource name us2Data(buf, 0, bigEndian); // NULL resource name
@ -618,8 +615,7 @@ namespace Exiv2 {
std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_ExifInfo << "\n"; std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_ExifInfo << "\n";
std::cerr << std::dec << "Writing ExifInfo: size: " << blob.size() << "\n"; std::cerr << std::dec << "Writing ExifInfo: size: " << blob.size() << "\n";
#endif #endif
ul2Data(buf, kPhotoshopResourceType, bigEndian); if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4) throw Error(21);
if (out.write(buf, 4) != 4) throw Error(21);
us2Data(buf, kPhotoshopResourceID_ExifInfo, bigEndian); us2Data(buf, kPhotoshopResourceID_ExifInfo, bigEndian);
if (out.write(buf, 2) != 2) throw Error(21); if (out.write(buf, 2) != 2) throw Error(21);
us2Data(buf, 0, bigEndian); // NULL resource name us2Data(buf, 0, bigEndian); // NULL resource name
@ -663,8 +659,7 @@ namespace Exiv2 {
std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_XMPPacket << "\n"; std::cerr << std::hex << "write: resourceId: " << kPhotoshopResourceID_XMPPacket << "\n";
std::cerr << std::dec << "Writing XMPPacket: size: " << xmpPacket.size() << "\n"; std::cerr << std::dec << "Writing XMPPacket: size: " << xmpPacket.size() << "\n";
#endif #endif
ul2Data(buf, kPhotoshopResourceType, bigEndian); if (out.write(reinterpret_cast<const byte*>(Photoshop::irbId_[0]), 4) != 4) throw Error(21);
if (out.write(buf, 4) != 4) throw Error(21);
us2Data(buf, kPhotoshopResourceID_XMPPacket, bigEndian); us2Data(buf, kPhotoshopResourceID_XMPPacket, bigEndian);
if (out.write(buf, 2) != 2) throw Error(21); if (out.write(buf, 2) != 2) throw Error(21);
us2Data(buf, 0, bigEndian); // NULL resource name us2Data(buf, 0, bigEndian); // NULL resource name

@ -210,6 +210,17 @@ cp -f ../data/exiv2-empty.jpg $filename
$bin/exiv2 -u -v -M"add Exif.Image.Make Canon" -M"add Exif.CanonCs.0x0001 Short 1" -M"add Exif.CanonCs.0x0000 Short 2" $filename $bin/exiv2 -u -v -M"add Exif.Image.Make Canon" -M"add Exif.CanonCs.0x0001 Short 1" -M"add Exif.CanonCs.0x0000 Short 2" $filename
$bin/exiv2 -u -v -PEkyct $filename $bin/exiv2 -u -v -PEkyct $filename
num=800
for type in 8BIM AgHg DCSR PHUT; do
for format in jpg psd; do
echo "------> Bug $num ($type in $format) <-------" >&2
filename=exiv2-bug$num-$type.$format
cp -f ../data/$filename .
$bin/exiv2 -u -v -M'set Exif.Photo.UserComment Test' $filename
$bin/exiv2 -u -pt $filename
done
done
) > $results 2>&1 ) > $results 2>&1
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.
Loading…
Cancel
Save