File indexing completed on 2025-01-05 03:58:04

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2020-09-24
0007  * Description : Test ImageMagick loader to QImage.
0008  *
0009  * SPDX-FileCopyrightText: 2020-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 // Qt includes
0016 
0017 #include <QImage>
0018 #include <QPixmap>
0019 #include <QLabel>
0020 #include <QDir>
0021 #include <QStringList>
0022 #include <QList>
0023 #include <QApplication>
0024 #include <QStandardPaths>
0025 #include <QFileDialog>
0026 #include <QMimeDatabase>
0027 
0028 // ImageMagick includes
0029 
0030 // Pragma directives to reduce warnings from ImageMagick header files.
0031 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
0032 #   pragma GCC diagnostic push
0033 #   pragma GCC diagnostic ignored "-Wignored-qualifiers"
0034 #   pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
0035 #endif
0036 
0037 #if defined(Q_CC_CLANG)
0038 #   pragma clang diagnostic push
0039 #   pragma clang diagnostic ignored "-Wignored-qualifiers"
0040 #   pragma clang diagnostic ignored "-Wkeyword-macro"
0041 #endif
0042 
0043 #include <Magick++.h>
0044 
0045 #if MagickLibVersion < 0x700
0046 #   include <magick/magick.h>
0047 #endif
0048 
0049 #if defined(Q_CC_CLANG)
0050 #   pragma clang diagnostic pop
0051 #endif
0052 
0053 #if defined(Q_CC_GNU)
0054 #   pragma GCC diagnostic pop
0055 #endif
0056 
0057 // Local includes
0058 
0059 #include "digikam_debug.h"
0060 
0061 using namespace Magick;
0062 using namespace MagickCore;
0063 
0064 /** Convert from QImage to IM::Image
0065  */
0066 /*Image* toImage(QImage* const qimage)
0067 {
0068     qCDebug(DIGIKAM_TESTS_LOG) << "toImage:" << qimage->width() << qimage->height();
0069 
0070     Image* const newImage = new Image(Magick::Geometry(qimage->width(), qimage->height()), Magick::ColorRGB(0.5, 0.2, 0.3));
0071     newImage->modifyImage();
0072 
0073     double scale                = 1 / 256.0;
0074     Magick::Quantum* pixels = 0;
0075     Magick::ColorRGB mgc;
0076 
0077     for (int y = 0 ; y < qimage->height() ; ++y)
0078     {
0079         pixels = newImage->setPixels(0, y, newImage->columns(), 1);
0080 
0081         for (int x = 0 ; x < qimage->width() ; ++x)
0082         {
0083             QColor pix = qimage->pixel(x, y);
0084             mgc.red  (scale * pix.red());
0085             mgc.green(scale * pix.green());
0086             mgc.blue (scale * pix.blue());
0087             *pixels++ = mgc;
0088         }
0089 
0090         newImage->syncPixels();
0091     }
0092 
0093     return newImage;
0094 }
0095 */
0096 /** Convert pixel from IM::Image to QImage.
0097  */
0098 
0099 // -- ImageMagick codecs to QImage --------------------------------------------------------
0100 
0101 bool loadWithImageMagick(const QString& path, QImage& qimg)
0102 {
0103     qCDebug(DIGIKAM_TESTS_LOG) << "Try to load image with ImageMagick codecs";
0104 
0105     try
0106     {
0107         Magick::Image image;
0108         image.read(path.toUtf8().constData());
0109 
0110         qCDebug(DIGIKAM_TESTS_LOG) << "IM toQImage     :" << image.columns() << image.rows();
0111         qCDebug(DIGIKAM_TESTS_LOG) << "IM QuantumRange :" << QuantumRange;
0112 
0113         Blob* const pixelBlob = new Blob;
0114         image.write(pixelBlob, "BGRA", 8);
0115         qCDebug(DIGIKAM_TESTS_LOG) << "IM blob size    :" << pixelBlob->length();
0116 
0117         qimg = QImage((uchar*)pixelBlob->data(), image.columns(), image.rows(), QImage::Format_ARGB32);
0118         qCDebug(DIGIKAM_TESTS_LOG) << "QImage data size:" << qimg.sizeInBytes();
0119 
0120         if (qimg.isNull())
0121         {
0122             return false;
0123         }
0124     }
0125     catch (Exception& error_)
0126     {
0127         qCWarning(DIGIKAM_TESTS_LOG) << "Cannot load [" << path << "] due to ImageMagick exception:" << error_.what();
0128         qimg = QImage();
0129         return false;
0130     }
0131 
0132     return true;
0133 }
0134 
0135 // ---------------------------------------------------------------------------------------------------
0136 
0137 int main(int argc, char** argv)
0138 {
0139     MagickCoreGenesis((char*)nullptr, MagickFalse);
0140 
0141     ExceptionInfo ex = *AcquireExceptionInfo();
0142     size_t n                  = 0;
0143     const MagickInfo** inflst = GetMagickInfoList("*", &n, &ex);
0144 
0145     if (!inflst)
0146     {
0147         qCWarning(DIGIKAM_TESTS_LOG) << "ImageMagick coders list is null!";
0148         return -1;
0149     }
0150 
0151     qCDebug(DIGIKAM_TESTS_LOG).noquote() << "Name             :: Module           :: Mime Type                    :: Mode  :: Version                      :: Description";
0152 
0153     for (uint i = 0 ; i < n ; ++i)
0154     {
0155         const MagickInfo* inf = inflst[i];
0156 
0157         if (inf)
0158         {
0159             QString mode;
0160 
0161             if (inf->decoder) mode.append(QLatin1Char('R'));
0162             else              mode.append(QLatin1Char('-'));
0163 
0164             if (inf->encoder) mode.append(QLatin1Char('W'));
0165             else              mode.append(QLatin1Char('-'));
0166 
0167 #if (MagickLibVersion >= 0x69A && defined(magick_module))
0168             QString mod  = QLatin1String(inf->magick_module);
0169 #else
0170             QString mod  = QLatin1String(inf->module);
0171 #endif
0172 
0173             QString mime = QMimeDatabase().mimeTypeForFile(QFileInfo(QString::fromLatin1("foo.%1").arg(mod))).name();
0174 
0175             if (mod != QLatin1String("DNG")  &&
0176                 mod != QLatin1String("JPEG") &&
0177                 mod != QLatin1String("PNG")  &&
0178                 mod != QLatin1String("TIFF") &&
0179                 mod != QLatin1String("JP2")  &&
0180                 mime.startsWith(QLatin1String("image/")))
0181             {
0182                 qCDebug(DIGIKAM_TESTS_LOG).noquote()
0183                      << QString::fromLatin1("%1").arg(QLatin1String(inf->name),        16) << "::"
0184                      << QString::fromLatin1("%1").arg(mod,                             16) << "::"
0185                      << QString::fromLatin1("%1").arg(mime,                            28) << "::"
0186                      << QString::fromLatin1("%1").arg(mode,                             5) << "::"
0187                      << QString::fromLatin1("%1").arg(QLatin1String(inf->version),     28) << "::"
0188                      << QString::fromLatin1("%1").arg(QLatin1String(inf->description), 64);
0189             }
0190         }
0191     }
0192 
0193     QApplication app(argc, argv);
0194 
0195     QStringList list;
0196 
0197     if (argc <= 1)
0198     {
0199         list = QFileDialog::getOpenFileNames(nullptr, QString::fromLatin1("Select Image Files to Load"),
0200                                              QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).first(),
0201                                              QLatin1String("Image Files (*.png *.jpg *.tif *.bmp *.gif *.xcf *.kra *.psd)"));
0202     }
0203     else
0204     {
0205         for (int i = 1 ; i < argc ; ++i)
0206         {
0207             list.append(QString::fromLocal8Bit(argv[i]));
0208         }
0209     }
0210 
0211     qCDebug(DIGIKAM_TESTS_LOG) << "Files to load:" << list;
0212 
0213     if (!list.isEmpty())
0214     {
0215         Q_FOREACH (const QString& path, list)
0216         {
0217             QImage qimg;
0218             bool ret = loadWithImageMagick(path, qimg);
0219 
0220             if (ret)
0221             {
0222                 QLabel* const lbl  = new QLabel;
0223                 lbl->setPixmap(QPixmap::fromImage(qimg.scaled(512, 512, Qt::KeepAspectRatio)));
0224                 lbl->show();
0225             }
0226             else
0227             {
0228                 qCWarning(DIGIKAM_TESTS_LOG) << "exit -1";
0229                 MagickCoreTerminus();
0230                 return -1;
0231             }
0232         }
0233 
0234         app.exec();
0235     }
0236 
0237     free(inflst);
0238     MagickCoreTerminus();
0239 
0240     return 0;
0241 }