File indexing completed on 2024-12-22 04:13:04
0001 /* 0002 * This file is part of the KDE project 0003 * 0004 * SPDX-FileCopyrightText: 2019 Carl Olsson <carl.olsson@gmail.com> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "KisDitherUtil.h" 0010 0011 #include <kis_filter_configuration.h> 0012 #include <kis_random_generator.h> 0013 #include <KisResourcesInterface.h> 0014 0015 KisDitherUtil::KisDitherUtil() 0016 : m_thresholdMode(ThresholdMode::Pattern), m_patternValueMode(PatternValueMode::Auto) 0017 , m_noiseSeed(0), m_patternUseAlpha(false), m_spread(1.0) 0018 { 0019 } 0020 0021 void KisDitherUtil::setThresholdMode(const ThresholdMode thresholdMode) 0022 { 0023 m_thresholdMode = thresholdMode; 0024 } 0025 0026 void KisDitherUtil::setPattern(const QString &md5sum, const QString &patternName, const PatternValueMode valueMode, KisResourcesInterfaceSP resourcesInterface) 0027 { 0028 m_patternValueMode = valueMode; 0029 0030 auto source = resourcesInterface->source<KoPattern>(ResourceType::Patterns); 0031 m_pattern = source.bestMatch(md5sum, "", patternName); 0032 0033 if (m_pattern && m_thresholdMode == ThresholdMode::Pattern && m_patternValueMode == PatternValueMode::Auto) { 0034 // Automatically pick between lightness-based and alpha-based patterns by whichever has maximum range 0035 qreal lightnessMin = 1.0, lightnessMax = 0.0; 0036 qreal alphaMin = 1.0, alphaMax = 0.0; 0037 const QImage &image = m_pattern->pattern(); 0038 for (int y = 0; y < image.height(); ++y) { 0039 for (int x = 0; x < image.width(); ++x) { 0040 const QColor pixel = image.pixelColor(x, y); 0041 lightnessMin = std::min(lightnessMin, pixel.lightnessF()); 0042 lightnessMax = std::max(lightnessMax, pixel.lightnessF()); 0043 alphaMin = std::min(alphaMin, pixel.alphaF()); 0044 alphaMax = std::max(alphaMax, pixel.alphaF()); 0045 } 0046 } 0047 m_patternUseAlpha = (alphaMax - alphaMin > lightnessMax - lightnessMin); 0048 } 0049 else { 0050 m_patternUseAlpha = (m_patternValueMode == PatternValueMode::Alpha); 0051 } 0052 } 0053 0054 void KisDitherUtil::setNoiseSeed(const quint64 &noiseSeed) 0055 { 0056 m_noiseSeed = noiseSeed; 0057 } 0058 0059 void KisDitherUtil::setSpread(const qreal &spread) 0060 { 0061 m_spread = spread; 0062 } 0063 0064 qreal KisDitherUtil::threshold(const QPoint &pos) 0065 { 0066 qreal threshold; 0067 if (m_thresholdMode == ThresholdMode::Pattern && m_pattern) { 0068 const QImage &image = m_pattern->pattern(); 0069 const QColor color = image.pixelColor(pos.x() % image.width(), pos.y() % image.height()); 0070 threshold = (m_patternUseAlpha ? color.alphaF() : color.lightnessF()); 0071 } 0072 else if (m_thresholdMode == ThresholdMode::Noise) { 0073 KisRandomGenerator random(m_noiseSeed); 0074 threshold = random.doubleRandomAt(pos.x(), pos.y()); 0075 } 0076 else threshold = 0.5; 0077 0078 return 0.5 - (m_spread / 2.0) + threshold * m_spread; 0079 } 0080 0081 void KisDitherUtil::setConfiguration(const KisFilterConfiguration &config, const QString &prefix) 0082 { 0083 setThresholdMode(ThresholdMode(config.getInt(prefix + "thresholdMode"))); 0084 setPattern(config.getString(prefix + "md5sum"), config.getString(prefix + "pattern"), PatternValueMode(config.getInt(prefix + "patternValueMode")), config.resourcesInterface()); 0085 setNoiseSeed(quint64(config.getInt(prefix + "noiseSeed"))); 0086 setSpread(config.getDouble(prefix + "spread")); 0087 }