1 /* ============================================================ 2 * 3 * This file is a part of digiKam project 4 * https://www.digikam.org 5 * 6 * Date : 2005-06-14 7 * Description : digiKam 8/16 bits image management API 8 * 9 * Copyright (C) 2005 by Renchi Raju <renchi dot raju at gmail dot com> 10 * Copyright (C) 2005-2021 by Gilles Caulier <caulier dot gilles at gmail dot com> 11 * Copyright (C) 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 12 * 13 * This program is free software; you can redistribute it 14 * and/or modify it under the terms of the GNU General 15 * Public License as published by the Free Software Foundation; 16 * either version 2, or (at your option) 17 * any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * ============================================================ */ 25 26 #ifndef DIGIKAM_DIMG_H 27 #define DIGIKAM_DIMG_H 28 29 // Qt includes 30 31 #include <QExplicitlySharedDataPointer> 32 #include <QByteArray> 33 #include <QFileInfo> 34 #include <QFlags> 35 #include <QSize> 36 #include <QRect> 37 #include <QVariant> 38 39 // Local includes 40 41 #include "digikam_export.h" 42 #include "drawdecoding.h" 43 #include "dcolor.h" 44 #include "dcolorcomposer.h" 45 #include "historyimageid.h" 46 #include "iccprofile.h" 47 #include "metaengine_data.h" 48 49 class QImage; 50 class QPixmap; 51 52 namespace Digikam 53 { 54 55 class ExposureSettingsContainer; 56 class DImageHistory; 57 class FilterAction; 58 class IccTransform; 59 class DImgLoaderObserver; 60 61 class DIGIKAM_EXPORT DImg 62 { 63 public: 64 65 enum FORMAT 66 { 67 /** 68 * NOTE: Order is important here: 69 * See filesaveoptionbox.cpp which use these values to fill a stack of widgets. 70 */ 71 NONE = 0, 72 JPEG, 73 PNG, 74 TIFF, 75 JP2K, 76 PGF, 77 HEIF, 78 // Others file formats. 79 RAW, 80 QIMAGE ///< QImage or ImageMagick 81 }; 82 83 enum ANGLE 84 { 85 ROT90 = 0, 86 ROT180, 87 ROT270, 88 ROTNONE 89 }; 90 91 enum FLIP 92 { 93 HORIZONTAL = 0, 94 VERTICAL 95 }; 96 97 enum COLORMODEL 98 { 99 COLORMODELUNKNOWN = 0, 100 RGB, 101 GRAYSCALE, 102 MONOCHROME, 103 INDEXED, 104 YCBCR, 105 CMYK, 106 CIELAB, 107 COLORMODELRAW 108 }; 109 110 public: 111 112 /** 113 * Identify file format 114 */ 115 static FORMAT fileFormat(const QString& filePath); 116 117 static QString formatToMimeType(FORMAT frm); 118 119 public: 120 121 class Private; 122 123 public: 124 125 /** 126 * Create null image 127 */ 128 DImg(); 129 130 /** 131 * Load image using QByteArray as file path 132 */ 133 explicit DImg(const QByteArray& filePath, DImgLoaderObserver* const observer = nullptr, 134 const DRawDecoding& rawDecodingSettings = DRawDecoding()); 135 136 /** 137 * Load image using QString as file path 138 */ 139 explicit DImg(const QString& filePath, DImgLoaderObserver* const observer = nullptr, 140 const DRawDecoding& rawDecodingSettings = DRawDecoding()); 141 142 /** 143 * Copy image: Creates a shallow copy that refers to the same shared data. 144 * The two images will be equal. Call detach() or copy() to create deep copies. 145 */ 146 DImg(const DImg& image); 147 148 /** 149 * Copy image: Creates a copy of a QImage object. If the QImage is null, a 150 * null DImg will be created. 151 */ 152 explicit DImg(const QImage& image); 153 154 /** 155 * Create image from data. 156 * If data is 0, a new buffer will be allocated, otherwise the given data will be used: 157 * If copydata is true, the data will be copied to a newly allocated buffer. 158 * If copyData is false, this DImg object will take ownership of the data pointer. 159 * If there is an alpha channel, the data shall be in non-premultiplied form (unassociated alpha). 160 */ 161 DImg(uint width, uint height, bool sixteenBit, bool alpha = false, uchar* const data = nullptr, bool copyData = true); 162 163 ~DImg(); 164 165 /** 166 * Equivalent to the copy constructor 167 */ 168 DImg& operator=(const DImg& image); 169 170 /** Detaches from shared data and makes sure that this image 171 * is the only one referring to the data. 172 * If multiple images share common data, this image makes a copy 173 * of the data and detaches itself from the sharing mechanism. 174 * Nothing is done if there is just a single reference. 175 */ 176 void detach(); 177 178 /** Returns whether two images are equal. 179 * Two images are equal if and only if they refer to the same shared data. 180 * (Thus, DImg() == DImg() is not true, both instances refer two their 181 * own shared data. image == DImg(image) is true.) 182 * If two or more images refer to the same data, they have the same 183 * image data, bits() returns the same data, they have the same metadata, 184 * and a change to one image also affects the others. 185 * Call detach() to split one image from the group of equal images. 186 */ 187 bool operator==(const DImg& image) const; 188 189 /** 190 * Replaces image data of this object. Metadata is unchanged. Parameters like constructor above. 191 */ 192 void putImageData(uint width, uint height, bool sixteenBit, bool alpha, uchar* const data, bool copyData = true); 193 194 /** 195 * Overloaded function, provided for convenience, behaves essentially 196 * like the function above if data is not 0. 197 * Uses current width, height, sixteenBit, and alpha values. 198 * If data is 0, the current data is deleted and the image is set to null 199 * (But metadata unchanged). 200 */ 201 void putImageData(uchar* const data, bool copyData = true); 202 203 /** 204 * Reset metadata and image data to null image 205 */ 206 void reset(); 207 208 /** 209 * Reset metadata, but do not change image data 210 */ 211 void resetMetaData(); 212 213 /** 214 * Returns the data of this image. 215 * Ownership of the buffer is passed to the caller, this image will be null afterwards. 216 */ 217 uchar* stripImageData(); 218 219 bool load(const QString& filePath, DImgLoaderObserver* const observer = nullptr, 220 const DRawDecoding& rawDecodingSettings = DRawDecoding()); 221 222 bool load(const QString& filePath, 223 bool loadMetadata, bool loadICCData, bool loadUniqueHash, bool loadHistory, 224 DImgLoaderObserver* const observer = nullptr, 225 const DRawDecoding& rawDecodingSettings = DRawDecoding()); 226 227 bool load(const QString& filePath, int loadFlags, DImgLoaderObserver* const observer, 228 const DRawDecoding& rawDecodingSettings = DRawDecoding()); 229 230 bool save(const QString& filePath, FORMAT frm, DImgLoaderObserver* const observer = nullptr); 231 bool save(const QString& filePath, const QString& format, DImgLoaderObserver* const observer = nullptr); 232 233 /** 234 * It is common that images are not directly saved to the destination path. 235 * For this reason, save() does not call addAsReferredImage(), and the stored 236 * save path may be wrong. 237 * Call this method after save() with the final destination path. 238 * This path will be stored in the image history as well. 239 */ 240 void imageSavedAs(const QString& savePath); 241 242 /** 243 * Loads most parts of the meta information, but never the image data. 244 * If loadMetadata is true, the metadata will be available with getComments, getExif, getIptc, getXmp . 245 * If loadICCData is true, the ICC profile will be available with getICCProfile. 246 */ 247 bool loadItemInfo(const QString& filePath, bool loadMetadata = true, 248 bool loadICCData = true, bool loadUniqueHash = true, 249 bool loadImageHistory = true); 250 251 bool isNull() const; 252 uint width() const; 253 uint height() const; 254 QSize size() const; 255 uchar* copyBits() const; 256 uchar* bits() const; 257 uchar* scanLine(uint i) const; 258 bool hasAlpha() const; 259 bool sixteenBit() const; 260 quint64 numBytes() const; 261 quint64 numPixels() const; 262 263 /** 264 * Return the number of bytes depth of one pixel : 4 (non sixteenBit) or 8 (sixteen) 265 */ 266 int bytesDepth() const; 267 268 /** 269 * Return the number of bits depth of one color component for one pixel : 8 (non sixteenBit) or 16 (sixteen) 270 */ 271 int bitsDepth() const; 272 273 /** 274 * Returns the file path from which this DImg was originally loaded. 275 * Returns a null string if the DImg was not loaded from a file. 276 */ 277 QString originalFilePath() const; 278 279 /** 280 * Returns the file path to which this DImg was saved. 281 * Returns the file path set with imageSavedAs(), if that was not called, 282 * save(), if that was not called, a null string. 283 */ 284 QString lastSavedFilePath() const; 285 286 /** 287 * Returns the color model in which the image was stored in the file. 288 * The color space of the loaded image data is always RGB. 289 */ 290 COLORMODEL originalColorModel() const; 291 292 /** 293 * Returns the bit depth (in bits per channel, e.g. 8 or 16) of the original file. 294 */ 295 int originalBitDepth() const; 296 297 /** 298 * Returns the size of the original file. 299 */ 300 QSize originalSize() const; 301 302 /** 303 * Returns the size of the original file 304 * in the same aspect ratio as size(). 305 */ 306 QSize originalRatioSize() const; 307 308 /** 309 * Returns the file format in form of the FORMAT enum that was detected in the load() 310 * method. Other than the format attribute which is written by the DImgLoader, 311 * this can include the QIMAGE or NONE values. 312 * Returns NONE for images that have not been loaded. 313 * For unknown image formats, a value of QIMAGE can be returned to indicate that the 314 * QImage-based loader will have been used. To find out if this has worked, check 315 * the return value you got from load(). 316 */ 317 FORMAT detectedFormat() const; 318 319 /** 320 * Returns the format string as written by the image loader this image was originally 321 * loaded from. Format strings used include JPEG, PNG, TIFF, PGF, JP2K, RAW, PPM. 322 * For images loaded with the platform QImage loader, the file suffix is used. 323 * Returns null if this DImg was not loaded from a file, but created in memory. 324 */ 325 QString format() const; 326 327 /** 328 * Returns the format string of the format that this image was last saved to. 329 * An image can be loaded from a file - retrieve that format with fileFormat() 330 * and loadedFormat() - and can the multiple times be saved to different formats. 331 * Format strings used include JPG, PGF, PNG, TIFF and JP2K. 332 * If this file was not save, a null string is returned. 333 */ 334 QString savedFormat() const; 335 336 /** 337 * Returns the DRawDecoding options that this DImg was loaded with. 338 * If this is not a RAW image or no options were specified, returns DRawDecoding(). 339 */ 340 DRawDecoding rawDecodingSettings() const; 341 342 /** 343 * Access a single pixel of the image. 344 * These functions add some safety checks and then use the methods from DColor. 345 * In optimized code working directly on the data, 346 * better use the inline methods from DColor. 347 */ 348 DColor getPixelColor(uint x, uint y) const; 349 void setPixelColor(uint x, uint y, const DColor& color); 350 void prepareSubPixelAccess(); 351 DColor getSubPixelColor(float x, float y) const; 352 DColor getSubPixelColorFast(float x, float y) const; 353 354 /** 355 * If the image has an alpha channel, check if there exist pixels 356 * which actually have non-opaque color, that is alpha < 1.0. 357 * Note that all pixels are scanned to reach a return value of "false". 358 * If hasAlpha() is false, always returns false. 359 */ 360 bool hasTransparentPixels() const; 361 362 /** 363 * Return true if the original image file format cannot be saved. 364 * This is depending of DImgLoader::save() implementation. For example 365 * RAW file formats are supported by DImg using dcraw than cannot support 366 * writing operations. 367 */ 368 bool isReadOnly() const; 369 370 /** 371 * Metadata manipulation methods 372 */ 373 MetaEngineData getMetadata() const; 374 IccProfile getIccProfile() const; 375 void setMetadata(const MetaEngineData& data); 376 void setIccProfile(const IccProfile& profile); 377 378 void setAttribute(const QString& key, const QVariant& value); 379 QVariant attribute(const QString& key) const; 380 bool hasAttribute(const QString& key) const; 381 void removeAttribute(const QString& key); 382 383 void setEmbeddedText(const QString& key, const QString& text); 384 QString embeddedText(const QString& key) const; 385 386 const DImageHistory& getItemHistory() const; 387 DImageHistory& getItemHistory(); 388 void setItemHistory(const DImageHistory& history); 389 bool hasImageHistory() const; 390 DImageHistory getOriginalImageHistory() const; 391 void addFilterAction(const FilterAction& action); 392 393 /** 394 * Sets a step in the history to constitute the beginning of a branch. 395 * Use setHistoryBranch() to take getOriginalImageHistory() and set the first added step as a branch. 396 * Use setHistoryBranchForLastSteps(n) to start the branch before the last n steps in the history. 397 * (Assume the history had 3 steps and you added 2, call setHistoryBranchForLastSteps(2)) 398 * Use setHistoryBranchAfter() if have a copy of the history before branching, 399 * the first added step on top of that history will be made a branch. 400 */ 401 void setHistoryBranchAfter(const DImageHistory& historyBeforeBranch, bool isBranch = true); 402 void setHistoryBranchForLastSteps(int numberOfLastHistorySteps, bool isBranch = true); 403 void setHistoryBranch(bool isBranch = true); 404 405 /** 406 * When saving, several changes to the image metadata are necessary 407 * before it can safely be written to the new file. 408 * This method updates the stored meta engine object in preparation to a subsequent 409 * call to save() with the same target file. 410 * 'intendedDestPath' is the finally intended file name. Do not give the temporary 411 * file name if you are going to save() to a temp file. 412 * 'destMimeType' is destination type mime. In some cases, metadata is updated depending on this value. 413 * 'originalFileName' is the original file's name, for simplistic history tracking in metadata. 414 * This is completely independent from the DImageHistory framework. 415 * For the 'flags' see below. 416 * Not all steps are optional and can be controlled with flags. 417 */ 418 enum PrepareMetadataFlag 419 { 420 /** 421 * A small preview can be stored in the metadata. 422 * Remove old preview entries 423 */ 424 RemoveOldMetadataPreviews = 1 << 0, 425 /** 426 * Create a new preview from current image data. 427 */ 428 CreateNewMetadataPreview = 1 << 1, 429 /** 430 * Set the exif orientation tag to "normal" 431 * Applicable if the image data was rotated according to the tag 432 */ 433 ResetExifOrientationTag = 1 << 2, 434 /** 435 * Creates a new UUID for the image history. 436 * Applicable if the file was changed. 437 */ 438 CreateNewImageHistoryUUID = 1 << 3, 439 440 PrepareMetadataFlagsAll = RemoveOldMetadataPreviews | 441 CreateNewMetadataPreview | 442 ResetExifOrientationTag | 443 CreateNewImageHistoryUUID 444 }; 445 Q_DECLARE_FLAGS(PrepareMetadataFlags, PrepareMetadataFlag) 446 447 void prepareMetadataToSave(const QString& intendedDestPath, 448 const QString& destMimeType, 449 const QString& originalFileName = QString(), 450 PrepareMetadataFlags flags = PrepareMetadataFlagsAll); 451 452 /** 453 * For convenience: Including all flags, except for ResetExifOrientationTag which can be selected. 454 * Uses originalFilePath() to fill the original file name. 455 */ 456 void prepareMetadataToSave(const QString& intendedDestPath, 457 const QString& destMimeType, 458 bool resetExifOrientationTag); 459 460 /** 461 * Create a HistoryImageId for _this_ image _already_ saved at the given file path. 462 */ 463 HistoryImageId createHistoryImageId(const QString& filePath, HistoryImageId::Type type); 464 465 /** 466 * If you have saved this DImg to filePath, and want to continue using this DImg object 467 * to add further changes to the image history, you can call this method to add to the image history 468 * a reference to the just saved image. 469 * First call updateMetadata(), then call save(), then call addAsReferredImage(). 470 * Do not call this directly after loading, before applying any changes: 471 * The history is correctly initialized when loading. 472 * If you need to insert the referred file to an entry which is not the last entry, 473 * which may happen if the added image was saved after this image's history was created, 474 * you can use insertAsReferredImage. 475 * The added id is returned. 476 */ 477 HistoryImageId addAsReferredImage(const QString& filePath, HistoryImageId::Type type = HistoryImageId::Intermediate); 478 void addAsReferredImage(const HistoryImageId& id); 479 void insertAsReferredImage(int afterHistoryStep, const HistoryImageId& otherImagesId); 480 481 /** 482 * In the history, adjusts the UUID of the ImageHistoryId of the current file. 483 * Call this if you have associated a UUID with this file which is not written to the metadata. 484 * If there is already a UUID present, read from metadata, it will not be replaced. 485 */ 486 void addCurrentUniqueImageId(const QString& uuid); 487 488 /** 489 * Retrieves the Exif orientation, either from the LoadSaveThread info provider if available, 490 * or from the metadata 491 */ 492 int exifOrientation(const QString& filePath); 493 494 /** 495 * When loaded from a file, some attributes like format and isReadOnly still depend on this 496 * originating file. When saving in a different format to a different file, 497 * you may wish to switch these attributes to the new file. 498 * - fileOriginData() returns the current origin data, bundled in the returned QVariant. 499 * - setFileOriginData() takes such a variant and adjusts the properties 500 * - lastSavedFileOriginData() returns the origin data as if the image was loaded from 501 * the last saved image. 502 * - switchOriginToLastSaved is equivalent to setting origin data returned from lastSavedFileOriginData() 503 * 504 * Example: an image loaded from a RAW and saved to PNG will be read-only and format RAW. 505 * After calling switchOriginToLastSaved, it will not be read-only, format will be PNG, 506 * and rawDecodingSettings will be null. detectedFormat() will not change. 507 * In the history, the last referred image that was added (as intermediate) is made 508 * the new Current image. 509 * NOTE: Set the saved image path with imageSavedAs() before! 510 */ 511 QVariant fileOriginData() const; 512 void setFileOriginData(const QVariant& data); 513 QVariant lastSavedFileOriginData() const; 514 void switchOriginToLastSaved(); 515 516 /** 517 * Return a deep copy of full image 518 */ 519 DImg copy() const; 520 521 /** 522 * Return a deep copy of the image, but do not include metadata. 523 */ 524 DImg copyImageData() const; 525 526 /** 527 * Return an image that contains a deep copy of 528 * this image's metadata and the information associated 529 * with the image data (width, height, hasAlpha, sixteenBit), 530 * but no image data, i.e. isNull() is true. 531 */ 532 DImg copyMetaData() const; 533 534 /** 535 * Return a region of image 536 */ 537 DImg copy(const QRect& rect) const; 538 DImg copy(const QRectF& relativeRect) const; 539 DImg copy(int x, int y, int w, int h) const; 540 541 /** 542 * Copy a region of pixels from a source image to this image. 543 * Parameters: 544 * sx|sy Coordinates in the source image of the rectangle to be copied 545 * w h Width and height of the rectangle (Default, or when both are -1: whole source image) 546 * dx|dy Coordinates in this image of the rectangle in which the region will be copied 547 * (Default: 0|0) 548 * The bit depth of source and destination must be identical. 549 */ 550 void bitBltImage(const DImg* const src, int dx, int dy); 551 void bitBltImage(const DImg* const src, int sx, int sy, int dx, int dy); 552 void bitBltImage(const DImg* const src, int sx, int sy, int w, int h, int dx, int dy); 553 void bitBltImage(const uchar* const src, int sx, int sy, int w, int h, int dx, int dy, 554 uint swidth, uint sheight, int sdepth); 555 556 /** 557 * Blend src image on this image (this is dest) with the specified composer 558 * and multiplication flags. See documentation of DColorComposer for more info. 559 * For the other arguments, see documentation of bitBltImage above. 560 */ 561 void bitBlendImage(DColorComposer* const composer, const DImg* const src, 562 int sx, int sy, int w, int h, int dx, int dy, 563 DColorComposer::MultiplicationFlags multiplicationFlags = 564 DColorComposer::NoMultiplication); 565 566 /** 567 * For the specified region, blend this image on the given color with the specified 568 * composer and multiplication flags. See documentation of DColorComposer for more info. 569 * Note that the result pixel is again written to this image, which is, for the blending, source. 570 */ 571 void bitBlendImageOnColor(DColorComposer* const composer, const DColor& color, 572 int x, int y, int w, int h, 573 DColorComposer::MultiplicationFlags multiplicationFlags = 574 DColorComposer::NoMultiplication); 575 void bitBlendImageOnColor(const DColor& color, int x, int y, int w, int h); 576 void bitBlendImageOnColor(const DColor& color); 577 578 /** 579 * QImage wrapper methods 580 */ 581 QImage copyQImage() const; 582 QImage copyQImage(const QRect& rect) const; 583 QImage copyQImage(const QRectF& relativeRect) const; 584 QImage copyQImage(int x, int y, int w, int h) const; 585 586 /** 587 * Crop image to the specified region 588 */ 589 void crop(const QRect& rect); 590 void crop(int x, int y, int w, int h); 591 592 /** 593 * Set width and height of this image, smoothScale it to the given size 594 */ 595 void resize(int w, int h); 596 597 /** 598 * If the image has an alpha channel and transparent pixels, 599 * it will be blended on the specified color and the alpha channel will be removed. 600 * This is a no-op if hasTransparentPixels() is false, but this method can be expensive, 601 * therefore it is _not_ checked inside removeAlphaChannel(). 602 * (the trivial hasAlpha() is checked) 603 */ 604 void removeAlphaChannel(const DColor& destColor); 605 void removeAlphaChannel(); 606 607 /** 608 * Return a version of this image scaled to the specified size with the specified mode. 609 * See QSize documentation for information on available modes 610 */ 611 DImg smoothScale(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio) const; 612 DImg smoothScale(const QSize& destSize, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio) const; 613 614 /** 615 * Executes the same scaling as smoothScale(width, height), but from the result of this call, 616 * returns only the section specified by clipx, clipy, clipwidth, clipheight. 617 * This is thus equivalent to calling 618 * Dimg scaled = smoothScale(width, height); scaled.crop(clipx, clipy, clipwidth, clipheight); 619 * but potentially much faster. 620 * In smoothScaleSection, you specify the source region, here, the result region. 621 * It will often not be possible to find _integer_ source coordinates for a result region! 622 */ 623 DImg smoothScaleClipped(int width, int height, int clipx, int clipy, int clipwidth, int clipheight) const; 624 DImg smoothScaleClipped(const QSize& destSize, const QRect& clip) const; 625 626 /** 627 * Take the region specified by the rectangle sx|sy, width and height sw * sh, 628 * and scale it to an image with size dw * dh 629 */ 630 DImg smoothScaleSection(int sx, int sy, int sw, int sh, int dw, int dh) const; 631 DImg smoothScaleSection(const QRect& sourceRect, const QSize& destSize) const; 632 633 void rotate(ANGLE angle); 634 void flip(FLIP direction); 635 636 /** 637 * Rotates and/or flip the DImg according to the given DMetadata::Orientation, 638 * so that the current state is orientation and the resulting step is normal orientation. 639 * Returns true if the image was actually rotated or flipped (e.g. if ORIENTATION_NORMAL 640 * is given, returns false, because no action is taken). 641 */ 642 bool rotateAndFlip(int orientation); 643 644 /** 645 * Reverses the previous function. 646 */ 647 bool reverseRotateAndFlip(int orientation); 648 649 /** 650 * Utility to make sure that an image is rotated according to Exif tag. 651 * Detects if an image has previously already been rotated: You can 652 * call this method more than one time on the same image. 653 * Returns true if the image has actually been rotated or flipped. 654 * Returns false if a rotation was not needed. 655 */ 656 bool wasExifRotated(); 657 bool exifRotate(const QString& filePath); 658 659 /** 660 * Reverses the previous function 661 */ 662 bool reverseExifRotate(const QString& filePath); 663 664 /** 665 * Returns current DMetadata::Orientation from DImg 666 */ 667 int orientation() const; 668 669 /** Rotates and/or flip the DImg according to the given transform action, 670 * which is a MetaEngineRotation::TransformAction. 671 * Returns true if the image was actually rotated or flipped. 672 */ 673 bool transform(int transformAction); 674 675 QPixmap convertToPixmap() const; 676 QPixmap convertToPixmap(IccTransform& monitorICCtrans) const; 677 678 /** 679 * Return a mask image where pure white and pure black pixels are over-colored. 680 * This way is used to identify over and under exposed pixels. 681 */ 682 QImage pureColorMask(ExposureSettingsContainer* const expoSettings) const; 683 684 /** 685 * Convert depth of image. Depth is bytesDepth * bitsDepth. 686 * If depth is 32, converts to 8 bits, 687 * if depth is 64, converts to 16 bits. 688 */ 689 void convertDepth(int depth); 690 691 /** 692 * Wrapper methods for convertDepth 693 */ 694 void convertToSixteenBit(); 695 void convertToEightBit(); 696 void convertToDepthOfImage(const DImg* const otherImage); 697 698 /** 699 * Fill whole image with specified color. 700 * The bit depth of the color must be identical to the depth of this image. 701 */ 702 void fill(const DColor& color); 703 704 /** 705 * This methods return a 128-bit MD5 hex digest which is meant to uniquely identify 706 * the file. The hash is calculated on parts of the file and the file metadata. 707 * It cannot be used to find similar images. It is not calculated from the image data. 708 * The hash will be returned as a 32-byte hexadecimal string. 709 * 710 * If you already have a DImg object of the file, use the member method. 711 * The object does not need to have the full image data loaded, but it shall at least 712 * have been loaded with loadItemInfo with loadMetadata = true, or have the metadata 713 * set later with setComments, setExif, setIptc, setXmp. 714 * If the object does not have the metadata loaded, a non-null, but invalid hash will 715 * be returned! In this case, use the static method. 716 * If the image has been loaded with loadUniqueHash = true, the hash can be retrieved 717 * with the member method. 718 * 719 * You do not need a DImg object of the file to retrieve the unique hash; 720 * Use the static method and pass just the file path. 721 */ 722 QByteArray getUniqueHash(); 723 static QByteArray getUniqueHash(const QString& filePath); 724 725 /** 726 * This methods return a 128-bit MD5 hex digest which is meant to uniquely identify 727 * the file. The hash is calculated on parts of the file. 728 * It cannot be used to find similar images. It is not calculated from the image data. 729 * The hash will be returned as a 32-byte hexadecimal string. 730 * 731 * If you already have a DImg object loaded from the file, use the member method. 732 * If the image has been loaded with loadUniqueHash = true, the hash will already 733 * be available. 734 * 735 * You do not need a DImg object of the file to retrieve the unique hash; 736 * Use the static method and pass just the file path. 737 */ 738 QByteArray getUniqueHashV2(); 739 static QByteArray getUniqueHashV2(const QString& filePath); 740 741 /** 742 * This method creates a new 256-bit UUID meant to be globally unique. 743 * The UUID will be returned as a 64-byte hexadecimal string. 744 * At least 128bits of the UUID will be created by the platform random number 745 * generator. The rest may be created from a content-based hash similar to the uniqueHash, see above. 746 * This method only generates a new UUID for this image without in any way changing this image object 747 * or saving the UUID anywhere. 748 */ 749 QByteArray createImageUniqueId(); 750 751 /** 752 * Helper method to translate enum values to user presentable strings 753 */ 754 static QString colorModelToString(COLORMODEL colorModel); 755 756 /** 757 * Return true if image file is an animation, as GIFa or NMG 758 */ 759 static bool isAnimatedImage(const QString& filePath); 760 761 private: 762 763 DImg(const DImg& image, uint w, uint h); 764 765 void copyMetaData(const QExplicitlySharedDataPointer<Private>& src); 766 void copyImageData(const QExplicitlySharedDataPointer<Private>& src); 767 void setImageData(bool null, uint width, uint height, bool sixteenBit, bool alpha); 768 void setImageDimension(uint width, uint height); 769 size_t allocateData() const; 770 771 bool clipped(int& x, int& y, int& w, int& h, uint width, uint height) const; 772 773 QDateTime creationDateFromFilesystem(const QFileInfo& fileInfo) const; 774 775 static QByteArray createUniqueHash(const QString& filePath, const QByteArray& ba); 776 static QByteArray createUniqueHashV2(const QString& filePath); 777 778 void bitBlt(const uchar* const src, uchar* const dest, 779 int sx, int sy, int w, int h, int dx, int dy, 780 uint swidth, uint sheight, uint dwidth, uint dheight, 781 bool sixteenBit, int sdepth, int ddepth); 782 void bitBlend(DColorComposer* const composer, uchar* const src, uchar* const dest, 783 int sx, int sy, int w, int h, int dx, int dy, 784 uint swidth, uint sheight, uint dwidth, uint dheight, 785 bool sixteenBit, int sdepth, int ddepth, 786 DColorComposer::MultiplicationFlags multiplicationFlags); 787 void bitBlendOnColor(DColorComposer* const composer, const DColor& color, 788 uchar* data, int x, int y, int w, int h, 789 uint width, uint height, bool sixteenBit, int depth, 790 DColorComposer::MultiplicationFlags multiplicationFlags); 791 bool normalizeRegionArguments(int& sx, int& sy, int& w, int& h, int& dx, int& dy, 792 uint swidth, uint sheight, uint dwidth, uint dheight) const; 793 794 private: 795 796 QExplicitlySharedDataPointer<Private> m_priv; 797 798 friend class DImgLoader; 799 }; 800 801 } // namespace Digikam 802 803 Q_DECLARE_OPERATORS_FOR_FLAGS(Digikam::DImg::PrepareMetadataFlags) 804 805 #endif // DIGIKAM_DIMG_H 806