[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