-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimageloader.cpp
More file actions
117 lines (104 loc) · 4.07 KB
/
imageloader.cpp
File metadata and controls
117 lines (104 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "imageloader.h"
#include <QDebug>
#include <QImage>
#include <QImageReader>
#include <memory>
#include <libraw/libraw.h>
#include <QBuffer>
imageLoader::imageLoader(QObject *parent)
: QObject(parent)
{}
void imageLoader::loadImageFile(const TreeNode *_node)
{
node = _node;
}
void imageLoader::loadImage()
{
QImage thumbnail;
constexpr int kMaxDim = 1024;
// safety: ensure node is valid
if (!node) {
QImage img(kMaxDim, (kMaxDim * 2) / 3, QImage::Format_RGB32);
img.fill(Qt::black);
emit imageLoaded(img, true);
emit loadingFailed();
emit finished();
return;
}
if (node->isFile) {
QList<QByteArray> items = QImageReader::supportedImageFormats();
if (items.indexOf(node->info.suffix().toLower().toLocal8Bit()) >= 0) {
QImageReader reader(node->filePath);
reader.setAutoTransform(true); // honor EXIF orientation
// Read at most kMaxDim in either dimension to save memory/time
const QSize origSize = reader.size();
if (origSize.isValid()) {
QSize target = origSize;
target.scale(kMaxDim, kMaxDim, Qt::KeepAspectRatio);
if (target != origSize)
reader.setScaledSize(target);
}
if (!reader.read(&thumbnail)) {
// Fallback: try basic QImage load
QImage img(node->filePath);
if (!img.isNull()) {
thumbnail = img.scaled(kMaxDim, kMaxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
}
} else {
std::unique_ptr<LibRaw> rawProc(new LibRaw());
// keep path bytes alive for the call
QByteArray path = node->filePath.toLocal8Bit();
auto state = rawProc->open_file(path.constData());
if (LIBRAW_SUCCESS != state) {
// clean up and emit failure
rawProc.reset();
QImage img(kMaxDim, (kMaxDim * 2) / 3, QImage::Format_RGB32);
img.fill(Qt::black);
emit imageLoaded(img, true);
emit loadingFailed();
emit finished();
return;
}
// Ensure a thumbnail is available
int ret = LIBRAW_SUCCESS;
if (!rawProc->imgdata.thumbnail.thumb) {
ret = rawProc->unpack_thumb();
}
if (ret == LIBRAW_SUCCESS && rawProc->imgdata.thumbnail.thumb && rawProc->imgdata.thumbnail.tlength > 0) {
QByteArray thumbData(reinterpret_cast<const char*>(rawProc->imgdata.thumbnail.thumb),
static_cast<int>(rawProc->imgdata.thumbnail.tlength));
QBuffer buf(&thumbData);
buf.open(QIODevice::ReadOnly);
QImageReader r(&buf);
r.setDecideFormatFromContent(true);
r.setAutoTransform(true);
if (!r.read(&thumbnail)) {
// Fallback to direct loadFromData
QImage tmp;
if (tmp.loadFromData(reinterpret_cast<const uchar*>(thumbData.constData()), thumbData.size())) {
thumbnail = tmp;
}
}
}
// free libraw object before further processing
rawProc.reset();
if (!thumbnail.isNull()) {
thumbnail = thumbnail.scaled(kMaxDim, kMaxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
}
}
// Check if the image was loaded successfully
if (thumbnail.isNull()) {
QImage img(kMaxDim, (kMaxDim * 2) / 3, QImage::Format_RGB32);
img.fill(Qt::black);
emit imageLoaded(img, true);
emit loadingFailed();
} else {
if (thumbnail.width() > kMaxDim || thumbnail.height() > kMaxDim) {
thumbnail = thumbnail.scaled(kMaxDim, kMaxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
emit imageLoaded(thumbnail);
}
emit finished();
}