diff --git a/core/dplugins/dimg/heif/dimgheifplugin.cpp b/core/dplugins/dimg/heif/dimgheifplugin.cpp index 5eae4f295b..c6cceb4392 100644 --- a/core/dplugins/dimg/heif/dimgheifplugin.cpp +++ b/core/dplugins/dimg/heif/dimgheifplugin.cpp @@ -1,208 +1,213 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : HEIF DImg plugin. * * Copyright (C) 2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "dimgheifplugin.h" // C++ includes #include // Qt includes #include #include // KDE includes #include // Local includes #include "digikam_config.h" #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgheifloader.h" namespace DigikamHEIFDImgPlugin { DImgHEIFPlugin::DImgHEIFPlugin(QObject* const parent) : DPluginDImg(parent) { } DImgHEIFPlugin::~DImgHEIFPlugin() { } QString DImgHEIFPlugin::name() const { return i18n("HEIF loader"); } QString DImgHEIFPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgHEIFPlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-x-generic")); } QString DImgHEIFPlugin::description() const { return i18n("An image loader based on Libheif codec"); } QString DImgHEIFPlugin::details() const { QString x265Notice = i18n("This library is not present on your system."); #ifdef HAVE_X265 int depth = DImgHEIFLoader::x265MaxBitsDepth(); if (depth != -1) { x265Notice = i18n("This library is available on your system with a maximum color depth " "support of %1 bits.", depth); } else { x265Notice = i18n("This library is available on your system but is not able to encode " "image with a suitable color depth."); } #endif return i18n("

This plugin permit to load and save image using Libheif codec.

" "

High Efficiency Image File Format (HEIF), also known as High Efficiency Image Coding (HEIC), " "is a file format for individual images and image sequences. It was developed by the " "Moving Picture Experts Group (MPEG) and it claims that twice as much information can be " "stored in a HEIF image as in a JPEG image of the same size, resulting in a better quality image. " "HEIF also supports animation, and is capable of storing more information than an animated GIF " "at a small fraction of the size.

" "

Encoding HEIC is relevant of optional libx265 codec. %1

" "

See " "High Efficiency Image File Format for details.

