[Digikam-devel] [Bug 145198] light-table should also work with the full image

Marcel Wiesweg marcel.wiesweg at gmx.de
Sat Jun 2 23:15:56 BST 2007


------- 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=145198         




------- Additional Comments From marcel.wiesweg gmx de  2007-06-03 00:15 -------
SVN commit 670899 by mwiesweg:

Fix rotation in LightTable for high quality image.
Move rotation method to a static method.
Store the fact that an image is exif-rotated in the image object.
Call method again in foreground thread, when as high quality
images are unrotated in the cache. Currently, previews are rotated
in the cache.

I hope this fixes the problem in all possible situations.

CCBUG: 145198


 M  +4 -1      digikam/imagepreviewview.cpp  
 M  +8 -5      libs/threadimageio/loadingdescription.h  
 M  +123 -0    libs/threadimageio/loadsavethread.cpp  
 M  +40 -20    libs/threadimageio/loadsavethread.h  
 M  +5 -110    libs/threadimageio/previewtask.cpp  
 M  +0 -1      libs/threadimageio/previewtask.h  
 M  +4 -1      utilities/lighttable/lighttablepreview.cpp  


--- branches/extragear/kde3/graphics/digikam/digikam/imagepreviewview.cpp #670898:670899
 @ -271,8 +271,11  @
     }
     else
     {
+        DImg img(preview);
+        if (AlbumSettings::instance()->getExifRotate())
+            d->previewThread->exifRotate(img, description.filePath);
         d->parent->setPreviewMode(AlbumWidgetStack::PreviewImageMode);
-        setImage(preview);
+        setImage(img);
         d->parent->previewLoaded();
         emit signalPreviewLoaded(true);
     }
--- branches/extragear/kde3/graphics/digikam/libs/threadimageio/loadingdescription.h #670898:670899
 @ -52,7 +52,7  @
 
     /**
      * An invalid LoadingDescription
-    */
+     */
     LoadingDescription()
     {
     }
 @ -60,7 +60,7  @
     /**
      * Use this for files that are not raw files.
      * Stores only the filePath.
-    */
+     */
     LoadingDescription(const QString &filePath)
         : filePath(filePath)
         {
 @ -70,15 +70,18  @
     /**
      * For raw files:
      * Stores filePath and RawDecodingSettings
-    */
+     */
     LoadingDescription(const QString &filePath, KDcrawIface::RawDecodingSettings settings)
         : filePath(filePath), rawDecodingSettings(settings)
         {};
 
     /**
      * For preview jobs:
-     * Stores preview max size and exif rotation
-    */
+     * Stores preview max size and exif rotation.
+     * The exif rotation is only a hint.
+     * Call LoadSaveThread::exifRotate to make sure that the image is really
+     * rotated. It is safe to call this method even if the image is rotated.
+     */
     LoadingDescription(const QString &filePath, int size, bool exifRotate)
         : filePath(filePath)
         {
--- branches/extragear/kde3/graphics/digikam/libs/threadimageio/loadsavethread.cpp #670898:670899
 @ -25,6 +25,7  @
 // Local includes.
 
 #include "ddebug.h"
+#include "dmetadata.h"
 #include "loadsavethread.h"
 #include "managedloadsavethread.h"
 #include "sharedloadsavethread.h"
 @ -201,7 +202,129  @
     return running() && !d->running;
 }
 
+bool LoadSaveThread::exifRotate(DImg &image, const QString& filePath)
+{
+    QVariant attribute(image.attribute("exifRotated"));
+    if (attribute.isValid() && attribute.toBool())
+        return false;
 
+    // Raw files are already rotated properlly by dcraw. Only perform auto-rotation with JPEG/PNG/TIFF file.
+    // We don't have a feedback from dcraw about auto-rotated RAW file during decoding. Return true anyway.
+
+    if (DImg::fileFormat(filePath) == DImg::RAW)
+    {
+        return true;
+    }
+
+    // Rotate thumbnail based on metadata orientation information
+
+    DMetadata metadata(filePath);
+    DMetadata::ImageOrientation orientation = metadata.getImageOrientation();
+
+    bool rotatedOrFlipped = false;
+
+    if(orientation != DMetadata::ORIENTATION_NORMAL)
+    {
+        switch (orientation) 
+        {
+            case DMetadata::ORIENTATION_NORMAL:
+            case DMetadata::ORIENTATION_UNSPECIFIED:
+                break;
+
+            case DMetadata::ORIENTATION_HFLIP:
+                image.flip(DImg::HORIZONTAL);
+                rotatedOrFlipped = true;
+                break;
+
+            case DMetadata::ORIENTATION_ROT_180:
+                image.rotate(DImg::ROT180);
+                rotatedOrFlipped = true;
+                break;
+
+            case DMetadata::ORIENTATION_VFLIP:
+                image.flip(DImg::VERTICAL);
+                rotatedOrFlipped = true;
+                break;
+
+            case DMetadata::ORIENTATION_ROT_90_HFLIP:
+                image.rotate(DImg::ROT90);
+                image.flip(DImg::HORIZONTAL);
+                rotatedOrFlipped = true;
+                break;
+
+            case DMetadata::ORIENTATION_ROT_90:
+                image.rotate(DImg::ROT90);
+                rotatedOrFlipped = true;
+                break;
+
+            case DMetadata::ORIENTATION_ROT_90_VFLIP:
+                image.rotate(DImg::ROT90);
+                image.flip(DImg::VERTICAL);
+                rotatedOrFlipped = true;
+                break;
+
+            case DMetadata::ORIENTATION_ROT_270:
+                image.rotate(DImg::ROT270);
+                rotatedOrFlipped = true;
+                break;
+        }
+    }
+
+    image.setAttribute("exifRotated", true);
+    return rotatedOrFlipped;
+
+    /*
+    if (orientation == DMetadata::ORIENTATION_NORMAL ||
+        orientation == DMetadata::ORIENTATION_UNSPECIFIED)
+        return;
+
+    QWMatrix matrix;
+
+    switch (orientation)
+    {
+        case DMetadata::ORIENTATION_NORMAL:
+        case DMetadata::ORIENTATION_UNSPECIFIED:
+            break;
+
+        case DMetadata::ORIENTATION_HFLIP:
+            matrix.scale(-1, 1);
+            break;
+
+        case DMetadata::ORIENTATION_ROT_180:
+            matrix.rotate(180);
+            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:
+            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
+    thumb = thumb.xForm( matrix );
+    */
+}
+
+
+
+
 }   // namespace Digikam
 
 #include "loadsavethread.moc"
