mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
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>
This commit is contained in:
parent
02638d7c3e
commit
13d1188c41
6 changed files with 98 additions and 10 deletions
|
@ -14,6 +14,9 @@
|
|||
#include <QSvgRenderer>
|
||||
#include <QDataStream>
|
||||
#include <QPainter>
|
||||
#ifdef LIBRAW_SUPPORT
|
||||
#include <libraw/libraw.h>
|
||||
#endif
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
|
@ -79,12 +82,40 @@ static bool hasVideoFileExtension(const QString &filename)
|
|||
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
|
||||
// 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
|
||||
// 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)
|
||||
{
|
||||
QUrl url = QUrl::fromUserInput(urlfilename);
|
||||
|
@ -102,6 +133,12 @@ Thumbnailer::Thumbnail Thumbnailer::fetchImage(const QString &urlfilename, const
|
|||
|
||||
// Try if Qt can parse this image. If it does, use this as a thumbnail.
|
||||
QImage thumb(filename);
|
||||
|
||||
#ifdef LIBRAW_SUPPORT
|
||||
// If note, perhaps a raw image?
|
||||
if (thumb.isNull())
|
||||
thumb = fetchRawThumbnail(filename);
|
||||
#endif
|
||||
if (!thumb.isNull()) {
|
||||
int size = maxThumbnailSize();
|
||||
thumb = thumb.scaled(size, size, Qt::KeepAspectRatio);
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#ifdef LIBRAW_SUPPORT
|
||||
#include <libraw/libraw.h>
|
||||
#endif
|
||||
|
||||
// Weirdly, android builds fail owing to undefined UINT64_MAX
|
||||
#ifndef UINT64_MAX
|
||||
|
@ -528,6 +531,33 @@ static bool parseASF(QFile &f, metadata *metadata)
|
|||
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
|
||||
|
||||
mediatype_t get_metadata(const char *filename_in, metadata *data)
|
||||
{
|
||||
data->timestamp = 0;
|
||||
|
@ -535,6 +565,11 @@ mediatype_t get_metadata(const char *filename_in, metadata *data)
|
|||
data->location.lat.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));
|
||||
QFile f(filename);
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
|
|
|
@ -1091,6 +1091,17 @@ const QStringList videoExtensionsList = {
|
|||
".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()
|
||||
{
|
||||
return imageExtensionFilters() + videoExtensionFilters();
|
||||
|
@ -1101,7 +1112,7 @@ QStringList imageExtensionFilters()
|
|||
QStringList filters;
|
||||
for (QString format: QImageReader::supportedImageFormats())
|
||||
filters.append("*." + format);
|
||||
return filters;
|
||||
return filters + rawExtensionsList;
|
||||
}
|
||||
|
||||
QStringList videoExtensionFilters()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue