Krita Source Code Documentation
Loading...
Searching...
No Matches
KisFilterPalettize Class Reference

#include <palettize.h>

+ Inheritance diagram for KisFilterPalettize:

Public Types

enum  AlphaMode { Clip , Index , Dither }
 
enum  ColorMode { PerChannelOffset , NearestColors }
 
enum  Colorspace { Lab , RGB }
 
enum  PatternValueMode { Auto , Lightness , Alpha }
 
enum  ThresholdMode { Pattern , Noise }
 

Public Member Functions

KisConfigWidgetcreateConfigurationWidget (QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
 
KisFilterConfigurationSP defaultConfiguration (KisResourcesInterfaceSP resourcesInterface) const override
 
KisFilterConfigurationSP factoryConfiguration (KisResourcesInterfaceSP resourcesInterface) const override
 
 KisFilterPalettize ()
 
void processImpl (KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
 
- Public Member Functions inherited from KisFilter
virtual QRect changedRect (const QRect &rect, const KisFilterConfigurationSP config, int lod) const
 
virtual bool configurationAllowedForMask (KisFilterConfigurationSP config) const
 
virtual void fixLoadedFilterConfigurationForMasks (KisFilterConfigurationSP config) const
 
 KisFilter (const KoID &id, const KoID &category, const QString &entry)
 
virtual QRect neededRect (const QRect &rect, const KisFilterConfigurationSP config, int lod) const
 
virtual bool needsTransparentPixels (const KisFilterConfigurationSP config, const KoColorSpace *cs) const
 
void process (const KisPaintDeviceSP src, KisPaintDeviceSP dst, KisSelectionSP selection, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater=0) const
 
void process (KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater=0) const
 
virtual bool supportsLevelOfDetail (const KisFilterConfigurationSP config, int lod) const
 
 ~KisFilter () override
 
- Public Member Functions inherited from KisBaseProcessor
KisBookmarkedConfigurationManagerbookmarkManager ()
 
const KisBookmarkedConfigurationManagerbookmarkManager () const
 
ColorSpaceIndependence colorSpaceIndependence () const
 
QString id () const
 
 KisBaseProcessor (const KoID &id, const KoID &category, const QString &entry)
 
KoID menuCategory () const
 
QString menuEntry () const
 
QString name () const
 
 Private ()
 
QKeySequence shortcut () const
 
bool showConfigurationWidget ()
 If true, the filter wants to show a configuration widget.
 
bool supportsAdjustmentLayers () const
 This filter can be used in adjustment layers.
 
bool supportsPainting () const
 
bool supportsThreading () const
 
virtual ~KisBaseProcessor ()
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 
- Public Member Functions inherited from KisShared
bool deref ()
 
bool ref ()
 
int refCount ()
 
QAtomicInt * sharedWeakReference ()
 

Static Public Member Functions

static KoID id ()
 

Additional Inherited Members

- Public Attributes inherited from KisBaseProcessor
KisBookmarkedConfigurationManagerbookmarkManager
 
KoID category
 
ColorSpaceIndependence colorSpaceIndependence
 
QString entry
 
KoID id
 
QKeySequence shortcut
 
bool showConfigurationWidget
 
bool supportsAdjustmentLayers
 
bool supportsPainting
 
bool supportsThreading
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 
- Protected Member Functions inherited from KisFilter
QString configEntryGroup () const
 
void setSupportsLevelOfDetail (bool value)
 
- Protected Member Functions inherited from KisBaseProcessor
void init (const QString &configEntryGroup)
 
void setColorSpaceIndependence (ColorSpaceIndependence v)
 
void setShortcut (const QKeySequence &shortcut)
 
void setShowConfigurationWidget (bool v)
 
void setSupportsAdjustmentLayers (bool v)
 
void setSupportsPainting (bool v)
 
void setSupportsThreading (bool v)
 
- Protected Member Functions inherited from KisShared
 KisShared ()
 
 ~KisShared ()
 

Detailed Description

Definition at line 42 of file palettize.h.

Member Enumeration Documentation

◆ AlphaMode

Enumerator
Clip 
Index 
Dither 

Definition at line 49 of file palettize.h.

◆ ColorMode

Enumerator
PerChannelOffset 
NearestColors 

Definition at line 63 of file palettize.h.

◆ Colorspace

Enumerator
Lab 
RGB 

Definition at line 45 of file palettize.h.

45 {
46 Lab,
47 RGB
48 };

◆ PatternValueMode

Enumerator
Auto 
Lightness 
Alpha 

Definition at line 58 of file palettize.h.

◆ ThresholdMode

Enumerator
Pattern 
Noise 

Definition at line 54 of file palettize.h.

Constructor & Destructor Documentation

◆ KisFilterPalettize()

KisFilterPalettize::KisFilterPalettize ( )

Definition at line 190 of file palettize.cpp.

190 : KisFilter(id(), FiltersCategoryMapId, i18n("&Palettize..."))
191{
195}
@ FULLY_INDEPENDENT
KisFilter(const KoID &id, const KoID &category, const QString &entry)
Definition kis_filter.cc:22
const KoID FiltersCategoryMapId("map_filters", ki18nc("The category of mapping filters, like bump map or gradient filter map. Verb.", "Map"))
void setShowConfigurationWidget(bool v)
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)

References FULLY_INDEPENDENT, KisBaseProcessor::setColorSpaceIndependence(), KisBaseProcessor::setShowConfigurationWidget(), and KisBaseProcessor::setSupportsPainting().

Member Function Documentation

◆ createConfigurationWidget()

KisConfigWidget * KisFilterPalettize::createConfigurationWidget ( QWidget * parent,
const KisPaintDeviceSP dev,
bool useForMasks ) const
overridevirtual

Create the configuration widget for this processor.

Parameters
parentthe Qt owner widget of this widget
devthe paintdevice this filter will act on
useForMasksshown if the filer is going to be used in a mask. Some filters may provide limited options when applied as a mask (e.g. Gaussian Blur)

Reimplemented from KisBaseProcessor.

Definition at line 178 of file palettize.cpp.

179{
180 Q_UNUSED(dev);
181 Q_UNUSED(useForMasks);
182
183 return new KisPalettizeWidget(parent);
184}

◆ defaultConfiguration()

KisFilterConfigurationSP KisFilterPalettize::defaultConfiguration ( KisResourcesInterfaceSP resourcesInterface) const
overridevirtual

Return the configuration set as the default by the user or the default configuration from the filter writer as returned by factoryConfiguration.

This configuration is used by default for the configuration widget and given to the process function if there is no configuration widget.

Returns
the default configuration of this widget

Reimplemented from KisBaseProcessor.

Definition at line 203 of file palettize.cpp.

204{
205 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
206
207 config->setProperty("palette", "Default");
208 config->setProperty("colorspace", Colorspace::Lab);
209 config->setProperty("ditherEnabled", false);
210 KisDitherWidget::factoryConfiguration(*config, "dither/");
211 config->setProperty("dither/colorMode", ColorMode::PerChannelOffset);
212 config->setProperty("dither/offsetScale", 0.125);
213 config->setProperty("alphaEnabled", true);
214 config->setProperty("alphaMode", AlphaMode::Clip);
215 config->setProperty("alphaClip", 0.5);
216 config->setProperty("alphaIndex", 0);
217 KisDitherWidget::factoryConfiguration(*config, "alphaDither/");
218
219 return config;
220}
static void factoryConfiguration(KisPropertiesConfiguration &config, const QString &prefix="")
KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const override

References Clip, KisDitherWidget::factoryConfiguration(), factoryConfiguration(), Lab, and PerChannelOffset.

◆ factoryConfiguration()

KisFilterConfigurationSP KisFilterPalettize::factoryConfiguration ( KisResourcesInterfaceSP resourcesInterface) const
overridevirtual
Returns
the default configuration object as defined by whoever wrote the plugin. This object must be filled in with fromXML after that.

Reimplemented from KisBaseProcessor.

Definition at line 197 of file palettize.cpp.

198{
199 return new KisFilterPalettizeConfiguration("palettize", 1, resourcesInterface);
200}

◆ id()

static KoID KisFilterPalettize::id ( )
inlinestatic

Definition at line 68 of file palettize.h.

68{ return KoID("palettize", i18n("Palettize")); }
Definition KoID.h:30

◆ processImpl()

void KisFilterPalettize::processImpl ( KisPaintDeviceSP device,
const QRect & applyRect,
const KisFilterConfigurationSP config,
KoUpdater * progressUpdater ) const
overridevirtual

Override this function with the implementation of your filter.

This is a low level function that expects all the conditions for the

Parameters
devicebe met. Use usual process() methods instead.
devicethe paint device to filter
applyRectthe rectangle where the filter is applied
configthe parameters of the filter
progressUpdaterto pass on the progress the filter is making

Implements KisFilter.

Definition at line 222 of file palettize.cpp.

223{
224 const KisFilterPalettizeConfiguration *config = dynamic_cast<const KisFilterPalettizeConfiguration*>(_config.data());
227
228 const KoColorSetSP palette = config->palette();
229
230 const int searchColorspace = config->getInt("colorspace");
231 const bool ditherEnabled = config->getBool("ditherEnabled");
232 const int colorMode = config->getInt("dither/colorMode");
233 const double offsetScale = config->getDouble("dither/offsetScale");
234 const bool alphaEnabled = config->getBool("alphaEnabled");
235 const int alphaMode = config->getInt("alphaMode");
236 const double alphaClip = config->getDouble("alphaClip");
237 const int alphaIndex = config->getInt("alphaIndex");
238
239 const KoColorSpace* colorspace = device->colorSpace();
240 const KoColorSpace* workColorspace = (searchColorspace == Colorspace::Lab
242 : KoColorSpaceRegistry::instance()->rgb16("sRGB-elle-V2-srgbtrc.icc"));
243
244 const quint8 colorCount = ditherEnabled && colorMode == ColorMode::NearestColors ? 2 : 1;
245
246 using SearchColor = boost::geometry::model::point<quint16, 3, boost::geometry::cs::cartesian>;
247 struct ColorCandidate {
248 KoColor color;
249 quint16 index;
250 double distance;
251 };
252 using SearchEntry = std::pair<SearchColor, ColorCandidate>;
253 boost::geometry::index::rtree<SearchEntry, boost::geometry::index::quadratic<16>> rtree;
254
255 if (palette) {
256 // Add palette colors to search tree
257 quint16 index = 0;
258 for (int row = 0; row < palette->rowCount(); ++row) {
259 for (int column = 0; column < palette->columnCount(); ++column) {
260 KisSwatch swatch = palette->getColorGlobal(column, row);
261 if (swatch.isValid()) {
262 KoColor color = swatch.color().convertedTo(colorspace);
263 KoColor workColor = swatch.color().convertedTo(workColorspace);
264 SearchColor searchColor;
265 memcpy(&searchColor, workColor.data(), sizeof(SearchColor));
266 // Don't add duplicates so won't dither between identical colors
267 std::vector<SearchEntry> result;
268 rtree.query(boost::geometry::index::contains(searchColor), std::back_inserter(result));
269 if (result.empty()) rtree.insert(SearchEntry(searchColor, {color, index, 0.0}));
270 }
271 ++index;
272 }
273 }
274
275 KisDitherUtil ditherUtil;
276 if (ditherEnabled) ditherUtil.setConfiguration(*config, "dither/");
277
278 KisDitherUtil alphaDitherUtil;
279 if (alphaMode == AlphaMode::Dither) alphaDitherUtil.setConfiguration(*config, "alphaDither/");
280
281 KisSequentialIteratorProgress pixel(device, applyRect, progressUpdater);
282 while (pixel.nextPixel()) {
283 KoColor workColor(pixel.oldRawData(), colorspace);
284 workColor.convertTo(workColorspace);
285
286 // Find dither threshold
287 double threshold = 0.5;
288 if (ditherEnabled) {
289 threshold = ditherUtil.threshold(QPoint(pixel.x(), pixel.y()));
290
291 // Traditional per-channel ordered dithering
292 if (colorMode == ColorMode::PerChannelOffset) {
293 QVector<float> normalized(int(workColorspace->channelCount()));
294 workColorspace->normalisedChannelsValue(workColor.data(), normalized);
295 for (int channel = 0; channel < int(workColorspace->channelCount()); ++channel) {
296 normalized[channel] += (threshold - 0.5) * offsetScale;
297 }
298 workColorspace->fromNormalisedChannelsValue(workColor.data(), normalized);
299 }
300 }
301
302 // Get candidate colors and their distances
303 SearchColor searchColor;
304 memcpy(reinterpret_cast<quint8 *>(&searchColor), workColor.data(), sizeof(SearchColor));
305 std::vector<ColorCandidate> candidateColors;
306 candidateColors.reserve(size_t(colorCount));
307 double distanceSum = 0.0;
308 for (auto it = rtree.qbegin(boost::geometry::index::nearest(searchColor, colorCount)); it != rtree.qend() && candidateColors.size() < colorCount; ++it) {
309 ColorCandidate candidate = it->second;
310 candidate.distance = boost::geometry::distance(searchColor, it->first);
311 candidateColors.push_back(candidate);
312 distanceSum += candidate.distance;
313 }
314
315 // Select color candidate
316 quint16 selected;
317 if (ditherEnabled && colorMode == ColorMode::NearestColors) {
318 // Sort candidates by palette order for stable dither color ordering
319 const bool swap = candidateColors[0].index > candidateColors[1].index;
320 selected = swap ^ (candidateColors[swap].distance / distanceSum > threshold);
321 }
322 else {
323 selected = 0;
324 }
325 ColorCandidate &candidate = candidateColors[selected];
326
327 // Set alpha
328 const double oldAlpha = colorspace->opacityF(pixel.oldRawData());
329 double newAlpha = oldAlpha;
330 if (alphaEnabled && !(!ditherEnabled && alphaMode == AlphaMode::Dither)) {
331 if (alphaMode == AlphaMode::Clip) {
332 newAlpha = oldAlpha < alphaClip? 0.0 : 1.0;
333 }
334 else if (alphaMode == AlphaMode::Index) {
335 newAlpha = (candidate.index == alphaIndex ? 0.0 : 1.0);
336 }
337 else if (alphaMode == AlphaMode::Dither) {
338 newAlpha = oldAlpha < alphaDitherUtil.threshold(QPoint(pixel.x(), pixel.y())) ? 0.0 : 1.0;
339 }
340 }
341 colorspace->setOpacity(candidate.color.data(), newAlpha, 1);
342
343 // Copy color to pixel
344 memcpy(pixel.rawData(), candidate.color.data(), colorspace->pixelSize());
345 }
346 }
347}
qreal distance(const QPointF &p1, const QPointF &p2)
qreal threshold(const QPoint &pos)
void setConfiguration(const KisFilterConfiguration &config, const QString &prefix="")
KoResourceLoadResult palette(KisResourcesInterfaceSP resourcesInterface) const
Definition palettize.cpp:59
const KoColorSpace * colorSpace() const
KoColor color() const
Definition KisSwatch.h:30
bool isValid() const
Definition KisSwatch.h:36
virtual quint32 channelCount() const =0
virtual void normalisedChannelsValue(const quint8 *pixel, QVector< float > &channels) const =0
virtual void fromNormalisedChannelsValue(quint8 *pixel, const QVector< float > &values) const =0
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
KoColor convertedTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
Definition KoColor.cpp:163
quint8 * data()
Definition KoColor.h:144
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
PROPAGATE_CONST_CONSTEXPR void swap(propagate_const< T > &pt, propagate_const< T > &pu) noexcept(noexcept(swap(declval< T & >(), declval< T & >())))
rgba palette[MAX_PALETTE]
Definition palette.c:35
bool getBool(const QString &name, bool def=false) const
int getInt(const QString &name, int def=0) const
double getDouble(const QString &name, double def=0.0) const
const KoColorSpace * lab16(const QString &profileName=QString())
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb16(const QString &profileName=QString())

References KoColorSpace::channelCount(), Clip, KisSwatch::color(), KisPaintDevice::colorSpace(), KoColor::convertedTo(), KoColor::convertTo(), KisSharedPtr< T >::data(), KoColor::data(), distance(), Dither, KoColorSpace::fromNormalisedChannelsValue(), KisPropertiesConfiguration::getBool(), KisPropertiesConfiguration::getDouble(), KisPropertiesConfiguration::getInt(), KisFilterConfiguration::hasLocalResourcesSnapshot(), Index, KoColorSpaceRegistry::instance(), KisSwatch::isValid(), KIS_SAFE_ASSERT_RECOVER_NOOP, KIS_SAFE_ASSERT_RECOVER_RETURN, Lab, KoColorSpaceRegistry::lab16(), NearestColors, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::nextPixel(), KoColorSpace::normalisedChannelsValue(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::oldRawData(), KisFilterPalettizeConfiguration::palette(), palette, PerChannelOffset, KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::rawData(), KoColorSpaceRegistry::rgb16(), KisDitherUtil::setConfiguration(), KisDitherUtil::threshold(), KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::x(), and KisSequentialIteratorBase< IteratorPolicy, SourcePolicy, ProgressPolicy >::y().


The documentation for this class was generated from the following files: