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