Bug 146764

Summary: media viewer sort images by date and try to fill videos without exiv in the correct order (by filename)
Product: [Applications] digikam Reporter: Michael Höchstetter <michael.hoechstetter>
Component: Import-SortAssignee: Digikam Developers <digikam-bugs-null>
Status: RESOLVED FIXED    
Severity: wishlist    
Priority: NOR    
Version: 0.9.3   
Target Milestone: ---   
Platform: Ubuntu   
OS: Linux   
Latest Commit: Version Fixed In: 0.10.0

Description Michael Höchstetter 2007-06-14 02:05:25 UTC
Version:           svn (using KDE KDE 3.5.6)
Installed from:    Ubuntu Packages

hi,

i had a wish. My digicam produces the normal exiv header on jpgs. But on avi it does not. 
Because of that, when sorting my photos in one album, all .avis appear on the bottom.
my camera creates filenames like DSCF0123.JPG and DSCF0124.AVI.

Therefore it would be nice, to implement the feature, that all "exiv"-containing pictures are sorted chronologically, and the avi files are filled into the correct positions between the jpgs determined by filename.

I miss such a feature.
Comment 1 caulier.gilles 2008-12-17 12:00:38 UTC
SVN commit 897995 by cgilles:

digiKam from KDE3 branch : Camera GUI improvements: USB mass Storage camera: items date management:
- Use metadata from THM files if available to get item informations.
- Video files date are extracted from THM if possible. In this case video files are sorted by date properlly.
- If THM files are not available, we trying to extract date from orginal file metadata.
- If metadata are not available, we use file creation time stamp instead file Modification time stamp.


 M  +103 -60   umscamera.cpp
 M  +8 -8      umscamera.h


--- branches/extragear/kde3/graphics/digikam/utilities/cameragui/umscamera.cpp #897994:897995
@@ -7,7 +7,7 @@
 * Description : USB Mass Storage camera interface
 *
 * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
- * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General
@@ -101,8 +101,10 @@
    if (!list)
        return false;

-    QFileInfoListIterator it( *list );
+    QFileInfoListIterator it(*list);
    QFileInfo *fi;
