Bug 131603

Summary: Orientation of RAW-images (especially Canons *.cr2)
Product: [Applications] digikam Reporter: Volker Christian <volker.christian>
Component: Metadata-RawAssignee: Digikam Developers <digikam-bugs-null>
Status: RESOLVED FIXED    
Severity: normal CC: caulier.gilles
Priority: NOR    
Version: 0.9.0   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In: 0.9.0
Sentry Crash Report:

Description Volker Christian 2006-07-31 20:04:57 UTC
Version:           0.9.0-beta1 (using KDE 3.5.3, Debian Package 4:3.5.3-1 (testing/unstable))
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.16.9voc

Since one of the last svn-updates the thumbnails of *.cr2 RAW images, also those which had been shot portrait-orientated, are all shown landscape-orientated.
The behaviour of previous digikam-versions has been much more user friendly.

Best regards
voc
Comment 1 Marcel Wiesweg 2006-07-31 23:14:06 UTC
Not immediately obvious, but that's the same problem.

*** This bug has been marked as a duplicate of 131532 ***
Comment 2 Marcel Wiesweg 2006-07-31 23:22:31 UTC
SVN commit 568344 by mwiesweg:

Older Exiv2 versions throw an error when they encounter Minolta Makernote key names.
Only query these keys if they are supported by Exiv2.
Otherwise, the Exif.Image.Orientation tag will be ignored as well.

CCBUGS: 131532, 131603



 M  +50 -34    dmetadata.cpp  


--- trunk/extragear/graphics/digikam/libs/dmetadata/dmetadata.cpp #568343:568344
@@ -550,8 +550,21 @@
     if (d->exifMetadata.empty())
        return ORIENTATION_UNSPECIFIED;
 
+    // Workaround for older Exiv2 versions which do not support
+    // Minolta Makernotes and throw an error for such keys.
+    bool supportMinolta = true;
     try
-    {   
+    {
+        Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation");
+        Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation");
+    }
+    catch( Exiv2::Error &e )
+    {
+        supportMinolta = false;
+    }
+
+    try
+    {
         Exiv2::ExifData exifData(d->exifMetadata);
         Exiv2::ExifData::iterator it;
         long orientation;
@@ -562,49 +575,52 @@
 
         // -- Minolta Cameras ----------------------------------
 
-        Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation");
-        it = exifData.findKey(minoltaKey1);
-        
-        if (it != exifData.end())
+        if (supportMinolta)
         {
-            orientation = it->toLong();
-            kdDebug() << "Minolta Makernote Orientation: " << orientation << endl;
-            switch(orientation)
+            Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation");
+            it = exifData.findKey(minoltaKey1);
+
+            if (it != exifData.end())
             {
-                case 76:
-                    imageOrient = ORIENTATION_ROT_90;
-                    break;
-                case 82:
-                    imageOrient = ORIENTATION_ROT_270;
-                    break;
+                orientation = it->toLong();
+                kdDebug() << "Minolta Makernote Orientation: " << orientation << endl;
+                switch(orientation)
+                {
+                    case 76:
+                        imageOrient = ORIENTATION_ROT_90;
+                        break;
+                    case 82:
+                        imageOrient = ORIENTATION_ROT_270;
+                        break;
+                }
+                return imageOrient;
             }
-            return imageOrient;
-        }
 
-        Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation");
-        it = exifData.findKey(minoltaKey2);
-        
-        if (it != exifData.end())
-        {
-            orientation = it->toLong();
-            kdDebug() << "Minolta Makernote Orientation: " << orientation << endl;
-            switch(orientation)
+            Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation");
+            it = exifData.findKey(minoltaKey2);
+
+            if (it != exifData.end())
             {
-                case 76:
-                    imageOrient = ORIENTATION_ROT_90;
-                    break;
-                case 82:
-                    imageOrient = ORIENTATION_ROT_270;
-                    break;
+                orientation = it->toLong();
+                kdDebug() << "Minolta Makernote Orientation: " << orientation << endl;
+                switch(orientation)
+                {
+                    case 76:
+                        imageOrient = ORIENTATION_ROT_90;
+                        break;
+                    case 82:
+                        imageOrient = ORIENTATION_ROT_270;
+                        break;
+                }
+                return imageOrient;
             }
-            return imageOrient;
         }
 
         // -- Standard Exif tag --------------------------------
 
         Exiv2::ExifKey keyStd("Exif.Image.Orientation");
         it = exifData.findKey(keyStd);
-        
+
         if (it != exifData.end())
         {
             orientation = it->toLong();
@@ -617,8 +633,8 @@
         kdDebug() << "Cannot parse Exif Orientation tag using Exiv2 (" 
                   << QString::fromLocal8Bit(e.what().c_str())
                   << ")" << endl;
-    }        
-    
+    }
+
     return ORIENTATION_UNSPECIFIED;
 }
 