", x265Notice); } QList DImgHEIFPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2019")) ; } void DImgHEIFPlugin::setup(QObject* const /*parent*/) { // Nothing to do } QMap DImgHEIFPlugin::extraAboutData() const { QMap map; map.insert(QLatin1String("HEIC"), i18n("High efficiency image coding")); return map; } QString DImgHEIFPlugin::loaderName() const { return QLatin1String("HEIF"); } QString DImgHEIFPlugin::typeMimes() const { return QLatin1String("HEIC"); } +bool DImgHEIFPlugin::previewSupported() const +{ + return true; +} + bool DImgHEIFPlugin::canRead(const QString& filePath, bool magic) const { QFileInfo fileInfo(filePath); if (!fileInfo.exists()) { qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; return false; } // First simply check file extension if (!magic) { QString ext = fileInfo.suffix().toUpper(); return (ext == QLatin1String("HEIC")); } // In second, we trying to parse file header. FILE* const f = fopen(QFile::encodeName(filePath).constData(), "rb"); if (!f) { qCDebug(DIGIKAM_DIMG_LOG) << "Failed to open file " << filePath; return false; } const int headerLen = 12; unsigned char header[headerLen]; if (fread(&header, headerLen, 1, f) != 1) { qCDebug(DIGIKAM_DIMG_LOG) << "Failed to read header of file " << filePath; fclose(f); return false; } fclose(f); if ((memcmp(&header[4], "ftyp", 4) == 0) || (memcmp(&header[8], "heic", 4) == 0) || (memcmp(&header[8], "heix", 4) == 0) || (memcmp(&header[8], "mif1", 4) == 0)) { return true; } return false; } bool DImgHEIFPlugin::canWrite(const QString& format) const { #ifdef HAVE_X265 if (format.toUpper() == QLatin1String("HEIC")) { return true; } #endif return false; } DImgLoader* DImgHEIFPlugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgHEIFLoader(image); } } // namespace DigikamHEIFDImgPlugin diff --git a/core/dplugins/dimg/heif/dimgheifplugin.h b/core/dplugins/dimg/heif/dimgheifplugin.h index 14ec2ea1ad..5f9a7e4d53 100644 --- a/core/dplugins/dimg/heif/dimgheifplugin.h +++ b/core/dplugins/dimg/heif/dimgheifplugin.h @@ -1,74 +1,76 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-26 * Description : HEIF DImg plugin. * * Copyright (C) 2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_DIMG_HEIF_PLUGIN_H #define DIGIKAM_DIMG_HEIF_PLUGIN_H // Qt includes #include #include // Local includes #include "dplugindimg.h" #include "dimg.h" #include "dimgloader.h" #define DPLUGIN_IID "org.kde.digikam.plugin.dimg.HEIF" using namespace Digikam; namespace DigikamHEIFDImgPlugin { class DImgHEIFPlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgHEIFPlugin(QObject* const parent = nullptr); ~DImgHEIFPlugin(); QString name() const override; QString iid() const override; QIcon icon() const override; QString details() const override; QString description() const override; QList authors() const override; void setup(QObject* const) override; QMap extraAboutData() const override; + bool previewSupported() const override; + QString loaderName() const; QString typeMimes() const; bool canRead(const QString& filePath, bool magic) const; bool canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamHEIFDImgPlugin #endif // DIGIKAM_DIMG_HEIF_PLUGIN_H diff --git a/core/libs/dimg/dimg_fileio.cpp b/core/libs/dimg/dimg_fileio.cpp index 8fcc8542e4..58c1f94aab 100644 --- a/core/libs/dimg/dimg_fileio.cpp +++ b/core/libs/dimg/dimg_fileio.cpp @@ -1,307 +1,312 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2005-06-14 * Description : digiKam 8/16 bits image management API * Files input output * * Copyright (C) 2005-2019 by Gilles Caulier * Copyright (C) 2006-2013 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "dimg.h" #include "dimg_p.h" namespace Digikam { bool DImg::loadItemInfo(const QString& filePath, bool loadMetadata, bool loadICCData, bool loadUniqueHash, bool loadImageHistory) { DImgLoader::LoadFlags loadFlags = DImgLoader::LoadItemInfo; if (loadMetadata) { loadFlags |= DImgLoader::LoadMetadata; } if (loadICCData) { loadFlags |= DImgLoader::LoadICCData; } if (loadUniqueHash) { loadFlags |= DImgLoader::LoadUniqueHash; } if (loadImageHistory) { loadFlags |= DImgLoader::LoadImageHistory; } return load(filePath, loadFlags, nullptr, DRawDecoding()); } bool DImg::load(const QString& filePath, DImgLoaderObserver* const observer, const DRawDecoding& rawDecodingSettings) { return load(filePath, DImgLoader::LoadAll, observer, rawDecodingSettings); } bool DImg::load(const QString& filePath, bool loadMetadata, bool loadICCData, bool loadUniqueHash, bool loadImageHistory, DImgLoaderObserver* const observer, const DRawDecoding& rawDecodingSettings) { DImgLoader::LoadFlags loadFlags = DImgLoader::LoadItemInfo | DImgLoader::LoadImageData; if (loadMetadata) { loadFlags |= DImgLoader::LoadMetadata; } if (loadICCData) { loadFlags |= DImgLoader::LoadICCData; } if (loadUniqueHash) { loadFlags |= DImgLoader::LoadUniqueHash; } if (loadImageHistory) { loadFlags |= DImgLoader::LoadImageHistory; } return load(filePath, loadFlags, observer, rawDecodingSettings); } bool DImg::load(const QString& filePath, int loadFlagsInt, DImgLoaderObserver* const observer, const DRawDecoding& rawDecodingSettings) { FORMAT format; QString name; DPluginDImg* plug = m_priv->pluginForFile(filePath, false, name, format); DImgLoader::LoadFlags loadFlags = (DImgLoader::LoadFlags)loadFlagsInt; setAttribute(QLatin1String("detectedFileFormat"), format); setAttribute(QLatin1String("originalFilePath"), filePath); FileReadLocker lock(filePath); // First step we check the file extension to find the right loader. if (plug) { + if (loadFlags & DImgLoader::LoadPreview && !plug->previewSupported()) + { + return false; + } + if (observer && !observer->continueQuery(nullptr)) { return false; } qCDebug(DIGIKAM_DIMG_LOG) << filePath << ":" << plug->loaderName() << "file identified"; DImgLoader* const loader = plug->loader(this, rawDecodingSettings); loader->setLoadFlags(loadFlags); if (loader->load(filePath, observer)) { m_priv->null = !loader->hasLoadedData(); m_priv->alpha = loader->hasAlpha(); m_priv->sixteenBit = loader->sixteenBit(); setAttribute(QLatin1String("isReadOnly"), loader->isReadOnly()); delete loader; return true; } delete loader; } if (observer && !observer->continueQuery(nullptr)) { return false; } plug = m_priv->pluginForFile(filePath, true, name, format); setAttribute(QLatin1String("detectedFileFormat"), format); // In the second step we check the magic bytes to find the right loader. if (plug) { if (observer && !observer->continueQuery(nullptr)) { return false; } qCDebug(DIGIKAM_DIMG_LOG) << filePath << ":" << plug->loaderName() << "file identified (magic)"; DImgLoader* const loader = plug->loader(this, rawDecodingSettings); loader->setLoadFlags(loadFlags); if (loader->load(filePath, observer)) { m_priv->null = !loader->hasLoadedData(); m_priv->alpha = loader->hasAlpha(); m_priv->sixteenBit = loader->sixteenBit(); setAttribute(QLatin1String("isReadOnly"), loader->isReadOnly()); delete loader; return true; } delete loader; if (observer && observer->continueQuery(nullptr)) { qCWarning(DIGIKAM_DIMG_LOG) << filePath << ": Cannot load file !!!"; } return false; } qCWarning(DIGIKAM_DIMG_LOG) << filePath << ": Unknown image format !!!"; return false; } QString DImg::formatToMimeType(FORMAT frm) { QString format; switch (frm) { case (NONE): { return format; } case (JPEG): { format = QLatin1String("JPG"); break; } case (TIFF): { format = QLatin1String("TIF"); break; } case (PNG): { format = QLatin1String("PNG"); break; } case (JP2K): { format = QLatin1String("JP2"); break; } case (PGF): { format = QLatin1String("PGF"); break; } default: { // For QImage or ImageMagick based. break; } } return format; } bool DImg::save(const QString& filePath, FORMAT frm, DImgLoaderObserver* const observer) { if (isNull()) { return false; } return(save(filePath, formatToMimeType(frm), observer)); } bool DImg::save(const QString& filePath, const QString& format, DImgLoaderObserver* const observer) { qCDebug(DIGIKAM_DIMG_LOG) << "Saving to " << filePath << " with format: " << format; if (isNull()) { return false; } if (format.isEmpty()) { return false; } QString name; QString frm = format.toUpper(); setAttribute(QLatin1String("savedFilePath"), filePath); FileWriteLocker lock(filePath); DPluginDImg* const plug = m_priv->pluginForFormat(frm, name); DImg copyForSave = copy(); if (frm == QLatin1String("JPEG") || frm == QLatin1String("JPG") || frm == QLatin1String("JPE")) { // JPEG does not support transparency, so we shall provide an image without alpha channel. // This is only necessary if the image has an alpha channel, and there are actually transparent pixels if (hasTransparentPixels()) { copyForSave.removeAlphaChannel(); } } if (plug) { DImgLoader* const loader = plug->loader(©ForSave); copyForSave.setAttribute(QLatin1String("savedFormat-isReadOnly"), loader->isReadOnly()); bool ret = loader->save(filePath, observer); delete loader; return ret; } qCWarning(DIGIKAM_DIMG_LOG) << filePath << " : Unknown save format !!!"; return false; } DImg::FORMAT DImg::fileFormat(const QString& filePath) { FORMAT format; QString name; DImg::Private::pluginForFile(filePath, false, name, format); return format; } } // namespace Digikam diff --git a/core/libs/dplugins/core/dplugindimg.h b/core/libs/dplugins/core/dplugindimg.h index 8d0e76053a..fa8c15728a 100644 --- a/core/libs/dplugins/core/dplugindimg.h +++ b/core/libs/dplugins/core/dplugindimg.h @@ -1,112 +1,116 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-19 * Description : digiKam plugin definition for DImg image loader. * * Copyright (C) 2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_DPLUGIN_DIMG_H #define DIGIKAM_DPLUGIN_DIMG_H // Local includes #include "dplugin.h" #include "dimgloader.h" #include "dpluginloader.h" #include "digikam_export.h" #include "drawdecoding.h" namespace Digikam { class DIGIKAM_EXPORT DPluginDImg : public DPlugin { Q_OBJECT public: /** * Constructor with optional parent object */ explicit DPluginDImg(QObject* const parent = nullptr); /** * Destructor */ ~DPluginDImg() override; public: /** This kind of plugin only provide one tool. */ int count() const override { return 1; }; /** This kind of plugin do not use a category. */ QStringList categories() const override { return QStringList(); }; /** This kind of plugin do not have GUI visibility attribute. */ void setVisible(bool) override {}; /** * Return the plugin interface identifier. */ QString ifaceIid() const override { return QLatin1String(DIGIKAM_DPLUGIN_DIMG_IID); }; /** This kind of plugin do not need to be configurable */ bool hasVisibilityProperty() const override { return false; }; /** With this kind of plugin, we will display the type-mimes list on about dialog. */ QMap extraAboutData() const override; QString extraAboutDataTitle() const override; public: /** Return a single capitalized word to identify the format supported by the loader. * Ex: jpeg => "JPG" ; tiff => "TIF", etc. */ virtual QString loaderName() const = 0; /** Return the list of white-listed type-mimes supported by the loader, * as a string of file-name suffix separated by spaces. * Ex: "jpeg jpg thm" */ virtual QString typeMimes() const = 0; + /** Return true if the loader can read a preview image. + */ + virtual bool previewSupported() const { return false; }; + /** Return true if source file path is supported by the loader and contents can be loaded. */ virtual bool canRead(const QString& filePath, bool magic) const = 0; /** Return true if target file format is supported by the loader and contents can be written. */ virtual bool canWrite(const QString& format) const = 0; /** Return the image loader instance for the DImg instance. */ virtual DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const = 0; }; } // namespace Digikam Q_DECLARE_INTERFACE(Digikam::DPluginDImg, DIGIKAM_DPLUGIN_DIMG_IID) #endif // DIGIKAM_DPLUGIN_DIMG_H