--- branches/extragear/kde3/graphics/digikam/libs/threadimageio/loadsavethread.h #670898:670899
 @ -55,12 +55,14  @
 
     enum NotificationPolicy
     {
-        // Always send notification, unless the last event is still in the event queue
+        /** Always send notification, unless the last event is still in the event queue */
         NotificationPolicyDirect,
-        // Always wait for a certain amount of time after the last event sent.
-        // In particular, the first event will be sent only after waiting for this time span.
-        // (Or no event will be sent, when the loading has finished before)
-        // This is the default.
+        /**
+         * Always wait for a certain amount of time after the last event sent.
+         * In particular, the first event will be sent only after waiting for this time span.
+         * (Or no event will be sent, when the loading has finished before)
+         * This is the default.
+         */
         NotificationPolicyTimeLimited
     };
 
 @ -74,35 +76,53  @
     };
 
     LoadSaveThread();
-    // The thread will execute all pending tasks and wait for this upon destruction
+    /**
+     * Destructor:
+     * The thread will execute all pending tasks and wait for this upon destruction
+     */
     ~LoadSaveThread();
 
-    // Append a task to load the given file to the task list
+    /** Append a task to load the given file to the task list */
     void load(LoadingDescription description);
-    // Append a task to save the image to the task list
+    /** Append a task to save the image to the task list */
     void save(DImg &image, const QString& filePath, const QString &format);
 
     void setNotificationPolicy(NotificationPolicy notificationPolicy);
 
     bool isShuttingDown();
 
+    /**
+     * Utility to make sure that an image is rotated according to exif tag.
+     * Detects if an image has previously already been rotated: You can
+     * call this method more than one time on the same image.
+     * Returns true if the image has actually been rotated or flipped.
+     * Returns false if a rotation was not needed.
+     */
+    static bool exifRotate(DImg &image, const QString& filePath);
+
 signals:
 
-    // This signal is emitted when the loading process begins.
+    /** This signal is emitted when the loading process begins. */
     void signalImageStartedLoading(const LoadingDescription &loadingDescription);
-    // This signal is emitted whenever new progress info is available
-    // and the notification policy allows emitting the signal.
-    // No progress info will be sent for preloaded images (ManagedLoadSaveThread).
+    /**
+     * This signal is emitted whenever new progress info is available
+     * and the notification policy allows emitting the signal.
+     * No progress info will be sent for preloaded images (ManagedLoadSaveThread).
+     */
     void signalLoadingProgress(const LoadingDescription &loadingDescription, float progress);
-    // This signal is emitted when the loading process has finished.
-    // If the process failed, img is null.
+    /**
+     * This signal is emitted when the loading process has finished.
+     * If the process failed, img is null.
+     */
     void signalImageLoaded(const LoadingDescription &loadingDescription, const DImg& img);
-    // This signal is emitted if
-    //  - you are doing shared loading (SharedLoadSaveThread)
-    //  - you started a loading operation with a LoadingDescription for
-    //    a reduced version of the image
-    //  - another thread started a loading operation for a more complete version
-    // You may want to cancel the current operation and start with the given loadingDescription
+    /**
+     * This signal is emitted if
+     *  - you are doing shared loading (SharedLoadSaveThread)
+     *  - you started a loading operation with a LoadingDescription for
+     *    a reduced version of the image
+     *  - another thread started a loading operation for a more complete version
+     * You may want to cancel the current operation and start with the given loadingDescription
+     */
     void signalMoreCompleteLoadingAvailable(const LoadingDescription &oldLoadingDescription,
                                             const LoadingDescription &newLoadingDescription);
 
