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

Maximiliano Curia maxy at moszumanska.debian.org
Thu Jul 13 17:47:11 UTC 2017


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

The following commit has been merged in the master branch:
commit 699e1c744e50782e3ed7411cc6ac28260aa169c0
Author: Robin Mills <robin at clanmills.com>
Date:   Wed Oct 12 20:24:27 2016 +0000

    #1243 Work in progress.  Implemented jp2image::printStructure.  Still to add iccProfile support to jp2image::writeMetadata()
---
 include/exiv2/jp2image.hpp |   9 ++
 src/jp2image.cpp           | 244 ++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 219 insertions(+), 34 deletions(-)

diff --git a/include/exiv2/jp2image.hpp b/include/exiv2/jp2image.hpp
index 8dd221a..09cc75a 100644
--- a/include/exiv2/jp2image.hpp
+++ b/include/exiv2/jp2image.hpp
@@ -84,6 +84,15 @@ namespace Exiv2
         //@{
         void readMetadata();
         void writeMetadata();
+
+        /*!
+          @brief Print out the structure of image file.
+          @throw Error if reading of the file fails or the image data is
+                not valid (does not look like data of the specific image type).
+          @caution This function is not thread safe and intended for exiv2 -pS for debugging.
+         */
+        void printStructure(std::ostream& out, PrintStructureOption option,int depth);
+
         /*!
           @brief Todo: Not supported yet(?). Calling this function will throw
               an instance of Error(32).
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
index b36e61f..1b1e36a 100644
--- a/src/jp2image.cpp
+++ b/src/jp2image.cpp
@@ -32,6 +32,7 @@ EXIV2_RCSID("@(#) $Id$")
 #include "jp2image.hpp"
 #include "tiffimage.hpp"
 #include "image.hpp"
+#include "image_int.hpp"
 #include "basicio.hpp"
 #include "error.hpp"
 #include "futils.hpp"
@@ -42,9 +43,12 @@ EXIV2_RCSID("@(#) $Id$")
 #include <iostream>
 #include <cassert>
 
+// #define DEBUG
+
 // JPEG-2000 box types
 const uint32_t kJp2BoxTypeJp2Header   = 0x6a703268; // 'jp2h'
 const uint32_t kJp2BoxTypeImageHeader = 0x69686472; // 'ihdr'
+const uint32_t kJp2BoxTypeColorHeader = 0x636f6c72; // 'colr'
 const uint32_t kJp2BoxTypeUuid        = 0x75756964; // 'uuid'
 
 // JPEG-2000 UUIDs for embedded metadata
@@ -79,8 +83,8 @@ const unsigned char Jp2Blank[] = { 0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,
 //! @cond IGNORE
 struct Jp2BoxHeader
 {
-    uint32_t boxLength;
-    uint32_t boxType;
+    uint32_t length;
+    uint32_t type;
 };
 
 struct Jp2ImageHeaderBox
@@ -138,6 +142,14 @@ namespace Exiv2
         throw(Error(32, "Image comment", "JP2"));
     } // Jp2Image::setComment
 
+    static std::string toAscii(long n)
+    {
+        const char* p = (const char*) &n;
+        std::string result;
+        for ( int i = 0 ; i < 4 ; i++) result += p[3-i];
+        return result;
+    }
+
     void Jp2Image::readMetadata()
     {
 #ifdef DEBUG
@@ -163,16 +175,16 @@ namespace Exiv2
 
         while (io_->read((byte*)&box, sizeof(box)) == sizeof(box))
         {
-            position      = io_->tell();
-            box.boxLength = getLong((byte*)&box.boxLength, bigEndian);
+            position   = io_->tell();
+            box.length = getLong((byte*)&box.length, bigEndian);
+            box.type   = getLong((byte*)&box.type, bigEndian);
 #ifdef DEBUG
             std::cout << "Exiv2::Jp2Image::readMetadata: Position: " << position << "
";
-            std::cout << "Exiv2::Jp2Image::readMetadata: Find box type: " << std::string((const char*)&box.boxType)
-                      << " length: " << box.boxLength << "
";
+            std::cout << "Exiv2::Jp2Image::readMetadata: Find box type: " << toAscii(box.type)
+                      << " length: " << box.length << "
";
 #endif
-            box.boxType   = getLong((byte*)&box.boxType, bigEndian);
 
-            if (box.boxLength == 0)
+            if (box.length == 0)
             {
 #ifdef DEBUG
                 std::cout << "Exiv2::Jp2Image::readMetadata: Null Box size has been found. "
@@ -180,27 +192,54 @@ namespace Exiv2
 #endif
                 return;
             }
-            if (box.boxLength == 1)
+            if (box.length == 1)
             {
                 // FIXME. Special case. the real box size is given in another place.
             }
 
-            switch(box.boxType)
+            switch(box.type)
             {
                 case kJp2BoxTypeJp2Header:
                 {
 #ifdef DEBUG
                     std::cout << "Exiv2::Jp2Image::readMetadata: JP2Header box found
";
 #endif
+                    long restore = io_->tell();
 
-                    if (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox))
+                    while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) && subBox.length )
                     {
-                        subBox.boxLength = getLong((byte*)&subBox.boxLength, bigEndian);
-                        subBox.boxType   = getLong((byte*)&subBox.boxType, bigEndian);
+                        subBox.length = getLong((byte*)&subBox.length, bigEndian);
+                        subBox.type   = getLong((byte*)&subBox.type, bigEndian);
+#ifdef DEBUG
+                        std::cout << "subBox = " << toAscii(subBox.type) << " length = " << subBox.length << std::endl;
+#endif
+                        if(subBox.type == kJp2BoxTypeColorHeader)
+                        {
+#ifdef DEBUG
+                            std::cout << "Exiv2::Jp2Image::readMetadata: Color data found
";
+#endif
+                            long pad = 3 ; // don't know why there are 3 padding bytes
+                            DataBuf data(subBox.length+8);
+                            io_->read(data.pData_,data.size_);
+                            long    iccLength = getULong(data.pData_+pad, bigEndian);
+                            DataBuf icc(iccLength);
+                            ::memcpy(icc.pData_,data.pData_+pad,icc.size_);
+#ifdef DEBUG
+                            const char* iccPath = "/tmp/jp2.icc";
+                            FILE* f = fopen(iccPath,"wb");
+                            if ( f ) {
+                                fwrite(icc.pData_,icc.size_,1,f);
+                                fclose(f);
+                            }
+                            std::cout << "Exiv2::Jp2Image::readMetadata: wrote iccProfile to " << iccPath << std::endl ;
 
-                        if((subBox.boxType == kJp2BoxTypeImageHeader) &&
-                           (io_->read((byte*)&ihdr, sizeof(ihdr)) == sizeof(ihdr)))
+#endif
+                            setIccProfile(icc);
+                        }
+
+                        if( subBox.type == kJp2BoxTypeImageHeader)
                         {
+                            io_->read((byte*)&ihdr, sizeof(ihdr));
 #ifdef DEBUG
                            std::cout << "Exiv2::Jp2Image::readMetadata: Ihdr data found
";
 #endif
@@ -213,10 +252,13 @@ namespace Exiv2
                             pixelWidth_  = ihdr.imageWidth;
                             pixelHeight_ = ihdr.imageHeight;
                         }
+
+                        io_->seek(restore,BasicIo::beg);
+                        io_->seek(subBox.length, Exiv2::BasicIo::cur);
+                        restore = io_->tell();
                     }
                     break;
                 }
-
                 case kJp2BoxTypeUuid:
                 {
 #ifdef DEBUG
@@ -236,7 +278,7 @@ namespace Exiv2
 #ifdef DEBUG
                            std::cout << "Exiv2::Jp2Image::readMetadata: Exif data found
";
 #endif
-                            rawData.alloc(box.boxLength - (sizeof(box) + sizeof(uuid)));
+                            rawData.alloc(box.length - (sizeof(box) + sizeof(uuid)));
                             bufRead = io_->read(rawData.pData_, rawData.size_);
                             if (io_->error()) throw Error(14);
                             if (bufRead != rawData.size_) throw Error(20);
@@ -286,7 +328,7 @@ namespace Exiv2
 #ifdef DEBUG
                            std::cout << "Exiv2::Jp2Image::readMetadata: Iptc data found
";
 #endif
-                            rawData.alloc(box.boxLength - (sizeof(box) + sizeof(uuid)));
+                            rawData.alloc(box.length - (sizeof(box) + sizeof(uuid)));
                             bufRead = io_->read(rawData.pData_, rawData.size_);
                             if (io_->error()) throw Error(14);
                             if (bufRead != rawData.size_) throw Error(20);
@@ -305,7 +347,7 @@ namespace Exiv2
 #ifdef DEBUG
                            std::cout << "Exiv2::Jp2Image::readMetadata: Xmp data found
";
 #endif
-                            rawData.alloc(box.boxLength - (uint32_t)(sizeof(box) + sizeof(uuid)));
+                            rawData.alloc(box.length - (uint32_t)(sizeof(box) + sizeof(uuid)));
                             bufRead = io_->read(rawData.pData_, rawData.size_);
                             if (io_->error()) throw Error(14);
                             if (bufRead != rawData.size_) throw Error(20);
@@ -339,13 +381,147 @@ namespace Exiv2
             }
 
             // Move to the next box.
-
-            io_->seek(static_cast<long>(position - sizeof(box) + box.boxLength), BasicIo::beg);
+            io_->seek(static_cast<long>(position - sizeof(box) + box.length), BasicIo::beg);
             if (io_->error()/* || io_->eof()*/) throw Error(14);
         }
 
     } // Jp2Image::readMetadata
 
+    static void lf(std::ostream& out,bool& bLF)
+    {
+        if ( bLF ) {
+            out << std::endl;
+            bLF = false ;
+        }
+    }
+
+    void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option,int depth)
+    {
+        if (io_->open() != 0) throw Error(9, io_->path(), strError());
+
+        // Ensure that this is the correct image type
+        if (!isJp2Type(*io_, false)) {
+            if (io_->error() || io_->eof()) throw Error(14);
+            throw Error(15);
+        }
+
+        out << "STRUCTURE OF JPEG2000 FILE: " << io_->path() << std::endl;
+        out << " address |   length | box       | data" << std::endl ;
+
+        bool bPrint     =  option==kpsBasic || option==kpsRecursive;
+        bool bRecursive =  option == kpsRecursive;
+        bool bICC       =  option == kpsIccProfile;
+        if ( bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase ) {
+
+            long              position  = 0;
+            Jp2BoxHeader      box       = {1,1};
+            Jp2BoxHeader      subBox    = {1,1};
+            Jp2UuidBox        uuid      = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+            long              address   = io_->tell();
+            bool              bLF       = false;
+
+            while (box.length && io_->read((byte*)&box, sizeof(box)) == sizeof(box))
+            {
+                position   = io_->tell();
+                box.length = getLong((byte*)&box.length, bigEndian);
+                box.type   = getLong((byte*)&box.type, bigEndian);
+
+                if ( bPrint ) {
+                    out << Internal::stringFormat("%8ld | %8ld | ",address,box.length) << toAscii(box.type) << "      | " ;
+                    bLF = true ;
+                }
+
+                if (box.length) switch(box.type)
+                {
+                    case kJp2BoxTypeJp2Header:
+                    {
+                        long restore = io_->tell();
+                        lf(out,bLF);
+
+                        while (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox) && subBox.length )
+                        {
+                            subBox.length = getLong((byte*)&subBox.length, bigEndian);
+                            subBox.type   = getLong((byte*)&subBox.type, bigEndian);
+
+                            DataBuf data(subBox.length+8);
+                            io_->read(data.pData_,data.size_);
+                            if ( bPrint ) out << Internal::stringFormat("%8ld | %8ld |  sub:",restore,subBox.length) << toAscii(subBox.type) <<" | " << "yyyyyy" << std::endl;
+
+                            if(subBox.type == kJp2BoxTypeColorHeader)
+                            {
+                                long pad = 3 ; // don't know why there are 3 padding bytes
+                                long    iccLength = getULong(data.pData_+pad, bigEndian);
+                                DataBuf icc(iccLength);
+                                if ( bICC ) out.write((const char*)icc.pData_,icc.size_);
+                            }
+
+                            io_->seek(restore,BasicIo::beg);
+                            io_->seek(subBox.length, Exiv2::BasicIo::cur);
+                            restore = io_->tell();
+                        }
+                        break;
+                    }
+
+                    case kJp2BoxTypeUuid:
+                    {
+
+                        if (io_->read((byte*)&uuid, sizeof(uuid)) == sizeof(uuid))
+                        {
+                            bool    bExif = memcmp(uuid.uuid, kJp2UuidExif, sizeof(uuid))==0;
+                            bool    bIptc = memcmp(uuid.uuid, kJp2UuidIptc, sizeof(uuid))==0;
+                            bool    bXMP  = memcmp(uuid.uuid, kJp2UuidXmp , sizeof(uuid))==0;
+
+                            if ( bPrint ) {
+                                if ( bExif ) out << "Exif" ;
+                                if ( bIptc ) out << "IPTC" ;
+                                if ( bXMP  ) out << "XMP"  ;
+                            }
+
+                            DataBuf rawData;
+                                    rawData.alloc(box.length);
+                            long    bufRead = io_->read(rawData.pData_, rawData.size_);
+                            if (io_->error()) throw Error(14);
+                            if (bufRead != rawData.size_) throw Error(20);
+
+                            if(bExif && bRecursive && rawData.size_ > 0)
+                            {
+                                if ( (rawData.pData_[0]      == rawData.pData_[1])
+                                &&   (rawData.pData_[0]=='I' || rawData.pData_[0]=='M' )
+                                ) {
+                                    lf(out,bLF);
+                                    BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_,rawData.size_));
+                                    TiffImage::printTiffStructure(*p,out,option,depth);
+                                }
+                            }
+
+                            if(bIptc && bRecursive)
+                            {
+                                IptcData::printStructure(out,rawData.pData_,rawData.size_,depth);
+                            }
+
+                            if(bXMP && option & kpsXMP )
+                            {
+                                out.write((const char*)rawData.pData_,rawData.size_);
+                            }
+                        }
+                        break;
+                    }
+
+                    default:
+                    {
+                        break;
+                    }
+                }
+                address   = io_->tell();
+
+                // Move to the next box.
+                io_->seek(static_cast<long>(position - sizeof(box) + box.length), BasicIo::beg);
+                if (io_->error()) throw Error(14);
+                if ( bPrint ) lf(out,bLF);
+            }
+        }
+    } // JpegBase::printStructure
+
     void Jp2Image::writeMetadata()
     {
         if (io_->open() != 0)
@@ -406,32 +582,32 @@ namespace Exiv2
 
             // Decode box header.
 
-            box.boxLength = getLong(bheaderBuf.pData_,     bigEndian);
-            box.boxType   = getLong(bheaderBuf.pData_ + 4, bigEndian);
+            box.length = getLong(bheaderBuf.pData_,     bigEndian);
+            box.type   = getLong(bheaderBuf.pData_ + 4, bigEndian);
 
 #ifdef DEBUG
             std::cout << "Exiv2::Jp2Image::doWriteMetadata: Find box type: " << bheaderBuf.pData_ + 4
-                      << " length: " << box.boxLength << "
";
+                      << " length: " << box.length << "
";
 #endif
 
-            if (box.boxLength == 0)
+            if (box.length == 0)
             {
 #ifdef DEBUG
                 std::cout << "Exiv2::Jp2Image::doWriteMetadata: Null Box size has been found. "
                              "This is the last box of file.
";
 #endif
-                box.boxLength = io_->size() - io_->tell() + 8;
+                box.length = io_->size() - io_->tell() + 8;
             }
-            if (box.boxLength == 1)
+            if (box.length == 1)
             {
                 // FIXME. Special case. the real box size is given in another place.
             }
 
             // Read whole box : Box header + Box data (not fixed size - can be null).
 
-            DataBuf boxBuf(box.boxLength);                             // Box header (8 bytes) + box data.
+            DataBuf boxBuf(box.length);                             // Box header (8 bytes) + box data.
             memcpy(boxBuf.pData_, bheaderBuf.pData_, 8);               // Copy header.
-            bufRead = io_->read(boxBuf.pData_ + 8, box.boxLength - 8); // Extract box data.
+            bufRead = io_->read(boxBuf.pData_ + 8, box.length - 8); // Extract box data.
             if (io_->error())
             {
 #ifdef DEBUG
@@ -441,7 +617,7 @@ namespace Exiv2
                 throw Error(14);
             }
 
-            if (bufRead != (long)(box.boxLength - 8))
+            if (bufRead != (long)(box.length - 8))
             {
 #ifdef DEBUG
                 std::cout << "Exiv2::Jp2Image::doWriteMetadata: Cannot read source file data
";
@@ -449,13 +625,13 @@ namespace Exiv2
                 throw Error(20);
             }
 
-            switch(box.boxType)
+            switch(box.type)
             {
                 case kJp2BoxTypeJp2Header:
                 {
 
 #ifdef DEBUG
-                    std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write JP2Header box (length: " << box.boxLength << ")
";
+                    std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write JP2Header box (length: " << box.length << ")
";
 #endif
                     if (outIo.write(boxBuf.pData_, boxBuf.size_) != boxBuf.size_) throw Error(21);
 
@@ -566,7 +742,7 @@ namespace Exiv2
                     else
                     {
 #ifdef DEBUG
-                        std::cout << "Exiv2::Jp2Image::doWriteMetadata: write Uuid box (length: " << box.boxLength << ")
";
+                        std::cout << "Exiv2::Jp2Image::doWriteMetadata: write Uuid box (length: " << box.length << ")
";
 #endif
                         if (outIo.write(boxBuf.pData_, boxBuf.size_) != boxBuf.size_) throw Error(21);
                     }
@@ -576,7 +752,7 @@ namespace Exiv2
                 default:
                 {
 #ifdef DEBUG
-                    std::cout << "Exiv2::Jp2Image::doWriteMetadata: write box (length: " << box.boxLength << ")
";
+                    std::cout << "Exiv2::Jp2Image::doWriteMetadata: write box (length: " << box.length << ")
";
 #endif
                     if (outIo.write(boxBuf.pData_, boxBuf.size_) != boxBuf.size_) throw Error(21);
 

-- 
exiv2 packaging



More information about the pkg-kde-commits mailing list