1 /*
2  *  Copyright (c) 2014 Manuel Riecke <spell1337@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "posterize.h"
20 #include <stdlib.h>
21 #include <vector>
22 
23 #include <QPoint>
24 #include <QTime>
25 
26 #include <klocalizedstring.h>
27 
28 #include <kis_debug.h>
29 #include <kpluginfactory.h>
30 
31 #include <kis_processing_information.h>
32 #include <kis_types.h>
33 #include <kis_selection.h>
34 #include <kis_layer.h>
35 #include <filter/kis_filter_category_ids.h>
36 #include <filter/kis_filter_registry.h>
37 #include <kis_global.h>
38 
39 #include <KoColorSpaceMaths.h>
40 #include <filter/kis_color_transformation_configuration.h>
41 #include <widgets/kis_multi_integer_filter_widget.h>
42 
43 K_PLUGIN_FACTORY_WITH_JSON(PosterizeFactory, "kritaposterize.json", registerPlugin<Posterize>();)
44 
Posterize(QObject * parent,const QVariantList &)45 Posterize::Posterize(QObject *parent, const QVariantList &)
46     : QObject(parent)
47 {
48     KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterPosterize()));
49 }
50 
~Posterize()51 Posterize::~Posterize()
52 {
53 }
54 
KisFilterPosterize()55 KisFilterPosterize::KisFilterPosterize() : KisColorTransformationFilter(id(), FiltersCategoryArtisticId, i18n("&Posterize..."))
56 {
57     setColorSpaceIndependence(FULLY_INDEPENDENT);
58     setSupportsPainting(true);
59     setShowConfigurationWidget(true);
60 }
61 
createTransformation(const KoColorSpace * cs,const KisFilterConfigurationSP config) const62 KoColorTransformation* KisFilterPosterize::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const
63 {
64     return new KisPosterizeColorTransformation(config->getInt("steps", 16), cs);
65 }
66 
KisPosterizeColorTransformation(int steps,const KoColorSpace * cs)67 KisPosterizeColorTransformation::KisPosterizeColorTransformation(int steps, const KoColorSpace* cs) : m_colorSpace(cs), m_psize(cs->pixelSize())
68 {
69     m_step = KoColorSpaceMathsTraits<quint16>::max / steps;
70     m_halfStep = m_step / 2;
71     m_fromConversion = KoColorSpaceRegistry::instance()->createColorConverter(
72         m_colorSpace,
73         KoColorSpaceRegistry::instance()->rgb16("sRGB-elle-V2-srgbtrc.icc"),
74         KoColorConversionTransformation::internalRenderingIntent(),
75         KoColorConversionTransformation::internalConversionFlags());
76     m_toConversion = KoColorSpaceRegistry::instance()->createColorConverter(
77         KoColorSpaceRegistry::instance()->rgb16("sRGB-elle-V2-srgbtrc.icc"),
78         m_colorSpace,
79         KoColorConversionTransformation::internalRenderingIntent(),
80         KoColorConversionTransformation::internalConversionFlags());
81 }
82 
~KisPosterizeColorTransformation()83 KisPosterizeColorTransformation::~KisPosterizeColorTransformation()
84 {
85     delete m_fromConversion;
86     delete m_toConversion;
87 }
88 
createConfigurationWidget(QWidget * parent,const KisPaintDeviceSP dev,bool) const89 KisConfigWidget* KisFilterPosterize::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev, bool) const
90 {
91     Q_UNUSED(dev);
92     vKisIntegerWidgetParam param;
93     param.push_back(KisIntegerWidgetParam(2, 128, 16, i18n("Steps"), "steps"));
94     return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param);
95 }
96 
defaultConfiguration() const97 KisFilterConfigurationSP KisFilterPosterize::defaultConfiguration() const
98 {
99     KisFilterConfigurationSP config = factoryConfiguration();
100     config->setProperty("steps", 16);
101     return config;
102 }
103 
transform(const quint8 * src,quint8 * dst,qint32 nPixels) const104 void KisPosterizeColorTransformation::transform(const quint8* src, quint8* dst, qint32 nPixels) const
105 {
106     quint16 m_rgba[4];
107     quint16 m_mod[4];
108 
109     while (nPixels--) {
110         m_fromConversion->transform(src, reinterpret_cast<quint8 *>(m_rgba), 1);
111 
112         m_mod[0] = m_rgba[0] % m_step;
113         m_mod[1] = m_rgba[1] % m_step;
114         m_mod[2] = m_rgba[2] % m_step;
115         m_mod[3] = m_rgba[3] % m_step;
116 
117         m_rgba[0] = m_rgba[0] + (m_mod[0] > m_halfStep ? m_step - m_mod[0] : -m_mod[0]);
118         m_rgba[1] = m_rgba[1] + (m_mod[1] > m_halfStep ? m_step - m_mod[1] : -m_mod[1]);
119         m_rgba[2] = m_rgba[2] + (m_mod[2] > m_halfStep ? m_step - m_mod[2] : -m_mod[2]);
120         m_rgba[3] = m_rgba[3] + (m_mod[3] > m_halfStep ? m_step - m_mod[3] : -m_mod[3]);
121 
122         m_toConversion->transform(reinterpret_cast<quint8 *>(m_rgba), dst, 1);
123         src += m_psize;
124         dst += m_psize;
125     }
126 }
127 
128 #include "posterize.moc"
129