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