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