Compare commits

...

2 Commits

Author SHA1 Message Date
Berthold Stoeger
b4a8e1afc6 ubuntu/debian: add libraw-dev to build dependencies
I have not idea if this is enough to make parsing of raw files
work for the Ubuntu/Debian package.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-30 14:32:39 +01:00
Berthold Stoeger
11163e4b5e media: load metadata and thumbnails of raw pictures using libraw
The distinguished photographer shoots raw images. There is a
comprehensive library that can extract metadata and thumbnails
from these images. Let's use it if available.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-03-30 14:32:38 +01:00
8 changed files with 100 additions and 10 deletions

View File

@ -6,6 +6,7 @@ desktop: fix gas switches in UDDF exports
core: allow of up to 6 O2 sensors (and corresponding voting logic) core: allow of up to 6 O2 sensors (and corresponding voting logic)
desktop: add divemode as a possible dive list column desktop: add divemode as a possible dive list column
profile-widget: Now zomed in profiles can be panned with horizontal scroll. profile-widget: Now zomed in profiles can be panned with horizontal scroll.
media: support raw files if libraw is installed
desktop: hide only events with the same severity when 'Hide similar events' is used desktop: hide only events with the same severity when 'Hide similar events' is used
equipment: mark gas mixes reported by the dive computer as 'inactive' as 'not used' equipment: mark gas mixes reported by the dive computer as 'inactive' as 'not used'
equipment: include unused cylinders in merged dive if the preference is enabled equipment: include unused cylinders in merged dive if the preference is enabled

View File

