Bug 136897 - THM files are not uploaded
Summary: THM files are not uploaded
Status: RESOLVED FIXED
Alias: None
Product: digikam
Classification: Applications
Component: Import-PostProcessing (show other bugs)
Version: 0.9.0
Platform: Compiled Sources Linux
: NOR wishlist
Target Milestone: ---
Assignee: Digikam Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-11-05 17:58 UTC by Paul Waldo
Modified: 2017-08-17 17:41 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In: 1.0.0


Attachments
EXIF data for CRW (8.06 KB, text/plain)
2006-11-06 16:37 UTC, Paul Waldo
Details
EXIF data for THM (12.77 KB, text/plain)
2006-11-06 16:38 UTC, Paul Waldo
Details
Sample thm file created by a Canon Ixus camera (9.44 KB, application/octet-stream)
2007-03-21 18:02 UTC, Fabien
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Waldo 2006-11-05 17:58:36 UTC
Version:           0.9.0-beta3 (using KDE KDE 3.5.5)
Installed from:    Compiled From Sources
Compiler:          g++ (GCC) 4.0.3 (Ubuntu 4.0.3-1ubuntu5) 
OS:                Linux

Canon RAW files (*.CRW) can be uploaded with no problem, but thumbnail files (*.THM) are ignored.
Comment 1 caulier.gilles 2006-11-05 21:13:15 UTC
Yes, file are ignored to download and removed is corresponding RAW file is deleted from camera. THM files are used by camera interface to render thumbnails.

What do you want to do with .THM files. There is only a small thumb and Exif metada-data in these files.

Gilles Caulier
Comment 2 Paul Waldo 2006-11-06 15:12:33 UTC
I would like to keep the THM files for two reasons:
1. They are generated by the camera and part of the "digital negative"
2. I'm not sure whether every bit of information in the THM is duplicated in the CRW.  I would hate to find out thousands of pictures later that some important piece of data is contained in the THM, but they were all discarded.

I propose copying the THM file along with the CRW, applying the same name transformation as the CRW.
Comment 3 caulier.gilles 2006-11-06 15:19:33 UTC
>1. They are generated by the camera and part of the "digital negative" 

THM is not a negative file. RAW file is...

> 2. I'm not sure whether every bit of information in the THM is duplicated in the CRW.  

Yes. You can find all Exif/makernote data in CRW. 

>I would hate to find out thousands of pictures later that some important piece of data is >contained in the THM, but they were all discarded. 

Note than in some camera model (my Dynax 5D for example), the THM file only content the standard Exif data, not the makernotes... My MRW raw file has all metadata.

This is why digiKam forget THM file to download. Also, i think than THM can be confuse for end users. THM are not valid pictures to use like a photograph for editing and publishing.

Gilles Caulier



Comment 4 Paul Waldo 2006-11-06 16:37:45 UTC
Created attachment 18433 [details]
EXIF data for CRW
Comment 5 Paul Waldo 2006-11-06 16:38:15 UTC
Created attachment 18434 [details]
EXIF data for THM
Comment 6 Paul Waldo 2006-11-06 16:39:45 UTC
While a great deal of the EXIF data is duplicated in the CRW, some data is ONLY contained in the THM.  

I've attached two files, both generated from exiv2 using the commands 
"exiv2 -b -p i CRW_7141.CRW" and 
"exiv2 -b -p i CRW_7141.THM".  

You can tell just from the size that they are not identical, but if you do a more detailed comparison, you can see that there is important data missing in the CRW's EXIF data:
grep -a ISO CRW*.txt
CRW_7141.CRW.txt:0x0002 CanonSi      ISOSpeed         Short       1  192
CRW_7141.CRW.txt:0x0010 CanonCs      ISOSpeed         Short       1  0
CRW_7141.THM.txt:0x8827 Photo        ISOSpeedRatings  Short       1  200
CRW_7141.THM.txt:0x0010 CanonCs      ISOSpeed         Short       1  0
CRW_7141.THM.txt:0x0002 CanonSi      ISOSpeed         Short       1  192

Note that the THM contains ISOSpeedRatings, but the CRW does not
Comment 7 caulier.gilles 2006-11-06 16:44:26 UTC
We currently working to update all makernotes from Exiv2 using ExifTool database. Canon makernote parser, witch give the extended Exif informations is an old implemented in Exiv2 an d need to be updated. 

If you want to check both file, try to use the last ExifTool version instead Exiv2

Gilles
Comment 8 Paul Waldo 2006-11-06 17:19:04 UTC
Is this a "configure" setting to use exiftool versus exiv2?

I ran exiftool on both the CRW and THM file and there are still differences in the data in each of the files.  Below is a diff between the sorted output of exiftool for the CRW and the THM.

Examples of the data *missing* from the CRW that *is* included in the THM is "Orientation" and "Scale Factor To 35mm Equivalent".  This is good stuff that shouldn't be thrown away!

pwaldo@office:~/Projects/photo/hdr-test/shack/exif$ diff sorted_CRW_7141.CRW.exiftool.txt sorted_CRW_7141.THM.exiftool.txt
4,5c4,6
< Aperture                        : 10
< Aperture                        : 10.1
---
> Aperture                        : 10.0
> Aperture                        : 10.0
> Aperture Value                  : 10.0
8d8
< Base ISO                        : 100
23c23
< Canon File Description          : EOS DIGITAL REBEL CMOS RAW
---
> Canon File Length               : 8917246
32,33c32
< Color Bit Depth                 : 24
< Color BW                        : 257
---
> Circle Of Confusion             : 0.019 mm
37c36,37
< Component Bit Depth             : 8
---
> Components Configuration        : YCbCr
> Compressed Bits Per Pixel       : 9
40c40,42
< Decoder Table                   : 0 0 514 5006108
---
> Custom Rendered                 : Normal
> Date/Time Of Digitization       : 2006:11:04 14:18:20
> Date/Time Of Last Modification  : 2006:11:04 14:18:20
44a47,48
> Exif Image Length               : 120
> Exif Image Width                : 160
45a50
> Exif Version                    : 0221
47c52
< File Format                     : CRW
---
> Exposure Mode                   : Manual
49c54
< File Name                       : CRW_7141.CRW
---
> File Name                       : CRW_7141.THM
51,52c56,58
< File Size                       : 9 MB
< File Type                       : Canon RAW
---
> File Size                       : 12 kB
> File Source                     : Digital Camera
> File Type                       : JPEG
55a62
> Flash                           : No Flash
56a64
> Flashpix Version                : 0100
58c66,68
< Focal Length                    : 25mm
---
> Focal Length                    : 25.0mm (35mm equivalent: 39.7mm)
> Focal Plane Resolution Unit     : inches
> Focal Plane X Resolution        : 3443.95
59a70
> Focal Plane Y Resolution        : 3442.02
67c78,79
< Image Height                    : 2048
---
> Hyperfocal Distance             : 3.30 m
> Image Height                    : 120
69,70c81,84
< Image Size                      : 3072x2048
< Image Width                     : 3072
---
> Image Size                      : 160x120
> Image Width                     : 160
> Interoperability Index          : THM
> Interoperability Version        : 0100
73,74d86
< Jpg From Raw                    : (Binary data 2275348 bytes, use -b option to extract)
< Lens                            : 18.0 - 55.0mm
75a88
> Lens                            : 18.0 - 55.0mm (35mm equivalent: 28.6 - 87.4mm)
81c94
< Measured EV                     : 9.375
---
> Max Aperture Value              : 4.0
83,84c96,97
< MIME Type                       : application/unknown
< Original File Name              : CRW_7141.CRW
---
> MIME Type                       : image/jpeg
> Orientation                     : Horizontal (normal)
86,88d98
< Pixel Aspect Ratio              : 1
< Raw Data                        : (Binary data 6635694 bytes, use -b option to extract)
< Record ID                       : 0
98,99c108,110
< ROM Operation Mode              : USA
< Rotation                        : 0
---
> Related Image Length            : 2048
> Related Image Width             : 3072
> Resolution Unit                 : inches
100a112,113
> Scale Factor To 35mm Equivalent : 1.6
> Scene Capture Type              : Standard
103,108c116
< Sensor Bottom Border            : 2063
< Sensor Height                   : 2068
< Sensor Left Border              : 72
< Sensor Right Border             : 3143
< Sensor Top Border               : 16
< Sensor Width                    : 3152
---
> Sensing Method                  : One-chip color area
114,115c122,124
< Shutter Speed                   : 1/406
< Shutter Speed                   : 1/406
---
> Shutter Speed                   : 1/400
> Shutter Speed                   : 1/400
> Shutter Speed Value             : 1/400
117d125
< Target Compression Ratio        : 10
119,122d126
< Target Image Type               : Real-world Subject
< Thumbnail File Name             : CRW_7141.THM
< Time Zone Code                  : 0
< Time Zone Info                  : 0
124a129,131
> X Resolution                    : 180
> Y Cb Cr Positioning             : Centered
> Y Resolution                    : 180
Comment 9 Luka Renko 2006-12-25 19:21:02 UTC
I also vote for this feature as .THM file is also used for video files from Canon cameras (my Powershot G3 also other non-SLR cameras). As .AVI does not contain thumbnail or any Exif data, using .THM does give opportunity to present videos better (with thumbnail, with proper properties, with correct date/time...).
Before switching to Linux (and digikam), I was using BreezeBrowser Pro/Downloader Pro from www.breezesys.com and they handle .THM together with RAW/AVI file as one entry (they do not show two entires) and all operations take care of both files.
Comment 10 Loïc Brarda 2007-01-14 19:30:32 UTC
*** This bug has been confirmed by popular vote. ***
Comment 11 Fabien 2007-03-21 18:00:24 UTC
I agree with comment #9

I lost the creation date of all my videos created by Canon Ixus digital cameras... There are also some Exif data that could be useful.
The creation date is very useful, because it allows us to correlate it with a GPS track and to know exactly where the video were taken...

Maybe THM files could be uploaded, but not displayed in the thumbnails, just used to get informations about video files ? Even if digiKam can't deal with it, it could be uploaded for future usage...
Comment 12 Fabien 2007-03-21 18:02:21 UTC
Created attachment 20062 [details]
Sample thm file created by a Canon Ixus camera
Comment 13 Lozito 2007-04-26 07:28:50 UTC
I use THM files to post these videos in my website. It is extremely convenient way since I dont need to generate them manually. DigiKam is a very good tool but I am still using my Windows to download the videos since I want to have the THM files.
Comment 14 Arnd Baecker 2007-04-26 07:47:27 UTC
If your camera acts like an USB storage device
it might be possible to directly copy them via konquerer
into the corresponding digikam.
Comment 15 caulier.gilles 2008-12-17 12:00:47 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 16 caulier.gilles 2008-12-17 15:14:09 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
Comment 17 Paul Waldo 2009-06-05 18:19:24 UTC
Exiftool seems to show the "missing" data in the CRW that is in the THM, so there is no need to copy the THM.  Thanks!