--- branches/extragear/kde3/graphics/digikam/libs/threadimageio/previewtask.cpp #670898:670899
 @ -77,16 +77,10  @
 
             // rotate if needed - images are unrotated in the cache,
             // except for RAW images, which are already rotated by dcraw.
-            if (m_loadingDescription.previewParameters.exifRotate &&
-                 DImg::fileFormat(m_loadingDescription.filePath) != DImg::RAW)
+            if (m_loadingDescription.previewParameters.exifRotate)
             {
-                QVariant attribute(cachedImg->attribute("exifRotated"));
-                if (!attribute.isValid() || !attribute.toBool())
-                {
-                    // images in the cache are unrotated - except for RAWs
-                    img = img.copy();
-                    exifRotate(m_loadingDescription.filePath, img);
-                }
+                img = img.copy();
+                LoadSaveThread::exifRotate(img, m_loadingDescription.filePath);
             }
 
             QApplication::postEvent(m_thread, new LoadedEvent(m_loadingDescription.filePath, img));
 @ -191,8 +185,9  @
         //img = img.fastScale(scaledSize.width(), scaledSize.height());
     }
 
+    // Scale if hinted, Store previews rotated in the cache (?)
     if (m_loadingDescription.previewParameters.exifRotate)
-        exifRotate(m_loadingDescription.filePath, img);
+        LoadSaveThread::exifRotate(img, m_loadingDescription.filePath);
 
     {
         LoadingCache::CacheLock lock(cache);
 @ -251,105 +246,5  @
     return false;
 }
 
-
-
-void PreviewLoadingTask::exifRotate(const QString& filePath, DImg& image)
-{
-    // Rotate thumbnail based on metadata orientation information
-
-    DMetadata metadata(filePath);
-    DMetadata::ImageOrientation orientation = metadata.getImageOrientation();
-
-    if(orientation != DMetadata::ORIENTATION_NORMAL)
-    {
-        switch (orientation) 
-        {
-            case DMetadata::ORIENTATION_NORMAL:
-            case DMetadata::ORIENTATION_UNSPECIFIED:
-                break;
-
-            case DMetadata::ORIENTATION_HFLIP:
-                image.flip(DImg::HORIZONTAL);
-                break;
-
-            case DMetadata::ORIENTATION_ROT_180:
-                image.rotate(DImg::ROT180);
-                break;
-
-            case DMetadata::ORIENTATION_VFLIP:
-                image.flip(DImg::VERTICAL);
-                break;
-
-            case DMetadata::ORIENTATION_ROT_90_HFLIP:
-                image.rotate(DImg::ROT90);
-                image.flip(DImg::HORIZONTAL);
-                break;
-
-            case DMetadata::ORIENTATION_ROT_90:
-                image.rotate(DImg::ROT90);
-                break;
-
-            case DMetadata::ORIENTATION_ROT_90_VFLIP:
-                image.rotate(DImg::ROT90);
-                image.flip(DImg::VERTICAL);
-                break;
-
-            case DMetadata::ORIENTATION_ROT_270:
-                image.rotate(DImg::ROT270);
-                break;
-        }
-    }
-
-    image.setAttribute("exifRotated", true);
-
-    /*
-    if (orientation == DMetadata::ORIENTATION_NORMAL ||
-        orientation == DMetadata::ORIENTATION_UNSPECIFIED)
-        return;
-
-    QWMatrix matrix;
-
-    switch (orientation)
-    {
-        case DMetadata::ORIENTATION_NORMAL:
-        case DMetadata::ORIENTATION_UNSPECIFIED:
-            break;
-
-        case DMetadata::ORIENTATION_HFLIP:
-            matrix.scale(-1, 1);
-            break;
-
-        case DMetadata::ORIENTATION_ROT_180:
-            matrix.rotate(180);
-            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:
-            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
-    thumb = thumb.xForm( matrix );
-    */
-}
-
 } // namespace Digikam
 
--- branches/extragear/kde3/graphics/digikam/libs/threadimageio/previewtask.h #670898:670899
 @ -50,7 +50,6  @
 
     bool needToScale(const QSize &imageSize, int previewSize);
     bool loadImagePreview(QImage& image, const QString& path);
-    void exifRotate(const QString& filePath, DImg& img);
 };
 
 
--- branches/extragear/kde3/graphics/digikam/utilities/lighttable/lighttablepreview.cpp #670898:670899
 @ -289,7 +289,10  @
     }
     else
     {
-        setImage(preview);
+        DImg img(preview);
+        if (AlbumSettings::instance()->getExifRotate())
+            d->previewThread->exifRotate(img, description.filePath);
+        setImage(img);
         emit signalPreviewLoaded(true);
     }



More information about the Digikam-devel mailing list