• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • krita API Reference
  • KDE Home
  • Contact Us
 

plugins/paintops/libpaintop

  • sources
  • kfour-appscomplete
  • krita
  • plugins
  • paintops
  • libpaintop
KisTextureMaskInfo.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <[email protected]>
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 
7 #include "KisTextureMaskInfo.h"
8 
9 #include <kis_paintop_settings.h>
10 #include <resources/KoPattern.h>
11 #include "kis_embedded_pattern_manager.h"
12 
13 #include <KoColorSpace.h>
14 #include <KoColorSpaceRegistry.h>
15 
16 #include <kis_algebra_2d.h>
17 #include <kis_lod_transform.h>
18 #include <kis_iterator_ng.h>
19 
20 #include <QGlobalStatic>
21 
22 /**********************************************************************/
23 /* KisTextureMaskInfo */
24 /**********************************************************************/
25 
26 
27 KisTextureMaskInfo::KisTextureMaskInfo(int levelOfDetail, bool preserveAlpha)
28  : m_levelOfDetail(levelOfDetail),
29  m_preserveAlpha(preserveAlpha)
30 {
31 }
32 
33 KisTextureMaskInfo::KisTextureMaskInfo(const KisTextureMaskInfo &rhs)
34  : m_levelOfDetail(rhs.m_levelOfDetail),
35  m_pattern(rhs.m_pattern),
36  m_scale(rhs.m_scale),
37  m_brightness(rhs.m_brightness),
38  m_contrast(rhs.m_contrast),
39  m_neutralPoint(rhs.m_neutralPoint),
40  m_invert(rhs.m_invert),
41  m_cutoffLeft(rhs.m_cutoffLeft),
42  m_cutoffRight(rhs.m_cutoffRight),
43  m_cutoffPolicy(rhs.m_cutoffPolicy),
44  m_preserveAlpha(rhs.m_preserveAlpha)
45 {
46 }
47 
48 KisTextureMaskInfo::~KisTextureMaskInfo()
49 {
50 }
51 
52 bool operator==(const KisTextureMaskInfo &lhs, const KisTextureMaskInfo &rhs) {
53  return
54  lhs.m_levelOfDetail == rhs.m_levelOfDetail &&
55  (lhs.m_pattern == rhs.m_pattern ||
56  (lhs.m_pattern &&
57  rhs.m_pattern &&
58  lhs.m_pattern->md5() == rhs.m_pattern->md5())) &&
59  qFuzzyCompare(lhs.m_scale, rhs.m_scale) &&
60  qFuzzyCompare(lhs.m_brightness, rhs.m_brightness) &&
61  qFuzzyCompare(lhs.m_contrast, rhs.m_contrast) &&
62  qFuzzyCompare(lhs.m_neutralPoint, rhs.m_neutralPoint) &&
63  lhs.m_invert == rhs.m_invert &&
64  lhs.m_cutoffLeft == rhs.m_cutoffLeft &&
65  lhs.m_cutoffRight == rhs.m_cutoffRight &&
66  lhs.m_cutoffPolicy == rhs.m_cutoffPolicy &&
67  lhs.m_preserveAlpha == rhs.m_preserveAlpha;
68 }
69 
70 KisTextureMaskInfo &KisTextureMaskInfo::operator=(const KisTextureMaskInfo &rhs)
71 {
72  m_levelOfDetail = rhs.m_levelOfDetail;
73  m_pattern = rhs.m_pattern;
74  m_scale = rhs.m_scale;
75  m_brightness = rhs.m_brightness;
76  m_contrast = rhs.m_contrast;
77  m_neutralPoint = rhs.m_neutralPoint;
78  m_invert = rhs.m_invert;
79  m_cutoffLeft = rhs.m_cutoffLeft;
80  m_cutoffRight = rhs.m_cutoffRight;
81  m_cutoffPolicy = rhs.m_cutoffPolicy;
82  m_preserveAlpha = rhs.m_preserveAlpha;
83 
84  return *this;
85 }
86 
87 int KisTextureMaskInfo::levelOfDetail() const {
88  return m_levelOfDetail;
89 }
90 
91 bool KisTextureMaskInfo::hasMask() const {
92  return m_mask;
93 }
94 
95 KisPaintDeviceSP KisTextureMaskInfo::mask() {
96  return m_mask;
97 }
98 
99 QRect KisTextureMaskInfo::maskBounds() const {
100  return m_maskBounds;
101 }
102 
103 bool KisTextureMaskInfo::fillProperties(const KisPropertiesConfigurationSP setting, KisResourcesInterfaceSP resourcesInterface)
104 {
105 
106  if (!setting->hasProperty("Texture/Pattern/PatternMD5")) {
107  return false;
108  }
109 
110  m_pattern = KisEmbeddedPatternManager::tryFetchPattern(setting, resourcesInterface);
111 
112  if (!m_pattern) {
113  warnKrita << "WARNING: Couldn't load the pattern for a stroke";
114  return false;
115  }
116 
117  m_scale = setting->getDouble("Texture/Pattern/Scale", 1.0);
118  m_brightness = setting->getDouble("Texture/Pattern/Brightness");
119  m_contrast = setting->getDouble("Texture/Pattern/Contrast", 1.0);
120  m_neutralPoint = setting->getDouble("Texture/Pattern/NeutralPoint", 0.5);
121  m_invert = setting->getBool("Texture/Pattern/Invert");
122  m_cutoffLeft = setting->getInt("Texture/Pattern/CutoffLeft", 0);
123  m_cutoffRight = setting->getInt("Texture/Pattern/CutoffRight", 255);
124  m_cutoffPolicy = setting->getInt("Texture/Pattern/CutoffPolicy", 0);
125 
126  return true;
127 }
128 
129 void KisTextureMaskInfo::recalculateMask()
130 {
131  if (!m_pattern) return;
132 
133  const KoColorSpace* cs;
134  const bool useAlpha = m_pattern->hasAlpha() && m_preserveAlpha;
135 
136  if (useAlpha) {
137  cs = KoColorSpaceRegistry::instance()->rgb8();
138  } else {
139  cs = KoColorSpaceRegistry::instance()->alpha8();
140  }
141  if (!m_mask) {
142  m_mask = new KisPaintDevice(cs);
143  }
144 
145  QImage mask = m_pattern->pattern();
146 
147  if ((mask.format() != QImage::Format_RGB32) |
148  (mask.format() != QImage::Format_ARGB32)) {
149 
150  mask = mask.convertToFormat(QImage::Format_ARGB32);
151  }
152 
153  qreal scale = m_scale * KisLodTransform::lodToScale(m_levelOfDetail);
154 
155  if (!qFuzzyCompare(scale, 0.0) && !qFuzzyCompare(scale, 1.0)) {
156  QTransform tf;
157  tf.scale(scale, scale);
158  QRect rc = KisAlgebra2D::ensureRectNotSmaller(tf.mapRect(mask.rect()), QSize(2,2));
159  mask = mask.scaled(rc.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
160  } else {
161  // detach the mask from the file loaded from the storage
162  mask = QImage(mask);
163  }
164 
165  QRgb* pixel = reinterpret_cast<QRgb*>(mask.bits());
166  const int width = mask.width();
167  const int height = mask.height();
168 
169  KisHLineIteratorSP iter = m_mask->createHLineIteratorNG(0, 0, width);
170 
171  for (int row = 0; row < height; ++row) {
172  for (int col = 0; col < width; ++col) {
173  const QRgb currentPixel = pixel[row * width + col];
174 
175  const int red = qRed(currentPixel);
176  const int green = qGreen(currentPixel);
177  const int blue = qBlue(currentPixel);
178  float alpha = qAlpha(currentPixel) / 255.0;
179 
180  const int grayValue = (red * 11 + green * 16 + blue * 5) / 32;
181  float maskValue = (grayValue / 255.0) * alpha + (1 - alpha);
182 
183  maskValue = maskValue - m_brightness;
184 
185  maskValue = ((maskValue - 0.5)*m_contrast)+0.5;
186 
187  if (maskValue > 1.0) {maskValue = 1;}
188  else if (maskValue < 0) {maskValue = 0;}
189 
190  if (m_invert) {
191  maskValue = 1 - maskValue;
192  }
193 
194  maskValue = qBound(0.0f, maskValue, 1.0f);
195 
196  float neutralAdjustedValue;
197 
198  //Adjust neutral point in linear fashion. Uses separate linear equations from 0 to neutralPoint, and neutralPoint to 1,
199  //to prevent loss of detail (clipping).
200  if (m_neutralPoint == 1 || (m_neutralPoint != 0 && maskValue <= m_neutralPoint)) {
201  neutralAdjustedValue = maskValue / (2 * m_neutralPoint);
202  } else {
203  neutralAdjustedValue = 0.5 + (maskValue - m_neutralPoint) / (2 - 2 * m_neutralPoint);
204  }
205 
206  if (m_cutoffPolicy == 1 && (neutralAdjustedValue < (m_cutoffLeft / 255.0) || neutralAdjustedValue >(m_cutoffRight / 255.0))) {
207  // mask out the dab if it's outside the pattern's cuttoff points
208  alpha = OPACITY_TRANSPARENT_F;
209  if (!useAlpha) {
210  neutralAdjustedValue = alpha;
211  }
212  } else if (m_cutoffPolicy == 2 && (neutralAdjustedValue < (m_cutoffLeft / 255.0) || neutralAdjustedValue >(m_cutoffRight / 255.0))) {
213  alpha = OPACITY_OPAQUE_F;
214  if (!useAlpha) {
215  neutralAdjustedValue = alpha;
216  }
217  }
218 
219  if (useAlpha) {
220  int finalValue = qRound(neutralAdjustedValue * 255.0);
221  pixel[row * width + col] = QColor(finalValue, finalValue, finalValue, qRound(alpha * 255.0)).rgba();
222  } else {
223  cs->setOpacity(iter->rawData(), neutralAdjustedValue, 1);
224  iter->nextPixel();
225  }
226  }
227  if (!useAlpha) {
228  iter->nextRow();
229  }
230  }
231  if (useAlpha) {
232  m_mask->convertFromQImage(mask, 0);
233  }
234  m_maskBounds = QRect(0, 0, width, height);
235 }
236 
237 bool KisTextureMaskInfo::hasAlpha() {
238  return m_pattern->hasAlpha();
239 }
240 
241 /**********************************************************************/
242 /* KisTextureMaskInfoCache */
243 /**********************************************************************/
244 
245 Q_GLOBAL_STATIC(KisTextureMaskInfoCache, s_instance)
246 
247 KisTextureMaskInfoCache *KisTextureMaskInfoCache::instance()
248 {
249  return s_instance;
250 }
251 
252 KisTextureMaskInfoSP KisTextureMaskInfoCache::fetchCachedTextureInfo(KisTextureMaskInfoSP info) {
253  QMutexLocker locker(&m_mutex);
254 
255  KisTextureMaskInfoSP &cachedInfo =
256  info->levelOfDetail() > 0 ? m_lodInfo : m_mainInfo;
257 
258  if (!cachedInfo || *cachedInfo != *info) {
259  cachedInfo = info;
260  cachedInfo->recalculateMask();
261  }
262 
263  return cachedInfo;
264 }
QColor
KisTextureMaskInfoCache
Definition: KisTextureMaskInfo.h:72
KisTextureMaskInfo::mask
KisPaintDeviceSP mask()
Definition: KisTextureMaskInfo.cpp:95
QRect::size
QSize size() const
QRect
KisTextureMaskInfo::maskBounds
QRect maskBounds() const
Definition: KisTextureMaskInfo.cpp:99
KisTextureMaskInfo.h
QSize
QSharedPointer
Definition: KisDabCacheUtils.h:110
KisTextureMaskInfo::levelOfDetail
int levelOfDetail() const
Definition: KisTextureMaskInfo.cpp:87
KisTextureMaskInfo::operator=
KisTextureMaskInfo & operator=(const KisTextureMaskInfo &rhs)
Definition: KisTextureMaskInfo.cpp:70
KisTextureMaskInfoCache::fetchCachedTextureInfo
KisTextureMaskInfoSP fetchCachedTextureInfo(KisTextureMaskInfoSP info)
Definition: KisTextureMaskInfo.cpp:252
kis_embedded_pattern_manager.h
QTransform
KisTextureMaskInfo::hasMask
bool hasMask() const
Definition: KisTextureMaskInfo.cpp:91
KisTextureMaskInfo
Definition: KisTextureMaskInfo.h:23
QTransform::scale
QTransform & scale(qreal sx, qreal sy)
KisTextureMaskInfo::hasAlpha
bool hasAlpha()
Definition: KisTextureMaskInfo.cpp:237
KisEmbeddedPatternManager::tryFetchPattern
static KoPatternSP tryFetchPattern(const KisPropertiesConfigurationSP setting, KisResourcesInterfaceSP resourcesInterface)
Definition: kis_embedded_pattern_manager.cpp:70
KisTextureMaskInfo::fillProperties
bool fillProperties(const KisPropertiesConfigurationSP setting, KisResourcesInterfaceSP resourcesInterface)
Definition: KisTextureMaskInfo.cpp:103
operator==
bool operator==(const KisTextureMaskInfo &lhs, const KisTextureMaskInfo &rhs)
Definition: KisTextureMaskInfo.cpp:52
QMutexLocker
KisTextureMaskInfo::~KisTextureMaskInfo
~KisTextureMaskInfo()
Definition: KisTextureMaskInfo.cpp:48
QTransform::mapRect
QRect mapRect(const QRect &rectangle) const
KisTextureMaskInfo::recalculateMask
void recalculateMask()
Definition: KisTextureMaskInfo.cpp:129
QImage
KisTextureMaskInfo::KisTextureMaskInfo
KisTextureMaskInfo(int levelOfDetail, bool preserveAlpha)
Definition: KisTextureMaskInfo.cpp:27
QColor::rgba
QRgb rgba() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Wed Jan 20 2021 23:47:25 by doxygen 1.8.16 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

plugins/paintops/libpaintop

Skip menu "plugins/paintops/libpaintop"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

krita API Reference

Skip menu "krita API Reference"
  • libs
  •   KritaBasicFlakes
  •   brush
  •   KritaUndo2
  •   KritaFlake
  •   image
  •   KritaPlugin
  •   Krita
  •   KritaPigment
  •   KritaResources
  •   KritaStore
  •   ui
  •   KritaWidgets
  •   KritaWidgetUtils
  • plugins
  •   Assitants
  •   Extensions
  •   Filters
  •   Generators
  •   Formats
  •           src
  •   PaintOps
  •     libpaintop

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal