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 */