[Kde-imaging] [Bug 107905] copy exif data from raw to converted images

Gilles Caulier caulier.gilles at free.fr
Fri Sep 15 15:57:04 CEST 2006


------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
         
http://bugs.kde.org/show_bug.cgi?id=107905         
caulier.gilles free fr changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |FIXED



------- Additional Comments From caulier.gilles free fr  2006-09-15 15:57 -------
SVN commit 584763 by cgilles:

kipi-plugins from trunk : Raw Converter : Exif/makernotes/iptc/gps metadata restoration after RAW image decoding.

- Add Exiv2 depency. I recommend to use the current implementation of Exiv2 from svn (Exiv2 0.11 will be release in a near future)

- Add a new Exiv2 interface class based on some part of digiKam core. This class will be will be moved later to the common plugins folder to remplace libkexif depency everywhere. I need to polish and improve the code before.

- Actually, 2 output file formats are fully supported to store metadata : JPEG and PNG. Note PNG Exif/Iptc storing use ImageMagick raw profile stored in compressed text chunk.
Tiff file format will be added when Exiv2 library will support Tiff write io (normally later 0.11 release)

To all digiKam users : after to have converted Raw files using this plugin, you will have the pleasure to see all metadata into target files using Metadata side bar (:=)))

CCMAIL: kde-imaging kde org

BUG : 107905
CCBUGS: 128394

 M  +0 -1      Makefile.am  
 M  +7 -0      configure.in.bot  
 M  +17 -0     configure.in.in  
 M  +6 -1      kipiplugins.kdevelop  
 M  +4 -2      rawconverter/Makefile.am  
 M  +201 -1    rawconverter/dcrawiface.cpp  
 M  +15 -0     rawconverter/dcrawiface.h  
 A             rawconverter/exiv2iface.cpp   [License: GPL]
 A             rawconverter/exiv2iface.h   [License: GPL]


--- trunk/extragear/libs/kipi-plugins/Makefile.am #584762:584763
 @ -25,7 +25,6  @
 TIMEADJUSTDIR = $(timeadjustdir)
 endif
 
-
 if compile_ACQUIREIMAGES
 ACQUIREIMAGESDIR = acquireimages
 endif
--- trunk/extragear/libs/kipi-plugins/configure.in.bot #584762:584763
 @ -58,3 +58,10  @
   echo ""
   all_tests=bad
 fi
+
+if test "x$have_exiv2" != "xyes"; then
+  echo ""
+  echo "You're missing Exiv2 library. The rawconverter plugin will not be compiled."
+  echo ""
+  all_tests=bad
+fi
--- trunk/extragear/libs/kipi-plugins/configure.in.in #584762:584763
 @ -168,6 +168,23  @
 
 AM_CONDITIONAL(compile_HTMLEXPORT, test -n "${XSLT_CONFIG}")
 
+#------------------------------------------------------------------
+# Check for Exiv2 library
+#------------------------------------------------------------------
+
+have_exiv2='no'
+AC_PATH_PROG(EXIV2_CONFIG,exiv2-config)
+KDE_CHECK_HEADER(exiv2/exif.hpp, have_exiv2=yes, have_exiv2=no)
+
+if test "x$have_exiv2" != "xyes"; then
+  AC_WARN([Exiv2 library is require for the rawconvert plugin.])
+else
+  LIB_EXIV2="-lexiv2"
+  AC_SUBST(LIB_EXIV2)
+fi
+
+AM_CONDITIONAL(compile_RAWCONVERTER, test -n "${EXIV2_CONFIG}")
+
 # ----------------------------------------------------------
 #
 # Slideshow plugin tests
--- trunk/extragear/libs/kipi-plugins/kipiplugins.kdevelop #584762:584763
 @ -110,7 +110,7  @
     <run>
       <directoryradio>custom</directoryradio>
       <customdirectory>/</customdirectory>
-      <mainprogram>/usr/bin/digikam</mainprogram>
+      <mainprogram>/opt/kde3/bin/digikam</mainprogram>
       <programargs/>
       <terminal>false</terminal>
       <autocompile>false</autocompile>
 @ -167,6 +167,11  @
       <inlineGet>true</inlineGet>
       <inlineSet>true</inlineSet>
     </creategettersetter>
+    <qt>
+      <used>false</used>
+      <version>3</version>
+      <root>/usr/lib/qt3</root>
+    </qt>
   </kdevcppsupport>
   <kdevcvsservice>
     <recursivewhenupdate>true</recursivewhenupdate>
