Krita

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

KDE's Doxygen guidelines are available online.