Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_pixelize_filter.cpp
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
12#include "kis_pixelize_filter.h"
13
14
15#include <stdlib.h>
16#include <vector>
17
18#include <QPoint>
19#include <QSpinBox>
20
21#include <klocalizedstring.h>
22#include <kpluginfactory.h>
23
24#include <KoUpdater.h>
25
26#include <kis_debug.h>
27#include <KisDocument.h>
29#include <kis_global.h>
30#include <kis_image.h>
31#include <kis_layer.h>
32#include <kis_selection.h>
33#include <kis_types.h>
37
39#include <KoMixColorsOp.h>
41#include "kis_algebra_2d.h"
42#include "kis_lod_transform.h"
43
44
53
55 const QRect& applyRect,
56 const KisFilterConfigurationSP config,
57 KoUpdater* progressUpdater
58 ) const
59{
60 Q_ASSERT(device);
61
62 KisLodTransformScalar t(device);
63 const int pixelWidth = qCeil(t.scale(config ? qMax(1, config->getInt("pixelWidth", 10)) : 10));
64 const int pixelHeight = qCeil(t.scale(config ? qMax(1, config->getInt("pixelHeight", 10)) : 10));
65
66 const qint32 pixelSize = device->pixelSize();
67
68 const QRect deviceBounds = device->defaultBounds()->bounds();
69
70 const int bufferSize = pixelSize * pixelWidth * pixelHeight;
71 QScopedArrayPointer<quint8> buffer(new quint8[bufferSize]);
72
73 KoColor pixelColor(Qt::black, device->colorSpace());
74 KoMixColorsOp *mixOp = device->colorSpace()->mixColorsOp();
75
76 using namespace KisAlgebra2D;
77 const qint32 firstCol = divideFloor(applyRect.x(), pixelWidth);
78 const qint32 firstRow = divideFloor(applyRect.y(), pixelHeight);
79
80 const qint32 lastCol = divideFloor(applyRect.x() + applyRect.width() - 1, pixelWidth);
81 const qint32 lastRow = divideFloor(applyRect.y() + applyRect.height() - 1, pixelHeight);
82
83 progressUpdater->setRange(firstRow, lastRow);
84
85 for(qint32 i = firstRow; i <= lastRow; i++) {
86 for(qint32 j = firstCol; j <= lastCol; j++) {
87 const QRect maxPatchRect(j * pixelWidth, i * pixelHeight,
88 pixelWidth, pixelHeight);
89 const QRect pixelRect = maxPatchRect & deviceBounds;
90 const int numColors = pixelRect.width() * pixelRect.height();
91
92
93 //read
94 KisSequentialConstIterator srcIt(device, pixelRect);
95
96 memset(buffer.data(), 0, bufferSize);
97 quint8 *bufferPtr = buffer.data();
98
99 while (srcIt.nextPixel()) {
100 memcpy(bufferPtr, srcIt.oldRawData(), pixelSize);
101 bufferPtr += pixelSize;
102 }
103
104 // mix all the colors
105 mixOp->mixColors(buffer.data(), numColors, pixelColor.data());
106
107 // write only colors in applyRect
108 const QRect writeRect = pixelRect & applyRect;
109
110 KisSequentialIterator dstIt(device, writeRect);
111 while (dstIt.nextPixel()) {
112 memcpy(dstIt.rawData(), pixelColor.data(), pixelSize);
113 }
114 }
115 progressUpdater->setValue(i);
116 }
117}
118
119QRect KisPixelizeFilter::neededRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const
120{
122
123 const int pixelWidth = qCeil(t.scale(config ? qMax(1, config->getInt("pixelWidth", 10)) : 10));
124 const int pixelHeight = qCeil(t.scale(config ? qMax(1, config->getInt("pixelHeight", 10)) : 10));
125
126 // TODO: make more precise calculation of the rect, including the alignment
127 return rect.adjusted(-2*pixelWidth, -2*pixelHeight, 2*pixelWidth, 2*pixelHeight);
128}
129
130QRect KisPixelizeFilter::changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const
131{
132 return neededRect(rect, config, lod);
133}
134
136{
138 param.push_back(KisIntegerWidgetParam(2, 512, 10, i18n("Pixel width"), "pixelWidth" /*"keepAspect"*/));
139 param.push_back(KisIntegerWidgetParam(2, 512, 10, i18n("Pixel height"), "pixelHeight", "keepAspect"));
140 return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param);
141}
142
144{
145 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
146 config->setProperty("pixelWidth", 10);
147 config->setProperty("pixelHeight", 10);
148 config->setProperty("keepAspect", true);
149 return config;
150}
151
@ FULLY_INDEPENDENT
virtual QRect bounds() const =0
void setSupportsLevelOfDetail(bool value)
qreal scale(qreal value) const
quint32 pixelSize() const
const KoColorSpace * colorSpace() const
KisDefaultBoundsBaseSP defaultBounds() const
QRect neededRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const override
QRect changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const override
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
void processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE const quint8 * oldRawData() const
KoMixColorsOp * mixColorsOp
quint8 * data()
Definition KoColor.h:144
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
void setValue(int value) override
Definition KoUpdater.cpp:64
void setRange(int minimum, int maximum) override
Definition KoUpdater.cpp:79
const KoID FiltersCategoryArtisticId("artistic_filters", ki18nc("The category of artistic filters, like raindrops. Adjective.", "Artistic"))
std::vector< KisIntegerWidgetParam > vKisIntegerWidgetParam
void setSupportsThreading(bool v)
virtual KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setSupportsAdjustmentLayers(bool v)
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)