--- trunk/extragear/libs/kipi-plugins/rawconverter/Makefile.am #584762:584763
 @ -1,5 +1,6  @
 METASOURCES = AUTO
 SUBDIRS = profiles
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
 
 INCLUDES = -I$(top_srcdir)/kipi-plugins/common/include \
               $(LIBKIPI_CFLAGS) $(all_includes)
 @ -12,10 +13,11  @
 # Srcs for the plugin
 kipiplugin_rawconverter_la_SOURCES = plugin_rawconverter.cpp dcrawiface.cpp savesettingswidget.cpp \
                                     batchdialog.cpp actionthread.cpp dcrawsettingswidget.cpp \
-                                    singledialog.cpp previewwidget.cpp iccjpeg.c dcrawbinary.cpp 
+                                    singledialog.cpp previewwidget.cpp iccjpeg.c dcrawbinary.cpp \
+                                    exiv2iface.cpp 
 
 # Libs needed by the plugin
-kipiplugin_rawconverter_la_LIBADD = -ljpeg -lpng $(LIB_TIFF) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+kipiplugin_rawconverter_la_LIBADD = -ljpeg -lpng $(LIB_TIFF) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_EXIV2) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
 
 # LD flags for the plugin
 kipiplugin_rawconverter_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
--- trunk/extragear/libs/kipi-plugins/rawconverter/dcrawiface.cpp #584762:584763
 @ -38,7 +38,6  @
 #include <jpeglib.h>
 #include <tiffio.h>
 #include <tiffvers.h>
-#include <png.h>
 #include "iccjpeg.h"
 }
 
 @ -63,6 +62,7  @
 
 #include "pluginsversion.h"
 #include "rawfiles.h"
+#include "exiv2iface.h"
 #include "dcrawbinary.h"
 #include "dcrawiface.h"
 #include "dcrawiface.moc"
 @ -468,6 +468,12  @
             
             jpeg_finish_compress(&cinfo);
             fclose(f);
+
+            // Metadata restoration.
+            Exiv2Iface exiv2Ifave;
+            exiv2Ifave.load(filePath);
+            exiv2Ifave.setImageProgramId(QString("Kipi Raw Converter"), QString(kipiplugins_version));
+            exiv2Ifave.save(destPath);
             break;
         }
         case RawDecodingSettings::PNG:
 @ -515,6 +521,23  @
             text.compression = PNG_TEXT_COMPRESSION_zTXt;
             png_set_text(png_ptr, info_ptr, &(text), 1);
 
+            // Metadata restoration.
+            Exiv2Iface exiv2Ifave;
+            exiv2Ifave.load(filePath);
+            exiv2Ifave.setImageProgramId(QString("Kipi Raw Converter"), QString(kipiplugins_version));
+
+            // Store Exif data.
+            QByteArray ba = exiv2Ifave.getExif();
+            const uchar ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+            QByteArray profile = QByteArray(ba.size() + sizeof(ExifHeader));
+            memcpy(profile.data(), ExifHeader, sizeof(ExifHeader));
+            memcpy(profile.data()+sizeof(ExifHeader), ba.data(), ba.size());
+            writeRawProfile(png_ptr, info_ptr, "exif", profile.data(), (png_uint_32) profile.size());
+
+            // Store Iptc data.
+            QByteArray ba2 = exiv2Ifave.getIptc();
+            writeRawProfile(png_ptr, info_ptr, "iptc", ba2.data(), (png_uint_32) ba2.size());
+
             png_write_info(png_ptr, info_ptr);
             png_set_shift(png_ptr, &sig_bit);
             png_set_packing(png_ptr);
 @ -570,6 +593,21  @
             w = TIFFScanlineSize(tif);
             TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,    TIFFDefaultStripSize(tif, 0));
 
+
+            // Metadata restoration.
+            Exiv2Iface exiv2Ifave;
+            exiv2Ifave.load(filePath);
+            exiv2Ifave.setImageProgramId(QString("Kipi Raw Converter"), QString(kipiplugins_version));
+
+            // Store Exif data.
+            // TODO
+
+            // Store Iptc data.
+            QByteArray ba2 = exiv2Ifave.getIptc(true);
+#if defined(TIFFTAG_PHOTOSHOP)
+            TIFFSetField (tif, TIFFTAG_PHOTOSHOP,      (uint32)ba2.size(), (uchar *)ba2.data());
+#endif
+
             QString libtiffver(TIFFLIB_VERSION_STR);
             libtiffver.replace('\n', ' ');
             soft.append(QString(" ( %1 )").arg(libtiffver));
 @ -841,4 +879,166  @
     kdDebug() << "Dcraw StdErr: " << message << endl;
 }
 
