File indexing completed on 2024-05-12 15:58:16

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #ifndef KIS_FIXED_PAINT_DEVICE_H
0007 #define KIS_FIXED_PAINT_DEVICE_H
0008 
0009 #include <kritaimage_export.h>
0010 #include <KoColorSpace.h>
0011 #include "kis_shared.h"
0012 #include <kis_shared_ptr.h>
0013 
0014 #include <QRect>
0015 #include <QImage>
0016 #include "KisOptimizedByteArray.h"
0017 
0018 class KoColor;
0019 
0020 
0021 /**
0022  * A fixed paint device is a simple paint device that consists of an array
0023  * of bytes and a rectangle. It cannot grow, it cannot shrink, all you can
0024  * do is fill the paint device with the right bytes and use it as an argument
0025  * to KisPainter or use the bytes as an argument to KoColorSpace functions.
0026  */
0027 class KRITAIMAGE_EXPORT KisFixedPaintDevice : public KisShared
0028 {
0029 
0030 public:
0031 
0032     KisFixedPaintDevice(const KoColorSpace* colorSpace,
0033                         KisOptimizedByteArray::MemoryAllocatorSP allocator = KisOptimizedByteArray::MemoryAllocatorSP());
0034     virtual ~KisFixedPaintDevice();
0035 
0036     /**
0037      * Deep copy the fixed paint device, including the data.
0038      */
0039     KisFixedPaintDevice(const KisFixedPaintDevice& rhs);
0040 
0041     /**
0042      * Deep copy the fixed paint device, including the data.
0043      */
0044     KisFixedPaintDevice& operator=(const KisFixedPaintDevice& rhs);
0045 
0046     /**
0047      * setRect sets the rect of the fixed paint device to rect.
0048      * This will _not_ create the associated data area.
0049      *
0050      * @param rc the bounds in pixels. The x,y of the rect represent the origin
0051      * of the fixed paint device.
0052      */
0053     void setRect(const QRect& rc);
0054 
0055     /**
0056      * setColorSpace reassigns the color space of the paint device
0057      * **without** converting or reallocating the buffer. One needs
0058      * to update the buffer manually after that.
0059      */
0060     void setColorSpace(const KoColorSpace *cs);
0061 
0062     /**
0063      * @return the rect that the data represents
0064      */
0065     QRect bounds() const;
0066 
0067     /**
0068      * @return the amount of allocated pixels (you can fake the size with setRect/bounds)
0069      * It is useful to know the accumulated memory size in pixels (not in bytes) for optimizations to avoid re-allocation.
0070      */
0071     int allocatedPixels() const;
0072 
0073 
0074     /**
0075      * @return the pixelSize associated with this fixed paint device.
0076      */
0077     quint32 pixelSize() const;
0078 
0079     const KoColorSpace* colorSpace() const {
0080         return m_colorSpace;
0081     }
0082 
0083     /**
0084      * initializes the paint device.
0085      *
0086      * @param defaultValue the default byte with which all pixels will be filled.
0087      * @return false if the allocation failed.
0088      */
0089     bool initialize(quint8 defaultValue = 0);
0090 
0091     /**
0092      * Changed the size of the internal buffer to accommodate the exact number of bytes
0093      * needed to store area bounds(). The allocated data is *not* initialized!
0094      */
0095     void reallocateBufferWithoutInitialization();
0096 
0097     /**
0098      * If the size of the internal buffer is smaller than the one needed to accommodate
0099      * bounds(), resize the buffer. Otherwise, do nothing. The allocated data is neither
0100      * copying or initialized!
0101      */
0102     void lazyGrowBufferWithoutInitialization();
0103 
0104     /**
0105      * @return a pointer to the beginning of the data associated with this fixed paint device.
0106      */
0107     quint8* data();
0108 
0109     const quint8* constData() const;
0110 
0111     quint8* data() const;
0112 
0113     /**
0114      * Read the bytes representing the rectangle described by x, y, w, h into
0115      * data. If data is not big enough, Krita will gladly overwrite the rest
0116      * of your precious memory.
0117      *
0118      * Since this is a copy, you need to make sure you have enough memory.
0119      *
0120      * The reading is done only if the rectangular area x,y,w,h is inside the bounds of the device
0121      * and the device is not empty
0122      */
0123     void readBytes(quint8 * dstData, qint32 x, qint32 y, qint32 w, qint32 h) const;
0124 
0125     /**
0126      *   Converts the paint device to a different colorspace
0127      */
0128     void convertTo(const KoColorSpace * dstColorSpace = 0,
0129                    KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(),
0130                    KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags());
0131 
0132     /**
0133      * Set color profile for the device without converting actual pixel data
0134      */
0135     void setProfile(const KoColorProfile *profile);
0136 
0137     /**
0138      * Fill this paint device with the data from image
0139      *
0140      * @param image the image
0141      * @param srcProfileName name of the RGB profile to interpret the image as. 0 is interpreted as sRGB
0142      */
0143     virtual void convertFromQImage(const QImage& image, const QString &srcProfileName);
0144 
0145     /**
0146      * Create an RGBA QImage from a rectangle in the paint device.
0147      *
0148      * @param dstProfile RGB profile to use in conversion. May be 0, in which
0149      * case it's up to the color strategy to choose a profile (most
0150      * like sRGB).
0151      * @param x Left coordinate of the rectangle
0152      * @param y Top coordinate of the rectangle
0153      * @param w Width of the rectangle in pixels
0154      * @param h Height of the rectangle in pixels
0155      * @param renderingIntent Rendering intent
0156      * @param conversionFlags Conversion flags
0157      */
0158     virtual QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h,
0159                                    KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(),
0160                                    KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()) const;
0161 
0162     /**
0163      * Create an RGBA QImage from a rectangle in the paint device. The
0164      * rectangle is defined by the parent image's bounds.
0165      *
0166      * @param dstProfile RGB profile to use in conversion. May be 0, in which
0167      * case it's up to the color strategy to choose a profile (most
0168      * like sRGB).
0169      * @param renderingIntent The rendering intent of conversion.
0170      * @param conversionFlags The conversion flags.
0171      */
0172     virtual QImage convertToQImage(const KoColorProfile *dstProfile,
0173                                    KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(),
0174                                    KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags()) const;
0175 
0176     /**
0177      * Clear the given rectangle to transparent black.
0178      *
0179      * XXX: this will not (yet) expand the paint device to contain the specified rect
0180      * but if the paintdevice has not been initialized, it will be.
0181      */
0182     void clear(const QRect & rc);
0183 
0184     /**
0185      * Fill the given rectangle with the given pixel. This does not take the
0186      * selection into account.
0187      *
0188      * XXX: this will not (yet) expand the paint device to contain the specified rect
0189      * but if the paintdevice has not been initialized, it will be.
0190      */
0191     void fill(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *fillPixel);
0192 
0193     void fill(const QRect &rc, const KoColor &color);
0194 
0195 
0196     /**
0197      * Mirrors the device.
0198      */
0199     void mirror(bool horizontal, bool vertical);
0200 
0201 private:
0202 
0203     const KoColorSpace* m_colorSpace;
0204     QRect m_bounds;
0205     KisOptimizedByteArray m_data;
0206 };
0207 
0208 #endif