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 732cbb0311..9f411ef844 100644 --- a/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp +++ b/core/dplugins/dimg/imagemagick/dimgimagemagickplugin.cpp @@ -1,306 +1,309 @@ /* ============================================================ * * 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 // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" #include "dimgimagemagickloader.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 } } QString ret; foreach (const QString& str, formats) { if (!ret.contains(str)) { ret += QString::fromUtf8("%1 ").arg(str.toUpper()); } } return ret; } int DImgImageMagickPlugin::canRead(const QFileInfo& fileInfo, bool magic) const { 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 0; } QStringList formats; ExceptionInfo ex; size_t n = 0; const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); if (!inflst) { qWarning() << "ImageMagick coders list is null!"; return 0; } 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 } } if (formats.contains(QLatin1String("JPEG"))) { formats.append(QLatin1String("JPG")); formats.append(QLatin1String("JPE")); } + // Remove known formats that are not stable. + formats.removeAll(QLatin1String("XCF")); + if (formats.contains(format)) { if (format == QLatin1String("WEBP")) { return 70; } else { return 90; } } } return 0; } int DImgImageMagickPlugin::canWrite(const QString& format) const { QStringList formats; ExceptionInfo ex; size_t n = 0; const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex); if (!inflst) { qWarning() << "ImageMagick coders list is null!"; return 0; } 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()); #else formats.append(QString::fromLatin1(inf->module).toUpper()); #endif } } if (formats.contains(format.toUpper())) { if (format.toUpper() == QLatin1String("WEBP")) { return 70; } else { return 90; } } return 0; } DImgLoader* DImgImageMagickPlugin::loader(DImg* const image, const DRawDecoding&) const { return new DImgImageMagickLoader(image); } } // namespace DigikamImageMagickDImgPlugin 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