@ -166,6 +166,11 @@ if(NOT ANDROID)
endif() endif()
pkg_config_library(LIBUSB libusb-1.0 QUIET) pkg_config_library(LIBUSB libusb-1.0 QUIET)
pkg_config_library(LIBMTP libmtp QUIET) pkg_config_library(LIBMTP libmtp QUIET)
pkg_config_library(LIBRAW libraw QUIET)
endif()
if(LIBRAW_FOUND)
add_definitions(-DLIBRAW_SUPPORT)
endif() endif()
include_directories(. include_directories(.

12
INSTALL
View File

@ -146,7 +146,7 @@ sudo dnf install autoconf automake bluez-libs-devel cmake gcc-c++ git \
qt5-qtbase-devel qt5-qtconnectivity-devel qt5-qtdeclarative-devel \ qt5-qtbase-devel qt5-qtconnectivity-devel qt5-qtdeclarative-devel \
qt5-qtlocation-devel qt5-qtscript-devel qt5-qtsvg-devel \ qt5-qtlocation-devel qt5-qtscript-devel qt5-qtsvg-devel \
qt5-qttools-devel qt5-qtwebkit-devel redhat-rpm-config \ qt5-qttools-devel qt5-qtwebkit-devel redhat-rpm-config \
bluez-libs-devel libgit2-devel libzip-devel libmtp-devel bluez-libs-devel libgit2-devel libzip-devel libmtp-devel libraw-devel
Package names are sadly different on OpenSUSE Package names are sadly different on OpenSUSE
@ -157,7 +157,7 @@ sudo zypper install git gcc-c++ make autoconf automake libtool cmake libzip-deve
libqt5-qtbase-devel libQt5WebKit5-devel libqt5-qtsvg-devel \ libqt5-qtbase-devel libQt5WebKit5-devel libqt5-qtsvg-devel \
libqt5-qtscript-devel libqt5-qtdeclarative-devel \ libqt5-qtscript-devel libqt5-qtdeclarative-devel \
libqt5-qtconnectivity-devel libqt5-qtlocation-devel libcurl-devel \ libqt5-qtconnectivity-devel libqt5-qtlocation-devel libcurl-devel \
bluez-devel libgit2-devel libmtp-devel bluez-devel libgit2-devel libmtp-devel libraw-devel
On Debian Bookworm this seems to work On Debian Bookworm this seems to work
@ -169,7 +169,7 @@ sudo apt install \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \ qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \ qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \ qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev libraw-dev
In order to build and run mobile-on-desktop, you also need In order to build and run mobile-on-desktop, you also need
@ -189,7 +189,7 @@ sudo apt install \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \ qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \ qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \ qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev libraw-dev
In order to build and run mobile-on-desktop, you also need In order to build and run mobile-on-desktop, you also need
@ -209,7 +209,7 @@ sudo apt install \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \ qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \ qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \ qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev libraw-dev
In order to build and run mobile-on-desktop, you also need In order to build and run mobile-on-desktop, you also need
@ -234,7 +234,7 @@ sudo apt install \
qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \ qml-module-qtlocation qml-module-qtpositioning qml-module-qtquick2 \
qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \ qt5-qmake qtchooser qtconnectivity5-dev qtdeclarative5-dev \
qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \ qtdeclarative5-private-dev qtlocation5-dev qtpositioning5-dev \
qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev qtscript5-dev qttools5-dev qttools5-dev-tools libmtp-dev libraw-dev
Note that you'll need to increase the swap space as the default of 100MB Note that you'll need to increase the swap space as the default of 100MB
doesn't seem to be enough. 1024MB worked on a 3B+. doesn't seem to be enough. 1024MB worked on a 3B+.

View File

@ -13,6 +13,9 @@
#include <QSvgRenderer> #include <QSvgRenderer>
#include <QDataStream> #include <QDataStream>
#include <QPainter> #include <QPainter>
#ifdef LIBRAW_SUPPORT
#include <libraw/libraw.h>
#endif
#include <QtConcurrent> #include <QtConcurrent>
@ -78,12 +81,40 @@ static bool hasVideoFileExtension(const QString &filename)
return false; return false;
} }
// Fetch a picture from the given filename and determine its type (picture of video). #ifdef LIBRAW_SUPPORT
QImage fetchRawThumbnail(const QString &filename)
{
LibRaw raw; // Might think about reusing that, one instance per thread
// TODO: Convert filename to UTF-16 for windows
if (raw.open_file(qPrintable(filename)) != LIBRAW_SUCCESS ||
raw.unpack_thumb() != LIBRAW_SUCCESS) {
return QImage();
}
switch (raw.imgdata.thumbnail.tformat) {
case LIBRAW_THUMBNAIL_JPEG: {
QImage res;
res.loadFromData(reinterpret_cast<unsigned char *>(raw.imgdata.thumbnail.thumb),
raw.imgdata.thumbnail.tlength);
return res;
}
case LIBRAW_THUMBNAIL_BITMAP:
return QImage(reinterpret_cast<unsigned char *>(raw.imgdata.thumbnail.thumb),
raw.imgdata.thumbnail.twidth, raw.imgdata.thumbnail.theight,
QImage::Format_RGB888);
default: // Unsupported
return QImage();
}
}
#endif
// Fetch a picture from the given filename and determine its type (picture or video).
// If this is a non-remote file, fetch it from disk. Remote files are fetched from the // If this is a non-remote file, fetch it from disk. Remote files are fetched from the
// net in a background thread. In such a case, the output-type is set to MEDIATYPE_STILL_LOADING. // net in a background thread. In such a case, the output-type is set to MEDIATYPE_STILL_LOADING.
// If the input-flag "tryDownload" is set to false, no download attempt is made. This is to // If the input-flag "tryDownload" is set to false, no download attempt is made. This is to
// prevent infinite loops, where failed image downloads would be repeated ad infinitum. // prevent infinite loops, where failed image downloads would be repeated ad infinitum.
// Returns: fetched image, type
Thumbnailer::Thumbnail Thumbnailer::fetchImage(const QString &urlfilename, const QString &originalFilename, bool tryDownload) Thumbnailer::Thumbnail Thumbnailer::fetchImage(const QString &urlfilename, const QString &originalFilename, bool tryDownload)
{ {
QUrl url = QUrl::fromUserInput(urlfilename); QUrl url = QUrl::fromUserInput(urlfilename);
@ -101,6 +132,12 @@ Thumbnailer::Thumbnail Thumbnailer::fetchImage(const QString &urlfilename, const
// Try if Qt can parse this image. If it does, use this as a thumbnail. // Try if Qt can parse this image. If it does, use this as a thumbnail.
QImage thumb(filename); QImage thumb(filename);
#ifdef LIBRAW_SUPPORT
// If note, perhaps a raw image?
if (thumb.isNull())
thumb = fetchRawThumbnail(filename);
#endif
if (!thumb.isNull()) { if (!thumb.isNull()) {
int size = maxThumbnailSize(); int size = maxThumbnailSize();
thumb = thumb.scaled(size, size, Qt::KeepAspectRatio); thumb = thumb.scaled(size, size, Qt::KeepAspectRatio);

View File

@ -7,6 +7,9 @@
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QDateTime> #include <QDateTime>
#ifdef LIBRAW_SUPPORT
#include <libraw/libraw.h>
#endif
// Weirdly, android builds fail owing to undefined UINT64_MAX // Weirdly, android builds fail owing to undefined UINT64_MAX
#ifndef UINT64_MAX #ifndef UINT64_MAX
@ -528,6 +531,33 @@ static bool parseASF(QFile &f, metadata *metadata)
return false; return false;
} }
// Transform a (deg, min, sec) float triple into microdegrees
degrees_t degminsec_to_udeg(float a[3])
{
if (a[0] == 0.0 && a[1] == 0.0 && a[2] == 0.0)
return { 0 };
return { static_cast<int>(round(a[0] * 1'000'000.0 +
a[1] * (1'000'000.0/60.0) +
a[2] * (1'000'000.0/3600.0))) };
}
#ifdef LIBRAW_SUPPORT
static bool parseRaw(const char *fn, metadata *metadata)
{
LibRaw raw; // Might think about reusing that
// TODO: Convert filename to UTF-16 for windows
if (raw.open_file(fn) != LIBRAW_SUCCESS)
return false;
metadata->timestamp = raw.imgdata.other.timestamp;
metadata->location.lat = degminsec_to_udeg(raw.imgdata.other.parsed_gps.latitude);
metadata->location.lon = degminsec_to_udeg(raw.imgdata.other.parsed_gps.longitude);
return true;
}
#endif
extern "C" mediatype_t get_metadata(const char *filename_in, metadata *data) extern "C" mediatype_t get_metadata(const char *filename_in, metadata *data)
{ {
data->timestamp = 0; data->timestamp = 0;
@ -535,6 +565,11 @@ extern "C" mediatype_t get_metadata(const char *filename_in, metadata *data)
data->location.lat.udeg = 0; data->location.lat.udeg = 0;
data->location.lon.udeg = 0; data->location.lon.udeg = 0;
#ifdef LIBRAW_SUPPORT
if (parseRaw(filename_in, data))
return MEDIATYPE_PICTURE;
#endif
QString filename = localFilePath(QString(filename_in)); QString filename = localFilePath(QString(filename_in));
QFile f(filename); QFile f(filename);
if (!f.open(QIODevice::ReadOnly)) if (!f.open(QIODevice::ReadOnly))

View File

@ -1168,6 +1168,17 @@ const QStringList videoExtensionsList = {
".avi", ".mp4", ".mov", ".mpeg", ".mpg", ".wmv" ".avi", ".mp4", ".mov", ".mpeg", ".mpg", ".wmv"
}; };
// Raw extensions according to https://en.wikipedia.org/wiki/Raw_image_format
static const QStringList rawExtensionsList = {
#ifdef LIBRAW_SUPPORT
"*.3fr", "*.ari", "*.arw", "*.bay", "*.braw", "*.crw", "*.cr2", "*.cr3", "*.cap",
"*.data", "*.dcs", "*.dcr", "*.dng", "*.drf", "*.eip", "*.erf", "*.fff", "*.gpr",
"*.iiq", "*.k25", "*.kdc", "*.mdc", "*.mef", "*.mos", "*.mrw", "*.nef", "*.nrw",
"*.obm", "*.orf", "*.pef", "*.ptx", "*.pxn", "*.r3d", "*.raf", "*.raw", "*.rwl",
"*.rw2", "*.rwz", "*.sr2", "*.srf", "*.srw", "*.x3f"
#endif
};
QStringList mediaExtensionFilters() QStringList mediaExtensionFilters()
{ {
return imageExtensionFilters() + videoExtensionFilters(); return imageExtensionFilters() + videoExtensionFilters();
@ -1178,7 +1189,7 @@ QStringList imageExtensionFilters()
QStringList filters; QStringList filters;
for (QString format: QImageReader::supportedImageFormats()) for (QString format: QImageReader::supportedImageFormats())
filters.append("*." + format); filters.append("*." + format);
return filters; return filters + rawExtensionsList;
} }
QStringList videoExtensionFilters() QStringList videoExtensionFilters()

View File

@ -9,6 +9,7 @@ Build-Depends: asciidoc,
libxslt-dev, libxslt-dev,
libgit2-dev, libgit2-dev,
libsoup2.4-dev, libsoup2.4-dev,
libraw-dev,
pkg-config, pkg-config,
txt2html, txt2html,
libzip-dev, libzip-dev,

View File

@ -17,7 +17,7 @@ RUN apt-get -y update && apt-get install -y \
gcc-7 g++-7 make git autoconf automake libtool pkg-config \ gcc-7 g++-7 make git autoconf automake libtool pkg-config \
curl libdbus-1-3 libexpat1 libfontconfig1 libfreetype6 \ curl libdbus-1-3 libexpat1 libfontconfig1 libfreetype6 \
libexpat1-dev libgl1-mesa-dev libgl1-mesa-glx \ libexpat1-dev libgl1-mesa-dev libgl1-mesa-glx \
ruby gperf bison libx11-6 libx11-xcb1 libjpeg-dev libpng-dev \ ruby gperf bison libx11-6 libx11-xcb1 libjpeg-dev libpng-dev libraw-dev \
libicu-dev libXcomposite-dev libXrender-dev libgstreamer-plugins-base1.0 \ libicu-dev libXcomposite-dev libXrender-dev libgstreamer-plugins-base1.0 \
libxml2-dev libxslt1-dev libzip-dev libsqlite3-dev libusb-1.0-0-dev \ libxml2-dev libxslt1-dev libzip-dev libsqlite3-dev libusb-1.0-0-dev \
libssl-dev libssh2-1-dev libcurl4-openssl-dev mesa-common-dev libqt5gui5 \ libssl-dev libssh2-1-dev libcurl4-openssl-dev mesa-common-dev libqt5gui5 \