[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a

Maximiliano Curia maxy at moszumanska.debian.org
Thu Jul 13 17:40:18 UTC 2017


Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=2ad2fb8

The following commit has been merged in the master branch:
commit 2ad2fb83d7c0a08060781686bdfb3e3dd075d94e
Author: Andreas Huggel <ahuggel at gmx.net>
Date:   Sat Jan 24 14:47:31 2009 +0000

    #606: Added IPTC write support for PSD images (Patch from Michael Ulbrich)
---
 src/psdimage.cpp | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/psdimage.hpp |   8 ++
 2 files changed, 241 insertions(+), 2 deletions(-)

diff --git a/src/psdimage.cpp b/src/psdimage.cpp
index b08e5f6..e7812f5 100644
--- a/src/psdimage.cpp
+++ b/src/psdimage.cpp
@@ -47,6 +47,9 @@ EXIV2_RCSID("@(#) $Id$")
 #include <string>
 #include <cstring>
 #include <iostream>
+#include <iomanip>
+#include <cassert>
+#include <memory>
 
 // Todo: Consolidate with existing code in struct Photoshop (jpgimage.hpp):
 //       Extend this helper to a proper class with all required functionality,
@@ -304,10 +307,238 @@ namespace Exiv2 {
 
     void PsdImage::writeMetadata()
     {
-        // Todo: implement me!
-        throw(Error(31, "Photoshop"));
+        if (io_->open() != 0)
+        {
+            throw Error(9, io_->path(), strError());
+        }
+        IoCloser closer(*io_);
+        BasicIo::AutoPtr tempIo(io_->temporary()); // may throw
+        assert (tempIo.get() != 0);
+
+        doWriteMetadata(*tempIo); // may throw
+        io_->close();
+        io_->transfer(*tempIo); // may throw
+
     } // PsdImage::writeMetadata
 
+    void PsdImage::doWriteMetadata(BasicIo& outIo)
+    {
+        if (!io_->isopen()) throw Error(20);
+        if (!outIo.isopen()) throw Error(21);
+
+#ifdef DEBUG
+        std::cout << "Exiv2::PsdImage::doWriteMetadata: Writing PSD file " << io_->path() << "
";
+        std::cout << "Exiv2::PsdImage::doWriteMetadata: tmp file created " << outIo.path() << "
";
+#endif
+
+        // Ensure that this is the correct image type
+        if (!isPsdType(*io_, true))
+        {
+            if (io_->error() || io_->eof()) throw Error(20);
+            throw Error(22);
+        }
+
+        io_->seek(0, BasicIo::beg);    // rewind
+
+        DataBuf lbuf(4096);
+        byte buf[8];
+
+        // Get Photoshop header from original file
+        byte psd_head[26];
+        if (io_->read(psd_head, 26) != 26)
+        {
+            throw Error(3, "Photoshop");
+        }
+
+        // Write Photoshop header data out to new PSD file
+        if (outIo.write(psd_head, 26) != 26) throw Error(21);
+
+        // Read colorDataLength from original PSD 
+        if (io_->read(buf, 4) != 4)
+        {
+            throw Error(3, "Photoshop");
+        }
+
+        uint32_t colorDataLength = getLong(buf, bigEndian);
+        
+        // Write colorDataLength
+        ul2Data(buf, colorDataLength, bigEndian);
+        if (outIo.write(buf, 4) != 4) throw Error(21);
+#ifdef DEBUG
+        std::cerr << std::dec << "colorDataLength: " << colorDataLength << "
";
+#endif
+        // Copy colorData
+        long readTotal = 0;
+        long toRead = 0;
+        while (readTotal < colorDataLength) {
+            toRead = colorDataLength - readTotal < lbuf.size_ ? colorDataLength - readTotal : lbuf.size_;
+            if (io_->read(lbuf.pData_, toRead) != toRead)
+            {
+                throw Error(3, "Photoshop");
+            }
+            readTotal += toRead;
+            if (outIo.write(lbuf.pData_, toRead) != toRead) throw Error(21);
+        }
+        if (outIo.error()) throw Error(21);
+
+        uint32_t resLenOffset = io_->tell();  // remember for later update
+
+        // Read length of all resource blocks from original PSD
+        if (io_->read(buf, 4) != 4)
+        {
+            throw Error(3, "Photoshop");
+        }
+
+        uint32_t oldResLength = getLong(buf, bigEndian);
+        uint32_t newResLength = 0;
+
+        // Write oldResLength (will be updated later)
+        ul2Data(buf, oldResLength, bigEndian);
+        if (outIo.write(buf, 4) != 4) throw Error(21);
+#ifdef DEBUG
+        std::cerr << std::dec << "oldResLength: " << oldResLength << "
";
+#endif
+        // Write metadata resource blocks: IPTC_NAA, (TODO: ExifInfo, XMPPacket)
+        if (iptcData_.count() > 0) {
+            DataBuf rawIptc = IptcParser::encode(iptcData_);
+            if (rawIptc.size_ > 0) {
+#ifdef DEBUG
+                std::cerr << std::dec << "Writing IPTC_NAA: size: " << rawIptc.size_ << "
";
+#endif
+                ul2Data(buf, kPhotoshopResourceType, bigEndian);
+                if (outIo.write(buf, 4) != 4) throw Error(21);
+                us2Data(buf, kPhotoshopResourceID_IPTC_NAA, bigEndian);
+                if (outIo.write(buf, 2) != 2) throw Error(21);
+                us2Data(buf, 0, bigEndian);                      // NULL resource name
+                if (outIo.write(buf, 2) != 2) throw Error(21);
+                ul2Data(buf, rawIptc.size_, bigEndian);
+                if (outIo.write(buf, 4) != 4) throw Error(21);
+                // Write encoded Iptc data
+                if (outIo.write(rawIptc.pData_, rawIptc.size_) != rawIptc.size_) throw Error(21);
+                newResLength += rawIptc.size_ + 12;
+                if (rawIptc.size_ & 1)    // even padding
+                {
+                    buf[0] = 0;
+                    if (outIo.write(buf, 1) != 1) throw Error(21);
+                    newResLength++;
+                }
+            }
+        }
+
+        // Iterate over original resource blocks and copy those not already processed
+        while (oldResLength > 0)
+        {
+            if (io_->read(buf, 8) != 8)
+            {
+                throw Error(3, "Photoshop");
+            }
+
+            // read resource type and ID
+            uint32_t resourceType = getLong(buf, bigEndian);
+            uint16_t resourceId = getShort(buf + 4, bigEndian);
+#ifdef DEBUG
+            std::cerr << std::hex << "resourceId: " << resourceId << "
";
+            std::cerr << std::dec;
+#endif
+            if (resourceType != kPhotoshopResourceType)
+            { 
+                break; // bad resource type
+            }
+            uint32_t resourceNameLength = buf[6];
+            uint32_t adjResourceNameLen = resourceNameLength & ~1;
+            unsigned char resourceNameFirstChar = buf[7];
+
+            // read rest of resource name, plus any padding
+            DataBuf resName(256);
+            if (io_->read(resName.pData_, adjResourceNameLen) != adjResourceNameLen)
+            {
+                throw Error(3, "Photoshop");
+            }
+
+            // read resource size (actual length w/o padding!)
+            if (io_->read(buf, 4) != 4) 
+            {
+                throw Error(3, "Photoshop"); 
+            }
+            uint32_t resourceSize = getLong(buf, bigEndian);
+            uint32_t curOffset = io_->tell();
+
+            switch(resourceId)
+            {
+                case kPhotoshopResourceID_IPTC_NAA:
+                {
+                    resourceSize = (resourceSize + 1) & ~1;    // adjust for padding
+                    break;   // already processed
+                }
+/*
+                case kPhotoshopResourceID_ExifInfo:
+                {
+                    // TODO: skip here, if exiv2 writes it's own EXIF data
+                    break;
+                }
+
+                case kPhotoshopResourceID_XMPPacket:
+                {
+                    // TODO: skip here, if exiv2 writes it's own XMP data
+                    break;
+                }
+*/
+                default:
+                {
+                    // Copy resource block to new PSD file
+                    ul2Data(buf, kPhotoshopResourceType, bigEndian);
+                    if (outIo.write(buf, 4) != 4) throw Error(21);
+                    us2Data(buf, resourceId, bigEndian);
+                    if (outIo.write(buf, 2) != 2) throw Error(21);
+                    // Write resource name as Pascal string
+                    buf[0] = resourceNameLength & 0x000f;
+                    if (outIo.write(buf, 1) != 1) throw Error(21);
+                    buf[0] = resourceNameFirstChar;
+                    if (outIo.write(buf, 1) != 1) throw Error(21);
+                    if (outIo.write(resName.pData_, adjResourceNameLen) != adjResourceNameLen) throw Error(21);
+                    ul2Data(buf, resourceSize, bigEndian);
+                    if (outIo.write(buf, 4) != 4) throw Error(21);
+
+                    readTotal = 0;
+                    toRead = 0;
+                    resourceSize = (resourceSize + 1) & ~1;        // pad to even
+                    while (readTotal < resourceSize) {
+                        toRead = resourceSize - readTotal < lbuf.size_ ? resourceSize - readTotal : lbuf.size_;
+                        if (io_->read(lbuf.pData_, toRead) != toRead)
+                        {
+                            throw Error(3, "Photoshop");
+                        }
+                        readTotal += toRead;
+                        if (outIo.write(lbuf.pData_, toRead) != toRead) throw Error(21);
+                    }
+                    if (outIo.error()) throw Error(21);
+                    newResLength += resourceSize + adjResourceNameLen + 12;
+                    break;
+                }
+            }
+
+            io_->seek(curOffset + resourceSize, BasicIo::beg);
+            oldResLength -= (12 + adjResourceNameLen + resourceSize);
+        }
+
+        // Copy remaining data
+        long readSize = 0;
+        while ((readSize=io_->read(lbuf.pData_, lbuf.size_))) {
+            if (outIo.write(lbuf.pData_, readSize) != readSize) throw Error(21);
+        }
+        if (outIo.error()) throw Error(21);
+
+        // Update length of resources
+#ifdef DEBUG
+        std::cerr << "newResLength: " << newResLength << "
";
+#endif
+        outIo.seek(resLenOffset, BasicIo::beg);
+        ul2Data(buf, newResLength, bigEndian);
+        if (outIo.write(buf, 4) != 4) throw Error(21);
+
+    } // PsdImage::doWriteMetadata
+
+
     // *************************************************************************
     // free functions
     Image::AutoPtr newPsdInstance(BasicIo::AutoPtr io, bool /*create*/)
diff --git a/src/psdimage.hpp b/src/psdimage.hpp
index bb8cb2e..9811217 100644
--- a/src/psdimage.hpp
+++ b/src/psdimage.hpp
@@ -127,6 +127,14 @@ namespace Exiv2 {
         //! @name Manipulators
         //@{
         EXV_DLLLOCAL void processResourceBlock(uint16_t resourceId, uint32_t resourceSize);
+        /*!
+          @brief Provides the main implementation of writeMetadata() by
+                writing all buffered metadata to the provided BasicIo.
+          @param oIo BasicIo instance to write to (a temporary location).
+
+          @return 4 if opening or writing to the associated BasicIo fails
+         */
+        EXV_DLLLOCAL void doWriteMetadata(BasicIo& oIo);
         //@}
 
     }; // class PsdImage

-- 
exiv2 packaging



More information about the pkg-kde-commits mailing list