mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-05-28 00:30:23 -04:00
RAW: Allow preview loading
This patch addresses reports of performance issues on large raw collections. Programs that generate previews must use the plugin correctly. **Setting quality to 0 may return a different image than in the past** (Nothing changes for all other quality values): the plugin loads the embedded thumbnail and, in case of error, decodes the image with quality 1. When compiled with libRAW 0.21+, the plugin automatically select the largest preview from the ones in the file.
This commit is contained in:
parent
c97ee00f5e
commit
1982557a55
@ -581,6 +581,66 @@ void setParams(QImageIOHandler *handler, LibRaw *rawProcessor)
|
||||
params.use_fuji_rotate = T_SR(quality) ? 0 : 1;
|
||||
}
|
||||
|
||||
bool LoadTHUMB(QImageIOHandler *handler, QImage &img)
|
||||
{
|
||||
std::unique_ptr<LibRaw> rawProcessor(new LibRaw);
|
||||
|
||||
// *** Open the stream
|
||||
auto device = handler->device();
|
||||
#ifndef EXCLUDE_LibRaw_QIODevice
|
||||
LibRaw_QIODevice stream(device);
|
||||
if (rawProcessor->open_datastream(&stream) != LIBRAW_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
auto ba = device->readAll();
|
||||
if (rawProcessor->open_buffer(ba.data(), ba.size()) != LIBRAW_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LIBRAW_VERSION < LIBRAW_MAKE_VERSION(0, 21, 0))
|
||||
// *** Unpacking selected thumbnail
|
||||
if (rawProcessor->unpack_thumb() != LIBRAW_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
// *** Search for the bigger thumbnail
|
||||
auto &&tlist = rawProcessor->imgdata.thumbs_list;
|
||||
auto idx = 0;
|
||||
for (auto n = 1; n < std::min(tlist.thumbcount, LIBRAW_THUMBNAIL_MAXCOUNT); ++n) {
|
||||
if (tlist.thumblist[n].twidth > tlist.thumblist[idx].twidth)
|
||||
idx = n;
|
||||
}
|
||||
|
||||
// *** Unpacking selected thumbnail
|
||||
if (rawProcessor->unpack_thumb_ex(idx) != LIBRAW_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// *** Convert to QImage
|
||||
pi_unique_ptr processedImage(rawProcessor->dcraw_make_mem_thumb(), LibRaw::dcraw_clear_mem);
|
||||
if (processedImage == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto ba = QByteArray(reinterpret_cast<const char *>(processedImage->data), qsizetype(processedImage->data_size));
|
||||
if (ba.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (processedImage->type == LIBRAW_IMAGE_BITMAP) {
|
||||
// clang-format off
|
||||
auto header = QString::fromUtf8("P%1\n%2 %3\n%4\n") // taken from KDcraw
|
||||
.arg(processedImage->colors == 3 ? QLatin1String("6") : QLatin1String("5"))
|
||||
.arg(processedImage->width)
|
||||
.arg(processedImage->height)
|
||||
.arg((1 << processedImage->bits)-1);
|
||||
// clang-format on
|
||||
ba.prepend(header.toLatin1());
|
||||
}
|
||||
return img.loadFromData(ba);
|
||||
}
|
||||
|
||||
bool LoadRAW(QImageIOHandler *handler, QImage &img)
|
||||
{
|
||||
std::unique_ptr<LibRaw> rawProcessor(new LibRaw);
|
||||
@ -679,6 +739,11 @@ bool LoadRAW(QImageIOHandler *handler, QImage &img)
|
||||
if (params.output_color == 7) {
|
||||
img.setColorSpace(QColorSpace(QColorSpace::DisplayP3));
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
||||
if (params.output_color == 8) {
|
||||
img.setColorSpace(QColorSpace(QColorSpace::Bt2020));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// *** Set the metadata
|
||||
@ -756,7 +821,16 @@ bool RAWHandler::read(QImage *image)
|
||||
}
|
||||
|
||||
QImage img;
|
||||
if (!LoadRAW(this, img)) {
|
||||
auto ok = false;
|
||||
if (m_quality == 0) {
|
||||
ok = LoadTHUMB(this, img);
|
||||
if (!ok && !dev->isSequential())
|
||||
dev->seek(m_startPos);
|
||||
}
|
||||
if (!ok) {
|
||||
ok = LoadRAW(this, img);
|
||||
}
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,8 @@ private:
|
||||
* @note It is safe to set both W and A: W is used if camera white balance is found, otherwise A is used.
|
||||
*
|
||||
* When quality is a positive value, a value between 0 and 100 is expected. The values are interpreted as follows:
|
||||
* - 00-09: I = 0, C = 1, B = 0, W = 1, A = 1, H = 1 (Linear, sRGB, 8-bits, Camera White, Auto White, Half-size)
|
||||
* - 00 : Embedded preview, if fails same as Half-Size (01-09)
|
||||
* - 01-09: I = 0, C = 1, B = 0, W = 1, A = 1, H = 1 (Linear, sRGB, 8-bits, Camera White, Auto White, Half-size)
|
||||
* - 10-19: I = 0, C = 1, B = 0, W = 1, A = 1, H = 0 (Linear, sRGB, 8-bits, Camera White, Auto White)
|
||||
* - 20-29: I = 3, C = 1, B = 0, W = 1, A = 1, H = 0 (AHD, sRGB, 8-bits, Camera White, Auto White)
|
||||
* - 30-39: I = 3, C = 1, B = 1, W = 1, A = 1, H = 0 (AHD, sRGB, 16-bits, Camera White, Auto White) [Default]
|
||||
@ -72,11 +73,12 @@ private:
|
||||
* - >= 90: I = 11, C = 4, B = 1, W = 1, A = 1, H = 0 (DHT, ProPhoto, 16-bits, Camera White, Auto White)
|
||||
*
|
||||
* When the quality is -1, default quality is used.
|
||||
* @sa m_subType
|
||||
*/
|
||||
qint32 m_quality;
|
||||
|
||||
/*!
|
||||
* \brief m_startPos
|
||||
/**
|
||||
* @brief m_startPos
|
||||
* The initial device position to allow multi image load (cache value).
|
||||
*/
|
||||
qint64 m_startPos;
|
||||
|
Loading…
Reference in New Issue
Block a user