File indexing completed on 2025-01-05 03:55:18

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2005-06-14
0007  * Description : digiKam 8/16 bits image management API
0008  *
0009  * SPDX-FileCopyrightText: 2005      by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #ifndef DIGIKAM_DIMG_H
0018 #define DIGIKAM_DIMG_H
0019 
0020 // Qt includes
0021 
0022 #include <QExplicitlySharedDataPointer>
0023 #include <QByteArray>
0024 #include <QFileInfo>
0025 #include <QFlags>
0026 #include <QSize>
0027 #include <QRect>
0028 #include <QVariant>
0029 
0030 // Local includes
0031 
0032 #include "digikam_export.h"
0033 #include "drawdecoding.h"
0034 #include "dcolor.h"
0035 #include "dcolorcomposer.h"
0036 #include "historyimageid.h"
0037 #include "iccprofile.h"
0038 #include "metaengine_data.h"
0039 
0040 class QImage;
0041 class QPixmap;
0042 
0043 namespace Digikam
0044 {
0045 
0046 class ExposureSettingsContainer;
0047 class DImageHistory;
0048 class FilterAction;
0049 class IccTransform;
0050 class DImgLoaderObserver;
0051 
0052 class DIGIKAM_EXPORT DImg
0053 {
0054 public:
0055 
0056     enum FORMAT
0057     {
0058         NONE = 0,
0059         JPEG,
0060         PNG,
0061         TIFF,
0062         JP2K,
0063         PGF,
0064         HEIF,
0065         // Others file formats.
0066         RAW,
0067         QIMAGE  ///< QImage or ImageMagick
0068     };
0069 
0070     enum ANGLE
0071     {
0072         ROT90 = 0,
0073         ROT180,
0074         ROT270,
0075         ROTNONE
0076     };
0077 
0078     enum FLIP
0079     {
0080         HORIZONTAL = 0,
0081         VERTICAL
0082     };
0083 
0084     enum COLORMODEL
0085     {
0086         COLORMODELUNKNOWN = 0,
0087         RGB,
0088         GRAYSCALE,
0089         MONOCHROME,
0090         INDEXED,
0091         YCBCR,
0092         CMYK,
0093         CIELAB,
0094         COLORMODELRAW
0095     };
0096 
0097 public:
0098 
0099     /**
0100      * Identify file format
0101      */
0102     static FORMAT fileFormat(const QString& filePath);
0103 
0104     static QString formatToMimeType(FORMAT frm);
0105 
0106 public:
0107 
0108     class Private;
0109 
0110 public:
0111 
0112     /**
0113      * Create null image
0114      */
0115     DImg();
0116 
0117     /**
0118      * Load image using QByteArray as file path
0119      */
0120     explicit DImg(const QByteArray& filePath, DImgLoaderObserver* const observer = nullptr,
0121                   const DRawDecoding& rawDecodingSettings = DRawDecoding());
0122 
0123     /**
0124      * Load image using QString as file path
0125      */
0126     explicit DImg(const QString& filePath, DImgLoaderObserver* const observer = nullptr,
0127                   const DRawDecoding& rawDecodingSettings = DRawDecoding());
0128 
0129     /**
0130      * Copy image: Creates a shallow copy that refers to the same shared data.
0131      * The two images will be equal. Call detach() or copy() to create deep copies.
0132      */
0133     DImg(const DImg& image);
0134 
0135     /**
0136      * Copy image: Creates a copy of a QImage object. If the QImage is null, a
0137      * null DImg will be created.
0138      */
0139     explicit DImg(const QImage& image);
0140 
0141     /**
0142      * Create image from data.
0143      * If data is 0, a new buffer will be allocated, otherwise the given data will be used:
0144      * If copydata is true, the data will be copied to a newly allocated buffer.
0145      * If copyData is false, this DImg object will take ownership of the data pointer.
0146      * If there is an alpha channel, the data shall be in non-premultiplied form (unassociated alpha).
0147      */
0148     DImg(uint width, uint height, bool sixteenBit, bool alpha = false, uchar* const data = nullptr, bool copyData = true);
0149 
0150     ~DImg();
0151 
0152     /**
0153      * Equivalent to the copy constructor
0154      */
0155     DImg&      operator=(const DImg& image);
0156 
0157     /** Detaches from shared data and makes sure that this image
0158      * is the only one referring to the data.
0159      * If multiple images share common data, this image makes a copy
0160      * of the data and detaches itself from the sharing mechanism.
0161      * Nothing is done if there is just a single reference.
0162      */
0163     void       detach();
0164 
0165     /** Returns whether two images are equal.
0166      * Two images are equal if and only if they refer to the same shared data.
0167      * (Thus, DImg() == DImg() is not true, both instances refer two their
0168      * own shared data. image == DImg(image) is true.)
0169      * If two or more images refer to the same data, they have the same
0170      * image data, bits() returns the same data, they have the same metadata,
0171      * and a change to one image also affects the others.
0172      * Call detach() to split one image from the group of equal images.
0173      */
0174     bool        operator==(const DImg& image) const;
0175 
0176     /**
0177      * Replaces image data of this object. Metadata is unchanged. Parameters like constructor above.
0178      */
0179     void        putImageData(uint width, uint height, bool sixteenBit, bool alpha, uchar* const data, bool copyData = true);
0180 
0181     /**
0182      * Overloaded function, provided for convenience, behaves essentially
0183      * like the function above if data is not 0.
0184      * Uses current width, height, sixteenBit, and alpha values.
0185      * If data is 0, the current data is deleted and the image is set to null
0186      * (But metadata unchanged).
0187      */
0188     void        putImageData(uchar* const data, bool copyData = true);
0189 
0190     /**
0191      * Reset metadata and image data to null image
0192      */
0193     void        reset();
0194 
0195     /**
0196      * Reset metadata, but do not change image data
0197      */
0198     void        resetMetaData();
0199 
0200     /**
0201      * Returns the data of this image.
0202      * Ownership of the buffer is passed to the caller, this image will be null afterwards.
0203      */
0204     uchar*      stripImageData();
0205 
0206     bool        load(const QString& filePath, DImgLoaderObserver* const observer = nullptr,
0207                      const DRawDecoding& rawDecodingSettings = DRawDecoding());
0208 
0209     bool        load(const QString& filePath,
0210                      bool loadMetadata, bool loadICCData, bool loadUniqueHash, bool loadHistory,
0211                      DImgLoaderObserver* const observer = nullptr,
0212                      const DRawDecoding& rawDecodingSettings = DRawDecoding());
0213 
0214     bool        load(const QString& filePath, int loadFlags, DImgLoaderObserver* const observer,
0215                      const DRawDecoding& rawDecodingSettings = DRawDecoding());
0216 
0217     bool        save(const QString& filePath, FORMAT frm, DImgLoaderObserver* const observer = nullptr);
0218     bool        save(const QString& filePath, const QString& format, DImgLoaderObserver* const observer = nullptr);
0219 
0220     /**
0221      * It is common that images are not directly saved to the destination path.
0222      * For this reason, save() does not call addAsReferredImage(), and the stored
0223      * save path may be wrong.
0224      * Call this method after save() with the final destination path.
0225      * This path will be stored in the image history as well.
0226      */
0227     void        imageSavedAs(const QString& savePath);
0228 
0229     /**
0230      * Loads most parts of the meta information, but never the image data.
0231      * If loadMetadata is true, the metadata will be available with getComments, getExif, getIptc, getXmp .
0232      * If loadICCData is true, the ICC profile will be available with getICCProfile.
0233      */
0234     bool        loadItemInfo(const QString& filePath, bool loadMetadata = true,
0235                              bool loadICCData = true, bool loadUniqueHash = true,
0236                              bool loadImageHistory = true);
0237 
0238     bool        isNull()         const;
0239     uint        width()          const;
0240     uint        height()         const;
0241     QSize       size()           const;
0242     uchar*      copyBits()       const;
0243     uchar*      bits()           const;
0244     uchar*      scanLine(uint i) const;
0245     bool        hasAlpha()       const;
0246     bool        sixteenBit()     const;
0247     quint64     numBytes()       const;
0248     quint64     numPixels()      const;
0249 
0250     /**
0251      * Return the number of bytes depth of one pixel : 4 (non sixteenBit) or 8 (sixteen)
0252      */
0253     int         bytesDepth() const;
0254 
0255     /**
0256      * Return the number of bits depth of one color component for one pixel : 8 (non sixteenBit) or 16 (sixteen)
0257      */
0258     int         bitsDepth()  const;
0259 
0260     /**
0261      * Returns the file path from which this DImg was originally loaded.
0262      * Returns a null string if the DImg was not loaded from a file.
0263      */
0264     QString     originalFilePath() const;
0265 
0266     /**
0267      * Returns the file path to which this DImg was saved.
0268      * Returns the file path set with imageSavedAs(), if that was not called,
0269      * save(), if that was not called, a null string.
0270      */
0271     QString     lastSavedFilePath() const;
0272 
0273     /**
0274      * Returns the color model in which the image was stored in the file.
0275      * The color space of the loaded image data is always RGB.
0276      */
0277     COLORMODEL  originalColorModel() const;
0278 
0279     /**
0280      * Returns the bit depth (in bits per channel, e.g. 8 or 16) of the original file.
0281      */
0282     int         originalBitDepth() const;
0283 
0284     /**
0285      * Returns the size of the original file.
0286      */
0287     QSize       originalSize() const;
0288 
0289     /**
0290      * Returns the size of the original file
0291      * in the same aspect ratio as size().
0292      */
0293     QSize       originalRatioSize() const;
0294 
0295     /**
0296      * Returns the file format in form of the FORMAT enum that was detected in the load()
0297      * method. Other than the format attribute which is written by the DImgLoader,
0298      * this can include the QIMAGE or NONE values.
0299      * Returns NONE for images that have not been loaded.
0300      * For unknown image formats, a value of QIMAGE can be returned to indicate that the
0301      * QImage-based loader will have been used. To find out if this has worked, check
0302      * the return value you got from load().
0303      */
0304     FORMAT      detectedFormat() const;
0305 
0306     /**
0307      * Returns the format string as written by the image loader this image was originally
0308      * loaded from. Format strings used include JPEG, PNG, TIFF, PGF, JP2K, RAW, PPM.
0309      * For images loaded with the platform QImage loader, the file suffix is used.
0310      * Returns null if this DImg was not loaded from a file, but created in memory.
0311      */
0312     QString     format() const;
0313 
0314     /**
0315      * Returns the format string of the format that this image was last saved to.
0316      * An image can be loaded from a file - retrieve that format with fileFormat()
0317      * and loadedFormat() - and can the multiple times be saved to different formats.
0318      * Format strings used include JPG, PGF, PNG, TIFF and JP2K.
0319      * If this file was not save, a null string is returned.
0320      */
0321     QString     savedFormat() const;
0322 
0323     /**
0324      * Returns the DRawDecoding options that this DImg was loaded with.
0325      * If this is not a RAW image or no options were specified, returns DRawDecoding().
0326      */
0327     DRawDecoding rawDecodingSettings() const;
0328 
0329     /**
0330      * Access a single pixel of the image.
0331      * These functions add some safety checks and then use the methods from DColor.
0332      * In optimized code working directly on the data,
0333      * better use the inline methods from DColor.
0334      */
0335     DColor      getPixelColor(uint x, uint y) const;
0336     void        setPixelColor(uint x, uint y, const DColor& color);
0337     void        prepareSubPixelAccess();
0338     DColor      getSubPixelColor(float x, float y) const;
0339     DColor      getSubPixelColorFast(float x, float y) const;
0340 
0341     /**
0342      * If the image has an alpha channel, check if there exist pixels
0343      * which actually have non-opaque color, that is alpha < 1.0.
0344      * Note that all pixels are scanned to reach a return value of "false".
0345      * If hasAlpha() is false, always returns false.
0346      */
0347     bool        hasTransparentPixels() const;
0348 
0349     /**
0350      * Return true if the original image file format cannot be saved.
0351      * This is depending of DImgLoader::save() implementation. For example
0352      * RAW file formats are supported by DImg using dcraw than cannot support
0353      * writing operations.
0354      */
0355     bool       isReadOnly()        const;
0356 
0357     /**
0358      * Metadata manipulation methods
0359      */
0360     MetaEngineData getMetadata()   const;
0361     IccProfile getIccProfile()     const;
0362     void       setMetadata(const MetaEngineData& data);
0363     void       setIccProfile(const IccProfile& profile);
0364 
0365     void       setAttribute(const QString& key, const QVariant& value);
0366     QVariant   attribute(const QString& key)    const;
0367     bool       hasAttribute(const QString& key) const;
0368     void       removeAttribute(const QString& key);
0369 
0370     void       setEmbeddedText(const QString& key, const QString& text);
0371     QString    embeddedText(const QString& key) const;
0372 
0373     const DImageHistory& getItemHistory() const;
0374     DImageHistory&       getItemHistory();
0375     void                 setItemHistory(const DImageHistory& history);
0376     bool                 hasImageHistory() const;
0377     DImageHistory        getOriginalImageHistory() const;
0378     void                 addFilterAction(const FilterAction& action);
0379 
0380     /**
0381      * Sets a step in the history to constitute the beginning of a branch.
0382      * Use setHistoryBranch() to take getOriginalImageHistory() and set the first added step as a branch.
0383      * Use setHistoryBranchForLastSteps(n) to start the branch before the last n steps in the history.
0384      * (Assume the history had 3 steps and you added 2, call setHistoryBranchForLastSteps(2))
0385      * Use setHistoryBranchAfter() if have a copy of the history before branching,
0386      * the first added step on top of that history will be made a branch.
0387      */
0388     void                 setHistoryBranchAfter(const DImageHistory& historyBeforeBranch, bool isBranch = true);
0389     void                 setHistoryBranchForLastSteps(int numberOfLastHistorySteps, bool isBranch = true);
0390     void                 setHistoryBranch(bool isBranch = true);
0391 
0392     /**
0393      * When saving, several changes to the image metadata are necessary
0394      * before it can safely be written to the new file.
0395      * This method updates the stored meta engine object in preparation to a subsequent
0396      * call to save() with the same target file.
0397      * 'intendedDestPath' is the finally intended file name. Do not give the temporary
0398      *   file name if you are going to save() to a temp file.
0399      * 'destMimeType' is destination type mime. In some cases, metadata is updated depending on this value.
0400      * 'originalFileName' is the original file's name, for simplistic history tracking in metadata.
0401      *   This is completely independent from the DImageHistory framework.
0402      * For the 'flags' see below.
0403      * Not all steps are optional and can be controlled with flags.
0404      */
0405     enum PrepareMetadataFlag
0406     {
0407         /**
0408          * A small preview can be stored in the metadata.
0409          * Remove old preview entries
0410          */
0411         RemoveOldMetadataPreviews = 1 << 0,
0412         /**
0413          * Create a new preview from current image data.
0414          */
0415         CreateNewMetadataPreview  = 1 << 1,
0416         /**
0417          * Set the exif orientation tag to "normal"
0418          * Applicable if the image data was rotated according to the tag
0419          */
0420         ResetExifOrientationTag   = 1 << 2,
0421         /**
0422          * Creates a new UUID for the image history.
0423          * Applicable if the file was changed.
0424          */
0425         CreateNewImageHistoryUUID = 1 << 3,
0426 
0427         PrepareMetadataFlagsAll   = RemoveOldMetadataPreviews |
0428                                     CreateNewMetadataPreview  |
0429                                     ResetExifOrientationTag   |
0430                                     CreateNewImageHistoryUUID
0431     };
0432     Q_DECLARE_FLAGS(PrepareMetadataFlags, PrepareMetadataFlag)
0433 
0434     void prepareMetadataToSave(const QString& intendedDestPath,
0435                                const QString& destMimeType,
0436                                const QString& originalFileName = QString(),
0437                                PrepareMetadataFlags flags      = PrepareMetadataFlagsAll);
0438 
0439     /**
0440      * For convenience: Including all flags, except for ResetExifOrientationTag which can be selected.
0441      * Uses originalFilePath() to fill the original file name.
0442      */
0443     void prepareMetadataToSave(const QString& intendedDestPath,
0444                                const QString& destMimeType,
0445                                bool           resetExifOrientationTag);
0446 
0447     /**
0448      * Create a HistoryImageId for _this_ image _already_ saved at the given file path.
0449      */
0450     HistoryImageId createHistoryImageId(const QString& filePath, HistoryImageId::Type type);
0451 
0452     /**
0453      * If you have saved this DImg to filePath, and want to continue using this DImg object
0454      * to add further changes to the image history, you can call this method to add to the image history
0455      * a reference to the just saved image.
0456      * First call updateMetadata(), then call save(), then call addAsReferredImage().
0457      * Do not call this directly after loading, before applying any changes:
0458      * The history is correctly initialized when loading.
0459      * If you need to insert the referred file to an entry which is not the last entry,
0460      * which may happen if the added image was saved after this image's history was created,
0461      * you can use insertAsReferredImage.
0462      * The added id is returned.
0463      */
0464     HistoryImageId addAsReferredImage(const QString& filePath, HistoryImageId::Type type = HistoryImageId::Intermediate);
0465     void           addAsReferredImage(const HistoryImageId& id);
0466     void           insertAsReferredImage(int afterHistoryStep, const HistoryImageId& otherImagesId);
0467 
0468     /**
0469      * In the history, adjusts the UUID of the ImageHistoryId of the current file.
0470      * Call this if you have associated a UUID with this file which is not written to the metadata.
0471      * If there is already a UUID present, read from metadata, it will not be replaced.
0472      */
0473     void addCurrentUniqueImageId(const QString& uuid);
0474 
0475     /**
0476      * Retrieves the Exif orientation, either from the LoadSaveThread info provider if available,
0477      * or from the metadata
0478      */
0479     int exifOrientation(const QString& filePath);
0480 
0481     /**
0482      * When loaded from a file, some attributes like format and isReadOnly still depend on this
0483      * originating file. When saving in a different format to a different file,
0484      * you may wish to switch these attributes to the new file.
0485      * - fileOriginData() returns the current origin data, bundled in the returned QVariant.
0486      * - setFileOriginData() takes such a variant and adjusts the properties
0487      * - lastSavedFileOriginData() returns the origin data as if the image was loaded from
0488      *   the last saved image.
0489      * - switchOriginToLastSaved is equivalent to setting origin data returned from lastSavedFileOriginData()
0490      *
0491      * Example: an image loaded from a RAW and saved to PNG will be read-only and format RAW.
0492      * After calling switchOriginToLastSaved, it will not be read-only, format will be PNG,
0493      * and rawDecodingSettings will be null. detectedFormat() will not change.
0494      * In the history, the last referred image that was added (as intermediate) is made
0495      * the new Current image.
0496      * NOTE: Set the saved image path with imageSavedAs() before!
0497      */
0498     QVariant    fileOriginData()          const;
0499     void        setFileOriginData(const QVariant& data);
0500     QVariant    lastSavedFileOriginData() const;
0501     void        switchOriginToLastSaved();
0502 
0503     /**
0504      * Return a deep copy of full image
0505      */
0506     DImg       copy() const;
0507 
0508     /**
0509      * Return a deep copy of the image, but do not include metadata.
0510      */
0511     DImg       copyImageData() const;
0512 
0513     /**
0514      * Return an image that contains a deep copy of
0515      * this image's metadata and the information associated
0516      * with the image data (width, height, hasAlpha, sixteenBit),
0517      * but no image data, i.e. isNull() is true.
0518      */
0519     DImg       copyMetaData() const;
0520 
0521     /**
0522      * Return a region of image
0523      */
0524     DImg       copy(const QRect& rect)          const;
0525     DImg       copy(const QRectF& relativeRect) const;
0526     DImg       copy(int x, int y, int w, int h) const;
0527 
0528     /**
0529      * Copy a region of pixels from a source image to this image.
0530      * Parameters:
0531      * sx|sy  Coordinates in the source image of the rectangle to be copied
0532      * w h    Width and height of the rectangle (Default, or when both are -1: whole source image)
0533      * dx|dy  Coordinates in this image of the rectangle in which the region will be copied
0534      * (Default: 0|0)
0535      * The bit depth of source and destination must be identical.
0536      */
0537     void       bitBltImage(const DImg* const src, int dx, int dy);
0538     void       bitBltImage(const DImg* const src, int sx, int sy, int dx, int dy);
0539     void       bitBltImage(const DImg* const src, int sx, int sy, int w, int h, int dx, int dy);
0540     void       bitBltImage(const uchar* const src, int sx, int sy, int w, int h, int dx, int dy,
0541                            uint swidth, uint sheight, int sdepth);
0542 
0543     /**
0544      * Blend src image on this image (this is dest) with the specified composer
0545      * and multiplication flags. See documentation of DColorComposer for more info.
0546      * For the other arguments, see documentation of bitBltImage above.
0547      */
0548     void       bitBlendImage(DColorComposer* const composer, const DImg* const src,
0549                              int sx, int sy, int w, int h, int dx, int dy,
0550                              DColorComposer::MultiplicationFlags multiplicationFlags =
0551                                  DColorComposer::NoMultiplication);
0552 
0553     /**
0554      * For the specified region, blend this image on the given color with the specified
0555      * composer and multiplication flags. See documentation of DColorComposer for more info.
0556      * Note that the result pixel is again written to this image, which is, for the blending, source.
0557      */
0558     void       bitBlendImageOnColor(DColorComposer* const composer, const DColor& color,
0559                                     int x, int y, int w, int h,
0560                                     DColorComposer::MultiplicationFlags multiplicationFlags =
0561                                     DColorComposer::NoMultiplication);
0562     void       bitBlendImageOnColor(const DColor& color, int x, int y, int w, int h);
0563     void       bitBlendImageOnColor(const DColor& color);
0564 
0565     /**
0566      * QImage wrapper methods
0567      */
0568     QImage     copyQImage()                           const;
0569     QImage     copyQImage(const QRect& rect)          const;
0570     QImage     copyQImage(const QRectF& relativeRect) const;
0571     QImage     copyQImage(int x, int y, int w, int h) const;
0572 
0573     /**
0574      * Crop image to the specified region
0575      */
0576     void       crop(const QRect& rect);
0577     void       crop(int x, int y, int w, int h);
0578 
0579     /**
0580      * Set width and height of this image, smoothScale it to the given size
0581      */
0582     void       resize(int w, int h);
0583 
0584     /**
0585      * If the image has an alpha channel and transparent pixels,
0586      * it will be blended on the specified color and the alpha channel will be removed.
0587      * This is a no-op if hasTransparentPixels() is false, but this method can be expensive,
0588      * therefore it is _not_ checked inside removeAlphaChannel().
0589      * (the trivial hasAlpha() is checked)
0590      */
0591     void       removeAlphaChannel(const DColor& destColor);
0592     void       removeAlphaChannel();
0593 
0594     /**
0595      * Return a version of this image scaled to the specified size with the specified mode.
0596      * See QSize documentation for information on available modes
0597      */
0598     DImg       smoothScale(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio) const;
0599     DImg       smoothScale(const QSize& destSize, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio) const;
0600 
0601     /**
0602      * Executes the same scaling as smoothScale(width, height), but from the result of this call,
0603      * returns only the section specified by clipx, clipy, clipwidth, clipheight.
0604      * This is thus equivalent to calling
0605      * Dimg scaled = smoothScale(width, height); scaled.crop(clipx, clipy, clipwidth, clipheight);
0606      * but potentially much faster.
0607      * In smoothScaleSection, you specify the source region, here, the result region.
0608      * It will often not be possible to find _integer_ source coordinates for a result region!
0609      */
0610     DImg smoothScaleClipped(int width, int height, int clipx, int clipy, int clipwidth, int clipheight) const;
0611     DImg smoothScaleClipped(const QSize& destSize, const QRect& clip) const;
0612 
0613     /**
0614      * Take the region specified by the rectangle sx|sy, width and height sw * sh,
0615      * and scale it to an image with size dw * dh
0616      */
0617     DImg       smoothScaleSection(int sx, int sy, int sw, int sh, int dw, int dh) const;
0618     DImg       smoothScaleSection(const QRect& sourceRect, const QSize& destSize) const;
0619 
0620     void       rotate(ANGLE angle);
0621     void       flip(FLIP direction);
0622 
0623     /**
0624      * Rotates and/or flip the DImg according to the given DMetadata::Orientation,
0625      * so that the current state is orientation and the resulting step is normal orientation.
0626      * Returns true if the image was actually rotated or flipped (e.g. if ORIENTATION_NORMAL
0627      * is given, returns false, because no action is taken).
0628      */
0629     bool       rotateAndFlip(int orientation);
0630 
0631     /**
0632      * Reverses the previous function.
0633      */
0634     bool       reverseRotateAndFlip(int orientation);
0635 
0636     /**
0637      * Utility to make sure that an image is rotated according to Exif tag.
0638      * Detects if an image has previously already been rotated: You can
0639      * call this method more than one time on the same image.
0640      * Returns true if the image has actually been rotated or flipped.
0641      * Returns false if a rotation was not needed.
0642      */
0643     bool       wasExifRotated();
0644     bool       exifRotate(const QString& filePath);
0645 
0646     /**
0647      * Reverses the previous function
0648      */
0649     bool       reverseExifRotate(const QString& filePath);
0650 
0651     /**
0652      * Returns current DMetadata::Orientation from DImg
0653      */
0654     int        orientation() const;
0655 
0656     /** Rotates and/or flip the DImg according to the given transform action,
0657      * which is a MetaEngineRotation::TransformAction.
0658      * Returns true if the image was actually rotated or flipped.
0659      */
0660     bool       transform(int transformAction);
0661 
0662     QPixmap    convertToPixmap()                              const;
0663     QPixmap    convertToPixmap(IccTransform& monitorICCtrans) const;
0664 
0665     /**
0666      * Return a mask image where pure white and pure black pixels are over-colored.
0667      * This way is used to identify over and under exposed pixels.
0668      */
0669     QImage     pureColorMask(ExposureSettingsContainer* const expoSettings) const;
0670 
0671     /**
0672      * Convert depth of image. Depth is bytesDepth * bitsDepth.
0673      * If depth is 32, converts to 8 bits,
0674      * if depth is 64, converts to 16 bits.
0675      */
0676     void       convertDepth(int depth);
0677 
0678     /**
0679      * Wrapper methods for convertDepth
0680      */
0681     void       convertToSixteenBit();
0682     void       convertToEightBit();
0683     void       convertToDepthOfImage(const DImg* const otherImage);
0684 
0685     /**
0686      * Fill whole image with specified color.
0687      * The bit depth of the color must be identical to the depth of this image.
0688      */
0689     void       fill(const DColor& color);
0690 
0691     /**
0692      * This methods return a 128-bit MD5 hex digest which is meant to uniquely identify
0693      * the file. The hash is calculated on parts of the file and the file metadata.
0694      * It cannot be used to find similar images. It is not calculated from the image data.
0695      * The hash will be returned as a 32-byte hexadecimal string.
0696      *
0697      * If you already have a DImg object of the file, use the member method.
0698      * The object does not need to have the full image data loaded, but it shall at least
0699      * have been loaded with loadItemInfo with loadMetadata = true, or have the metadata
0700      * set later with setComments, setExif, setIptc, setXmp.
0701      * If the object does not have the metadata loaded, a non-null, but invalid hash will
0702      * be returned! In this case, use the static method.
0703      * If the image has been loaded with loadUniqueHash = true, the hash can be retrieved
0704      * with the member method.
0705      *
0706      * You do not need a DImg object of the file to retrieve the unique hash;
0707      * Use the static method and pass just the file path.
0708      */
0709     QByteArray getUniqueHash();
0710     static QByteArray getUniqueHash(const QString& filePath);
0711 
0712     /**
0713      * This methods return a 128-bit MD5 hex digest which is meant to uniquely identify
0714      * the file. The hash is calculated on parts of the file.
0715      * It cannot be used to find similar images. It is not calculated from the image data.
0716      * The hash will be returned as a 32-byte hexadecimal string.
0717      *
0718      * If you already have a DImg object loaded from the file, use the member method.
0719      * If the image has been loaded with loadUniqueHash = true, the hash will already
0720      * be available.
0721      *
0722      * You do not need a DImg object of the file to retrieve the unique hash;
0723      * Use the static method and pass just the file path.
0724      */
0725     QByteArray getUniqueHashV2();
0726     static QByteArray getUniqueHashV2(const QString& filePath);
0727 
0728     /**
0729      * This method creates a new 256-bit UUID meant to be globally unique.
0730      * The UUID will be returned as a 64-byte hexadecimal string.
0731      * At least 128bits of the UUID will be created by the platform random number
0732      * generator. The rest may be created from a content-based hash similar to the uniqueHash, see above.
0733      * This method only generates a new UUID for this image without in any way changing this image object
0734      * or saving the UUID anywhere.
0735      */
0736     QByteArray createImageUniqueId();
0737 
0738     /**
0739      * Helper method to translate enum values to user presentable strings
0740      */
0741     static QString colorModelToString(COLORMODEL colorModel);
0742 
0743     /**
0744      * Return true if image file is an animation, as GIFa or NMG
0745      */
0746     static bool isAnimatedImage(const QString& filePath);
0747 
0748 private:
0749 
0750     DImg(const DImg& image, uint w, uint h);
0751 
0752     void copyMetaData(const QExplicitlySharedDataPointer<Private>& src);
0753     void copyImageData(const QExplicitlySharedDataPointer<Private>& src);
0754     void setImageData(bool null, uint width, uint height, bool sixteenBit, bool alpha);
0755     void setImageDimension(uint width, uint height);
0756     size_t allocateData() const;
0757 
0758     bool clipped(int& x, int& y, int& w, int& h, uint width, uint height) const;
0759 
0760     QDateTime         creationDateFromFilesystem(const QFileInfo& fileInfo) const;
0761 
0762     static QByteArray createUniqueHash(const QString& filePath, const QByteArray& ba);
0763     static QByteArray createUniqueHashV2(const QString& filePath);
0764 
0765     void bitBlt(const uchar* const src, uchar* const dest,
0766                 int sx, int sy, int w, int h, int dx, int dy,
0767                 uint swidth, uint sheight, uint dwidth, uint dheight,
0768                 bool sixteenBit, int sdepth, int ddepth);
0769     void bitBlend(DColorComposer* const composer, uchar* const src, uchar* const dest,
0770                   int sx, int sy, int w, int h, int dx, int dy,
0771                   uint swidth, uint sheight, uint dwidth, uint dheight,
0772                   bool sixteenBit, int sdepth, int ddepth,
0773                   DColorComposer::MultiplicationFlags multiplicationFlags);
0774     void bitBlendOnColor(DColorComposer* const composer, const DColor& color,
0775                          uchar* data, int x, int y, int w, int h,
0776                          uint width, uint height, bool sixteenBit, int depth,
0777                          DColorComposer::MultiplicationFlags multiplicationFlags);
0778     bool normalizeRegionArguments(int& sx, int& sy, int& w, int& h, int& dx, int& dy,
0779                                   uint swidth, uint sheight, uint dwidth, uint dheight) const;
0780 
0781 private:
0782 
0783     QExplicitlySharedDataPointer<Private> m_priv;
0784 
0785     friend class DImgLoader;
0786 };
0787 
0788 } // namespace Digikam
0789 
0790 Q_DECLARE_OPERATORS_FOR_FLAGS(Digikam::DImg::PrepareMetadataFlags)
0791 
0792 #endif // DIGIKAM_DIMG_H