+    QFileInfo thmlo, thmup;
+    DMetadata meta;

    while ((fi = it.current()) != 0 && !m_cancel)
    {
@@ -112,38 +114,68 @@

        if (!mime.isEmpty())
        {
+            QSize      dims;
+            QDateTime  dt;
            GPItemInfo info;
-            QSize dims(-1, -1);
+            thmlo.setFile(folder + QString("/") + fi->baseName() + QString(".thm"));
+            thmup.setFile(folder + QString("/") + fi->baseName() + QString(".THM"));

-            if (getImageDimensions)
+            if (thmlo.exists())
            {
-                if (mime == QString("image/x-raw"))
+                // Try thumbnail sidecar files with lowercase extension.
+                meta.load(thmlo.filePath());
+                dt   = meta.getImageDateTime();
+                dims = meta.getImageDimensions();
+            }
+            else if (thmup.exists())
+            {
+                // Try thumbnail sidecar files with uppercase extension.
+                meta.load(thmup.filePath());
+                dt   = meta.getImageDateTime();
+                dims = meta.getImageDimensions();
+            }
+            else if (mime == QString("image/x-raw"))
+            {
+                // If no thumbnail sidecar file available , try to load image metadata with Raw files.
+                meta.load(fi->filePath());
+                dt   = meta.getImageDateTime();
+                dims = meta.getImageDimensions();
+            }
+            else
+            {
+                meta.load(fi->filePath());
+                dt   = meta.getImageDateTime();
+                dims = meta.getImageDimensions();
+
+                if (dims.isNull())
                {
-                    DMetadata metaData(fi->filePath());
-                    dims = metaData.getImageDimensions();
-                }
-                else
-                {
-                    KFileMetaInfo meta(fi->filePath());
-                    if (meta.isValid())
+                    // In all others case, try KFileMetaInfo.
+                    KFileMetaInfo kmeta(fi->filePath());
+                    if (kmeta.isValid())
                    {
-                        if (meta.containsGroup("Jpeg EXIF Data"))
-                            dims = meta.group("Jpeg EXIF Data").item("Dimensions").value().toSize();
-                        else if (meta.containsGroup("General"))
-                            dims = meta.group("General").item("Dimensions").value().toSize();
-                        else if (meta.containsGroup("Technical"))
-                            dims = meta.group("Technical").item("Dimensions").value().toSize();
+                        if (kmeta.containsGroup("Jpeg EXIF Data"))
+                            dims = kmeta.group("Jpeg EXIF Data").item("Dimensions").value().toSize();
+                        else if (kmeta.containsGroup("General"))
+                            dims = kmeta.group("General").item("Dimensions").value().toSize();
+                        else if (kmeta.containsGroup("Technical"))
+                            dims = kmeta.group("Technical").item("Dimensions").value().toSize();
                    }
                }
            }

+            if (dt.isNull())
+            {
+                // If date is not found in metadata, use file time stamp
+                dt = fi->created();
+            }
+
            info.name             = fi->fileName();
            info.folder           = !folder.endsWith("/") ? folder + QString("/") : folder;
            info.mime             = mime;
-            info.mtime            = fi->lastModified().toTime_t();
+            info.mtime            = dt.toTime_t();
            info.size             = fi->size();
-            info.width            = dims.width();
-            info.height           = dims.height();
+            info.width            = getImageDimensions ? dims.width()  : -1;
+            info.height           = getImageDimensions ? dims.height() : -1;
            info.downloaded       = GPItemInfo::DownloadUnknow;
            info.readPermissions  = fi->isReadable();
            info.writePermissions = fi->isWritable();
@@ -173,10 +205,9 @@
        return true;

    // THM files: try to get thumbnail from '.thm' files if we didn't manage to get
-    // thumbnail from Exif. Any cameras provides *.thm files like JPEG files with RAW files.
-    // Using this way is always speed up than ultimate loading using DImg.
-    // Nota: the thumbnail extracted with this method can be in poor quality.
-    // 2006/27/01 - Gilles - Tested with my Minolta Dynax 5D USM camera.
+    // thumbnail from Exif. Any cameras provides *.thm files like JPEG files with RAW/video files.
+    // Using this way speed up thumbnailization and limit data transfered between camera and computer.
+    // NOTE: the thumbnail extracted with this method can provide a poor quality preview.

    QFileInfo fi(folder + QString("/") + itemName);

@@ -191,7 +222,6 @@
           return true;
    }

-
    // Finaly, we trying to get thumbnail using DImg API (slow).

    DImg dimgThumb(QFile::encodeName(folder + QString("/") + itemName));
@@ -215,8 +245,7 @@

 bool UMSCamera::downloadItem(const QString& folder, const QString& itemName, const QString& saveFile)
 {
-    m_cancel = false;
-
+    m_cancel     = false;
    QString src  = folder + QString("/") + itemName;
    QString dest = saveFile;

@@ -226,7 +255,7 @@
    if ( !sFile.open(IO_ReadOnly) )
    {
        DWarning() << "Failed to open source file for reading: "
-                    << src << endl;
+                   << src << endl;
        return false;
    }

@@ -271,7 +300,7 @@

 bool UMSCamera::setLockItem(const QString& folder, const QString& itemName, bool lock)
 {
-    QString src  = folder + QString("/") + itemName;
+    QString src = folder + QString("/") + itemName;

    if (lock)
    {
@@ -312,10 +341,9 @@
 }

 bool UMSCamera::uploadItem(const QString& folder, const QString& itemName, const QString& localFile,
-                           GPItemInfo& itemInfo, bool getImageDimensions)
+                           GPItemInfo& info, bool getImageDimensions)
 {
-    m_cancel = false;
-
+    m_cancel     = false;
    QString dest = folder + QString("/") + itemName;
    QString src  = localFile;

@@ -367,45 +395,60 @@

    // Get new camera item information.

+    DMetadata meta;
    QFileInfo fi(dest);
-    QString mime = mimeType(fi.extension(false).lower());
+    QString   mime = mimeType(fi.extension(false).lower());

    if (!mime.isEmpty())
    {
-        QSize dims(-1, -1);
+        QSize     dims;
+        QDateTime dt;

-        if (getImageDimensions)
+        if (mime == QString("image/x-raw"))
        {
-            if (mime == QString("image/x-raw"))
+            // Try to load image metadata with Raw files.
+            meta.load(fi.filePath());
+            dt   = meta.getImageDateTime();
+            dims = meta.getImageDimensions();
+        }
+        else
+        {
+            meta.load(fi.filePath());
+            dt   = meta.getImageDateTime();
+            dims = meta.getImageDimensions();
+
+            if (dims.isNull())
            {
-                DMetadata metaData(fi.filePath());
-                dims = metaData.getImageDimensions();
-            }
-            else
-            {
-                KFileMetaInfo meta(fi.filePath());
-                if (meta.isValid())
+                // In all others case, try KFileMetaInfo.
+                KFileMetaInfo kmeta(fi.filePath());
+                if (kmeta.isValid())
                {
-                    if (meta.containsGroup("Jpeg EXIF Data"))
-                        dims = meta.group("Jpeg EXIF Data").item("Dimensions").value().toSize();
-                    else if (meta.containsGroup("General"))
-                        dims = meta.group("General").item("Dimensions").value().toSize();
-                    else if (meta.containsGroup("Technical"))
-                        dims = meta.group("Technical").item("Dimensions").value().toSize();
+                    if (kmeta.containsGroup("Jpeg EXIF Data"))
+                        dims = kmeta.group("Jpeg EXIF Data").item("Dimensions").value().toSize();
+                    else if (kmeta.containsGroup("General"))
+                        dims = kmeta.group("General").item("Dimensions").value().toSize();
+                    else if (kmeta.containsGroup("Technical"))
+                        dims = kmeta.group("Technical").item("Dimensions").value().toSize();
                }
            }
        }

-        itemInfo.name             = fi.fileName();
-        itemInfo.folder           = !folder.endsWith("/") ? folder + QString("/") : folder;
-        itemInfo.mime             = mime;
-        itemInfo.mtime            = fi.lastModified().toTime_t();
-        itemInfo.size             = fi.size();
-        itemInfo.width            = dims.width();
-        itemInfo.height           = dims.height();
-        itemInfo.downloaded       = GPItemInfo::DownloadUnknow;
-        itemInfo.readPermissions  = fi.isReadable();
-        itemInfo.writePermissions = fi.isWritable();
+        if (dt.isNull())
+        {
+            // If date is not found in metadata, use file time stamp
+            dt = fi.created();
+        }
+
+        info.name             = fi.fileName();
+        info.folder           = !folder.endsWith("/") ? folder + QString("/") : folder;
+        info.mime             = mime;
+        info.mtime            = dt.toTime_t();
+        info.size             = fi.size();
+        info.width            = getImageDimensions ? dims.width()  : -1;
+        info.height           = getImageDimensions ? dims.height() : -1;
+        info.downloaded       = GPItemInfo::DownloadUnknow;
+        info.readPermissions  = fi.isReadable();
+        info.writePermissions = fi.isWritable();
    }

    return true;
--- branches/extragear/kde3/graphics/digikam/utilities/cameragui/umscamera.h #897994:897995
@@ -5,21 +5,21 @@
 *
 * Date        : 2004-12-21
 * Description : USB Mass Storage camera interface
- *
+ *
 * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
- * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation;
 * either version 2, or (at your option)
 * any later version.
- *
+ *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
- *
+ *
 * ============================================================ */

 #ifndef UMSCAMERA_H
@@ -49,7 +49,7 @@
    void cancel();

    void getAllFolders(const QString& folder, QStringList& subFolderList);
-    bool getItemsInfoList(const QString& folder, GPItemInfoList& infoList, bool getImageDimensions = true);
+    bool getItemsInfoList(const QString& folder, GPItemInfoList& infoList, bool getImageDimensions=true);
    bool getThumbnail(const QString& folder, const QString& itemName, QImage& thumbnail);
    bool getExif(const QString& folder, const QString& itemName, char **edata, int& esize);

@@ -57,8 +57,8 @@

    bool downloadItem(const QString& folder, const QString& itemName, const QString& saveFile);
    bool deleteItem(const QString& folder, const QString& itemName);
-    bool uploadItem(const QString& folder, const QString& itemName, const QString& localFile,
-                    GPItemInfo& itemInfo, bool getImageDimensions=true);
+    bool uploadItem(const QString& folder, const QString& itemName, const QString& localFile,
+                    GPItemInfo& info, bool getImageDimensions=true);

    bool cameraSummary(QString& summary);
    bool cameraManual(QString& manual);
@@ -68,7 +68,7 @@

    void listFolders(const QString& folder, QStringList& subFolderList);

-private :
+private:

    bool m_cancel;
 };
Comment 2 caulier.gilles 2008-12-17 15:14:07 UTC
SVN commit 898140 by cgilles:

backport commit #897995 from KDE3 branch
BUG: 177242
BUG: 151275
BUG: 146764
CCBUG: 136897


 M  +1 -2      cameracontroller.cpp  
 M  +1 -2      gpcamera.cpp  
 M  +60 -84    umscamera.cpp  
 M  +4 -4      umscamera.h  


WebSVN link: http://websvn.kde.org/?view=rev&revision=898140