+void DcrawIface::writeRawProfile(png_struct *ping, png_info *ping_info, char *profile_type, 
+                                 char *profile_data, png_uint_32 length)
+{
+    png_textp      text;
+    
+    register long  i;
+    
+    uchar         *sp;
+    
+    png_charp      dp;
+    
+    png_uint_32    allocated_length, description_length;
+
+    const uchar hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+    
+    kdDebug() << "Writing Raw profile: type=" << profile_type << ", length=" << length << endl;
+    
+    text               = (png_textp) png_malloc(ping, (png_uint_32) sizeof(png_text));
+    description_length = strlen((const char *) profile_type);
+    allocated_length   = (png_uint_32) (length*2 + (length >> 5) + 20 + description_length);
+    
+    text[0].text   = (png_charp) png_malloc(ping, allocated_length);
+    text[0].key    = (png_charp) png_malloc(ping, (png_uint_32) 80);
+    text[0].key[0] = '\0';
+    
+    concatenateString(text[0].key, "Raw profile type ", 4096);
+    concatenateString(text[0].key, (const char *) profile_type, 62);
+    
+    sp = (uchar*)profile_data;
+    dp = text[0].text;
+    *dp++='\n';
+    
+    copyString(dp, (const char *) profile_type, allocated_length);
+    
+    dp += description_length;
+    *dp++='\n';
+    
+    formatString(dp, allocated_length-strlen(text[0].text), "%8lu ", length);
+    
+    dp += 8;
+    
+    for (i=0; i < (long) length; i++)
+    {
+        if (i%36 == 0)
+            *dp++='\n';
+
+        *(dp++)=(char) hex[((*sp >> 4) & 0x0f)];
+        *(dp++)=(char) hex[((*sp++ ) & 0x0f)]; 
+    }
+
+    *dp++='\n';
+    *dp='\0';
+    text[0].text_length = (png_size_t) (dp-text[0].text);
+    text[0].compression = -1;
+
+    if (text[0].text_length <= allocated_length)
+        png_set_text(ping, ping_info,text, 1);
+
+    png_free(ping, text[0].text);
+    png_free(ping, text[0].key);
+    png_free(ping, text);
+}
+
+size_t DcrawIface::concatenateString(char *destination, const char *source, const size_t length)
+{
+    register char       *q;
+    
+    register const char *p;
+    
+    register size_t      i;
+    
+    size_t               count;
+  
+    if ( !destination || !source || length == 0 )
+        return 0;
+
+    p = source;
+    q = destination;
+    i = length;
+
+    while ((i-- != 0) && (*q != '\0'))
+        q++;
+
+    count = (size_t) (q-destination);
+    i     = length-count;
+
+    if (i == 0)
+        return(count+strlen(p));
+
+    while (*p != '\0')
+    {
+        if (i != 1)
+        {
+            *q++=(*p);
+            i--;
+        }
+        p++;
+    }
+
+    *q='\0';
+    
+    return(count+(p-source));
+}
+
+size_t DcrawIface::copyString(char *destination, const char *source, const size_t length)
+{
+    register char       *q;
+    
+    register const char *p;
+    
+    register size_t      i;
+        
+    if ( !destination || !source || length == 0 )
+        return 0;
+
+    p = source;
+    q = destination;
+    i = length;
+
+    if ((i != 0) && (--i != 0))
+    {
+        do
+        {
+            if ((*q++=(*p++)) == '\0')
+                break;
+        } 
+        while (--i != 0);
+    }
+
+    if (i == 0)
+    {
+        if (length != 0)
+            *q='\0';
+  
+        while (*p++ != '\0');
+    }
+    
+    return((size_t) (p-source-1));
+}
+
+long DcrawIface::formatString(char *string, const size_t length, const char *format,...)
+{
+    long n;
+    
+    va_list operands;
+    
+    va_start(operands,format);
+    n = (long) formatStringList(string, length, format, operands);
+    va_end(operands);
+    return(n);
+}
+
+long DcrawIface::formatStringList(char *string, const size_t length, const char *format, va_list operands)
+{
+    int n = vsnprintf(string, length, format, operands);
+    
+    if (n < 0)
+        string[length-1] = '\0';
+    
+    return((long) n);
+}
+
 }  // namespace KIPIRawConverterPlugin
--- trunk/extragear/libs/kipi-plugins/rawconverter/dcrawiface.h #584762:584763
 @ -22,6 +22,13  @
 #ifndef DCRAWIFACE_H
 #define DCRAWIFACE_H
 
+// C Ansi includes.
+
+extern "C"
+{
+#include <png.h>
+}
+
 // Qt Includes.
 
 #include <qstring.h>
 @ -87,6 +94,14  @
 
     virtual void customEvent(QCustomEvent *);
 
+    void   writeRawProfile(png_struct *ping, png_info *ping_info, char *profile_type, 
+                           char *profile_data, png_uint_32 length);
+
+    size_t concatenateString(char *destination, const char *source, const size_t length);
+    size_t copyString(char *destination, const char *source, const size_t length);
+    long   formatString(char *string, const size_t length, const char *format,...);
+    long   formatStringList(char *string, const size_t length, const char *format, va_list operands);
+
 private slots:
 
     void slotProcessExited(KProcess *);


More information about the Kde-imaging mailing list