File indexing completed on 2024-05-12 15:59:04
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 #include "Channel.h" 0007 0008 #include <QByteArray> 0009 #include <QDataStream> 0010 0011 #include <KoColorModelStandardIds.h> 0012 #include <KoConfig.h> 0013 #include <KoColorSpaceRegistry.h> 0014 #include <KoColorSpace.h> 0015 #include <kis_sequential_iterator.h> 0016 #include <kis_layer.h> 0017 0018 #ifdef HAVE_OPENEXR 0019 #include <half.h> 0020 #endif 0021 0022 struct Channel::Private { 0023 Private() {} 0024 0025 KisNodeSP node; 0026 KoChannelInfo *channel {0}; 0027 0028 }; 0029 0030 Channel::Channel(KisNodeSP node, KoChannelInfo *channel, QObject *parent) 0031 : QObject(parent) 0032 , d(new Private) 0033 { 0034 d->node = node; 0035 d->channel = channel; 0036 } 0037 0038 Channel::~Channel() 0039 { 0040 delete d; 0041 } 0042 0043 0044 bool Channel::operator==(const Channel &other) const 0045 { 0046 return (d->node == other.d->node 0047 && d->channel == other.d->channel); 0048 } 0049 0050 bool Channel::operator!=(const Channel &other) const 0051 { 0052 return !(operator==(other)); 0053 } 0054 0055 0056 bool Channel::visible() const 0057 { 0058 if (!d->node || !d->channel) return false; 0059 if (!d->node->inherits("KisLayer")) return false; 0060 0061 for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) { 0062 if (d->node->colorSpace()->channels()[i] == d->channel) { 0063 KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data()); 0064 const QBitArray& flags = layer->channelFlags(); 0065 return flags.isEmpty() || flags.testBit(i); 0066 } 0067 } 0068 return false; 0069 } 0070 0071 void Channel::setVisible(bool value) 0072 { 0073 if (!d->node || !d->channel) return; 0074 if (!d->node->inherits("KisLayer")) return; 0075 0076 KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data()); 0077 QBitArray flags = layer->channelFlags(); 0078 if (flags.isEmpty()) { 0079 flags.fill(1, d->node->colorSpace()->channelCount()); 0080 } 0081 0082 for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) { 0083 if (d->node->colorSpace()->channels()[i] == d->channel) { 0084 flags.setBit(i, value); 0085 layer->setChannelFlags(flags); 0086 break; 0087 } 0088 } 0089 0090 } 0091 0092 QString Channel::name() const 0093 { 0094 return d->channel->name(); 0095 } 0096 0097 int Channel::position() const 0098 { 0099 return d->channel->pos(); 0100 } 0101 0102 int Channel::channelSize() const 0103 { 0104 return d->channel->size(); 0105 } 0106 0107 QRect Channel::bounds() const 0108 { 0109 if (!d->node || !d->channel) return QRect(); 0110 0111 QRect rect = d->node->exactBounds(); 0112 0113 KisPaintDeviceSP dev; 0114 if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) { 0115 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8()); 0116 } 0117 else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) { 0118 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha16()); 0119 } 0120 #ifdef HAVE_OPENEXR 0121 else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) { 0122 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha16f()); 0123 } 0124 #endif 0125 else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) { 0126 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha32f()); 0127 } 0128 0129 KisSequentialConstIterator srcIt(d->node->projection(), rect); 0130 KisSequentialIterator dstIt(dev, rect); 0131 0132 while(srcIt.nextPixel() && dstIt.nextPixel()) { 0133 const quint8 *srcPtr = srcIt.rawDataConst(); 0134 memcpy(dstIt.rawData(), srcPtr + d->channel->pos(), d->channel->size()); 0135 0136 } 0137 0138 if (dev) { 0139 return dev->exactBounds(); 0140 } 0141 0142 return QRect(); 0143 } 0144 0145 QByteArray Channel::pixelData(const QRect &rect) const 0146 { 0147 QByteArray ba; 0148 0149 if (!d->node || !d->channel) return ba; 0150 0151 QDataStream stream(&ba, QIODevice::WriteOnly); 0152 KisSequentialConstIterator srcIt(d->node->projection(), rect); 0153 0154 if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) { 0155 while(srcIt.nextPixel()) { 0156 stream << (quint8) *srcIt.rawDataConst() + (d->channel->pos() * d->channel->size()); 0157 } 0158 } 0159 else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) { 0160 while(srcIt.nextPixel()) { 0161 stream << (quint16) *srcIt.rawDataConst() + (d->channel->pos() * d->channel->size()); 0162 } 0163 } 0164 #ifdef HAVE_OPENEXR 0165 else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) { 0166 while(srcIt.nextPixel()) { 0167 half h = (half)*srcIt.rawDataConst() + (d->channel->pos() * d->channel->size()); 0168 stream << (float)h; 0169 } 0170 } 0171 #endif 0172 else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) { 0173 while(srcIt.nextPixel()) { 0174 stream << (float) *srcIt.rawDataConst() + (d->channel->pos() * d->channel->size()); 0175 } 0176 0177 } 0178 0179 return ba; 0180 } 0181 0182 void Channel::setPixelData(QByteArray value, const QRect &rect) 0183 { 0184 if (!d->node || !d->channel || d->node->paintDevice() == 0) return; 0185 0186 QDataStream stream(&value, QIODevice::ReadOnly); 0187 KisSequentialIterator dstIt(d->node->paintDevice(), rect); 0188 0189 if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) { 0190 while (dstIt.nextPixel()) { 0191 quint8 v; 0192 stream >> v; 0193 *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ; 0194 } 0195 } 0196 else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) { 0197 while (dstIt.nextPixel()) { 0198 quint16 v; 0199 stream >> v; 0200 *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ; 0201 } 0202 } 0203 #ifdef HAVE_OPENEXR 0204 else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) { 0205 while (dstIt.nextPixel()) { 0206 float f; 0207 stream >> f; 0208 half v = f; 0209 *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ; 0210 } 0211 0212 } 0213 #endif 0214 else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) { 0215 while (dstIt.nextPixel()) { 0216 float v; 0217 stream >> v; 0218 *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ; 0219 } 0220 } 0221 } 0222 0223 0224 0225