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

KDE's Doxygen guidelines are available online.