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  const QList<KoChannelInfo *> channelInfo = d->node->colorSpace()->channels();
62 
63  for (uint i = 0; i < channelInfo.size(); ++i) {
64  if (channelInfo[i] == d->channel) {
65  KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
66  const QBitArray& flags = layer->channelFlags();
67  return flags.isEmpty() || flags.testBit(i);
68  }
69  }
70 
71  return false;
72 }
73 
74 void Channel::setVisible(bool value)
75 {
76  if (!d->node || !d->channel) return;
77  if (!d->node->inherits("KisLayer")) return;
78 
79  const QList<KoChannelInfo *> channelInfo = d->node->colorSpace()->channels();
80 
81  KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
82  QBitArray flags = layer->channelFlags();
83  if (flags.isEmpty()) {
84  flags.fill(1, channelInfo.size());
85  }
86 
87  for (uint i = 0; i < channelInfo.size(); ++i) {
88  if (channelInfo[i] == d->channel) {
89  flags.setBit(i, value);
90  layer->setChannelFlags(flags);
91  break;
92  }
93  }
94 
95 }
96 
98 {
99  return d->channel->name();
100 }
101 
102 int Channel::position() const
103 {
104  return d->channel->pos();
105 }
106 
108 {
109  return d->channel->size();
110 }
111 
113 {
114  if (!d->node || !d->channel) return QRect();
115 
116  QRect rect = d->node->exactBounds();
117 
118  KisPaintDeviceSP dev;
119  if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) {
120  dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
121  }
122  else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) {
123  dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha16());
124  }
125 #ifdef HAVE_OPENEXR
126  else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) {
127  dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha16f());
128  }
129 #endif
130  else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) {
131  dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha32f());
132  }
133 
134  KisSequentialConstIterator srcIt(d->node->projection(), rect);
135  KisSequentialIterator dstIt(dev, rect);
136 
137  while(srcIt.nextPixel() && dstIt.nextPixel()) {
138  const quint8 *srcPtr = srcIt.rawDataConst();
139  memcpy(dstIt.rawData(), srcPtr + d->channel->pos(), d->channel->size());
140 
141  }
142 
143  if (dev) {
144  return dev->exactBounds();
145  }
146 
147  return QRect();
148 }
149 
151 {
152  QByteArray ba;
153 
154  if (!d->node || !d->channel) return ba;
155 
156  QDataStream stream(&ba, QIODevice::WriteOnly);
157  KisSequentialConstIterator srcIt(d->node->projection(), rect);
158 
159  if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) {
160  while(srcIt.nextPixel()) {
161  stream << (quint8) *srcIt.rawDataConst() + (d->channel->pos() * d->channel->size());
162  }
163  }
164  else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) {
165  while(srcIt.nextPixel()) {
166  stream << (quint16) *srcIt.rawDataConst() + (d->channel->pos() * d->channel->size());
167  }
168  }
169 #ifdef HAVE_OPENEXR
170  else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) {
171  while(srcIt.nextPixel()) {
172  half h = (half)*srcIt.rawDataConst() + (d->channel->pos() * d->channel->size());
173  stream << (float)h;
174  }
175  }
176 #endif
177  else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) {
178  while(srcIt.nextPixel()) {
179  stream << (float) *srcIt.rawDataConst() + (d->channel->pos() * d->channel->size());
180  }
181 
182  }
183 
184  return ba;
185 }
186 
187 void Channel::setPixelData(QByteArray value, const QRect &rect)
188 {
189  if (!d->node || !d->channel || d->node->paintDevice() == 0) return;
190 
191  QDataStream stream(&value, QIODevice::ReadOnly);
192  KisSequentialIterator dstIt(d->node->paintDevice(), rect);
193 
194  if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) {
195  while (dstIt.nextPixel()) {
196  quint8 v;
197  stream >> v;
198  *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ;
199  }
200  }
201  else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) {
202  while (dstIt.nextPixel()) {
203  quint16 v;
204  stream >> v;
205  *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ;
206  }
207  }
208 #ifdef HAVE_OPENEXR
209  else if (d->node->colorSpace()->colorDepthId() == Float16BitsColorDepthID) {
210  while (dstIt.nextPixel()) {
211  float f;
212  stream >> f;
213  half v = f;
214  *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ;
215  }
216 
217  }
218 #endif
219  else if (d->node->colorSpace()->colorDepthId() == Float32BitsColorDepthID) {
220  while (dstIt.nextPixel()) {
221  float v;
222  stream >> v;
223  *(dstIt.rawData() + (d->channel->pos() * d->channel->size())) = v ;
224  }
225  }
226 }
227 
228 
229 
230 
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:102
bool isEmpty() const const
int size() const const
void setVisible(bool value)
setvisible set the visibility of the channel to the given value.
Definition: Channel.cpp:74
bool testBit(int i) const const
QRect bounds() const
Definition: Channel.cpp:112
void setBit(int i)
QString name() const
Definition: Channel.cpp:97
int channelSize() const
Definition: Channel.cpp:107
void setPixelData(QByteArray value, const QRect &rect)
setPixelData writes the given data to the relevant channel in the Node.
Definition: Channel.cpp:187
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:150
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Fri Sep 22 2023 04:09:51 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.