Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_channel_separator.cc
Go to the documentation of this file.
1/*
2 * This file is part of Krita
3 *
4 * SPDX-FileCopyrightText: 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
5 *
6 * ported from Gimp, SPDX-FileCopyrightText: 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
7 * original pixelize.c for GIMP 0.54 by Tracy Scott
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
13
14#include <limits.h>
15#include <stdlib.h>
16#include <vector>
17
18#include <QStandardPaths>
19
20#include <klocalizedstring.h>
21#include <kis_debug.h>
22#include <kpluginfactory.h>
23
24
26#include <KoUpdater.h>
27#include <KoFileDialog.h>
28#include <KoColorSpace.h>
30#include <KoChannelInfo.h>
32
33#include <KisDocument.h>
34#include <kis_image.h>
35#include <kis_layer.h>
36#include <kis_paint_layer.h>
37#include <kis_group_layer.h>
38#include <kis_transaction.h>
39#include <kis_undo_adapter.h>
40#include <kis_global.h>
41#include <kis_types.h>
42#include "kis_iterator_ng.h"
43#include <KisPart.h>
44#include <KisViewManager.h>
45#include <kis_paint_device.h>
46#include <kis_node_manager.h>
48#include <KisMimeDatabase.h>
49#include "KisImageBarrierLock.h"
50
52 : m_viewManager(view)
53{
54}
55
56void KisChannelSeparator::separate(KoUpdater * progressUpdater, enumSepAlphaOptions alphaOps, enumSepSource sourceOps, bool downscale, bool toColor, bool activateCurrentChannel)
57{
59 if (!image) return;
60
62
63 // Use the flattened image, if required
64 switch (sourceOps) {
65 case ALL_LAYERS:
66 // the content will be locked later
67 src = image->projection();
68 break;
69 case CURRENT_LAYER:
71 break;
72 default:
73 break;
74 }
75
76 if (!src) return;
77
78 progressUpdater->setProgress(1);
79
80 const KoColorSpace * dstCs = 0;
81
82 quint32 numberOfChannels = src->channelCount();
83 const KoColorSpace * srcCs = src->colorSpace();
84 const QList<KoChannelInfo *> channels = srcCs->channels();
85 vKisPaintDeviceSP paintDevices;
86
92 const QRect rect = image->bounds();
93
94 KisImageBarrierLock lock(image);
95 int i = 0;
96 for (QList<KoChannelInfo *>::const_iterator it = channels.constBegin(); it != channels.constEnd(); ++it) {
97
98
99 KoChannelInfo *ch = (*it);
100
101 bool channelToColor = (toColor && ch->channelType() != KoChannelInfo::ALPHA);
102
103 if (ch->channelType() == KoChannelInfo::ALPHA && alphaOps != CREATE_ALPHA_SEPARATION) {
104 continue;
105 }
106
107 qint32 channelSize = ch->size();
108 qint32 channelPos = ch->pos();
109 qint32 destSize = 1;
110
112 if (channelToColor) {
113 // We don't downscale if we separate to color channels
114 dev = new KisPaintDevice(srcCs);
115 } else {
116 if (channelSize == 1 || downscale) {
118 } else {
120 destSize = 2;
121 }
122 }
123
124 dstCs = dev->colorSpace();
125
126 paintDevices.push_back(dev);
127
128 KisHLineConstIteratorSP srcIt = src->createHLineConstIteratorNG(rect.x(), rect.y(), rect.width());
129 KisHLineIteratorSP dstIt = dev->createHLineIteratorNG(rect.x(), rect.y(), rect.width());
130
131 for (qint32 row = 0; row < rect.height(); ++row) {
132 do {
133 if (channelToColor) {
134 dstCs->singleChannelPixel(dstIt->rawData(), srcIt->oldRawData(), channelPos);
135
136 if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) {
137 dstCs->setOpacity(dstIt->rawData(), srcCs->opacityU8(srcIt->oldRawData()), 1);
138 } else {
139 dstCs->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1);
140 }
141 } else {
142
143 // To grayscale
144
145 // Decide whether we need downscaling
146 if (channelSize == 1 && destSize == 1) {
147
148 // Both 8-bit channels
149 dstIt->rawData()[0] = srcIt->oldRawData()[channelPos];
150
151 if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) {
152 dstCs->setOpacity(dstIt->rawData(), srcCs->opacityU8(srcIt->oldRawData()), 1);
153 } else {
154 dstCs->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1);
155 }
156 } else if (channelSize == 2 && destSize == 2) {
157
158 // Both 16-bit
159 dstIt->rawData()[0] = srcIt->oldRawData()[channelPos];
160 dstIt->rawData()[1] = srcIt->oldRawData()[channelPos + 1];
161
162 if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) {
163 dstCs->setOpacity(dstIt->rawData(), srcCs->opacityU8(srcIt->oldRawData()), 1);
164 } else {
165 dstCs->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1);
166 }
167 } else if (channelSize != 1 && destSize == 1) {
168 // Downscale
169 memset(dstIt->rawData(), srcCs->scaleToU8(srcIt->oldRawData(), channelPos), 1);
170
171 dstCs->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1);
172 } else if (channelSize != 2 && destSize == 2) {
173 // Upscale
174 dstIt->rawData()[0] = srcCs->scaleToU8(srcIt->oldRawData(), channelPos);
175
176 dstCs->setOpacity(dstIt->rawData(), OPACITY_OPAQUE_U8, 1);
177
178 }
179 }
180
181 } while (dstIt->nextPixel() && srcIt->nextPixel());
182 dstIt->nextRow();
183 srcIt->nextRow();
184 }
185 ++i;
186
187 progressUpdater->setProgress((i * 100) / numberOfChannels);
188 if (progressUpdater->interrupted()) {
189 break;
190 }
191 }
192
193 vKisPaintDeviceSP::const_iterator paintDeviceIterator = paintDevices.cbegin();
194
195 if (!progressUpdater->interrupted()) {
197 adapter.beginMacro(kundo2_i18n("Separate Image"));
198
199 for (QList<KoChannelInfo *>::const_iterator it = channels.constBegin(); it != channels.constEnd(); ++it) {
200
201 KoChannelInfo *ch = (*it);
202 if (ch->channelType() == KoChannelInfo::ALPHA && alphaOps != CREATE_ALPHA_SEPARATION) {
203 // Don't make an separate separation of the alpha channel if the user didn't ask for it.
204 continue;
205 }
206
207 KisPaintLayerSP l = new KisPaintLayer(image, ch->name(), OPACITY_OPAQUE_U8, *paintDeviceIterator);
208
209 if (toColor && ch->channelType() != KoChannelInfo::ALPHA && activateCurrentChannel) {
210 QBitArray channelFlags(channels.count());
211 int i = 0;
212 for (QList<KoChannelInfo *>::const_iterator it2 = channels.constBegin(); it2 != channels.constEnd(); ++it2) {
213 channelFlags.setBit(i, (it == it2));
214 i++;
215 }
216 l->setChannelFlags(channelFlags);
217 }
218
219 adapter.addNode(l.data(), image->rootLayer(), 0);
220 ++paintDeviceIterator;
221 }
222
223 adapter.endMacro();
224 }
225
226 progressUpdater->setProgress(100);
227
228
229}
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const quint8 OPACITY_OPAQUE_U8
#define downscale(quantum)
virtual const quint8 * oldRawData() const =0
virtual bool nextPixel()=0
void separate(KoUpdater *progress, enumSepAlphaOptions alphaOps, enumSepSource sourceOps, bool downscale, bool toColor, bool activateCurrentChannel)
KisChannelSeparator(KisViewManager *view)
KisViewManager * m_viewManager
virtual void nextRow()=0
KisGroupLayerSP rootLayer() const
KisPaintDeviceSP projection() const
QRect bounds() const override
void addNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis, KisImageLayerAddCommand::Flags flags=KisImageLayerAddCommand::DoRedoUpdates|KisImageLayerAddCommand::DoUndoUpdates)
void beginMacro(const KUndo2MagicString &macroName)
KisHLineIteratorSP createHLineIteratorNG(qint32 x, qint32 y, qint32 w)
const KoColorSpace * colorSpace() const
KisPaintDeviceSP activeDevice()
Convenience method to get at the active paint device.
KisImageWSP image() const
Return the image this view is displaying.
@ ALPHA
The channel represents the opacity of a pixel.
qint32 size() const
qint32 pos() const
enumChannelType channelType() const
QString name() const
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0
QList< KoChannelInfo * > channels
virtual quint8 scaleToU8(const quint8 *srcPixel, qint32 channelPos) const =0
virtual void singleChannelPixel(quint8 *dstPixel, const quint8 *srcPixel, quint32 channelIndex) const =0
virtual quint8 opacityU8(const quint8 *pixel) const =0
QString id() const
Definition KoID.cpp:63
bool interrupted() const
Definition KoUpdater.cpp:54
void setProgress(int percent)
Definition KoUpdater.cpp:38
@ CURRENT_LAYER
enumSepAlphaOptions
@ COPY_ALPHA_TO_SEPARATIONS
@ CREATE_ALPHA_SEPARATION
KUndo2MagicString kundo2_i18n(const char *text)
virtual void setChannelFlags(const QBitArray &channelFlags)
Definition kis_layer.cc:342
static KoColorSpaceRegistry * instance()