File indexing completed on 2024-06-23 04:27:08
0001 /* 0002 * KDE. Krita Project. 0003 * 0004 * SPDX-FileCopyrightText: 2021 Deif Lou <ginoba@gmail.com> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #ifndef KISSCREENTONEGENERATORTEMPLATESAMPLER_H 0010 #define KISSCREENTONEGENERATORTEMPLATESAMPLER_H 0011 0012 #include <QtGlobal> 0013 #include <QVector> 0014 #include <QTransform> 0015 0016 #include <cmath> 0017 0018 template <typename Template> 0019 class KisScreentoneGeneratorAlignedTemplateSampler 0020 { 0021 public: 0022 KisScreentoneGeneratorAlignedTemplateSampler(const Template &the_template) 0023 : m_template(the_template) 0024 {} 0025 0026 qreal operator()(qreal x, qreal y) const 0027 { 0028 // Get the coordinates in template space 0029 QPointF p( 0030 x + std::round(m_template.screenPosition().x()), 0031 y + std::round(m_template.screenPosition().y()) 0032 ); 0033 // Get the coordinates in screen space 0034 const QPointF screenPos = m_template.templateToScreenTransform().map(p); 0035 // Get x/y indices in macrocell units or the current macrocell tile 0036 // position 0037 const qreal a = -std::floor(screenPos.x() / static_cast<qreal>(m_template.macrocellSize().width())); 0038 const qreal b = -std::floor(screenPos.y() / static_cast<qreal>(m_template.macrocellSize().height())); 0039 // Get the correspondent point in the (0, 0) macrocell tile 0040 p += QPointF(a * m_template.v1().x() + b * m_template.v2().x(), a * m_template.v1().y() + b * m_template.v2().y()); 0041 0042 const int i = static_cast<int>(std::floor(p.x())) + m_template.originOffset().x(); 0043 const int j = static_cast<int>(std::floor(p.y())) + m_template.originOffset().y(); 0044 const int macrocellPointIndex = j * m_template.templateSize().width() + i; 0045 return m_template.templateData()[macrocellPointIndex]; 0046 } 0047 0048 private: 0049 const Template& m_template; 0050 }; 0051 0052 template <typename Template> 0053 class KisScreentoneGeneratorUnAlignedTemplateSampler 0054 { 0055 public: 0056 KisScreentoneGeneratorUnAlignedTemplateSampler(const Template &the_template) 0057 : m_template(the_template) 0058 {} 0059 0060 qreal operator()(qreal x, qreal y) const 0061 { 0062 // Get the coordinates in screen space 0063 qreal xx, yy; 0064 m_template.imageToScreenTransform().map(x, y, &xx, &yy); 0065 // Convert to coordinate inside the macrocell 0066 xx -= std::floor(xx / m_template.macrocellSize().width()) * m_template.macrocellSize().width(); 0067 yy -= std::floor(yy / m_template.macrocellSize().height()) * m_template.macrocellSize().height(); 0068 // Get template coordinates 0069 QPointF templatePoint = m_template.screenToTemplateTransform().map(QPointF(xx, yy)) + 0070 m_template.originOffset(); 0071 0072 // Bilinear interpolation 0073 // Get integer coordinates of the template points to use in the interpolation 0074 const int ix0 = 0075 templatePoint.x() < 0.0 ? m_template.templateSize().width() - 1 : 0076 (templatePoint.x() >= m_template.templateSize().width() ? 0.0 : 0077 static_cast<int>(std::floor(templatePoint.x()))); 0078 const int iy0 = 0079 templatePoint.y() < 0.0 ? m_template.templateSize().height() - 1 : 0080 (templatePoint.y() >= m_template.templateSize().height() ? 0.0 : 0081 static_cast<int>(std::floor(templatePoint.y()))); 0082 const int ix1 = ix0 == m_template.templateSize().width() - 1 ? 0 : ix0 + 1; 0083 const int iy1 = iy0 == m_template.templateSize().height() - 1 ? 0 : iy0 + 1; 0084 // Get the template values for the points 0085 const qreal topLeftValue = m_template.templateData()[iy0 * m_template.templateSize().width() + ix0]; 0086 const qreal topRightValue = m_template.templateData()[iy0 * m_template.templateSize().width() + ix1]; 0087 const qreal bottomLeftValue = m_template.templateData()[iy1 * m_template.templateSize().width() + ix0]; 0088 const qreal bottomRightValue = m_template.templateData()[iy1 * m_template.templateSize().width() + ix1]; 0089 // Get the fractional part of the point to use in the interpolation 0090 const qreal fractionalX = templatePoint.x() - std::floor(templatePoint.x()); 0091 const qreal fractionalY = templatePoint.y() - std::floor(templatePoint.y()); 0092 // Perform bilinear interpolation 0093 const qreal a = topLeftValue * (1.0 - fractionalX) + topRightValue * fractionalX; 0094 const qreal b = bottomLeftValue * (1.0 - fractionalX) + bottomRightValue * fractionalX; 0095 const qreal c = a * (1.0 - fractionalY) + b * fractionalY; 0096 // ---- 0097 return c; 0098 } 0099 0100 private: 0101 const Template& m_template; 0102 }; 0103 0104 #endif