Krita Source Code Documentation
Loading...
Searching...
No Matches
simplexnoisegenerator.cpp
Go to the documentation of this file.
1/*
2 * KDE. Krita Project.
3 *
4 * SPDX-FileCopyrightText: 2019 Eoin O 'Neill <eoinoneill1991@gmail.com>
5 * SPDX-FileCopyrightText: 2019 Emmet O 'Neill <emmetoneill.pdx@gmail.com>
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
11#include "ui_wdgsimplexnoiseoptions.h"
14
16#include <KoUpdater.h>
17#include <QCryptographicHash>
23#include <kpluginfactory.h>
24
25K_PLUGIN_FACTORY_WITH_JSON(KritaSimplexNoiseGeneratorFactory, "kritasimplexnoisegenerator.json", registerPlugin<KisSimplexNoiseGeneratorHandle>();)
26
28 : QObject(parent)
29{
31
32}
33
37
43
44void KisSimplexNoiseGenerator::generate(KisProcessingInformation dst, const QSize &size, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const
45{
46 KisPaintDeviceSP device = dst.paintDevice();
47 Q_ASSERT(!device.isNull());
48
49 osn_context *noise_context;
50
51 QRect bounds = QRect(dst.topLeft(), size);
52 QRect whole_image_bounds = device->defaultBounds()->bounds();
53
54 const KoColorSpace *cs = device->colorSpace();
55 const KoColorSpace *src = KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Float32BitsColorDepthID.id(), "Gray-D50-elle-V2-srgbtrc.icc");
57
58 KisSequentialIteratorProgress it(device, bounds, progressUpdater);
59
60 QVariant property;
61
62 const uint default_seed = (config->getProperty("seed", property)) ? property.toUInt() : 0;
63 const QString custom_seed_string = (config->getProperty("custom_seed_string", property)) ? property.toString() : "";
64 const bool use_custom_seed = !custom_seed_string.trimmed().isEmpty();
65
66 const uint seed = use_custom_seed ? seedFromString(custom_seed_string) : default_seed;
67 open_simplex_noise(seed, &noise_context);
68
69 double frequency = (config && config->getProperty("frequency", property)) ? property.toDouble() : 25.0;
70 double ratio_x = (config && config->getProperty("ratio_x", property)) ? property.toDouble() : 1.0;
71 double ratio_y = (config && config->getProperty("ratio_y", property)) ? property.toDouble() : 1.0;
72
73 bool looping = (config && config->getProperty("looping", property)) ? property.toBool() : false;
74
75 if( looping ){
76 float major_radius = 0.5f * frequency * ratio_x;
77 float minor_radius = 0.5f * frequency * ratio_y;
78 while(it.nextPixel()){
79 double x_phase = (double)it.x() / (double)whole_image_bounds.width() * M_PI * 2;
80 double y_phase = (double)it.y() / (double)(whole_image_bounds.height()) * M_PI * 2;
81 double x_coordinate = major_radius * map_range(cos(x_phase), -1.0, 1.0, 0.0, 1.0);
82 double y_coordinate = major_radius * map_range(sin(x_phase), -1.0, 1.0, 0.0, 1.0);
83 double z_coordinate = minor_radius * map_range(cos(y_phase), -1.0, 1.0, 0.0, 1.0);
84 double w_coordinate = minor_radius * map_range(sin(y_phase), -1.0, 1.0, 0.0, 1.0);
85 double value = open_simplex_noise4(noise_context, x_coordinate, y_coordinate, z_coordinate, w_coordinate);
86 value = map_range(value, -1.0, 1.0, 0.0, 1.0);
87
88 KoColor c(src);
89 reinterpret_cast<float *>(c.data())[0] = value;
91
92 conv->transform(c.data(), it.rawData(), 1);
93 }
94 } else {
95 while(it.nextPixel()){
96 double x_phase = (double)it.x() / (double)(whole_image_bounds.width()) * ratio_x;
97 double y_phase = (double)it.y() / (double)(whole_image_bounds.height()) * ratio_y;
98 double value = open_simplex_noise4(noise_context, x_phase * frequency, y_phase * frequency, x_phase * frequency, y_phase * frequency);
99 value = map_range(value, -1.0, 1.0, 0.0, 1.0);
100
101 KoColor c(src);
102 reinterpret_cast<float *>(c.data())[0] = value;
104
105 conv->transform(c.data(), it.rawData(), 1);
106 }
107 }
108 delete conv;
109 open_simplex_noise_free(noise_context);
110}
111
113{
114 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
115 config->setProperty("looping", false);
116 config->setProperty("frequency", 25.0);
117 uint seed = static_cast<uint>(rand());
118 config->setProperty("seed", seed);
119 config->setProperty("custom_seed_string", "");
120 config->setProperty("ratio_x", 1.0f);
121 config->setProperty("ratio_y", 1.0f);
122 return config;
123}
124
126{
127 Q_UNUSED(dev);
128 return new KisWdgSimplexNoise((KisFilter*)this, (QWidget*)parent);
129}
130
131
133{
134 QByteArray bytes = QCryptographicHash::hash(string.toUtf8(),QCryptographicHash::Md5);
135 uint hash = 0;
136 for( int index = 0; index < bytes.length(); index++){
137 hash += rotateLeft(bytes[index], index % 32);
138 }
139 return hash;
140}
141
142quint64 KisSimplexNoiseGenerator::rotateLeft(const quint64 input, uint shift) const
143{
144 return (input << shift)|(input >> (64 - shift));
145}
146
147#include "simplexnoisegenerator.moc"
148
float value(const T *src, size_t ch)
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const qreal OPACITY_OPAQUE_F
@ FULLY_INDEPENDENT
unsigned int uint
virtual QRect bounds() const =0
static KisGeneratorRegistry * instance()
void add(KisGeneratorSP item)
const KoColorSpace * colorSpace() const
KisDefaultBoundsBaseSP defaultBounds() const
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE int x() const
ALWAYS_INLINE int y() const
bool isNull() const
KisSimplexNoiseGeneratorHandle(QObject *parent, const QVariantList &)
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
quint64 rotateLeft(const quint64 input, uint d) const
static double map_range(double value, double curr_min, double curr_max, double new_min, double new_max)
virtual void generate(KisProcessingInformation dst, const QSize &size, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
uint seedFromString(const QString &string) const
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
quint8 * data()
Definition KoColor.h:144
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
#define bounds(x, a, b)
#define M_PI
Definition kis_global.h:111
int open_simplex_noise(int64_t seed, struct osn_context **ctx)
void open_simplex_noise_free(struct osn_context *ctx)
double open_simplex_noise4(struct osn_context *ctx, double x, double y, double z, double w)
virtual KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)
void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override=0
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
KoColorConversionTransformation * createColorConverter(const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
static KoColorSpaceRegistry * instance()