diff --git a/NEWS b/NEWS index c41765697c..619f099a9b 100644 --- a/NEWS +++ b/NEWS @@ -1,72 +1,73 @@ digiKam 6.4.0 - Release date: 2019-??-?? ***************************************************************************************************** NEW FEATURES: General : new RawImport plugin interface to delegate Raw decoding function to extra engine with ImageEditor. General : new DImg plugin interface to externalize image loaders from core implementation. General : new HEIC image loader compatible with media generated by Apple devices. Import : add new option to convert on the fly to HEIC lossless format while downloading. ImageEditor: add new setting from setup dialog to select right Raw Import plugin. ImageEditor: add new clone tool to fix artifacts on image. ImageEditor: add new tool to import RAW image using UFRaw. ImageEditor: add new tool to import RAW image using RawTherapee. ImageEditor: add new tool to import RAW image using DarkTable. BQM : add new tool to convert to HEIC format. ***************************************************************************************************** BUGFIXES: 001 ==> 411587 - [digiKam] Crash when reopening Google Photos import wizard. 002 ==> 411578 - White Balance changes global luminosity. 003 ==> 411696 - Cannot launch digikam-6.3.0-x86-64.appimage in Kubuntu 14.04. 004 ==> 406503 - Histogram initializes greyer than white. 005 ==> 411714 - Correction of ticket 408881 (Restore default tools settings) is not enforced. 006 ==> 411702 - Video/picture Filter. 007 ==> 411726 - Geolocation not working. 008 ==> 387768 - File system corruption after renaming folder. 009 ==> 411808 - digiKam quit unexpectedly. 010 ==> 411880 - Existing file is count but not displayed. 011 ==> 411882 - I don't get image stack or panorama. 012 ==> 403269 - Stacked image and Panorama tools cannot find required binaries. 013 ==> 411651 - New tool to export photos to Canon Irista. 014 ==> 411927 - Crash during initial scan. 015 ==> 389652 - Interface freezes during initial scan. 016 ==> 389949 - Very slow startup [patch]. 017 ==> 316865 - SCAN : Add new option to don't scan file bigger than n Mb or stop scan if longer than n seconds. 018 ==> 370019 - Sidecar metadata not loading sporadically. 019 ==> 329353 - Make slow processing better. 020 ==> 392090 - While scanning collection the progess bar shows 0%. 021 ==> 411929 - Can not move or delete videos that were not played till the end. 022 ==> 392727 - Images are missing (Windows). 023 ==> 396559 - "digikam.dbengine: Database is locked." when scanning for new items. 024 ==> 411946 - Crash when saving captions to picture. 025 ==> 411902 - Interface icons become very large and unusable. 026 ==> 330168 - MYSQL : allow read only database. 027 ==> 351658 - Prevent to fill whole memory when all CPU cores are used to process Maintenance tools. 028 ==> 110920 - Support for removing complex objects from photos. 029 ==> 103332 - Blurring brushes for image correction. 030 ==> 150161 - UFRaw as tool for RAW. 032 ==> 411214 - digiKam git beta 6.4 eats huge memory. 033 ==> 181941 - Add an option to image editor to remember or not tools settings between sessions. 034 ==> 221571 - Integrate RawTherapee into digikam 035 ==> 341186 - Integrate with darktable. 036 ==> 412083 - Image previews scaled incorrectly on hidpi. 037 ==> 411612 - When using Tags Manager and then closing crashes digiKam. 038 ==> 412291 - Mac: Opening Preferences zooms the main window to unusable state. 039 ==> 412372 - Image editor view is expanded to 100% and shows only partial amount of picture. 040 ==> 412293 - Image editor Tools sidebar width not restored. 041 ==> 412425 - UI "breaks" / scales after opening any dialog. 042 ==> 412437 - Opening Preferences on MacOS 10.14.6 breaks resolution of main screen. 043 ==> 412442 - Website points to obsolete versions. 044 ==> 411027 - image files *.heic from iphones do not show up in digikam thumbnails although ther are find in MS file browser. 045 ==> 412574 - New images are not recognized when externally added to a DK folder. 046 ==> 195583 - FILEIO : read header metadata from JPEG2000 files with Exiv2. 047 ==> 116225 - JPEG compression quality should be shown in Properties. 048 ==> 405232 - digiKam crashes in Slideshow and Presentation. 049 ==> 412730 - Main window double resolution on retina after dialog is open. 050 ==> 412728 - MacOS: Image editor tools for colour adjustment incorrectly apply crop automatically and cut out most of the image. 051 ==> 412777 - DigiKam+MySQL: Failed to create database tables. 052 ==> 412854 - Digikam Impossible to select "write metadata in Raw files" in configuration menu. 053 ==> 411480 - Problems with database migration on remote host. -054 ==> +054 ==> 412880 - Since version 6.2.0 video thumbnails are generated from the very first scene of the movie files. +055 ==> diff --git a/core/dplugins/dimg/heif/dimgheifplugin.cpp b/core/dplugins/dimg/heif/dimgheifplugin.cpp index 9f9d1c8556..e036e7e77f 100644 --- a/core/dplugins/dimg/heif/dimgheifplugin.cpp +++ b/core/dplugins/dimg/heif/dimgheifplugin.cpp @@ -1,214 +1,205 @@ /* ============================================================ * * 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 libde265 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")); map.insert(QLatin1String("HEIF"), i18n("High efficiency image file format")); return map; } bool DImgHEIFPlugin::previewSupported() const { return true; } QString DImgHEIFPlugin::loaderName() const { return QLatin1String("HEIF"); } QString DImgHEIFPlugin::typeMimes() const { return QLatin1String("HEIC HEIF"); } -bool DImgHEIFPlugin::canRead(const QString& filePath, bool magic) const +int DImgHEIFPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); // First simply check file extension if (!magic) { - QString ext = fileInfo.suffix().toUpper(); - - return (ext == QLatin1String("HEIC")); + return (format == QLatin1String("HEIC")) ? 10 : 0; } // 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; + return 0; } 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; + return 0; } 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)) + if (memcmp(&header[4], "ftypheic", 8) == 0 || + memcmp(&header[4], "ftypheix", 8) == 0 || + memcmp(&header[4], "ftypmif1", 8) == 0) { - return true; + return 10; } - return false; + return 0; } -bool DImgHEIFPlugin::canWrite(const QString& format) const +int DImgHEIFPlugin::canWrite(const QString& format) const { #ifdef HAVE_X265 if (format.toUpper() == QLatin1String("HEIC")) { - return true; + return 10; } #endif - return false; + return 0; } 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 5f9a7e4d53..fba434490e 100644 --- a/core/dplugins/dimg/heif/dimgheifplugin.h +++ b/core/dplugins/dimg/heif/dimgheifplugin.h @@ -1,76 +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; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int 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/dplugins/dimg/imagemagick/dimgimagemagickloader.cpp b/core/dplugins/dimg/imagemagick/dimgimagemagickloader.cpp index 265ba4fb99..c66c2884ca 100644 --- a/core/dplugins/dimg/imagemagick/dimgimagemagickloader.cpp +++ b/core/dplugins/dimg/imagemagick/dimgimagemagickloader.cpp @@ -1,296 +1,276 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-04-19 * Description : ImageMagick loader for DImg framework. * * Copyright (C) 2019 by Caulier Gilles * Copyright (c) 2019 by Maik Qualmann * * 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 "dimgimagemagickloader.h" -// Qt includes - -#include - // ImageMagick includes // Pragma directives to reduce warnings from ImageMagick header files. #if defined(Q_CC_GNU) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif #if defined(Q_CC_CLANG) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wkeyword-macro" #endif #include // Restore warnings #if defined(Q_CC_CLANG) # pragma clang diagnostic pop #endif #if defined(Q_CC_GNU) # pragma GCC diagnostic pop #endif // Local includes #include "digikam_debug.h" #include "dimgloaderobserver.h" using namespace Magick; namespace DigikamImageMagickDImgPlugin { DImgImageMagickLoader::DImgImageMagickLoader(DImg* const image) : DImgLoader(image) { m_hasAlpha = false; m_sixteenBit = false; } DImgImageMagickLoader::~DImgImageMagickLoader() { } bool DImgImageMagickLoader::load(const QString& filePath, DImgLoaderObserver* const observer) { - QStringList blackList; - blackList << QLatin1String("image/x-xcf"); - - QString mimeType(QMimeDatabase().mimeTypeForFile(filePath).name()); - - // qCDebug(DIGIKAM_DIMG_LOG) << "Mime type name:" << mimeType; - - if (blackList.contains(mimeType) || - mimeType.startsWith(QLatin1String("video/")) || - mimeType.startsWith(QLatin1String("audio/"))) - { - qCWarning(DIGIKAM_DIMG_LOG) << "Blacklisted from ImageMagick loader:" << mimeType; - loadingFailed(); - return false; - } - readMetadata(filePath); // Loading is opaque to us. No support for stopping from observer, // progress info are only pseudo values if (observer) { observer->progressInfo(m_image, 0.5F); } qCDebug(DIGIKAM_DIMG_LOG) << "Try to load image with ImageMagick codecs"; try { Image image; if (m_loadFlags & LoadImageData) { try { image.read(filePath.toUtf8().constData()); } catch (Warning& warning) { qCWarning(DIGIKAM_DIMG_LOG) << "ImageMagick warning [" << filePath << "]" << warning.what(); } if (observer) { observer->progressInfo(m_image, 0.8F); } qCDebug(DIGIKAM_DIMG_LOG) << "IM to DImg :" << image.columns() << image.rows(); qCDebug(DIGIKAM_DIMG_LOG) << "IM QuantumRange :" << QuantumRange; qCDebug(DIGIKAM_DIMG_LOG) << "IM Depth :" << image.depth(); qCDebug(DIGIKAM_DIMG_LOG) << "IM Format :" << image.format().c_str(); int depth = image.depth(); Blob* const pixelBlob = new Blob; image.write(pixelBlob, "BGRA", depth); qCDebug(DIGIKAM_DIMG_LOG) << "IM blob size :" << pixelBlob->length(); if (observer) { observer->progressInfo(m_image, 0.9F); } if (m_loadFlags & LoadICCData) { Blob iccBlob(image.iccColorProfile()); QByteArray iccRawProfile((char*)iccBlob.data(), iccBlob.length()); if (!iccRawProfile.isEmpty()) { imageSetIccProfile(IccProfile(iccRawProfile)); } } if (observer) { observer->progressInfo(m_image, 1.0F); } imageWidth() = image.columns(); imageHeight() = image.rows(); imageData() = (uchar*)pixelBlob->data(); #if MagickLibVersion < 0x700 m_hasAlpha = image.matte(); #else m_hasAlpha = image.alpha(); #endif m_sixteenBit = (depth == 16); // We considering that PNG is the most representative format of an image loaded by ImageMagick imageSetAttribute(QLatin1String("format"), QLatin1String("PNG")); imageSetAttribute(QLatin1String("originalColorModel"), DImg::RGB); imageSetAttribute(QLatin1String("originalBitDepth"), depth); imageSetAttribute(QLatin1String("originalSize"), QSize(image.columns(), image.rows())); } else { try { image.ping(filePath.toUtf8().constData()); } catch (Warning& warning) { qCWarning(DIGIKAM_DIMG_LOG) << "ImageMagick warning [" << filePath << "]" << warning.what(); } imageWidth() = image.columns(); imageHeight() = image.rows(); #if MagickLibVersion < 0x700 m_hasAlpha = image.matte(); #else m_hasAlpha = image.alpha(); #endif m_sixteenBit = (image.depth() == 16); imageSetAttribute(QLatin1String("format"), QLatin1String("PNG")); imageSetAttribute(QLatin1String("originalColorModel"), DImg::RGB); imageSetAttribute(QLatin1String("originalBitDepth"), m_sixteenBit ? 16 : 8); imageSetAttribute(QLatin1String("originalSize"), QSize(image.columns(), image.rows())); } } catch (Exception& error) { qCWarning(DIGIKAM_DIMG_LOG) << "ImageMagick exception [" << filePath << "]" << error.what(); loadingFailed(); return false; } return true; } bool DImgImageMagickLoader::save(const QString& filePath, DImgLoaderObserver* const observer) { // Saving is opaque to us. No support for stopping from observer, // progress info are only pseudo values if (observer) { observer->progressInfo(m_image, 0.5F); } qCDebug(DIGIKAM_DIMG_LOG) << "Try to save image with ImageMagick codecs"; try { QVariant formatAttr = imageGetAttribute(QLatin1String("format")); QByteArray format = formatAttr.toByteArray(); if (observer) { observer->progressInfo(m_image, 0.8F); } Blob pixelBlob(imageData(), imageNumBytes()); Image image; image.size(Geometry(imageWidth(), imageHeight())); image.magick("BGRA"); image.depth(imageBitsDepth()); #if MagickLibVersion < 0x700 image.matte(imageHasAlpha()); #else image.alpha(imageHasAlpha()); #endif image.read(pixelBlob); image.magick(format.data()); QByteArray iccRawProfile = m_image->getIccProfile().data(); if (!iccRawProfile.isEmpty()) { Blob iccBlob(iccRawProfile.data(), iccRawProfile.size()); image.iccColorProfile(iccBlob); } image.write(filePath.toUtf8().constData()); if (observer) { observer->progressInfo(m_image, 1.0F); } imageSetAttribute(QLatin1String("format"), format.toUpper()); saveMetadata(filePath); return true; } catch (Exception& error) { qCWarning(DIGIKAM_DIMG_LOG) << "ImageMagick exception [" << filePath << "]" << error.what(); return false; } return true; } bool DImgImageMagickLoader::hasAlpha() const { return m_hasAlpha; } bool DImgImageMagickLoader::sixteenBit() const { return m_sixteenBit; } bool DImgImageMagickLoader::isReadOnly() const { return false; } } // namespace DigikamImageMagickDImgPlugin diff --git a/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp b/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp index e791d25489..9d8a810007 100644 --- a/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp +++ b/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp @@ -1,334 +1,292 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-21 * Description : ImageMagick 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 "dimgimagemagickplugin.h" // Image Magick includes #include #if MagickLibVersion < 0x700 # include #endif using namespace Magick; using namespace MagickCore; // Qt includes -#include #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgimagemagickloader.h" -#include "drawdecoder.h" namespace DigikamImageMagickDImgPlugin { DImgImageMagickPlugin::DImgImageMagickPlugin(QObject* const parent) : DPluginDImg(parent) { MagickCoreGenesis((char*)NULL ,MagickFalse); } DImgImageMagickPlugin::~DImgImageMagickPlugin() { MagickCoreTerminus(); } QString DImgImageMagickPlugin::name() const { return i18n("ImageMagick loader"); } QString DImgImageMagickPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgImageMagickPlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-x-generic")); } QString DImgImageMagickPlugin::description() const { return i18n("An image loader based on ImageMagick coders"); } QString DImgImageMagickPlugin::details() const { return i18n("

This plugin permit to load and save image using ImageMagick coders.

" "

ImageMagick is a free and open-source software suite for converting raster image and vector image files. " "It can read and write over 200 image file formats.

" "

See ImageMagick documentation for details.

" ); } QList DImgImageMagickPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Maik Qualmann"), QString::fromUtf8("metzpinguin at gmail dot com"), QString::fromUtf8("(C) 2019")) << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2006-2019")) ; } void DImgImageMagickPlugin::setup(QObject* const /*parent*/) { // Nothing to do } QMap DImgImageMagickPlugin::extraAboutData() const { QString mimes = typeMimes(); QMap map; ExceptionInfo ex; size_t n = 0; const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); if (!inflst) { qWarning() << "ImageMagick coders list is null!"; return QMap(); } for (uint i = 0 ; i < n ; ++i) { const MagickInfo* inf = inflst[i]; if (inf) { QString mod = #if (MagickLibVersion >= 0x69A && defined(magick_module)) QString::fromLatin1(inf->magick_module).toUpper(); #else QString::fromLatin1(inf->module).toUpper(); #endif if (mimes.contains(mod)) { map.insert(mod, QLatin1String(inf->description)); } } } return map; } QString DImgImageMagickPlugin::loaderName() const { return QLatin1String("IMAGEMAGICK"); } QString DImgImageMagickPlugin::typeMimes() const { - QStringList formats; - ExceptionInfo ex; - size_t n = 0; - const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); - - if (!inflst) - { - qWarning() << "ImageMagick coders list is null!"; - return QString(); - } - - for (uint i = 0 ; i < n ; ++i) - { - const MagickInfo* inf = inflst[i]; - - if (inf && inf->decoder) - { -#if (MagickLibVersion >= 0x69A && defined(magick_module)) - formats.append(QString::fromLatin1(inf->magick_module).toUpper()); -#else - formats.append(QString::fromLatin1(inf->module).toUpper()); -#endif - } - } - - qDebug() << "ImageMagick support this formats:" << formats; - - formats.removeAll(QLatin1String("JPEG")); // JPEG file format - formats.removeAll(QLatin1String("JPG")); // JPEG file format - formats.removeAll(QLatin1String("JPE")); // JPEG file format - formats.removeAll(QLatin1String("PNG")); - formats.removeAll(QLatin1String("TIFF")); - formats.removeAll(QLatin1String("TIF")); - formats.removeAll(QLatin1String("PGF")); - formats.removeAll(QLatin1String("JP2")); // JPEG2000 file format - formats.removeAll(QLatin1String("JPX")); // JPEG2000 file format - formats.removeAll(QLatin1String("JPC")); // JPEG2000 code stream - formats.removeAll(QLatin1String("J2K")); // JPEG2000 code stream - formats.removeAll(QLatin1String("PGX")); // JPEG2000 WM format - formats.removeAll(QLatin1String("HEIC")); - formats.removeAll(QLatin1String("HEIF")); - - QString rawFilesExt = QString(DRawDecoder::rawFiles()).remove(QLatin1String("*.")).toUpper(); - - foreach (const QString& str, rawFilesExt.split(QLatin1Char(' '))) - { - formats.removeAll(str); // All Raw image formats - } + QStringList formats = decoderFormats(); + formats.sort(); QString ret; foreach (const QString& str, formats) { if (!ret.contains(str)) { ret += QString::fromUtf8("%1 ").arg(str.toUpper()); } } return ret; } -bool DImgImageMagickPlugin::canRead(const QString& filePath, bool magic) const +int DImgImageMagickPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); if (!magic) { QString mimeType(QMimeDatabase().mimeTypeForFile(filePath).name()); // Ignore non image format. if ( mimeType.startsWith(QLatin1String("video/")) || mimeType.startsWith(QLatin1String("audio/")) ) { - return false; + return 0; } - QString format = fileInfo.suffix().toUpper(); - QString blackList = QString(DRawDecoder::rawFiles()).remove(QLatin1String("*.")).toUpper(); // Ignore RAW files - blackList.append(QLatin1String(" JPEG JPG JPE PNG TIF TIFF PGF JP2 JPX JPC J2K PGX HEIC HEIF ")); // Ignore native loaders - - if (blackList.toUpper().contains(format)) + if (decoderFormats().contains(format)) { - return false; + if (format == QLatin1String("WEBP")) + { + return 70; + } + else + { + return 90; + } } + } - QStringList formats; - ExceptionInfo ex; - size_t n = 0; - const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); + return 0; +} - if (!inflst) - { - qWarning() << "ImageMagick coders list is null!"; - return false; - } +int DImgImageMagickPlugin::canWrite(const QString& format) const +{ + QStringList formats; + ExceptionInfo ex; + size_t n = 0; + const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); - for (uint i = 0 ; i < n ; ++i) - { - const MagickInfo* inf = inflst[i]; + if (!inflst) + { + qWarning() << "ImageMagick coders list is null!"; + return 0; + } - if (inf && inf->decoder) - { + for (uint i = 0 ; i < n ; ++i) + { + const MagickInfo* inf = inflst[i]; + + if (inf && inf->encoder) + { #if (MagickLibVersion >= 0x69A && defined(magick_module)) - formats.append(QString::fromLatin1(inf->magick_module).toUpper()); + formats.append(QString::fromLatin1(inf->magick_module).toUpper()); #else - formats.append(QString::fromLatin1(inf->module).toUpper()); + formats.append(QString::fromLatin1(inf->module).toUpper()); #endif - } } + } - return (formats.contains(format)); + if (formats.contains(format.toUpper())) + { + if (format.toUpper() == QLatin1String("WEBP")) + { + return 70; + } + else + { + return 90; + } } - return false; + return 0; } -bool DImgImageMagickPlugin::canWrite(const QString& format) const +DImgLoader* DImgImageMagickPlugin::loader(DImg* const image, const DRawDecoding&) const { - QString blackList = QString(DRawDecoder::rawFiles()).remove(QLatin1String("*.")).toUpper(); // Ignore RAW files - blackList.append(QLatin1String(" JPEG JPG JPE PNG TIF TIFF PGF JP2 JPX JPC J2K PGX HEIC HEIF ")); // Ignore native loaders - - if (blackList.toUpper().contains(format)) - { - return false; - } - - // NOTE: Native loaders support are previously black-listed. - // For ex, if tiff is supported in write mode by ImageMagick it will never be handled. + return new DImgImageMagickLoader(image); +} +QStringList DImgImageMagickPlugin::decoderFormats() const +{ QStringList formats; ExceptionInfo ex; size_t n = 0; const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); if (!inflst) { qWarning() << "ImageMagick coders list is null!"; - return false; + return formats; } for (uint i = 0 ; i < n ; ++i) { const MagickInfo* inf = inflst[i]; - if (inf && inf->encoder) + if (inf && inf->decoder) { #if (MagickLibVersion >= 0x69A && defined(magick_module)) formats.append(QString::fromLatin1(inf->magick_module).toUpper()); #else formats.append(QString::fromLatin1(inf->module).toUpper()); #endif } } - if (!formats.contains(format)) + if (formats.contains(QLatin1String("JPEG"))) { - return false; + formats.append(QLatin1String("JPG")); + formats.append(QLatin1String("JPE")); } - return true; -} + // Remove known formats that are not stable. + formats.removeAll(QLatin1String("XCF")); -DImgLoader* DImgImageMagickPlugin::loader(DImg* const image, const DRawDecoding&) const -{ - return new DImgImageMagickLoader(image); + return formats; } } // namespace DigikamImageMagickDImgPlugin diff --git a/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.h b/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.h index 4da0f02b0b..f41424eb81 100644 --- a/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.h +++ b/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.h @@ -1,73 +1,77 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-21 * Description : ImageMagick 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_IMAGE_MAGICK_PLUGIN_H #define DIGIKAM_DIMG_IMAGE_MAGICK_PLUGIN_H // Qt includes #include #include // Local includes #include "dplugindimg.h" #include "dimg.h" #define DPLUGIN_IID "org.kde.digikam.plugin.dimg.ImageMagick" using namespace Digikam; namespace DigikamImageMagickDImgPlugin { class DImgImageMagickPlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgImageMagickPlugin(QObject* const parent = nullptr); ~DImgImageMagickPlugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; + +private: + + QStringList decoderFormats() const; }; } // namespace DigikamImageMagickDImgPlugin #endif // DIGIKAM_DIMG_IMAGE_MAGICK_PLUGIN_H diff --git a/core/dplugins/dimg/jpeg/dimgjpegplugin.cpp b/core/dplugins/dimg/jpeg/dimgjpegplugin.cpp index 3df69b4ea8..69e0538d3b 100644 --- a/core/dplugins/dimg/jpeg/dimgjpegplugin.cpp +++ b/core/dplugins/dimg/jpeg/dimgjpegplugin.cpp @@ -1,182 +1,180 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-21 * Description : JPEG 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 "dimgjpegplugin.h" // C++ includes #include // Qt includes #include -#include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgjpegloader.h" namespace DigikamJPEGDImgPlugin { DImgJPEGPlugin::DImgJPEGPlugin(QObject* const parent) : DPluginDImg(parent) { } DImgJPEGPlugin::~DImgJPEGPlugin() { } QString DImgJPEGPlugin::name() const { return i18n("JPEG loader"); } QString DImgJPEGPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgJPEGPlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-jpeg")); } QString DImgJPEGPlugin::description() const { return i18n("An image loader based on Libjpeg codec"); } QString DImgJPEGPlugin::details() const { return i18n("

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

" "

Joint Photographic Experts Group (JPEG) is a commonly used method of lossy " "compression for digital images, particularly for those images produced by " "digital photography. The degree of compression can be adjusted, allowing " "a selectable tradeoff between storage size and image quality.

" "

See " "Joint Photographic Experts Group documentation for details.

" ); } QList DImgJPEGPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Renchi Raju"), QString::fromUtf8("renchi dot raju at gmail dot com"), QString::fromUtf8("(C) 2005")) << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2006-2019")) ; } void DImgJPEGPlugin::setup(QObject* const /*parent*/) { // Nothing to do } QString DImgJPEGPlugin::loaderName() const { return QLatin1String("JPEG"); } QString DImgJPEGPlugin::typeMimes() const { return QLatin1String("JPG JPEG JPE"); } -bool DImgJPEGPlugin::canRead(const QString& filePath, bool magic) const +int DImgJPEGPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); // First simply check file extension if (!magic) { - QString ext = fileInfo.suffix().toUpper(); - - return (ext == QLatin1String("JPEG") || ext == QLatin1String("JPG") || ext == QLatin1String("JPE")); + return ( + format == QLatin1String("JPEG") || + format == QLatin1String("JPG") || + format == QLatin1String("JPE") + ) ? 10 : 0; } // 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; + return 0; } const int headerLen = 9; 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); uchar jpegID[2] = { 0xFF, 0xD8 }; if (memcmp(&header, &jpegID, 2) == 0) { - return true; + return 10; } - return false; + return 0; } -bool DImgJPEGPlugin::canWrite(const QString& format) const +int DImgJPEGPlugin::canWrite(const QString& format) const { - if ((format == QLatin1String("JPEG") || format == QLatin1String("JPG") || format == QLatin1String("JPE"))) + if (format == QLatin1String("JPEG") || + format == QLatin1String("JPG") || + format == QLatin1String("JPE")) { - return true; + return 10; } - return false; + return 0; } DImgLoader* DImgJPEGPlugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgJPEGLoader(image); } } // namespace DigikamJPEGDImgPlugin diff --git a/core/dplugins/dimg/jpeg/dimgjpegplugin.h b/core/dplugins/dimg/jpeg/dimgjpegplugin.h index c7bb0f29da..7198f52d67 100644 --- a/core/dplugins/dimg/jpeg/dimgjpegplugin.h +++ b/core/dplugins/dimg/jpeg/dimgjpegplugin.h @@ -1,73 +1,73 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-21 * Description : JPEG 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_JPEG_PLUGIN_H #define DIGIKAM_DIMG_JPEG_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.JPEG" using namespace Digikam; namespace DigikamJPEGDImgPlugin { class DImgJPEGPlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgJPEGPlugin(QObject* const parent = nullptr); ~DImgJPEGPlugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamJPEGDImgPlugin #endif // DIGIKAM_DIMG_JPEG_PLUGIN_H diff --git a/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.cpp b/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.cpp index 9c7b55a246..6769875e6f 100644 --- a/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.cpp +++ b/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.cpp @@ -1,199 +1,191 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : JPEG-2000 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 "dimgjpeg2000plugin.h" // C++ includes #include // Qt includes #include -#include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgjpeg2000loader.h" namespace DigikamJPEG2000DImgPlugin { DImgJPEG2000Plugin::DImgJPEG2000Plugin(QObject* const parent) : DPluginDImg(parent) { } DImgJPEG2000Plugin::~DImgJPEG2000Plugin() { } QString DImgJPEG2000Plugin::name() const { return i18n("JPEG-2000 loader"); } QString DImgJPEG2000Plugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgJPEG2000Plugin::icon() const { return QIcon::fromTheme(QLatin1String("image-jpeg2000")); } QString DImgJPEG2000Plugin::description() const { return i18n("An image loader based on Libjasper codec"); } QString DImgJPEG2000Plugin::details() const { return i18n("

This plugin permit to load and save image using Libjasper codec

" "

The JPEG (Joint Photographic Experts Group) 2000 standard, finalized in 2001, " "defines a image-coding scheme using state-of-the-art compression techniques based " "on wavelet technology. Its architecture is useful for many diverse applications, " "including image archiving, security systems, digital photography, and medical imaging.

" "

See " "Joint Photographic Experts Group documentation for details.

" ); } QList DImgJPEG2000Plugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2006-2019")) ; } void DImgJPEG2000Plugin::setup(QObject* const /*parent*/) { // Nothing to do } QMap DImgJPEG2000Plugin::extraAboutData() const { QMap map; map.insert(QLatin1String("JP2"), i18n("JPEG-2000 image")); map.insert(QLatin1String("JPX"), i18n("JPEG-2000 image")); map.insert(QLatin1String("JPC"), i18n("JPEG-2000 stream")); map.insert(QLatin1String("J2K"), i18n("JPEG-2000 stream")); map.insert(QLatin1String("PGX"), i18n("JPEG-2000 verification model")); return map; } QString DImgJPEG2000Plugin::loaderName() const { return QLatin1String("JPEG2000"); } QString DImgJPEG2000Plugin::typeMimes() const { return QLatin1String("JP2 JPX JPC JP2K PGX"); } -bool DImgJPEG2000Plugin::canRead(const QString& filePath, bool magic) const +int DImgJPEG2000Plugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); // First simply check file extension if (!magic) { - QString ext = fileInfo.suffix().toUpper(); - return ( - ext == QLatin1String("JP2") || ext == QLatin1String("JPX") || // JPEG2000 file format - ext == QLatin1String("JPC") || ext == QLatin1String("J2K") || // JPEG2000 code stream - ext == QLatin1String("PGX") // JPEG2000 Verification Model - ); + format == QLatin1String("JP2") || format == QLatin1String("JPX") || // JPEG2000 file format + format == QLatin1String("JPC") || format == QLatin1String("J2K") || // JPEG2000 code stream + format == QLatin1String("PGX") // JPEG2000 Verification Model + ) ? 10 : 0; } // 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; + return 0; } const int headerLen = 9; 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; + return 0; } fclose(f); uchar jp2ID[5] = { 0x6A, 0x50, 0x20, 0x20, 0x0D, }; uchar jpcID[2] = { 0xFF, 0x4F }; if (memcmp(&header[4], &jp2ID, 5) == 0 || memcmp(&header, &jpcID, 2) == 0) { - return true; + return 10; } - return false; + return 0; } -bool DImgJPEG2000Plugin::canWrite(const QString& format) const +int DImgJPEG2000Plugin::canWrite(const QString& format) const { if (format == QLatin1String("JP2") || format == QLatin1String("JPX") || // JPEG2000 file format format == QLatin1String("JPC") || format == QLatin1String("J2K") || // JPEG2000 code stream format == QLatin1String("PGX")) // JPEG2000 Verification Model { - return true; + return 10; } - return false; + return 0; } DImgLoader* DImgJPEG2000Plugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgJPEG2000Loader(image); } } // namespace DigikamJPEG2000DImgPlugin diff --git a/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.h b/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.h index 8fadc9ff07..baeb04be5e 100644 --- a/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.h +++ b/core/dplugins/dimg/jpeg2000/dimgjpeg2000plugin.h @@ -1,74 +1,74 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : JPEG-2000 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_JPEG_2000_PLUGIN_H #define DIGIKAM_DIMG_JPEG_2000_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.JPEG2000" using namespace Digikam; namespace DigikamJPEG2000DImgPlugin { class DImgJPEG2000Plugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgJPEG2000Plugin(QObject* const parent = nullptr); ~DImgJPEG2000Plugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamJPEG2000DImgPlugin #endif // DIGIKAM_DIMG_JPEG_2000_PLUGIN_H diff --git a/core/dplugins/dimg/pgf/dimgpgfplugin.cpp b/core/dplugins/dimg/pgf/dimgpgfplugin.cpp index ff2f789520..a4078c8e75 100644 --- a/core/dplugins/dimg/pgf/dimgpgfplugin.cpp +++ b/core/dplugins/dimg/pgf/dimgpgfplugin.cpp @@ -1,186 +1,178 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : PGF 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 "dimgpgfplugin.h" // C++ includes #include // Qt includes #include -#include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgpgfloader.h" namespace DigikamPGFDImgPlugin { DImgPGFPlugin::DImgPGFPlugin(QObject* const parent) : DPluginDImg(parent) { } DImgPGFPlugin::~DImgPGFPlugin() { } QString DImgPGFPlugin::name() const { return i18n("PGF loader"); } QString DImgPGFPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgPGFPlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-x-generic")); } QString DImgPGFPlugin::description() const { return i18n("An image loader based on Libpgf codec"); } QString DImgPGFPlugin::details() const { return i18n("

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

" "

The Progressive Graphics File (PGF) is an efficient image file format, " "that is based on a fast, discrete wavelet transform with progressive coding " "features. PGF can be used for lossless and lossy compression. It's most suitable " "for natural images. PGF can be used as a very efficient and fast replacement of JPEG-2000.

" "

See " "Progressive Graphics File documentation for details.

" ); } QList DImgPGFPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2009-2019")) ; } void DImgPGFPlugin::setup(QObject* const /*parent*/) { // Nothing to do } QMap DImgPGFPlugin::extraAboutData() const { QMap map; map.insert(QLatin1String("PGF"), i18n("Progressive Graphics File")); return map; } QString DImgPGFPlugin::loaderName() const { return QLatin1String("PGF"); } QString DImgPGFPlugin::typeMimes() const { return QLatin1String("PGF"); } -bool DImgPGFPlugin::canRead(const QString& filePath, bool magic) const +int DImgPGFPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); // First simply check file extension if (!magic) { - QString ext = fileInfo.suffix().toUpper(); - - return (ext == QLatin1String("PGF")); + return (format == QLatin1String("PGF")) ? 10 : 0; } // 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; + return 0; } const int headerLen = 9; 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; + return 0; } fclose(f); uchar pgfID[3] = { 0x50, 0x47, 0x46 }; if (memcmp(&header, &pgfID, 3) == 0) { - return true; + return 10; } - return false; + return 0; } -bool DImgPGFPlugin::canWrite(const QString& format) const +int DImgPGFPlugin::canWrite(const QString& format) const { if (format == QLatin1String("PGF")) { - return true; + return 10; } - return false; + return 0; } DImgLoader* DImgPGFPlugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgPGFLoader(image); } } // namespace DigikamPGFDImgPlugin diff --git a/core/dplugins/dimg/pgf/dimgpgfplugin.h b/core/dplugins/dimg/pgf/dimgpgfplugin.h index 0c732619e2..d61b9559bf 100644 --- a/core/dplugins/dimg/pgf/dimgpgfplugin.h +++ b/core/dplugins/dimg/pgf/dimgpgfplugin.h @@ -1,74 +1,74 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : PGF 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_PGF_PLUGIN_H #define DIGIKAM_DIMG_PGF_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.PGF" using namespace Digikam; namespace DigikamPGFDImgPlugin { class DImgPGFPlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgPGFPlugin(QObject* const parent = nullptr); ~DImgPGFPlugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamPGFDImgPlugin #endif // DIGIKAM_DIMG_PGF_PLUGIN_H diff --git a/core/dplugins/dimg/png/dimgpngplugin.cpp b/core/dplugins/dimg/png/dimgpngplugin.cpp index 2f232913d3..ab4ed56dd4 100644 --- a/core/dplugins/dimg/png/dimgpngplugin.cpp +++ b/core/dplugins/dimg/png/dimgpngplugin.cpp @@ -1,178 +1,170 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : PNG 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 "dimgpngplugin.h" // C++ includes #include // Qt includes #include -#include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgpngloader.h" namespace DigikamPNGDImgPlugin { DImgPNGPlugin::DImgPNGPlugin(QObject* const parent) : DPluginDImg(parent) { } DImgPNGPlugin::~DImgPNGPlugin() { } QString DImgPNGPlugin::name() const { return i18n("PNG loader"); } QString DImgPNGPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgPNGPlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-png")); } QString DImgPNGPlugin::description() const { return i18n("An image loader based on Libpng codec"); } QString DImgPNGPlugin::details() const { return i18n("

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

" "

Portable Network Graphics (PNG) is a raster-graphics file-format that supports " "lossless data compression. PNG was developed as an improved, non-patented replacement " "for Graphics Interchange Format.

" "

See " "Portable Network Graphics documentation for details.

" ); } QList DImgPNGPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2005-2019")) ; } void DImgPNGPlugin::setup(QObject* const /*parent*/) { // Nothing to do } QString DImgPNGPlugin::loaderName() const { return QLatin1String("PNG"); } QString DImgPNGPlugin::typeMimes() const { return QLatin1String("PNG"); } -bool DImgPNGPlugin::canRead(const QString& filePath, bool magic) const +int DImgPNGPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); // First simply check file extension if (!magic) { - QString ext = fileInfo.suffix().toUpper(); - - return (ext == QLatin1String("PNG")); + return (format == QLatin1String("PNG")) ? 10 : 0; } // 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; + return 0; } const int headerLen = 9; 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; + return 0; } fclose(f); uchar pngID[8] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; if (memcmp(&header, &pngID, 8) == 0) { - return true; + return 10; } - return false; + return 0; } -bool DImgPNGPlugin::canWrite(const QString& format) const +int DImgPNGPlugin::canWrite(const QString& format) const { if (format == QLatin1String("PNG")) { - return true; + return 10; } - return false; + return 0; } DImgLoader* DImgPNGPlugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgPNGLoader(image); } } // namespace DigikamPNGDImgPlugin diff --git a/core/dplugins/dimg/png/dimgpngplugin.h b/core/dplugins/dimg/png/dimgpngplugin.h index 68a164b3fd..6b408d42c5 100644 --- a/core/dplugins/dimg/png/dimgpngplugin.h +++ b/core/dplugins/dimg/png/dimgpngplugin.h @@ -1,73 +1,73 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : PNG 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_PNG_PLUGIN_H #define DIGIKAM_DIMG_PNG_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.PNG" using namespace Digikam; namespace DigikamPNGDImgPlugin { class DImgPNGPlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgPNGPlugin(QObject* const parent = nullptr); ~DImgPNGPlugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamPNGDImgPlugin #endif // DIGIKAM_DIMG_PNG_PLUGIN_H diff --git a/core/dplugins/dimg/qimage/dimgqimageloader.cpp b/core/dplugins/dimg/qimage/dimgqimageloader.cpp index 41d2acaf3d..bd7483f145 100644 --- a/core/dplugins/dimg/qimage/dimgqimageloader.cpp +++ b/core/dplugins/dimg/qimage/dimgqimageloader.cpp @@ -1,221 +1,210 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2005-06-14 * Description : A QImage loader for DImg framework. * * Copyright (C) 2005 by Renchi Raju * Copyright (C) 2006-2019 by Caulier Gilles * * 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 "dimgqimageloader.h" // Qt includes #include #include #include -#include // Local includes #include "digikam_debug.h" #include "dimgloaderobserver.h" namespace DigikamQImageDImgPlugin { DImgQImageLoader::DImgQImageLoader(DImg* const image) : DImgLoader(image) { m_hasAlpha = false; } DImgQImageLoader::~DImgQImageLoader() { } bool DImgQImageLoader::load(const QString& filePath, DImgLoaderObserver* const observer) { - QString mimeType(QMimeDatabase().mimeTypeForFile(filePath).name()); - - if (mimeType.startsWith(QLatin1String("video/")) || - mimeType.startsWith(QLatin1String("audio/"))) - { - qCWarning(DIGIKAM_DIMG_LOG) << "Blacklisted from DImg::QImageLoader:" << mimeType; - loadingFailed(); - return false; - } - readMetadata(filePath); // Loading is opaque to us. No support for stopping from observer, // progress info are only pseudo values QImageReader reader(filePath); reader.setDecideFormatFromContent(true); QImage image = reader.read(); if (observer) { observer->progressInfo(m_image, 0.9F); } if (image.isNull()) { qCWarning(DIGIKAM_DIMG_LOG_QIMAGE) << "Can not load \"" << filePath << "\" using DImg::DImgQImageLoader!"; qCWarning(DIGIKAM_DIMG_LOG_QIMAGE) << "Error message from loader:" << reader.errorString(); loadingFailed(); return false; } int colorModel = DImg::COLORMODELUNKNOWN; int originalDepth = 0; switch (image.format()) { case QImage::Format_Invalid: default: colorModel = DImg::COLORMODELUNKNOWN; originalDepth = 0; break; case QImage::Format_Mono: case QImage::Format_MonoLSB: colorModel = DImg::MONOCHROME; originalDepth = 1; break; case QImage::Format_Indexed8: colorModel = DImg::INDEXED; originalDepth = 0; break; case QImage::Format_RGB32: colorModel = DImg::RGB; originalDepth = 8; break; case QImage::Format_ARGB32: case QImage::Format_ARGB32_Premultiplied: colorModel = DImg::RGB; originalDepth = 8; break; } m_hasAlpha = image.hasAlphaChannel(); QImage target = image.convertToFormat(QImage::Format_ARGB32); uint w = target.width(); uint h = target.height(); uchar* const data = new_failureTolerant(w, h, 4); if (!data) { qCWarning(DIGIKAM_DIMG_LOG_QIMAGE) << "Failed to allocate memory for loading" << filePath; loadingFailed(); return false; } uint* sptr = reinterpret_cast(target.bits()); uchar* dptr = data; for (uint i = 0 ; i < w * h ; ++i) { dptr[0] = qBlue(*sptr); dptr[1] = qGreen(*sptr); dptr[2] = qRed(*sptr); dptr[3] = qAlpha(*sptr); dptr += 4; sptr++; } if (observer) { observer->progressInfo(m_image, 1.0F); } imageWidth() = w; imageHeight() = h; imageData() = data; // We considering that PNG is the most representative format of an image loaded by Qt imageSetAttribute(QLatin1String("format"), QLatin1String("PNG")); imageSetAttribute(QLatin1String("originalColorModel"), colorModel); imageSetAttribute(QLatin1String("originalBitDepth"), originalDepth); imageSetAttribute(QLatin1String("originalSize"), QSize(w, h)); return true; } bool DImgQImageLoader::save(const QString& filePath, DImgLoaderObserver* const observer) { QVariant qualityAttr = imageGetAttribute(QLatin1String("quality")); int quality = qualityAttr.isValid() ? qualityAttr.toInt() : 90; if (quality < 0) { quality = 90; } if (quality > 100) { quality = 100; } QVariant formatAttr = imageGetAttribute(QLatin1String("format")); QByteArray format = formatAttr.toByteArray(); QImage image = m_image->copyQImage(); if (observer) { observer->progressInfo(m_image, 0.1F); } // Saving is opaque to us. No support for stopping from observer, // progress info are only pseudo values bool success = image.save(filePath, format.toUpper().constData(), quality); if (observer && success) { observer->progressInfo(m_image, 1.0F); } imageSetAttribute(QLatin1String("format"), format.toUpper()); saveMetadata(filePath); return success; } bool DImgQImageLoader::hasAlpha() const { return m_hasAlpha; } bool DImgQImageLoader::sixteenBit() const { return false; } bool DImgQImageLoader::isReadOnly() const { return false; } } // namespace DigikamQImageDImgPlugin diff --git a/core/dplugins/dimg/qimage/dimgqimageplugin.cpp b/core/dplugins/dimg/qimage/dimgqimageplugin.cpp index cf86f28733..9e9a572628 100644 --- a/core/dplugins/dimg/qimage/dimgqimageplugin.cpp +++ b/core/dplugins/dimg/qimage/dimgqimageplugin.cpp @@ -1,207 +1,163 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-20 * Description : QImage 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 "dimgqimageplugin.h" // Qt includes -#include #include #include #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgqimageloader.h" -#include "drawdecoder.h" namespace DigikamQImageDImgPlugin { DImgQImagePlugin::DImgQImagePlugin(QObject* const parent) : DPluginDImg(parent) { } DImgQImagePlugin::~DImgQImagePlugin() { } QString DImgQImagePlugin::name() const { return i18n("QImage loader"); } QString DImgQImagePlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgQImagePlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-x-generic")); } QString DImgQImagePlugin::description() const { return i18n("An image loader based on QImage plugins"); } QString DImgQImagePlugin::details() const { return i18n("

This plugin permit to load and save image using QImage plugins from Qt Framework.

" "

See Qt Framework documentation for details.

" ); } QList DImgQImagePlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Renchi Raju"), QString::fromUtf8("renchi dot raju at gmail dot com"), QString::fromUtf8("(C) 2005")) << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2006-2019")) ; } void DImgQImagePlugin::setup(QObject* const /*parent*/) { // Nothing to do } QString DImgQImagePlugin::loaderName() const { return QLatin1String("QIMAGE"); } QString DImgQImagePlugin::typeMimes() const { - QList formats = QImageReader::supportedImageFormats(); - - qDebug(DIGIKAM_DIMG_LOG_QIMAGE) << "QImage support this formats:" << formats; - - formats.removeAll(QByteArray("JPEG")); // JPEG file format - formats.removeAll(QByteArray("JPG")); // JPEG file format - formats.removeAll(QByteArray("JPE")); // JPEG file format - formats.removeAll(QByteArray("PNG")); - formats.removeAll(QByteArray("TIFF")); - formats.removeAll(QByteArray("TIF")); - formats.removeAll(QByteArray("PGF")); - formats.removeAll(QByteArray("JP2")); // JPEG2000 file format - formats.removeAll(QByteArray("JPX")); // JPEG2000 file format - formats.removeAll(QByteArray("JPC")); // JPEG2000 code stream - formats.removeAll(QByteArray("J2K")); // JPEG2000 code stream - formats.removeAll(QByteArray("PGX")); // JPEG2000 WM format - formats.removeAll(QByteArray("HEIC")); - formats.removeAll(QByteArray("HEIF")); - - QString rawFilesExt = QString(DRawDecoder::rawFiles()).remove(QLatin1String("*.")).toUpper(); - - foreach (const QString& str, rawFilesExt.split(QLatin1Char(' '))) - { - formats.removeAll(str.toLatin1()); // All Raw image formats - } - QString ret; - foreach (const QByteArray& ba, formats) + foreach (const QByteArray& ba, QImageReader::supportedImageFormats()) { ret += QString::fromUtf8("%1 ").arg(QString::fromUtf8(ba).toUpper()); } return ret; } -bool DImgQImagePlugin::canRead(const QString& filePath, bool magic) const +int DImgQImagePlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); if (!magic) { QString mimeType(QMimeDatabase().mimeTypeForFile(filePath).name()); // Ignore non image format. if ( mimeType.startsWith(QLatin1String("video/")) || mimeType.startsWith(QLatin1String("audio/")) ) { - return false; + return 0; } - QString format = fileInfo.suffix().toUpper(); - QString blackList = QString(DRawDecoder::rawFiles()).remove(QLatin1String("*.")).toUpper(); // Ignore RAW files - blackList.append(QLatin1String(" JPEG JPG JPE PNG TIF TIFF PGF JP2 JPX JPC J2K PGX HEIC HEIF ")); // Ignore native loaders - - return (!blackList.toUpper().contains(format)); + foreach (const QByteArray& ba, QImageReader::supportedImageFormats()) + { + if (QString::fromUtf8(ba).toUpper() == format) + { + return 80; + } + } } - return false; + return 0; } -bool DImgQImagePlugin::canWrite(const QString& format) const +int DImgQImagePlugin::canWrite(const QString& format) const { - QString blackList = QString(DRawDecoder::rawFiles()).remove(QLatin1String("*.")).toUpper(); // Ignore RAW files - blackList.append(QLatin1String(" JPEG JPG JPE PNG TIF TIFF PGF JP2 JPX JPC J2K PGX HEIC HEIF")); // Ignore native loaders - - if (blackList.toUpper().contains(format)) - { - return false; - } - - // NOTE: Native loaders support are previously black-listed. - // For ex, if tiff is supported in write mode by QImage it will never be handled. - - QList formats = QImageWriter::supportedImageFormats(); - - foreach (const QByteArray& ba, formats) + foreach (const QByteArray& ba, QImageWriter::supportedImageFormats()) { - if (QString::fromUtf8(ba).toUpper().contains(format.toUpper())) + if (QString::fromUtf8(ba).toUpper() == format.toUpper()) { - return true; + return 80; } } - return false; + return 0; } DImgLoader* DImgQImagePlugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgQImageLoader(image); } } // namespace DigikamQImageDImgPlugin diff --git a/core/dplugins/dimg/qimage/dimgqimageplugin.h b/core/dplugins/dimg/qimage/dimgqimageplugin.h index 0a13285e06..3cf380cd32 100644 --- a/core/dplugins/dimg/qimage/dimgqimageplugin.h +++ b/core/dplugins/dimg/qimage/dimgqimageplugin.h @@ -1,72 +1,72 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-20 * Description : QImage 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_QIMAGE_PLUGIN_H #define DIGIKAM_DIMG_QIMAGE_PLUGIN_H // Qt includes #include #include // Local includes #include "dplugindimg.h" #include "dimg.h" #define DPLUGIN_IID "org.kde.digikam.plugin.dimg.QImage" using namespace Digikam; namespace DigikamQImageDImgPlugin { class DImgQImagePlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgQImagePlugin(QObject* const parent = nullptr); ~DImgQImagePlugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamQImageDImgPlugin #endif // DIGIKAM_DIMG_QIMAGE_PLUGIN_H diff --git a/core/dplugins/dimg/raw/dimgrawplugin.cpp b/core/dplugins/dimg/raw/dimgrawplugin.cpp index fb994e6dc5..c01893a3fe 100644 --- a/core/dplugins/dimg/raw/dimgrawplugin.cpp +++ b/core/dplugins/dimg/raw/dimgrawplugin.cpp @@ -1,157 +1,144 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : RAW 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 "dimgrawplugin.h" // C++ includes #include -// Qt includes - -#include -#include - // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgrawloader.h" #include "drawdecoder.h" #include "drawfiles.h" namespace DigikamRAWDImgPlugin { DImgRAWPlugin::DImgRAWPlugin(QObject* const parent) : DPluginDImg(parent) { } DImgRAWPlugin::~DImgRAWPlugin() { } QString DImgRAWPlugin::name() const { return i18n("RAW loader"); } QString DImgRAWPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgRAWPlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-x-adobe-dng")); } QString DImgRAWPlugin::description() const { return i18n("An image loader based on Libraw codec"); } QString DImgRAWPlugin::details() const { return i18n("

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

" "

A camera raw image file contains minimally processed data from the image sensor " "of either a digital camera, a motion picture film scanner, or other image scanner. " "Raw files are not yet processed and therefore are not ready to be printed or edited " "with a bitmap graphics editor. RAW are processed by a raw converter in a wide-gamut " "internal color space where precise adjustments can be made before conversion to a TIFF " "or JPEG for storage, printing, or further manipulation. This often encodes the image in " "a device-dependent color space.

" "

See " "Raw Image File documentation for details.

" ); } QList DImgRAWPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Marcel Wiesweg"), QString::fromUtf8("marcel dot wiesweg at gmx dot de"), QString::fromUtf8("(C) 2005-2012")) << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2009-2019")) ; } void DImgRAWPlugin::setup(QObject* const /*parent*/) { // Nothing to do } QMap DImgRAWPlugin::extraAboutData() const { return s_rawFileExtensionsdWithDesc(); } QString DImgRAWPlugin::loaderName() const { return QLatin1String("RAW"); } QString DImgRAWPlugin::typeMimes() const { return QString(DRawDecoder::rawFiles()).toUpper().remove(QLatin1String("*.")); } -bool DImgRAWPlugin::canRead(const QString& filePath, bool magic) const +int DImgRAWPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } - if (!magic) { - QString ext = fileInfo.suffix().toUpper(); QString rawFilesExt = DRawDecoder::rawFiles(); + QString format = fileInfo.suffix().toUpper(); - return (rawFilesExt.toUpper().contains(ext)); + return (rawFilesExt.toUpper().contains(format)) ? 10 : 0; } - return false; + return 0; } -bool DImgRAWPlugin::canWrite(const QString& /*format*/) const +int DImgRAWPlugin::canWrite(const QString& /*format*/) const { // NOTE: Raw are read only files. - return false; + return 0; } DImgLoader* DImgRAWPlugin::loader(DImg* const image, const DRawDecoding& rawSettings) const { return new DImgRAWLoader(image, rawSettings); } } // namespace DigikamRAWDImgPlugin diff --git a/core/dplugins/dimg/raw/dimgrawplugin.h b/core/dplugins/dimg/raw/dimgrawplugin.h index a2f20cb470..b9673985d6 100644 --- a/core/dplugins/dimg/raw/dimgrawplugin.h +++ b/core/dplugins/dimg/raw/dimgrawplugin.h @@ -1,74 +1,74 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : RAW 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_RAW_PLUGIN_H #define DIGIKAM_DIMG_RAW_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.RAW" using namespace Digikam; namespace DigikamRAWDImgPlugin { class DImgRAWPlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgRAWPlugin(QObject* const parent = nullptr); ~DImgRAWPlugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamRAWDImgPlugin #endif // DIGIKAM_DIMG_RAW_PLUGIN_H diff --git a/core/dplugins/dimg/tiff/dimgtiffplugin.cpp b/core/dplugins/dimg/tiff/dimgtiffplugin.cpp index 1b0c919a09..5d7aab3f4d 100644 --- a/core/dplugins/dimg/tiff/dimgtiffplugin.cpp +++ b/core/dplugins/dimg/tiff/dimgtiffplugin.cpp @@ -1,185 +1,181 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : TIFF 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 "dimgtiffplugin.h" // C++ includes #include // Qt includes #include -#include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgtiffloader.h" namespace DigikamTIFFDImgPlugin { DImgTIFFPlugin::DImgTIFFPlugin(QObject* const parent) : DPluginDImg(parent) { } DImgTIFFPlugin::~DImgTIFFPlugin() { } QString DImgTIFFPlugin::name() const { return i18n("TIFF loader"); } QString DImgTIFFPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DImgTIFFPlugin::icon() const { return QIcon::fromTheme(QLatin1String("image-tiff")); } QString DImgTIFFPlugin::description() const { return i18n("An image loader based on Libtiff codec"); } QString DImgTIFFPlugin::details() const { return i18n("

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

" "

Tagged Image File Format, abbreviated TIFF or TIF, is a computer file format " "for storing raster graphics images, popular among graphic artists, the publishing " "industry, and photographers. TIFF is widely supported by scanning, faxing, " "word processing, optical character recognition, image manipulation, " "desktop publishing, and page-layout applications.

" "

See " "Tagged Image File Format documentation for details.

" ); } QList DImgTIFFPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Renchi Raju"), QString::fromUtf8("renchi dot raju at gmail dot com"), QString::fromUtf8("(C) 2005")) << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2006-2019")) ; } void DImgTIFFPlugin::setup(QObject* const /*parent*/) { // Nothing to do } QString DImgTIFFPlugin::loaderName() const { return QLatin1String("TIFF"); } QString DImgTIFFPlugin::typeMimes() const { return QLatin1String("TIF TIFF"); } -bool DImgTIFFPlugin::canRead(const QString& filePath, bool magic) const +int DImgTIFFPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { - QFileInfo fileInfo(filePath); - - if (!fileInfo.exists()) - { - qCDebug(DIGIKAM_DIMG_LOG) << "File " << filePath << " does not exist"; - return false; - } + QString filePath = fileInfo.filePath(); + QString format = fileInfo.suffix().toUpper(); // First simply check file extension if (!magic) { - QString ext = fileInfo.suffix().toUpper(); - - return (ext == QLatin1String("TIFF") || ext == QLatin1String("TIF")); + return ( + format == QLatin1String("TIFF") || + format == QLatin1String("TIF") + ) ? 10 : 0; } // 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; + return 0; } const int headerLen = 9; 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; + return 0; } fclose(f); - uchar tiffBigID[4] = { 0x4D, 0x4D, 0x00, 0x2A }; - uchar tiffLilID[4] = { 0x49, 0x49, 0x2A, 0x00 }; + uchar tiffBigID[4] = { 0x4D, 0x4D, 0x00, 0x2A }; + uchar tiffLilID[4] = { 0x49, 0x49, 0x2A, 0x00 }; if (memcmp(&header, &tiffBigID, 4) == 0 || memcmp(&header, &tiffLilID, 4) == 0) { - return true; + return 10; } - return false; + return 0; } -bool DImgTIFFPlugin::canWrite(const QString& format) const +int DImgTIFFPlugin::canWrite(const QString& format) const { - if ((format == QLatin1String("TIFF") || format == QLatin1String("TIF"))) + if (format == QLatin1String("TIFF") || + format == QLatin1String("TIF")) { - return true; + return 10; } - return false; + return 0; } DImgLoader* DImgTIFFPlugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgTIFFLoader(image); } } // namespace DigikamTIFFDImgPlugin diff --git a/core/dplugins/dimg/tiff/dimgtiffplugin.h b/core/dplugins/dimg/tiff/dimgtiffplugin.h index f90263ab94..d38f87ce90 100644 --- a/core/dplugins/dimg/tiff/dimgtiffplugin.h +++ b/core/dplugins/dimg/tiff/dimgtiffplugin.h @@ -1,73 +1,73 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2019-09-22 * Description : TIFF 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_TIFF_PLUGIN_H #define DIGIKAM_DIMG_TIFF_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.TIFF" using namespace Digikam; namespace DigikamTIFFDImgPlugin { class DImgTIFFPlugin : public DPluginDImg { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginDImg) public: explicit DImgTIFFPlugin(QObject* const parent = nullptr); ~DImgTIFFPlugin(); 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; QString loaderName() const; QString typeMimes() const; - bool canRead(const QString& filePath, bool magic) const; - bool canWrite(const QString& format) const; + int canRead(const QFileInfo& fileInfo, bool magic) const; + int canWrite(const QString& format) const; DImgLoader* loader(DImg* const image, const DRawDecoding& rawSettings = DRawDecoding()) const; }; } // namespace DigikamTIFFDImgPlugin #endif // DIGIKAM_DIMG_TIFF_PLUGIN_H diff --git a/core/dplugins/generic/webservices/dropbox/dbplugin.cpp b/core/dplugins/generic/webservices/dropbox/dbplugin.cpp index 999612d4ad..080bd44f46 100644 --- a/core/dplugins/generic/webservices/dropbox/dbplugin.cpp +++ b/core/dplugins/generic/webservices/dropbox/dbplugin.cpp @@ -1,118 +1,118 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 - * Description : a plugin to export to DropBox web-service. + * Description : a plugin to export to Dropbox web-service. * * Copyright (C) 2018-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 "dbplugin.h" // Qt includes #include // KDE includes #include // Local includes #include "dbwindow.h" namespace DigikamGenericDropBoxPlugin { DBPlugin::DBPlugin(QObject* const parent) : DPluginGeneric(parent) { } DBPlugin::~DBPlugin() { } void DBPlugin::cleanUp() { delete m_toolDlg; } QString DBPlugin::name() const { - return i18n("DropBox"); + return i18n("Dropbox"); } QString DBPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon DBPlugin::icon() const { return QIcon::fromTheme(QLatin1String("dk-dropbox")); } QString DBPlugin::description() const { - return i18n("A tool to export to DropBox web-service"); + return i18n("A tool to export to Dropbox web-service"); } QString DBPlugin::details() const { - return i18n("

This tool permit to export items to DropBox web-service.

" - "

See DropBox web site for details: https://www.dropbox.com/

"); + return i18n("

This tool permit to export items to Dropbox web-service.

" + "

See Dropbox web site for details: https://www.dropbox.com/

"); } QList DBPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Pankaj Kumar"), QString::fromUtf8("me at panks dot me"), QString::fromUtf8("(C) 2013")) << DPluginAuthor(QString::fromUtf8("Maik Qualmann"), QString::fromUtf8("metzpinguin at gmail dot com"), QString::fromUtf8("(C) 2018-2019")) ; } void DBPlugin::setup(QObject* const parent) { DPluginAction* const ac = new DPluginAction(parent); ac->setIcon(icon()); ac->setText(i18nc("@action", "Export to &Dropbox...")); ac->setObjectName(QLatin1String("export_dropbox")); ac->setActionCategory(DPluginAction::GenericExport); ac->setShortcut(Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_D); connect(ac, SIGNAL(triggered(bool)), this, SLOT(slotDropBox())); addAction(ac); } void DBPlugin::slotDropBox() { if (!reactivateToolDialog(m_toolDlg)) { delete m_toolDlg; m_toolDlg = new DBWindow(infoIface(sender()), nullptr); m_toolDlg->setPlugin(this); m_toolDlg->show(); } } } // namespace DigikamGenericDropBoxPlugin diff --git a/core/dplugins/generic/webservices/dropbox/dbplugin.h b/core/dplugins/generic/webservices/dropbox/dbplugin.h index e3dd502194..735863b078 100644 --- a/core/dplugins/generic/webservices/dropbox/dbplugin.h +++ b/core/dplugins/generic/webservices/dropbox/dbplugin.h @@ -1,71 +1,71 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 - * Description : a plugin to export to DropBox web-service. + * Description : a plugin to export to Dropbox web-service. * * Copyright (C) 2018-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_DB_PLUGIN_H #define DIGIKAM_DB_PLUGIN_H // Local includes #include "dplugingeneric.h" #define DPLUGIN_IID "org.kde.digikam.plugin.generic.DropBox" using namespace Digikam; namespace DigikamGenericDropBoxPlugin { class DBWindow; class DBPlugin : public DPluginGeneric { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginGeneric) public: explicit DBPlugin(QObject* const parent = nullptr); ~DBPlugin(); 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; void cleanUp() override; private Q_SLOTS: void slotDropBox(); private: QPointer m_toolDlg; }; } // namespace DigikamGenericDropBoxPlugin #endif // DIGIKAM_DB_PLUGIN_H diff --git a/core/dplugins/generic/webservices/facebook/fbplugin.cpp b/core/dplugins/generic/webservices/facebook/fbplugin.cpp index 94c915b81a..15908013f2 100644 --- a/core/dplugins/generic/webservices/facebook/fbplugin.cpp +++ b/core/dplugins/generic/webservices/facebook/fbplugin.cpp @@ -1,136 +1,136 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 - * Description : a plugin to export to FaceBook web-service. + * Description : a plugin to export to Facebook web-service. * * Copyright (C) 2018-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 "fbplugin.h" // Qt includes #include #include // KDE includes #include // Local includes #include "fbwindow.h" namespace DigikamGenericFaceBookPlugin { FbPlugin::FbPlugin(QObject* const parent) : DPluginGeneric(parent) { } FbPlugin::~FbPlugin() { } void FbPlugin::cleanUp() { delete m_toolDlg; } QString FbPlugin::name() const { - return i18n("FaceBook"); + return i18n("Facebook"); } QString FbPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon FbPlugin::icon() const { return QIcon::fromTheme(QLatin1String("dk-facebook")); } QString FbPlugin::description() const { - return i18n("A tool to export to FaceBook web-service"); + return i18n("A tool to export to Facebook web-service"); } QString FbPlugin::details() const { - return i18n("

This tool permit to export items to FaceBook web-service.

" - "

See FaceBook web site for details: https://www.facebook.com/

"); + return i18n("

This tool permit to export items to Facebook web-service.

" + "

See Facebook web site for details: https://www.facebook.com/

"); } QList FbPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Luka Renko"), QString::fromUtf8("lure at kubuntu dot org"), QString::fromUtf8("(C) 2009")) << DPluginAuthor(QString::fromUtf8("Vardhman Jain"), QString::fromUtf8("vardhman at gmail dot com"), QString::fromUtf8("(C) 2005-2008")) << DPluginAuthor(QString::fromUtf8("Maik Qualmann"), QString::fromUtf8("metzpinguin at gmail dot com"), QString::fromUtf8("(C) 2017-2019")) << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2012-2019")) ; } void FbPlugin::setup(QObject* const parent) { DPluginAction* const ac = new DPluginAction(parent); ac->setIcon(icon()); - ac->setText(i18nc("@action", "Export to &FaceBook...")); + ac->setText(i18nc("@action", "Export to &Facebook...")); ac->setObjectName(QLatin1String("export_facebook")); ac->setActionCategory(DPluginAction::GenericExport); ac->setShortcut(Qt::CTRL + Qt::ALT + Qt::SHIFT + Qt::Key_F); connect(ac, SIGNAL(triggered(bool)), this, SLOT(slotFaceBook())); addAction(ac); } void FbPlugin::slotFaceBook() { // if (!reactivateToolDialog(m_toolDlg)) { QPointer msgBox = new QMessageBox(QMessageBox::Information, i18n("Facebook"), i18n("

Currently, as an open source project, we are unable to meet " "the Facebook requirements for reactivating this plugin.

" "

For more information look here: " "" "KDE Bugtracking System

")); msgBox->setTextInteractionFlags(Qt::LinksAccessibleByMouse); msgBox->exec(); delete msgBox; // delete m_toolDlg; // m_toolDlg = new FbWindow(infoIface(sender()), nullptr); // m_toolDlg->setPlugin(this); // m_toolDlg->show(); } } } // namespace DigikamGenericFaceBookPlugin diff --git a/core/dplugins/generic/webservices/facebook/fbplugin.h b/core/dplugins/generic/webservices/facebook/fbplugin.h index 08c81e151b..ea7d41c69c 100644 --- a/core/dplugins/generic/webservices/facebook/fbplugin.h +++ b/core/dplugins/generic/webservices/facebook/fbplugin.h @@ -1,71 +1,71 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 - * Description : a plugin to export to FaceBook web-service. + * Description : a plugin to export to Facebook web-service. * * Copyright (C) 2018-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_FB_PLUGIN_H #define DIGIKAM_FB_PLUGIN_H // Local includes #include "dplugingeneric.h" #define DPLUGIN_IID "org.kde.digikam.plugin.generic.FaceBook" using namespace Digikam; namespace DigikamGenericFaceBookPlugin { class FbWindow; class FbPlugin : public DPluginGeneric { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginGeneric) public: explicit FbPlugin(QObject* const parent = nullptr); ~FbPlugin(); 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; void cleanUp() override; private Q_SLOTS: void slotFaceBook(); private: QPointer m_toolDlg; }; } // namespace DigikamGenericFaceBookPlugin #endif // DIGIKAM_FB_PLUGIN_H diff --git a/core/libs/dimg/dimg_fileio.cpp b/core/libs/dimg/dimg_fileio.cpp index 3e8c713784..f704063fc4 100644 --- a/core/libs/dimg/dimg_fileio.cpp +++ b/core/libs/dimg/dimg_fileio.cpp @@ -1,317 +1,344 @@ /* ============================================================ * * 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; + QFileInfo fileInfo(filePath); + + if (!fileInfo.exists() || !fileInfo.isReadable()) + { + qCDebug(DIGIKAM_DIMG_LOG) << "File" << filePath << "does not exist"; + return false; + } - setAttribute(QLatin1String("detectedFileFormat"), format); - setAttribute(QLatin1String("originalFilePath"), filePath); + QList pluginList = m_priv->pluginsForFile(fileInfo, false); + DImgLoader::LoadFlags loadFlags = (DImgLoader::LoadFlags)loadFlagsInt; + setAttribute(QLatin1String("originalFilePath"), filePath); FileReadLocker lock(filePath); // First step we check the file extension to find the right loader. - if (plug) + foreach (DPluginDImg* const plug, pluginList) { if (observer && !observer->continueQuery(nullptr)) { return false; } if (loadFlags & DImgLoader::LoadPreview && !plug->previewSupported()) { - return false; + continue; } qCDebug(DIGIKAM_DIMG_LOG) << filePath << ":" << plug->loaderName() << "file identified"; + FORMAT format = m_priv->loaderNameToFormat(plug->loaderName()); DImgLoader* const loader = plug->loader(this, rawDecodingSettings); + setAttribute(QLatin1String("detectedFileFormat"), format); 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) + pluginList = m_priv->pluginsForFile(fileInfo, true); + + foreach (DPluginDImg* const plug, pluginList) { if (observer && !observer->continueQuery(nullptr)) { return false; } if (loadFlags & DImgLoader::LoadPreview && !plug->previewSupported()) { - return false; + continue; } qCDebug(DIGIKAM_DIMG_LOG) << filePath << ":" << plug->loaderName() << "file identified (magic)"; + FORMAT format = m_priv->loaderNameToFormat(plug->loaderName()); DImgLoader* const loader = plug->loader(this, rawDecodingSettings); + setAttribute(QLatin1String("detectedFileFormat"), format); 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 !!!"; - } - + if (pluginList.isEmpty() && !(loadFlags & DImgLoader::LoadPreview)) + { + qCWarning(DIGIKAM_DIMG_LOG) << filePath << ": Unknown image format !!!"; return false; } - qCWarning(DIGIKAM_DIMG_LOG) << filePath << ": Unknown image format !!!"; + if (observer && + observer->continueQuery(nullptr) && + !(loadFlags & DImgLoader::LoadPreview)) + { + qCWarning(DIGIKAM_DIMG_LOG) << filePath << ": Cannot load file !!!"; + } 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); + DPluginDImg* const plug = m_priv->pluginForFormat(frm); 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; + FORMAT format = DImg::NONE; + + if (filePath.isEmpty()) + { + return format; + } - DImg::Private::pluginForFile(filePath, false, name, format); + QFileInfo fileInfo(filePath); + + if (!fileInfo.exists() || !fileInfo.isReadable()) + { + return format; + } + + QList pluginList = DImg::Private::pluginsForFile(fileInfo, false); + + if (!pluginList.isEmpty()) + { + QString name = pluginList.first()->loaderName(); + format = DImg::Private::loaderNameToFormat(name); + } return format; } } // namespace Digikam diff --git a/core/libs/dimg/dimg_p.h b/core/libs/dimg/dimg_p.h index 202d300328..1fc8f4c1ef 100644 --- a/core/libs/dimg/dimg_p.h +++ b/core/libs/dimg/dimg_p.h @@ -1,284 +1,283 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2005-06-15 * Description : digiKam 8/16 bits image management API. * Private data container. * * Copyright (C) 2005 by Renchi Raju * Copyright (C) 2005-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_PRIVATE_H #define DIGIKAM_DIMG_PRIVATE_H #include "digikam_config.h" // C ANSI includes #ifndef Q_OS_WIN extern "C" { #endif #include #ifndef Q_OS_WIN #include } #endif // C++ includes #include // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include #include // Local includes #include "dimg.h" #include "dplugindimg.h" #include "digikam_export.h" #include "digikam_debug.h" #include "dmetadata.h" #include "dshareddata.h" #include "dimagehistory.h" #include "iccprofile.h" #include "metaengine_rotation.h" #include "drawdecoder.h" #include "filereadwritelock.h" #include "iccmanager.h" #include "icctransform.h" #include "exposurecontainer.h" #include "dimgloaderobserver.h" #include "randomnumbergenerator.h" /** Lanczos kernel is precomputed in a table with this resolution The value below seems to be enough for HQ upscaling up to eight times */ #define LANCZOS_TABLE_RES 256 /** A support of 3 gives an overall sharper looking image, but it is a) slower b) gives more sharpening artifacts */ #define LANCZOS_SUPPORT 2 /** Define this to use a floating-point implementation of Lanczos interpolation. The integer implementation is a little bit less accurate, but MUCH faster (even on machines with FPU - ~2.5 times faster on Core2); besides, it will run a hell lot faster on computers without a FPU (e.g. PDAs). */ //#define LANCZOS_DATA_FLOAT #ifdef LANCZOS_DATA_FLOAT # define LANCZOS_DATA_TYPE float # define LANCZOS_DATA_ONE 1.0 #else # define LANCZOS_DATA_TYPE int # define LANCZOS_DATA_ONE 4096 #endif typedef uint64_t ullong; // krazy:exclude=typedefs typedef int64_t llong; // krazy:exclude=typedefs namespace Digikam { class DIGIKAM_EXPORT DImg::Private : public DSharedData { public: explicit Private() { null = true; width = 0; height = 0; data = nullptr; lanczos_func = nullptr; alpha = false; sixteenBit = false; } ~Private() { delete [] data; delete [] lanczos_func; } - static DPluginDImg* pluginForFile(const QString& filePath, bool magic, QString& name, DImg::FORMAT& format) + static QList pluginsForFile(const QFileInfo& fileInfo, bool magic) { - if (!filePath.isNull()) + QMap pluginMap; + + foreach (DPlugin* const p, DPluginLoader::instance()->allPlugins()) { - foreach (DPlugin* const p, DPluginLoader::instance()->allPlugins()) - { - DPluginDImg* const plug = dynamic_cast(p); + int prio; + DPluginDImg* const plug = dynamic_cast(p); - if (plug) - { -/* - qCDebug(DIGIKAM_DIMG_LOG) << filePath << "=>" - << plug->loaderName() << ":: can read:" - << plug->canRead(filePath); -*/ - if (plug->canRead(filePath, magic)) - { - name = plug->loaderName(); - - if (name.isNull()) - { - format = DImg::NONE; - } - else if (name == QLatin1String("JPEG")) - { - format = DImg::JPEG; - } - else if (name == QLatin1String("PNG")) - { - format = DImg::PNG; - } - else if (name == QLatin1String("TIFF")) - { - format = DImg::TIFF; - } - else if (name == QLatin1String("RAW")) - { - format = DImg::RAW; - } - else if (name == QLatin1String("JPEG2000")) - { - format = DImg::JP2K; - } - else if (name == QLatin1String("PGF")) - { - format = DImg::PGF; - } - else if (name == QLatin1String("HEIF")) - { - format = DImg::HEIF; - } - else - { - // In others cases, ImageMagick or QImage will be used to try to open file. - format = DImg::QIMAGE; - } - - return plug; - } - } + if (plug && ((prio = plug->canRead(fileInfo, magic)) > 0)) + { + /* + qCDebug(DIGIKAM_DIMG_LOG) << "File path:" << filePath + << "Priority:" << prio + << "Loader:" << plug->loaderName(); + */ + pluginMap.insertMulti(prio, plug); } } - format = DImg::NONE; - name = QString(); - return nullptr; + return pluginMap.values(); } - static DPluginDImg* pluginForFormat(const QString& format, QString& name) + static DPluginDImg* pluginForFormat(const QString& format) { + QMap pluginMap; + if (!format.isNull()) { foreach (DPlugin* const p, DPluginLoader::instance()->allPlugins()) { + int prio; DPluginDImg* const plug = dynamic_cast(p); - if (plug && (plug->canWrite(format))) + if (plug && ((prio = plug->canWrite(format)) > 0)) { - name = plug->loaderName(); - - return plug; + pluginMap.insertMulti(prio, plug); } } } - name = QString(); + if (!pluginMap.isEmpty()) + { + return pluginMap.first(); + } + return nullptr; } + static DImg::FORMAT loaderNameToFormat(const QString& name) + { + if (name.isNull()) + { + return DImg::NONE; + } + else if (name == QLatin1String("JPEG")) + { + return DImg::JPEG; + } + else if (name == QLatin1String("PNG")) + { + return DImg::PNG; + } + else if (name == QLatin1String("TIFF")) + { + return DImg::TIFF; + } + else if (name == QLatin1String("RAW")) + { + return DImg::RAW; + } + else if (name == QLatin1String("JPEG2000")) + { + return DImg::JP2K; + } + else if (name == QLatin1String("PGF")) + { + return DImg::PGF; + } + else if (name == QLatin1String("HEIF")) + { + return DImg::HEIF; + } + + // In others cases, ImageMagick or QImage will be used to try to open file. + return DImg::QIMAGE; + } + static QStringList fileOriginAttributes() { QStringList list; list << QLatin1String("format") << QLatin1String("isReadOnly") << QLatin1String("originalFilePath") << QLatin1String("originalSize") << QLatin1String("originalImageHistory") << QLatin1String("rawDecodingSettings") << QLatin1String("rawDecodingFilterAction") << QLatin1String("uniqueHash") << QLatin1String("uniqueHashV2"); return list; } /** * x,y, w x h is a section of the image. The image size is width x height. * Clips the section to the bounds of the image. * Returns if the (clipped) section is a valid rectangle. */ static bool clipped(int& x, int& y, int& w, int& h, uint width, uint height) { QRect inner(x, y, w, h); QRect outer(0, 0, width, height); if (!outer.contains(inner)) { QRect clipped = inner.intersected(outer); x = clipped.x(); y = clipped.y(); w = clipped.width(); h = clipped.height(); return clipped.isValid(); } return inner.isValid(); } public: bool null; bool alpha; bool sixteenBit; unsigned int width; unsigned int height; unsigned char* data; LANCZOS_DATA_TYPE* lanczos_func; MetaEngineData metaData; QMap attributes; QMap embeddedText; IccProfile iccProfile; DImageHistory imageHistory; }; } // namespace Digikam #endif // DIGIKAM_DIMG_PRIVATE_H diff --git a/core/libs/dimg/loaders/dimgloader.h b/core/libs/dimg/loaders/dimgloader.h index 3736a04ccf..cf58713dc5 100644 --- a/core/libs/dimg/loaders/dimgloader.h +++ b/core/libs/dimg/loaders/dimgloader.h @@ -1,219 +1,219 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2005-06-14 * Description : DImg image loader interface * * Copyright (C) 2005 by Renchi Raju * Copyright (C) 2005-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_LOADER_H #define DIGIKAM_DIMG_LOADER_H // C++ includes #include // Qt includes #include #include #include #include // Local includes #include "digikam_debug.h" #include "digikam_config.h" #include "digikam_export.h" #include "dimg.h" namespace Digikam { class DImgLoaderObserver; class DMetadata; class DImgLoader { public: /** This is the list of loading modes usable by DImg image plugins */ enum LoadFlag { // Load image information without image data LoadItemInfo = 1, /// Image info as width and height LoadMetadata = 2, /// Image metadata LoadICCData = 4, /// Image color profile LoadImageData = 8, /// Full image data LoadUniqueHash = 16, /// Image unique hash LoadImageHistory = 32, /// Image version history - + // Special mode to load reduced image data - + LoadPreview = 64, /// Load embeded preview image instead full size image - + // Helper to load all information, metadata and full image. - - LoadAll = LoadItemInfo | LoadMetadata | LoadUniqueHash | LoadICCData | LoadImageData | LoadImageHistory + + LoadAll = LoadItemInfo | LoadMetadata | LoadICCData | LoadImageData | LoadUniqueHash | LoadImageHistory }; Q_DECLARE_FLAGS(LoadFlags, LoadFlag) public: void setLoadFlags(LoadFlags flags); virtual ~DImgLoader(); virtual bool load(const QString& filePath, DImgLoaderObserver* const observer) = 0; virtual bool save(const QString& filePath, DImgLoaderObserver* const observer) = 0; virtual bool hasLoadedData() const; virtual bool hasAlpha() const = 0; virtual bool sixteenBit() const = 0; virtual bool isReadOnly() const = 0; static QByteArray uniqueHashV2(const QString& filePath, const DImg* const img = nullptr); static QByteArray uniqueHash(const QString& filePath, const DImg& img, bool loadMetadata); static HistoryImageId createHistoryImageId(const QString& filePath, const DImg& img, const DMetadata& metadata); static unsigned char* new_failureTolerant(size_t unsecureSize); static unsigned char* new_failureTolerant(quint64 w, quint64 h, uint typesPerPixel); static unsigned short* new_short_failureTolerant(size_t unsecureSize); static unsigned short* new_short_failureTolerant(quint64 w, quint64 h, uint typesPerPixel); /** Value returned : -1 : unsupported platform * 0 : parse failure from supported platform * 1 : parse done with success from supported platform */ static qint64 checkAllocation(qint64 fullSize); template static Type* new_failureTolerant(size_t unsecureSize); template static Type* new_failureTolerant(quint64 w, quint64 h, uint typesPerPixel); protected: explicit DImgLoader(DImg* const image); unsigned char*& imageData(); unsigned int& imageWidth(); unsigned int& imageHeight(); bool imageHasAlpha() const; bool imageSixteenBit() const; unsigned int imageNumBytes() const; int imageBitsDepth() const; int imageBytesDepth() const; void imageSetIccProfile(const IccProfile& profile); QVariant imageGetAttribute(const QString& key) const; void imageSetAttribute(const QString& key, const QVariant& value); QMap& imageEmbeddedText() const; QString imageGetEmbbededText(const QString& key) const; void imageSetEmbbededText(const QString& key, const QString& text); void loadingFailed(); bool checkExifWorkingColorSpace() const; void purgeExifWorkingColorSpace(); void storeColorProfileInMetadata(); virtual bool readMetadata(const QString& filePath); virtual bool saveMetadata(const QString& filePath); virtual int granularity(DImgLoaderObserver* const observer, int total, float progressSlice = 1.0); protected: DImg* m_image; LoadFlags m_loadFlags; private: DImgLoader(); }; // --------------------------------------------------------------------------------------------------- /// Allows safe multiplication of requested pixel number and bytes per pixel, avoiding particularly /// 32bit overflow and exceeding the size_t type template Q_INLINE_TEMPLATE Type* DImgLoader::new_failureTolerant(quint64 w, quint64 h, uint typesPerPixel) { quint64 requested = w * h * quint64(typesPerPixel); quint64 maximum = std::numeric_limits::max(); if (requested > maximum) { qCCritical(DIGIKAM_DIMG_LOG) << "Requested memory of" << requested*quint64(sizeof(Type)) << "is larger than size_t supported by platform."; return nullptr; } return new_failureTolerant(requested); } template Q_INLINE_TEMPLATE Type* DImgLoader::new_failureTolerant(size_t size) { qint64 res = checkAllocation(size); switch(res) { case 0: // parse failure from supported platform return nullptr; break; case -1: // unsupported platform // We will try to continue to allocate break; default: // parse done with success from supported platform break; } Type* reserved = nullptr; #ifdef Q_OS_WIN reserved = new Type[size]; if (reserved == nullptr) { qCCritical(DIGIKAM_DIMG_LOG) << "Failed to allocate chunk of memory of size" << size; } #else try { reserved = new Type[size]; } catch (std::bad_alloc& ex) { qCCritical(DIGIKAM_DIMG_LOG) << "Failed to allocate chunk of memory of size" << size << ex.what(); reserved = nullptr; } #endif return reserved; } Q_DECLARE_OPERATORS_FOR_FLAGS(DImgLoader::LoadFlags) } // namespace Digikam #endif // DIGIKAM_DIMG_LOADER_H diff --git a/core/libs/dplugins/core/dplugindimg.h b/core/libs/dplugins/core/dplugindimg.h index fa8c15728a..950c30efb3 100644 --- a/core/libs/dplugins/core/dplugindimg.h +++ b/core/libs/dplugins/core/dplugindimg.h @@ -1,116 +1,126 @@ /* ============================================================ * * 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 +// Qt includes +#include + // 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. + /** Return > 0 if source file path is supported by the loader and contents can be loaded. + * The return value (1 - 100) is a priority. + * DigiKam default loaders have a priority of 10, the + * QImage loader has a priority of 80 and the + * ImageMagick loader has a priority of 90. + * If the loader is to be used before the default loader, + * the value must be less than 10. */ - virtual bool canRead(const QString& filePath, bool magic) const = 0; + virtual int canRead(const QFileInfo& fileInfo, bool magic) const = 0; - /** Return true if target file format is supported by the loader and contents can be written. + /** Return > 0 if target file format is supported by the loader and contents can be written. + * The return value (1 - 100) is a priority. */ - virtual bool canWrite(const QString& format) const = 0; + virtual int 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 diff --git a/core/libs/threadimageio/video/videodecoder.cpp b/core/libs/threadimageio/video/videodecoder.cpp index 93aa6e8f76..7a26a152c9 100644 --- a/core/libs/threadimageio/video/videodecoder.cpp +++ b/core/libs/threadimageio/video/videodecoder.cpp @@ -1,271 +1,272 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2016-04-21 * Description : video thumbnails extraction based on ffmpeg * * Copyright (C) 2010 by Dirk Vanden Boer * Copyright (C) 2016-2018 by Maik Qualmann * Copyright (C) 2016-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 "videodecoder.h" #include "videodecoder_p.h" // Local includes #include "digikam_debug.h" namespace Digikam { VideoDecoder::VideoDecoder(const QString& filename) : d(new Private) { initialize(filename); } VideoDecoder::~VideoDecoder() { destroy(); delete d; } void VideoDecoder::initialize(const QString& filename) { d->lastWidth = -1; d->lastHeight = -1; d->lastPixfmt = AV_PIX_FMT_NONE; #if LIBAVFORMAT_VERSION_MAJOR < 58 av_register_all(); #endif #if LIBAVCODEC_VERSION_MAJOR < 58 avcodec_register_all(); #endif if (avformat_open_input(&d->pFormatContext, filename.toUtf8().data(), nullptr, nullptr) != 0) { qDebug(DIGIKAM_GENERAL_LOG) << "Could not open input file: " << filename; return; } if (avformat_find_stream_info(d->pFormatContext, nullptr) < 0) { qDebug(DIGIKAM_GENERAL_LOG) << "Could not find stream information"; return; } if (!d->initializeVideo()) { return; } d->pFrame = av_frame_alloc(); if (d->pFrame) { d->initialized = true; } } bool VideoDecoder::getInitialized() const { return d->initialized; } void VideoDecoder::destroy() { d->deleteFilterGraph(); if (d->pVideoCodecContext) { avcodec_close(d->pVideoCodecContext); d->pVideoCodecContext = nullptr; } if (d->pFormatContext) { avformat_close_input(&d->pFormatContext); d->pFormatContext = nullptr; } if (d->pPacket) { av_packet_unref(d->pPacket); delete d->pPacket; d->pPacket = nullptr; } if (d->pFrame) { av_frame_free(&d->pFrame); d->pFrame = nullptr; } if (d->pFrameBuffer) { av_free(d->pFrameBuffer); d->pFrameBuffer = nullptr; } } QString VideoDecoder::getCodec() const { QString codecName; if (d->pVideoCodec) { codecName = QLatin1String(d->pVideoCodec->name); } return codecName; } int VideoDecoder::getWidth() const { if (d->pVideoCodecContext) { return d->pVideoCodecContext->width; } return -1; } int VideoDecoder::getHeight() const { if (d->pVideoCodecContext) { return d->pVideoCodecContext->height; } return -1; } int VideoDecoder::getDuration() const { if (d->pFormatContext) { return static_cast(d->pFormatContext->duration / AV_TIME_BASE); } return 0; } void VideoDecoder::seek(int timeInSeconds) { if (!d->allowSeek) { return; } qint64 timestamp = AV_TIME_BASE * static_cast(timeInSeconds); if (timestamp < 0) { timestamp = 0; } - int ret = av_seek_frame(d->pFormatContext, -1, timestamp, 0); + int ret = av_seek_frame(d->pFormatContext, -1, timestamp, + AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD); if (ret >= 0) { avcodec_flush_buffers(d->pVideoCodecContext); } else { qDebug(DIGIKAM_GENERAL_LOG) << "Seeking in video failed"; return; } int keyFrameAttempts = 0; - bool gotFrame = 0; + bool gotFrame = false; do { int count = 0; - gotFrame = 0; + gotFrame = false; while (!gotFrame && count < 20) { d->getVideoPacket(); gotFrame = d->decodeVideoPacket(); count++; } keyFrameAttempts++; } while ((!gotFrame || !d->pFrame->key_frame) && keyFrameAttempts < 200); - if (gotFrame == 0) + if (!gotFrame) { qDebug(DIGIKAM_GENERAL_LOG) << "Seeking in video failed"; } } bool VideoDecoder::decodeVideoFrame() const { bool frameFinished = false; while (!frameFinished && d->getVideoPacket()) { frameFinished = d->decodeVideoPacket(); } if (!frameFinished) { qDebug(DIGIKAM_GENERAL_LOG) << "decodeVideoFrame() failed: frame not finished"; } return frameFinished; } void VideoDecoder::getScaledVideoFrame(int scaledSize, bool maintainAspectRatio, VideoFrame& videoFrame) { if (d->pFrame->interlaced_frame) { d->processFilterGraph(d->pFrame, d->pFrame, d->pVideoCodecContext->pix_fmt, d->pVideoCodecContext->width, d->pVideoCodecContext->height); } int scaledWidth, scaledHeight; d->convertAndScaleFrame(AV_PIX_FMT_RGB24, scaledSize, maintainAspectRatio, scaledWidth, scaledHeight); videoFrame.width = scaledWidth; videoFrame.height = scaledHeight; videoFrame.lineSize = d->pFrame->linesize[0]; videoFrame.frameData.clear(); videoFrame.frameData.resize(videoFrame.lineSize * videoFrame.height); memcpy((&(videoFrame.frameData.front())), d->pFrame->data[0], videoFrame.lineSize * videoFrame.height); } } // namespace Digikam diff --git a/core/libs/threadimageio/video/videothumbnailer.cpp b/core/libs/threadimageio/video/videothumbnailer.cpp index 60d31d9690..c4ed6ba46c 100644 --- a/core/libs/threadimageio/video/videothumbnailer.cpp +++ b/core/libs/threadimageio/video/videothumbnailer.cpp @@ -1,330 +1,330 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2016-04-21 * Description : video thumbnails extraction based on ffmpeg * * Copyright (C) 2010 by Dirk Vanden Boer * Copyright (C) 2016-2018 by Maik Qualmann * Copyright (C) 2016-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 "videothumbnailer.h" // C++ includes #include // Qt includes #include #include #include // Local includes #include "videodecoder.h" #include "videostripfilter.h" #include "videothumbwriter.h" #include "digikam_debug.h" using namespace std; namespace Digikam { class Q_DECL_HIDDEN VideoThumbnailer::Private { public: template class Q_DECL_HIDDEN Histogram { public: explicit Histogram() { memset(r, 0, 255 * sizeof(T)); memset(g, 0, 255 * sizeof(T)); memset(b, 0, 255 * sizeof(T)); } ~Histogram() { } public: T r[256]; T g[256]; T b[256]; }; public: explicit Private() : SMART_FRAME_ATTEMPTS(25) { thumbnailSize = 256; seekPercentage = 10; overlayFilmStrip = false; - workAroundIssues = true; + workAroundIssues = false; maintainAspectRatio = true; smartFrameSelection = false; } void generateHistogram(const VideoFrame& videoFrame, Histogram& histogram); int getBestThumbnailIndex(std::vector& videoFrames, const std::vector >& histograms); public: int thumbnailSize; quint16 seekPercentage; bool overlayFilmStrip; bool workAroundIssues; bool maintainAspectRatio; bool smartFrameSelection; QString seekTime; QVector filters; const int SMART_FRAME_ATTEMPTS; }; VideoThumbnailer::VideoThumbnailer() : d(new Private) { } VideoThumbnailer::VideoThumbnailer(int thumbnailSize, bool workaroundIssues, bool maintainAspectRatio, bool smartFrameSelection) : d(new Private) { d->thumbnailSize = thumbnailSize; d->workAroundIssues = workaroundIssues; d->maintainAspectRatio = maintainAspectRatio; d->smartFrameSelection = smartFrameSelection; } VideoThumbnailer::~VideoThumbnailer() { delete d; } void VideoThumbnailer::setSeekPercentage(int percentage) { d->seekTime.clear(); d->seekPercentage = percentage > 95 ? 95 : percentage; } void VideoThumbnailer::setSeekTime(const QString& seekTime) { d->seekTime = seekTime; } void VideoThumbnailer::setThumbnailSize(int size) { d->thumbnailSize = size; } void VideoThumbnailer::setWorkAroundIssues(bool workAround) { d->workAroundIssues = workAround; } void VideoThumbnailer::setMaintainAspectRatio(bool enabled) { d->maintainAspectRatio = enabled; } void VideoThumbnailer::setSmartFrameSelection(bool enabled) { d->smartFrameSelection = enabled; } int VideoThumbnailer::timeToSeconds(const QString& time) const { return QTime::fromString(time, QLatin1String("hh:mm:ss")).secsTo(QTime(0, 0, 0)); } void VideoThumbnailer::generateThumbnail(const QString& videoFile, VideoThumbWriter& imageWriter, QImage &image) { VideoDecoder movieDecoder(videoFile); if (movieDecoder.getInitialized()) { // before seeking, a frame has to be decoded if (!movieDecoder.decodeVideoFrame()) { return; } if ((!d->workAroundIssues) || (movieDecoder.getCodec() != QLatin1String("h264"))) { // workaround for bug in older ffmpeg (100% cpu usage when seeking in h264 files) int secondToSeekTo = d->seekTime.isEmpty() ? movieDecoder.getDuration() * d->seekPercentage / 100 : timeToSeconds(d->seekTime); movieDecoder.seek(secondToSeekTo); } VideoFrame videoFrame; if (d->smartFrameSelection) { generateSmartThumbnail(movieDecoder, videoFrame); } else { movieDecoder.getScaledVideoFrame(d->thumbnailSize, d->maintainAspectRatio, videoFrame); } applyFilters(videoFrame); imageWriter.writeFrame(videoFrame, image); } } void VideoThumbnailer::generateSmartThumbnail(VideoDecoder& movieDecoder, VideoFrame& videoFrame) { vector videoFrames(d->SMART_FRAME_ATTEMPTS); vector > histograms(d->SMART_FRAME_ATTEMPTS); for (int i = 0 ; i < d->SMART_FRAME_ATTEMPTS ; ++i) { movieDecoder.decodeVideoFrame(); movieDecoder.getScaledVideoFrame(d->thumbnailSize, d->maintainAspectRatio, videoFrames[i]); d->generateHistogram(videoFrames[i], histograms[i]); } int bestFrame = d->getBestThumbnailIndex(videoFrames, histograms); Q_ASSERT(bestFrame != -1); videoFrame = videoFrames[bestFrame]; } void VideoThumbnailer::generateThumbnail(const QString& videoFile, QImage &image) { VideoThumbWriter* const imageWriter = new VideoThumbWriter(); generateThumbnail(videoFile, *imageWriter, image); delete imageWriter; } void VideoThumbnailer::addFilter(VideoStripFilter* const filter) { d->filters.append(filter); } void VideoThumbnailer::removeFilter(VideoStripFilter* const filter) { for (QVector::iterator it = d->filters.begin() ; it != d->filters.end() ; ++it) { if (*it == filter) { d->filters.erase(it); break; } } } void VideoThumbnailer::clearFilters() { d->filters.clear(); } void VideoThumbnailer::applyFilters(VideoFrame& videoFrame) { for (QVector::iterator it = d->filters.begin() ; it != d->filters.end() ; ++it) { (*it)->process(videoFrame); } } void VideoThumbnailer::Private::generateHistogram(const VideoFrame& videoFrame, Private::Histogram& histogram) { for (quint32 i = 0 ; i < videoFrame.height ; ++i) { int pixelIndex = i * videoFrame.lineSize; for (quint32 j = 0 ; j < videoFrame.width * 3 ; j += 3) { ++histogram.r[videoFrame.frameData[pixelIndex + j]]; ++histogram.g[videoFrame.frameData[pixelIndex + j + 1]]; ++histogram.b[videoFrame.frameData[pixelIndex + j + 2]]; } } } int VideoThumbnailer::Private::getBestThumbnailIndex(vector& videoFrames, const vector >& histograms) { Q_UNUSED(videoFrames); Private::Histogram avgHistogram; for (size_t i = 0 ; i < histograms.size() ; ++i) { for (int j = 0 ; j < 255 ; ++j) { avgHistogram.r[j] += static_cast(histograms[i].r[j]) / histograms.size(); avgHistogram.g[j] += static_cast(histograms[i].g[j]) / histograms.size(); avgHistogram.b[j] += static_cast(histograms[i].b[j]) / histograms.size(); } } int bestFrame = -1; float minRMSE = FLT_MAX; for (size_t i = 0 ; i < histograms.size() ; ++i) { // calculate root mean squared error float rmse = 0.0; for (int j = 0 ; j < 255 ; ++j) { float error = qFabs(avgHistogram.r[j] - histograms[i].r[j]) + qFabs(avgHistogram.g[j] - histograms[i].g[j]) + qFabs(avgHistogram.b[j] - histograms[i].b[j]); rmse += (error * error) / 255; } rmse = qSqrt(rmse); if (rmse < minRMSE) { minRMSE = rmse; bestFrame = i; } } /* qCDebug(DIGIKAM_GENERAL_LOG) << "Best frame was: " << bestFrame << "(RMSE: " << minRMSE << ")" << endl; */ return bestFrame; } } // namespace Digikam diff --git a/project/scripts/bootstrap-exiv2.linux.sh b/project/scripts/bootstrap-exiv2.linux.sh index 3e48846802..d298238565 100755 --- a/project/scripts/bootstrap-exiv2.linux.sh +++ b/project/scripts/bootstrap-exiv2.linux.sh @@ -1,51 +1,52 @@ #!/bin/bash # Copyright (c) 2008-2019, Gilles Caulier, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # Copy this script on root folder where are source code export PATH=$QTDIR/bin:$PATH export PKG_CONFIG_PATH=/usr/lib/pkgconfig #export VERBOSE=1 # We will work on command line using MinGW compiler export MAKEFILES_TYPE='Unix Makefiles' if [ ! -d "build" ]; then mkdir build fi cd build export Exiv2Options='-DBUILD_SHARED_LIBS=ON \ -DEXIV2_ENABLE_XMP=ON \ -DEXIV2_ENABLE_EXTERNAL_XMP=OFF \ -DEXIV2_ENABLE_PNG=ON \ + -DEXIV2_ENABLE_HEIF=ON \ -DEXIV2_ENABLE_NLS=ON \ -DEXIV2_ENABLE_PRINTUCS2=ON \ -DEXIV2_ENABLE_LENSDATA=ON \ -DEXIV2_ENABLE_VIDEO=OFF \ -DEXIV2_ENABLE_WEBREADY=OFF \ -DEXIV2_ENABLE_DYNAMIC_RUNTIME=OFF \ -DEXIV2_ENABLE_CURL=OFF \ -DEXIV2_ENABLE_SSH=OFF \ -DEXIV2_BUILD_SAMPLES=OFF \ -DEXIV2_BUILD_PO=OFF \ - -DEXIV2_BUILD_EXIV2_COMMAND=OFF \ + -DEXIV2_BUILD_EXIV2_COMMAND=ON \ -DEXIV2_BUILD_UNIT_TESTS=OFF \ -DEXIV2_BUILD_DOC=OFF \ -DEXIV2_TEAM_EXTRA_WARNINGS=OFF \ -DEXIV2_TEAM_WARNINGS_AS_ERRORS=OFF \ -DEXIV2_TEAM_USE_SANITIZERS=OFF \ -DEXIV2_ENABLE_WIN_UNICODE=OFF' cmake -G "$MAKEFILES_TYPE" . \ -DCMAKE_INSTALL_PREFIX=/usr \ -Wno-dev \ $Exiv2Options \ ..