File indexing completed on 2025-07-06 04:48:05

0001 /*
0002     SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "kitinerary_export.h"
0010 
0011 #include <QExplicitlySharedDataPointer>
0012 #include <QMetaType>
0013 
0014 #include <functional>
0015 
0016 class QImage;
0017 class QTransform;
0018 
0019 namespace KItinerary {
0020 class PdfImagePrivate;
0021 class PdfImageRef;
0022 }
0023 
0024 namespace std {
0025 template<>
0026 struct hash<KItinerary::PdfImageRef>
0027 {
0028     inline std::size_t operator()(const KItinerary::PdfImageRef &ref) const noexcept;
0029 };
0030 }
0031 
0032 namespace KItinerary {
0033 
0034 /** PDF image element type. */
0035 enum class PdfImageType {
0036     Image,
0037     Mask,
0038     SMask
0039 };
0040 
0041 /** PDF object reference for an image, with the ability to address attached masks as well. */
0042 class PdfImageRef
0043 {
0044 public:
0045     constexpr PdfImageRef() = default;
0046     constexpr inline PdfImageRef(int num, int gen, PdfImageType type = PdfImageType::Image)
0047         : m_refNum(num)
0048         , m_refGen(gen)
0049         , m_type(type)
0050     {}
0051 
0052     constexpr inline bool isNull() const
0053     {
0054         return m_refNum < 0;
0055     }
0056 
0057     constexpr inline bool operator==(const PdfImageRef &other) const
0058     {
0059         return m_refNum == other.m_refNum && m_refGen == other.m_refGen && m_type == other.m_type;
0060     }
0061 
0062 private:
0063     int m_refNum = -1;
0064     int m_refGen = -1;
0065     PdfImageType m_type = PdfImageType::Image;
0066     friend class PdfImagePrivate;
0067     friend std::size_t std::hash<PdfImageRef>::operator ()(const PdfImageRef&) const noexcept;
0068 };
0069 
0070 /** An image in a PDF document.
0071  */
0072 class KITINERARY_EXPORT PdfImage
0073 {
0074     Q_GADGET
0075     Q_PROPERTY(int width READ width)
0076     Q_PROPERTY(int height READ height)
0077 public:
0078     PdfImage();
0079     PdfImage(const PdfImage&);
0080     ~PdfImage();
0081     PdfImage& operator=(const PdfImage&);
0082 
0083     /** Width of the image in PDF 1/72 dpi coordinates. */
0084     int width() const;
0085     /** Height of the image in PDF 1/72 dpi coordinates. */
0086     int height() const;
0087 
0088     /** Height of the source image. */
0089     int sourceHeight() const;
0090     /** Width of the source image. */
0091     int sourceWidth() const;
0092 
0093     /** Transformation from source image to final size/position on the page.
0094      *  Values are 1/72 inch.
0095      */
0096     QTransform transform() const;
0097 
0098     /** Hints for loading image data. */
0099     enum LoadingHint {
0100         NoHint = 0, ///< Load image data as-is. The default.
0101         AbortOnColorHint = 1, ///< Abort loading when encountering a non black/white pixel, as a shortcut for barcode detection.
0102         ConvertToGrayscaleHint = 2, ///< Convert to QImage::Format_Grayscale8 during loading. More efficient than converting later if all you need is grayscale.
0103     };
0104     Q_DECLARE_FLAGS(LoadingHints, LoadingHint)
0105 
0106     /** Sets image loading hints. */
0107     void setLoadingHints(LoadingHints hints);
0108 
0109     /** The source image without display transformations applied. */
0110     QImage image() const;
0111 
0112     /** Returns whether this image has an object id.
0113      *  Vector graphic "images" don't have that.
0114      */
0115     bool hasObjectId() const;
0116 
0117     /** PDF-internal unique identifier of this image.
0118      *  Use this to detect multiple occurrences of the same image in different
0119      *  places, if that reduces e.g. computation cost.
0120      */
0121     PdfImageRef objectId() const;
0122 
0123     /** Returns whether this is a raster or vector image. */
0124     bool isVectorImage() const;
0125 
0126     /** If this is a vector image, this returns the number
0127      *  of vector path elemets.
0128      */
0129     int pathElementsCount() const;
0130 
0131     /** Returns @c true if this image has an aspect-ratio changing transform.
0132      *  That might need to be applied before doing barcode decoding for example.
0133      */
0134     [[nodiscard]] bool hasAspectRatioTransform() const;
0135 
0136     /** Applies the aspect ratio changing part of the transform
0137      *  to the given image (which typically should be the one returned
0138      *  by image()).
0139      */
0140     [[nodiscard]] QImage applyAspectRatioTransform(const QImage &image) const;
0141 
0142 private:
0143     friend class PdfExtractorOutputDevice;
0144     friend class PdfPagePrivate;
0145     friend class PdfPage;
0146     QExplicitlySharedDataPointer<PdfImagePrivate> d;
0147 };
0148 
0149 Q_DECLARE_OPERATORS_FOR_FLAGS(PdfImage::LoadingHints)
0150 
0151 }
0152 
0153 std::size_t std::hash<KItinerary::PdfImageRef>::operator()(const KItinerary::PdfImageRef &ref) const noexcept
0154 {
0155     // first part is how poppler hashes its Ref type
0156     return std::hash<int>{}(ref.m_refNum) ^ (std::hash<int>{}(ref.m_refGen) << 1) ^ std::hash<int>{}((int)ref.m_type);
0157 }