Krita

Channel.cpp
1/*
2 * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6#include "Channel.h"
7
8#include <cstring>
9
10#include <QByteArray>
11#include <QDataStream>
12#include <QIODevice>
13
14#include <KoColorModelStandardIds.h>
15#include <KoConfig.h>
16#include <KoColorSpaceRegistry.h>
17#include <KoColorSpace.h>
18#include <kis_sequential_iterator.h>
19#include <kis_layer.h>
20
21#ifdef HAVE_OPENEXR
22#include <half.h>
23#endif
24
25struct Channel::Private {
26 Private() {}
27
28 KisNodeSP node;
29 KoChannelInfo *channel {0};
30
31};
32
33Channel::Channel(KisNodeSP node, KoChannelInfo *channel, QObject *parent)
34 : QObject(parent)
35 , d(new Private)
36{
37 d->node = node;
38 d->channel = channel;
39}
40
41Channel::~Channel()
42{
43 delete d;
44}
45
46
47bool Channel::operator==(const Channel &other) const
48{
49 return (d->node == other.d->node
50 && d->channel == other.d->channel);
51}
52
53bool Channel::operator!=(const Channel &other) const
54{
55 return !(operator==(other));
56}
57
58
59bool Channel::visible() const
60{
61 if (!d->node || !d->channel) return false;
62 if (!d->node->inherits("KisLayer")) return false;
63
64 const QList<KoChannelInfo *> channelInfo = d->node->colorSpace()->channels();
65
66 for (uint i = 0; i < channelInfo.size(); ++i) {
67 if (channelInfo[i] == d->channel) {
68 KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
69 const QBitArray& flags = layer->channelFlags();
70 return flags.isEmpty() || flags.testBit(i);
71 }
72 }
73
74 return false;
75}
76
77void Channel::setVisible(bool value)
78{
79 if (!d->node || !d->channel) return;
80 if (!d->node->inherits("KisLayer")) return;
81
82 const QList<KoChannelInfo *> channelInfo = d->node->colorSpace()->channels();
83
84 KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
85 QBitArray flags = layer->channelFlags();
86 if (flags.isEmpty()) {
87 flags.fill(1, channelInfo.size());
88 }
89
90 for (uint i = 0; i < channelInfo.size(); ++i) {
91 if (channelInfo[i] == d->channel) {
92 flags.setBit(i, value);
93 layer->setChannelFlags(flags);
94 break;
95 }
96 }
97
98}
99
101{
102 return d->channel->name();
103}
104
106{
107 return d->channel->pos();
108}
109
111{
112 return d->channel->size();
113}
114
116{
117 if (!d->node || !d->channel) return QRect();
118
119 QRect rect = d->node->exactBounds();
120
121 KisPaintDeviceSP dev;
122 if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) {
123 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
124 }
125 else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) {
126 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha16());
127 }
128#ifdef HAVE_OPENEXR
129 else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) {
130 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha16f());
131 }
132#endif
133 else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) {
134 dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha32f());
135 }
136
137 KisSequentialConstIterator srcIt(d->node->projection(), rect);
138 KisSequentialIterator dstIt(dev, rect);
139
140 while(srcIt.nextPixel() && dstIt.nextPixel()) {
141 const quint8 *srcPtr = srcIt.rawDataConst();
142 memcpy(dstIt.rawData(), srcPtr + d->channel->pos(), d->channel->size());
143
144 }
145
146 if (dev) {
147 return dev->exactBounds();
148 }
149
150 return QRect();
151}
152
154{
155 QByteArray ba;
156
157 if (!d->node || !d->channel) return ba;
158
160 KisSequentialConstIterator srcIt(d->node->projection(), rect);
161
162 if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) {
163 while(srcIt.nextPixel()) {
164 quint8 v;
165 memcpy(&v, srcIt.rawDataConst() + d->channel->pos(), sizeof(v));
166 stream << v;
167 }
168 }
169 else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) {
170 while(srcIt.nextPixel()) {
171 quint16 v;
172 memcpy(&v, srcIt.rawDataConst() + d->channel->pos(), sizeof(v));
173 stream << v;
174 }
175 }
176#ifdef HAVE_OPENEXR
177 else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) {
178 while(srcIt.nextPixel()) {
179 half v;
180 memcpy(&v, srcIt.rawDataConst() + d->channel->pos(), sizeof(v));
181 stream << (float) v;
182 }
183 }
184#endif
185 else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) {
186 while(srcIt.nextPixel()) {
187 float v;
188 memcpy(&v, srcIt.rawDataConst() + d->channel->pos(), sizeof(v));
189 stream << v;
190 }
191
192 }
193
194 return ba;
195}
196
197void Channel::setPixelData(QByteArray value, const QRect &rect)
198{
199 if (!d->node || !d->channel || d->node->paintDevice() == 0) return;
200
201 QDataStream stream(&value, QIODevice::ReadOnly);
202 KisSequentialIterator dstIt(d->node->paintDevice(), rect);
203
204 if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) {
205 while (dstIt.nextPixel()) {
206 quint8 v;
207 stream >> v;
208 memcpy(dstIt.rawData() + d->channel->pos(), &v, sizeof(v));
209 }
210 }
211 else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) {
212 while (dstIt.nextPixel()) {
213 quint16 v;
214 stream >> v;
215 memcpy(dstIt.rawData() + d->channel->pos(), &v, sizeof(v));
216 }
217 }
218#ifdef HAVE_OPENEXR
219 else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) {
220 while (dstIt.nextPixel()) {
221 float f;
222 stream >> f;
223 half v = f;
224 memcpy(dstIt.rawData() + d->channel->pos(), &v, sizeof(v));
225 }
226
227 }
228#endif
229 else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) {
230 while (dstIt.nextPixel()) {
231 float v;
232 stream >> v;
233 memcpy(dstIt.rawData() + d->channel->pos(), &v, sizeof(v));
234 }
235 }
236}
237
238
239
240
A Channel represents a single channel in a Node.
Definition Channel.h:23
int position() const
Definition Channel.cpp:105
void setVisible(bool value)
setvisible set the visibility of the channel to the given value.
Definition Channel.cpp:77
bool visible() const
visible checks whether this channel is visible in the node
Definition Channel.cpp:59
void setPixelData(QByteArray value, const QRect &rect)
setPixelData writes the given data to the relevant channel in the Node.
Definition Channel.cpp:197
QRect bounds() const
Definition Channel.cpp:115
QByteArray pixelData(const QRect &rect) const
Read the values of the channel into the a byte array for each pixel in the rect from the Node this ch...
Definition Channel.cpp:153
QString name() const
Definition Channel.cpp:100
int channelSize() const
Definition Channel.cpp:110
bool fill(bool value, qsizetype size)
bool isEmpty() const const
void setBit(qsizetype i)
bool testBit(qsizetype i) const const
qsizetype size() const const
T qobject_cast(QObject *object)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 21 2025 11:55:31 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.