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
|
/* This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000 Carsten Pfeiffer <pfeiffer@kde.org>
SPDX-FileCopyrightText: 2000 Malte Starostik <malte@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "imagecreator.h"
#include <QImageReader>
#include <KMemoryInfo>
#include <KPluginFactory>
K_PLUGIN_CLASS_WITH_JSON(ImageCreator, "imagethumbnail.json")
ImageCreator::ImageCreator(QObject *parent, const QVariantList &args)
: KIO::ThumbnailCreator(parent, args)
{
}
#define MiB(bytes) ((bytes)*1024ll * 1024ll)
#define GiB(bytes) (MiB(bytes) * 1024ll)
// When the ram check is disabled or not available, this is the expected default value of free RAM
#define DEFAULT_FREE_RAM GiB(2)
// The maximum usable RAM is the free RAM is divided by this number:
// if the calculated image size is greater than this value, the preview is skipped.
#define RAM_DIVISOR 3
// An image smaller than 64 MiB will be loaded even if the usable RAM check fails.
#define MINIMUM_GUARANTEED_SIZE MiB(64)
/**
* @brief maximumThumbnailRam
* Calculates the maximum RAM that can be used to generate the thumbnail.
*
* The value returned is a third of the available free RAM.
*/
qint64 maximumThumbnailRam()
{
// read available RAM (physical free ram only)
auto freeRam = DEFAULT_FREE_RAM;
KMemoryInfo m;
if (!m.isNull()) {
freeRam = qint64(m.availablePhysical());
}
/*
* NOTE 1: a minimal 64MiB image is always guaranteed (this small size should never cause OS thrashing).
* NOTE 2: the freeRam is divided by 3 for the following reasons:
* - the image could be converted (e.g. when depth() != 32)
* - we don't want to use all free ram for a thumbnail :)
*/
return std::max(MINIMUM_GUARANTEED_SIZE, freeRam / RAM_DIVISOR);
}
KIO::ThumbnailResult ImageCreator::create(const KIO::ThumbnailRequest &request)
{
// create image preview
QImageReader ir(request.url().toLocalFile());
/* The idea is to read the free ram and try to avoid OS trashing when the
* image is too big:
* - Qt 6: we can simply limit the maximum size that image reader can handle.
* - Qt 5: the image plugin that allows big images should help us by implementing
* the QImageIOHandler::Size option (TIFF, PSB and XCF already have).
*/
auto ram = maximumThumbnailRam();
QImageReader::setAllocationLimit(ram / 1024 / 1024);
ir.setAutoTransform(true);
ir.setDecideFormatFromContent(true);
if (ir.format() == QByteArray("raw")) {
// make preview generation of raw files ~3 times faster (requires setDecideFormatFromContent(true))
ir.setQuality(1);
}
QImage img;
ir.read(&img);
if (!img.isNull()) {
return KIO::ThumbnailResult::pass(img);
}
return KIO::ThumbnailResult::fail();
}
#include "imagecreator.moc"
#include "moc_imagecreator.cpp"
|