Comment 3 Marcel Wiesweg 2006-07-31 23:40:33 UTC
SVN commit 568351 by mwiesweg:

Rotate RAW thumbnails as well, not only JPEGs contains rotation information.

CCBUGS: 131532, 131603


 M  +38 -47    digikamthumbnail.cpp  


--- trunk/extragear/graphics/digikam/kioslave/digikamthumbnail.cpp #568350:568351
@@ -422,65 +422,56 @@
 
 void kio_digikamthumbnailProtocol::exifRotate(const QString& filePath, QImage& thumb)
 {
-    // Check if the file is an JPEG image
-    KFileMetaInfo metaInfo(filePath, "image/jpeg", KFileMetaInfo::Fastest);
+    // Rotate thumbnail based on metadata orientation information
 
-    if (metaInfo.isValid())
-    {
-        if (metaInfo.mimeType() == "image/jpeg" &&
-            metaInfo.containsGroup("Jpeg EXIF Data"))
-        {
-            // Rotate thumbnail from JPEG files based on EXIF rotate tag
+    DMetadata metadata(filePath);
+    DMetadata::ImageOrientation orientation = metadata.getImageOrientation();
 
-            QWMatrix matrix;
-            DMetadata metadata(filePath);
-            DMetadata::ImageOrientation orientation = metadata.getImageOrientation();
+    if (orientation == DMetadata::ORIENTATION_NORMAL ||
+        orientation == DMetadata::ORIENTATION_UNSPECIFIED)
+        return;
 
-            bool doXform = (orientation != DMetadata::ORIENTATION_NORMAL &&
-                            orientation != DMetadata::ORIENTATION_UNSPECIFIED);
+    QWMatrix matrix;
 
-            switch (orientation) 
-            {
-                case DMetadata::ORIENTATION_NORMAL:
-                case DMetadata::ORIENTATION_UNSPECIFIED:
-                    break;
+    switch (orientation)
+    {
+        case DMetadata::ORIENTATION_NORMAL:
+        case DMetadata::ORIENTATION_UNSPECIFIED:
+            break;
 
-                case DMetadata::ORIENTATION_HFLIP:
-                    matrix.scale(-1, 1);
-                    break;
+        case DMetadata::ORIENTATION_HFLIP:
+            matrix.scale(-1, 1);
+            break;
 
-                case DMetadata::ORIENTATION_ROT_180:
-                    matrix.rotate(180);
-                    break;
+        case DMetadata::ORIENTATION_ROT_180:
+            matrix.rotate(180);
+            break;
 
-                case DMetadata::ORIENTATION_VFLIP:
-                    matrix.scale(1, -1);
-                    break;
+        case DMetadata::ORIENTATION_VFLIP:
+            matrix.scale(1, -1);
+            break;
 
-                case DMetadata::ORIENTATION_ROT_90_HFLIP:
-                    matrix.scale(-1, 1);
-                    matrix.rotate(90);
-                    break;
+        case DMetadata::ORIENTATION_ROT_90_HFLIP:
+            matrix.scale(-1, 1);
+            matrix.rotate(90);
+            break;
 
-                case DMetadata::ORIENTATION_ROT_90:
-                    matrix.rotate(90);
-                    break;
+        case DMetadata::ORIENTATION_ROT_90:
+            matrix.rotate(90);
+            break;
 
-                case DMetadata::ORIENTATION_ROT_90_VFLIP:
-                    matrix.scale(1, -1);
-                    matrix.rotate(90);
-                    break;
+        case DMetadata::ORIENTATION_ROT_90_VFLIP:
+            matrix.scale(1, -1);
+            matrix.rotate(90);
+            break;
 
-                case DMetadata::ORIENTATION_ROT_270:
-                    matrix.rotate(270);
-                    break;
-            }
-
-            //transform accordingly
-            if ( doXform )
-                thumb = thumb.xForm( matrix );
-        }
+        case DMetadata::ORIENTATION_ROT_270:
+            matrix.rotate(270);
+            break;
     }
+
+    // transform accordingly
+    thumb = thumb.xForm( matrix );
 }
 
 QImage kio_digikamthumbnailProtocol::loadPNG(const QString& path)
Comment 4 Gerhard Kulzer 2006-08-01 10:02:33 UTC
Thanks Marcel,
now the thumbnail orientation of my cr2 files is correct for the first time in 
0.9

Gerhard

Am Montag, 31. Juli 2006 23:40 schrieb Marcel Wiesweg:
[bugs.kde.org quoted mail]
Comment 5 Volker Christian 2006-08-01 16:37:33 UTC
Marcel,

thanks for the quick fix - thumpnail orientation is OK again. Though, i had to recreate all thumpnails. Nevertheless, this wasn't bad!

I just want to note that the orientation of the quick-preview (F3) of my *.cr2 files is also broken. Should i fill another bug-report for this issue?

regards
voc
Comment 6 caulier.gilles 2006-08-17 02:42:38 UTC
Marcel, 

Said "Rotate RAW thumbnails as well, not only JPEGs contains rotation information" is right but not always...

The problem is more complex in fact : some RAW files set properlly the Exif orientation tags, some others _NO_ !

I recommend you to test your implementation with my complete RAW files collection in vertical orientation :

http://digikam3rdparty.free.fr/TEST_IMAGES/RAW/VERTICAL

And look like some thumbs orientation are dummy (:=)))... This is why i have limited the auto-rotation of thumbs to JPEG files.

Gilles
 

Comment 7 caulier.gilles 2006-08-17 14:38:57 UTC
SVN commit 573883 by cgilles:

digikam from trunk: Bug fix: with Minolta camera (Dynax5D and 7D), we need to set the Minolta Makernote Orientation tag to "Normal" 
when we set the Exif orientation tag, else preview and thumb will not be orientated properlly after to have created a new image 
from editor using a Minolta picture.
CCBUGS: 131603, 131532



 M  +44 -0     dmetadata.cpp  


--- trunk/extragear/graphics/digikam/libs/dmetadata/dmetadata.cpp #573882:573883
@@ -643,7 +643,20 @@
     if (d->exifMetadata.empty())
        return false;
 
+    // Workaround for older Exiv2 versions which do not support
+    // Minolta Makernotes and throw an error for such keys.
+    bool supportMinolta = true;
     try
+    {
+        Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation");
+        Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation");
+    }
+    catch( Exiv2::Error &e )
+    {
+        supportMinolta = false;
+    }
+
+    try
     {    
         if (orientation < ORIENTATION_UNSPECIFIED || orientation > ORIENTATION_ROT_270)
         {
@@ -653,6 +666,37 @@
         
         d->exifMetadata["Exif.Image.Orientation"] = (uint16_t)orientation;
         kdDebug() << "Exif orientation tag set to: " << orientation << endl;
+
+        // -- Minolta Cameras ----------------------------------
+
+        if (supportMinolta)
+        {
+            uint16_t MinoltaOrientation = 72;    // Horizontal (Normal)
+            switch((uint16_t)orientation)
+            {    
+                case ORIENTATION_ROT_90:
+                        MinoltaOrientation = 76; // Rotate 90 CW
+                    break;
+        
+                case ORIENTATION_ROT_270:
+                        MinoltaOrientation = 82; // Rotate 180 CW
+                    break;
+            }
+    
+            Exiv2::ExifData exifData(d->exifMetadata);
+            Exiv2::ExifData::iterator it;
+
+            Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation");
+            it = exifData.findKey(minoltaKey1);
+            if (it != exifData.end())
+                d->exifMetadata["Exif.MinoltaCs7D.Rotation"] = MinoltaOrientation;
+        
+            Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation");
+            it = exifData.findKey(minoltaKey2);
+            if (it != exifData.end())
+                d->exifMetadata["Exif.MinoltaCs5D.Rotation"] = MinoltaOrientation;
+        }
+
         return true;
     }
     catch( Exiv2::Error &e )