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

0001 /*
0002  *  SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_CROSS_DEVICE_COLOR_SAMPLER_H
0008 #define __KIS_CROSS_DEVICE_COLOR_SAMPLER_H
0009 
0010 #include "KoColorSpace.h"
0011 #include "kis_random_sub_accessor.h"
0012 
0013 
0014 struct SamplerTraitReal {
0015     typedef qreal coord_type;
0016     typedef KisRandomSubAccessorSP accessor_type;
0017     static inline accessor_type createAccessor(KisPaintDeviceSP dev) {
0018         return dev->createRandomSubAccessor();
0019     }
0020 
0021     template <bool useOldData>
0022     static inline void sampleData(accessor_type accessor, quint8 *data, const KoColorSpace*) {
0023         if (useOldData) {
0024             accessor->sampledOldRawData(data);
0025         } else {
0026             accessor->sampledRawData(data);
0027         }
0028     }
0029 };
0030 
0031 struct SamplerTraitInt {
0032     typedef int coord_type;
0033     typedef KisRandomConstAccessorSP accessor_type;
0034     static inline accessor_type createAccessor(KisPaintDeviceSP dev) {
0035         return dev->createRandomConstAccessorNG();
0036     }
0037 
0038     template <bool useOldData>
0039     static inline void sampleData(accessor_type accessor, quint8 *data, const KoColorSpace *cs) {
0040         if (useOldData) {
0041             memcpy(data, accessor->oldRawData(), cs->pixelSize());
0042         } else {
0043             memcpy(data, accessor->rawDataConst(), cs->pixelSize());
0044         }
0045     }
0046 };
0047 
0048 /**
0049  * The sampler class is supposed to help to sample color from one device
0050  * and automatically convert it to the color space of another device
0051  *
0052  * WARNING: Please note, that if you want to access correct rawData(),
0053  *          you shouldn't store the sampler class (as well as any
0054  *          random accessor class) across different calls to
0055  *          paintAt. This is related to the fact that
0056  *          KisRandomAccessor has an internal cache of the tiles, but
0057  *          any tile may become 'old' with the time, so you'll end up
0058  *          reading from the old tile instead of current one.
0059  */
0060 
0061 template <class Traits>
0062 class KisCrossDeviceColorSamplerImpl
0063 {
0064 public:
0065     KisCrossDeviceColorSamplerImpl(KisPaintDeviceSP src, KisPaintDeviceSP dst) {
0066         init(src, dst);
0067     }
0068 
0069     KisCrossDeviceColorSamplerImpl(KisPaintDeviceSP src, KisFixedPaintDeviceSP dst) {
0070         init(src, dst);
0071     }
0072 
0073     KisCrossDeviceColorSamplerImpl(KisPaintDeviceSP src, const KoColor &dst) {
0074         init(src, &dst);
0075     }
0076 
0077     ~KisCrossDeviceColorSamplerImpl() {
0078         delete[] m_data;
0079     }
0080 
0081     inline void sampleColor(typename Traits::coord_type x,
0082                           typename Traits::coord_type y,
0083                           quint8 *dst) {
0084         sampleColorImpl<false>(x, y, dst);
0085     }
0086 
0087     inline void sampleOldColor(typename Traits::coord_type x,
0088                              typename Traits::coord_type y,
0089                              quint8 *dst) {
0090         sampleColorImpl<true>(x, y, dst);
0091     }
0092 
0093 private:
0094     template <typename T>
0095     inline void init(KisPaintDeviceSP src, T dst) {
0096         m_srcCS = src->colorSpace();
0097         m_dstCS = dst->colorSpace();
0098         m_data = new quint8[m_srcCS->pixelSize()];
0099 
0100         m_accessor = Traits::createAccessor(src);
0101     }
0102 
0103     template <bool useOldData>
0104     inline void sampleColorImpl(typename Traits::coord_type x,
0105                               typename Traits::coord_type y,
0106                               quint8 *dst) {
0107         m_accessor->moveTo(x, y);
0108 
0109         Traits::template sampleData<useOldData>(m_accessor, m_data, m_srcCS);
0110 
0111         m_srcCS->convertPixelsTo(m_data, dst, m_dstCS, 1,
0112                                  KoColorConversionTransformation::internalRenderingIntent(),
0113                                  KoColorConversionTransformation::internalConversionFlags());
0114     }
0115 
0116 private:
0117     const KoColorSpace *m_srcCS;
0118     const KoColorSpace *m_dstCS;
0119     typename Traits::accessor_type m_accessor;
0120     quint8 *m_data;
0121 };
0122 
0123 typedef KisCrossDeviceColorSamplerImpl<SamplerTraitReal> KisCrossDeviceColorSampler;
0124 typedef KisCrossDeviceColorSamplerImpl<SamplerTraitInt> KisCrossDeviceColorSamplerInt;
0125 
0126 #endif /* __KIS_CROSS_DEVICE_COLOR_SAMPLER_H */