Version: 0.8.2-beta1 (using KDE 3.5.2, Kubuntu Package 4:3.5.2-0ubuntu10 dapper) Compiler: Target: i486-linux-gnu OS: Linux (i686) release 2.6.15-21-686 This is not a duplicate of "Bug 118501: exifs lost when modifying the images" ('cause my debug output did not show up;) This report is triggered by a Kubuntu/Dapper bug report: https://launchpad.net/distros/ubuntu/+source/digikam/+bug/34462 To reproduce: o copy images from http://digikam3rdparty.free.fr/TEST_IMAGES/JPEG/Vertical/ into an empty folder o Goto 'Add camera' and add a 'Mounted camera' with mountpoint as the download dir as above. Name it, e.g. 'Vertial' o download from camera 'Vertical' all pics with 'automaticly rotate/flip using camera ... (EXIF)' selected. ==> 7 x 'no EXIF information' and 7 pictures lost their exif info Adding some debug statements I found that everytime exifDate.getImageOrientation return > 1 (or !=) there's a problem: exif data lost. Achim
Debug output (I'll commit and CCBUGS the correponding code soon) [.. snip with orient=1 ..] digikam: Autorotate : Coolpix4500_2.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 1137188 bytes, orient =1 digikam: Autorotate : DSCN9703.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 821436 bytes, orient =1 digikam: Autorotate : DSCN9704.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 833656 bytes, orient =1 digikam: Autorotate : IMG_0001.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 3815715 bytes, orient =1 digikam: Autorotate : IMG_0002.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 3376701 bytes, orient =1 digikam: Dirty: /00-New/test digikam: Autorotate : IMG_0003.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 3289163 bytes, orient =1 digikam: Autorotate : IMG_0004.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 3468711 bytes, orient =1 digikam: Autorotate : IMG_1515.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 1037958 bytes, orient =8 digikam: No EXIF information found. digikam: Autorotate : IMG_1517.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: Dirty: / digikam: Dirty: /00-New/test digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 1640353 bytes, orient =6 digikam: No EXIF information found. digikam: Autorotate : IMG_2261.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 520608 bytes, orient =6 digikam: No EXIF information found. digikam: Autorotate : IMG_2265.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 1186947 bytes, orient =6 digikam: No EXIF information found. digikam: Autorotate : IMG_2266.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 1161070 bytes, orient =8 digikam: No EXIF information found. digikam: Autorotate : IMG_3809.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 3720604 bytes, orient =8 digikam: No EXIF information found. digikam: Autorotate : IMG_3810.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 4132549 bytes, orient =6 digikam: No EXIF information found. digikam: Autorotate : MINOLTA-DYNAX5D.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 4144978 bytes, orient =1 digikam: Autorotate : NIKON-D200-01.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 2292238 bytes, orient =1 digikam: Autorotate : PICT0001.JPG using /home/ach/Pictures/00-New/test/.digikam-camera-25106 digikam: /home/ach/Pictures/00-New/test/.digikam-camera-25106 = 2238757 bytes, orient =1 [.. snap with orient=1]
SVN commit 534392 by ach: digikam stable: more debug output CCBUGS: 126326 M +5 -1 libs/jpegutils/exifrotate.cpp M +4 -1 utilities/cameragui/cameracontroller.cpp --- branches/stable/extragear/graphics/digikam/libs/jpegutils/exifrotate.cpp #534391:534392 @@ -61,9 +61,13 @@ KExifData exifData; if (!exifData.readFromFile(file)) { - kdDebug() << "No exif data found into " << file << endl; + kdDebug() << "No exif data found into " << file << endl; return true; } + // start debug: + QFile foo(file); + kdDebug() << file << " = " << foo.size() << " bytes, orient =" << exifData.getImageOrientation() << endl; + JCOPY_OPTION copyoption = JCOPYOPT_ALL; jpeg_transform_info transformoption; --- branches/stable/extragear/graphics/digikam/utilities/cameragui/cameracontroller.cpp #534391:534392 @@ -324,10 +324,13 @@ { if (autoRotate) { + kdDebug() << "Autorotate : " << file << " \tusing " << tempURL.path() << endl; sendInfo(i18n("EXIF rotating file %1...") .arg(file)); Digikam::exifRotate(tempURL.path()); - } + } else { + kdDebug() << "No Autorotate: " << file << endl; + } // move the file to the destination file if (rename(QFile::encodeName(tempURL.path()),
nota : I have tested indeep using 0.9.0-svn : I cannot reproduce this problem. Important : ExifRotate in 0.8.x use libexif/libkexif and in 0.9.0-svn it use Exiv2. It's different... Gilles
SVN commit 534496 by cgilles: digikam from stable : ExifRotate : - Cleanup source code like in trunk branch. There are no fondamental change about exif orientation rules use to perform JPEG transformation. - Add a test to check we have a real JPEG image like in trunk. - Add indeep debug messages Tested indeep : i cannot reproduce the problem here. No Exif informations are lost after rotation CCBUGS: 126326 CCMAIL: digikam-devel@kde.org M +215 -180 exifrotate.cpp M +7 -5 exifrotate.h
Achim, Very important : after to have performed Exif rotation on image collection, are you used : 1- Image/Properties/exif dialog tab (always work here) 2- album file tip : here this way don't show Exif info because jpeg image are detected like RAW files by KDE. In trunk, this problem have been fixed. Gilles
Hi Gilles, in both, Tooltip and RMB menu over thumbnail -> Properties, EXIF tab The EXIF tab is completely empty. Achim
It's not the case here. All work fine. I have reproduce the download many time on 3 computers without problem. Please checkout the code and try again. You can look in the console : there are a lot of debug infos now. Gilles
about the Tooltip. Hmm, when I look at those images as downloaded from free.fr the tooltip shows e.g. creation time and exposure time. So tooltip display some exif info. After I download with auto-rotate this is no longer displayed. e.g. this happens with IMG_2266.JPG and IMG_2265.JPG. Achim P.S. I will not find time to test the new code before friday night.
SVN commit 539367 by ach: digikam trunk: forward port of r539364: o disable enable final for jpegutils/. Fixes bug 126326 when --enable-final is used. Thx to Gilles for the hint. M +5 -0 Makefile.am --- trunk/extragear/graphics/digikam/libs/jpegutils/Makefile.am #539366:539367 @@ -1,5 +1,10 @@ METASOURCES = AUTO +# --enable-final triggers: http://bugs.kde.org/show_bug.cgi?id=126326 +# digikam: camera download: auto-rotated images loose EXIF info ... +# So make sure nofinal is always used here! +KDE_OPTIONS = nofinal + INCLUDES = $(all_includes) \ -I$(top_srcdir)/digikam/libs/dmetadata \
SVN commit 539482 by cgilles: JpegLossLess plugin : backport fix from digiKam (see file 126326 in B.K.O) about an incompatibility with JPEG implementation and "enable-final" option! CCMAIL: kde-imaging@kde.org CCBUGS: 126326 M +6 -2 Makefile.am M +4 -4 convert2grayscale.cpp M +4 -4 imageflip.cpp M +62 -44 imagerotate.cpp --- trunk/extragear/libs/kipi-plugins/jpeglossless/Makefile.am #539481:539482 @@ -1,7 +1,11 @@ METASOURCES = AUTO -KDE_CXXFLAGS = $(USE_EXCEPTIONS) INCLUDES = $(LIBKIPI_CFLAGS) $(LIBKEXIF_CFLAGS) $(all_includes) +# --enable-final triggers: http://bugs.kde.org/show_bug.cgi?id=126326 +# digikam: camera download: auto-rotated images loose EXIF info ... +# So make sure nofinal is always used here! +KDE_OPTIONS = nofinal + # Install this plugin in the KDE modules directory kde_module_LTLIBRARIES = kipiplugin_jpeglossless.la @@ -12,7 +16,7 @@ imagerotate.cpp convert2grayscale.cpp imageflip.cpp kipiplugin_jpeglossless_la_LIBADD = $(LIB_KPARTS) \ - -ljpeg -lMagick++ $(LIBKIPI_LIBS) $(LIBKEXIF_LIBS) + -ljpeg -lWand $(LIBKIPI_LIBS) $(LIBKEXIF_LIBS) kipiplugin_jpeglossless_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) --- trunk/extragear/libs/kipi-plugins/jpeglossless/convert2grayscale.cpp #539481:539482 @@ -41,9 +41,9 @@ #include <kdebug.h> #include <kurl.h> -// ImageMgick includes. +// ImageMagick includes. -#include <Magick++.h> +//#include <Magick++.h> // Local includes. @@ -192,7 +192,7 @@ bool image2GrayScaleImageMagick(const QString& src, const QString& dest, QString& err) { - try +/* try { Magick::Image image; std::string srcFileName(QFile::encodeName(src)); @@ -209,7 +209,7 @@ err = i18n("Cannot convert to gray scale: %1").arg(error_.what()); kdError() << "Convert2GrayScale: ImageMagick exception: " << error_.what() << endl; return false; - } + }*/ } } // NameSpace KIPIJPEGLossLessPlugin --- trunk/extragear/libs/kipi-plugins/jpeglossless/imageflip.cpp #539481:539482 @@ -44,9 +44,9 @@ #include <libkexif/kexifdata.h> -// ImageMgick includes. +// ImageMagick includes. -#include <Magick++.h> +//#include <Magick++.h> // Local includes @@ -131,7 +131,7 @@ bool flipImageMagick(const QString& src, const QString& dest, FlipAction action, QString& err) { - try +/* try { Magick::Image image; std::string srcFileName(QFile::encodeName(src)); @@ -166,7 +166,7 @@ err = i18n("Cannot flip: %1").arg(error_.what()); kdError() << "ImageFlip: ImageMagick exception: " << error_.what() << endl; return false; - } + }*/ } } // NameSpace KIPIJPEGLossLessPlugin --- trunk/extragear/libs/kipi-plugins/jpeglossless/imagerotate.cpp #539481:539482 @@ -26,8 +26,6 @@ #include <cstdio> #include <cstdlib> -#include <cassert> -#include <string> // Qt includes. @@ -47,10 +45,6 @@ #include <libkexif/kexifdata.h> -// ImageMgick includes. - -#include <Magick++.h> - // Local includes. #include "imagerotate.h" @@ -63,6 +57,7 @@ #include <sys/types.h> #include <unistd.h> #include <jpeglib.h> +#include <wand/magick-wand.h> #include "transupp.h" #include "jpegtransform.h" } @@ -145,51 +140,74 @@ bool rotateImageMagick(const QString& src, const QString& dest, RotateAction angle, QString& err) { - try + bool valRet = true; + MagickWandGenesis(); + PixelWand *background = NewPixelWand(); + MagickWand *magickWand = NewMagickWand(); + MagickBooleanType status = MagickReadImage(magickWand, QFile::encodeName(src)); + + if (status == MagickFalse) { - Magick::Image image; - std::string srcFileName(QFile::encodeName(src)); - image.read(srcFileName); + err = i18n("Failed to load original image"); + valRet = false; + goto Exit_Method; + } - switch(angle) + PixelSetColor(background, "#000000"); + + switch(angle) + { + case (Rot90): + { + status = MagickRotateImage(magickWand, background, 90.0); + break; + } + case (Rot180): { - case (Rot90): - { - image.rotate(90.0); - break; - } - case (Rot180): - { - image.rotate(180.0); - break; - } - case (Rot270): - { - image.rotate(270.0); - break; - } - case (Rot0): - { - break; - } - default: - { - kdError() << "ImageRotate: Nonstandard rotation angle" << endl; - err = i18n("Nonstandard rotation angle"); - return false; - } + status = MagickRotateImage(magickWand, background, 180.0); + break; } - - std::string destFileName(QFile::encodeName(dest)); - image.write(destFileName); - return true; + case (Rot270): + { + status = MagickRotateImage(magickWand, background, 270.0); + break; + } + case (Rot0): + { + break; + } + default: + { + kdError() << "ImageRotate: Nonstandard rotation angle" << endl; + err = i18n("Nonstandard rotation angle"); + valRet = false; + goto Exit_Method; + } } - catch( std::exception &error_ ) + + if (status == MagickFalse) { - err = i18n("Cannot rotating: %1").arg(error_.what()); - kdError() << "ImageRotate: ImageMagick exception: " << error_.what() << endl; - return false; + err = i18n("Failed to process image rotation image"); + valRet = false; + goto Exit_Method; } + + status = MagickWriteImages(magickWand, QFile::encodeName(dest), MagickTrue); + + if (status == MagickFalse) + { + err = i18n("Failed to save target image"); + valRet = false; + goto Exit_Method; + } + +Exit_Method: + + if (background) DestroyPixelWand(background); + MagickClearException(magickWand); + if (magickWand) DestroyMagickWand(magickWand); + MagickWandTerminus(); + return valRet; } } // NameSpace KIPIJPEGLossLessPlugin