File indexing completed on 2024-05-12 15:59:30
0001 /* 0002 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org> 0003 * SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 #ifndef KOCHANNELINFO_H_ 0008 #define KOCHANNELINFO_H_ 0009 0010 #include <limits> 0011 0012 #include <QColor> 0013 #include <QString> 0014 #include <QList> 0015 0016 /** 0017 * This class gives some basic information about a channel, 0018 * that is, one of the components that makes up a particular 0019 * pixel. 0020 */ 0021 class KoChannelInfo 0022 { 0023 public: 0024 /** 0025 * Used to represent a min and max range. 0026 */ 0027 struct DoubleRange 0028 { 0029 public: 0030 double minVal, maxVal; 0031 public: 0032 /// creates an invalid range of 0,0 0033 DoubleRange(void) : minVal(0), maxVal(0) { } 0034 /// creates 0035 DoubleRange(qreal _minVal, qreal _maxVal) : minVal(_minVal), maxVal(_maxVal) { Q_ASSERT(minVal <= maxVal); } 0036 /// true if this range is usable 0037 bool isValid(void) const { return minVal < maxVal; } 0038 }; 0039 public: 0040 /// enum to define the type of the channel 0041 enum enumChannelType { 0042 COLOR, ///< The channel represents a color 0043 ALPHA ///< The channel represents the opacity of a pixel 0044 //SUBSTANCE, ///< The channel represents a real-world substance like pigments or medium 0045 //SUBSTRATE ///< The channel represents a real-world painting substrate like a canvas 0046 }; 0047 /// enum to define the value of the channel 0048 enum enumChannelValueType { 0049 UINT8, ///< use this for an unsigned integer 8bits channel 0050 UINT16, ///< use this for an integer 16bits channel 0051 UINT32, ///< use this for an unsigned integer 21bits channel 0052 FLOAT16, ///< use this for a float 16bits channel 0053 FLOAT32, ///< use this for a float 32bits channel 0054 FLOAT64, ///< use this for a float 64bits channel 0055 INT8, ///< use this for an integer 8bits channel 0056 INT16, ///< use this for an integer 16bits channel 0057 OTHER ///< Use this if the channel is neither an integer or a float 0058 }; 0059 0060 public: 0061 KoChannelInfo() { } 0062 /** 0063 * @param name of the channel 0064 * @param npos position of the channel in the pixel (in bytes) 0065 * @param displayPosition the position of the channel in the user-visible order 0066 * @param channelType type of the channel 0067 * @param channelValueType type of the numerical data used by the channel 0068 * @param size number of bytes (not bits) of the channel (if -1, it is deduced from the channelType) 0069 * @param color a color to represent that channel (for instance in an histogram) 0070 * @param uiMinMax the UI range 0071 */ 0072 KoChannelInfo(const QString & name, 0073 qint32 npos, 0074 qint32 displayPosition, 0075 enumChannelType channelType, 0076 enumChannelValueType channelValueType, 0077 qint32 size = -1, 0078 const QColor &color = QColor(0, 0, 0), 0079 const DoubleRange &uiMinMax = DoubleRange()) 0080 : m_name(name) 0081 , m_pos(npos) 0082 , m_displayPosition(displayPosition) 0083 , m_channelType(channelType) 0084 , m_channelValueType(channelValueType) 0085 , m_size(size) 0086 , m_color(color) 0087 , m_uiMinMax(uiMinMax) 0088 { 0089 switch(m_channelValueType) 0090 { 0091 case UINT8: 0092 case INT8: 0093 Q_ASSERT(m_size == -1 || m_size == 1); 0094 m_size = 1; 0095 break; 0096 case UINT16: 0097 case INT16: 0098 Q_ASSERT(m_size == -1 || m_size == 2); 0099 m_size = 2; 0100 break; 0101 case UINT32: 0102 Q_ASSERT(m_size == -1 || m_size == 4); 0103 m_size = 4; 0104 break; 0105 case FLOAT16: 0106 Q_ASSERT(m_size == -1 || m_size == 2); 0107 m_size = 2; 0108 break; 0109 case FLOAT32: 0110 Q_ASSERT(m_size == -1 || m_size == 4); 0111 m_size = 4; 0112 break; 0113 case FLOAT64: 0114 Q_ASSERT(m_size == -1 || m_size == 8); 0115 m_size = 8; 0116 break; 0117 case OTHER: 0118 Q_ASSERT(m_size != -1); 0119 } 0120 if (!uiMinMax.isValid()) { 0121 switch (m_channelValueType) { 0122 case UINT8: 0123 m_uiMinMax.minVal = std::numeric_limits<quint8>::min(); 0124 m_uiMinMax.maxVal = std::numeric_limits<quint8>::max(); 0125 break; 0126 case INT8: 0127 m_uiMinMax.minVal = std::numeric_limits<qint8>::min(); 0128 m_uiMinMax.maxVal = std::numeric_limits<qint8>::max(); 0129 break; 0130 case UINT16: 0131 m_uiMinMax.minVal = std::numeric_limits<quint16>::min(); 0132 m_uiMinMax.maxVal = std::numeric_limits<quint16>::max(); 0133 break; 0134 case INT16: 0135 m_uiMinMax.minVal = std::numeric_limits<qint16>::min(); 0136 m_uiMinMax.maxVal = std::numeric_limits<qint16>::max(); 0137 break; 0138 case UINT32: 0139 m_uiMinMax.minVal = std::numeric_limits<quint32>::min(); 0140 m_uiMinMax.maxVal = std::numeric_limits<quint32>::max(); 0141 break; 0142 default: 0143 // assume real otherwise, which is 0..1 by default 0144 m_uiMinMax.minVal = 0.0; 0145 m_uiMinMax.maxVal = 1.0; 0146 break; 0147 } 0148 } 0149 Q_ASSERT(m_uiMinMax.isValid()); 0150 } 0151 public: 0152 0153 /** 0154 * converts the display position to the pixel-order index in the channels vector. 0155 */ 0156 static int displayPositionToChannelIndex(int displayPosition, const QList<KoChannelInfo*> &channels) 0157 { 0158 for (int i = 0; i < channels.size(); ++i) { 0159 if (channels.at(i)->displayPosition() == displayPosition) { 0160 return i; 0161 } 0162 } 0163 return -1; 0164 } 0165 0166 static QList<KoChannelInfo*> displayOrderSorted(const QList<KoChannelInfo*> &channels) 0167 { 0168 QList <KoChannelInfo*> sortedChannels; 0169 for (int i = 0; i < channels.size(); ++i) { 0170 Q_FOREACH (KoChannelInfo* channel, channels) { 0171 if (channel->displayPosition() == i) { 0172 sortedChannels << channel; 0173 break; 0174 } 0175 } 0176 } 0177 Q_ASSERT(channels.size() == sortedChannels.size()); 0178 return sortedChannels; 0179 } 0180 0181 /** 0182 * User-friendly name for this channel for presentation purposes in the gui 0183 */ 0184 inline QString name() const { 0185 return m_name; 0186 } 0187 0188 /** 0189 * @return the position of the first byte of the channel in the pixel 0190 */ 0191 inline qint32 pos() const { 0192 return m_pos; 0193 } 0194 0195 /** 0196 * @return the displayPosition of the channel in the pixel 0197 */ 0198 inline qint32 displayPosition() const { 0199 return m_displayPosition; 0200 } 0201 0202 /** 0203 * @return the number of bytes this channel takes 0204 */ 0205 inline qint32 size() const { 0206 return m_size; 0207 } 0208 0209 /** 0210 * @return the type of the channel 0211 */ 0212 inline enumChannelType channelType() const { 0213 return m_channelType; 0214 } 0215 /** 0216 * @return the type of the value of the channel (float, uint8 or uint16) 0217 */ 0218 inline enumChannelValueType channelValueType() const { 0219 return m_channelValueType; 0220 } 0221 /** 0222 * This is a color that can be used to represent this channel in histograms and so. 0223 * By default this is black, so keep in mind that many channels might look the same 0224 */ 0225 inline QColor color() const { 0226 return m_color; 0227 } 0228 0229 /** 0230 * A channel is less than another channel if its pos is smaller. 0231 */ 0232 inline bool operator<(const KoChannelInfo & info) { 0233 return m_pos < info.m_pos; 0234 } 0235 0236 /** 0237 * Gets the minimum value that this channel should have. 0238 * This is suitable for UI use. 0239 */ 0240 inline double getUIMin(void) const { 0241 return m_uiMinMax.minVal; 0242 } 0243 0244 /** 0245 * Gets the minimum value that this channel should have. 0246 * This is suitable for UI use. 0247 */ 0248 inline double getUIMax(void) const { 0249 return m_uiMinMax.maxVal; 0250 } 0251 0252 /** 0253 * @brief getUIUnitValue 0254 * Gets the unit value for this channel. 0255 * This is suitable for converting between representations. 0256 */ 0257 inline double getUIUnitValue(void) const { 0258 return m_uiMinMax.maxVal - m_uiMinMax.minVal; 0259 } 0260 0261 private: 0262 0263 QString m_name; 0264 qint32 m_pos; 0265 qint32 m_displayPosition; 0266 enumChannelType m_channelType; 0267 enumChannelValueType m_channelValueType; 0268 qint32 m_size; 0269 QColor m_color; 0270 DoubleRange m_uiMinMax; 0271 0272 }; 0273 0274 #endif // KOCHANNELINFO_H_