File indexing completed on 2024-04-28 03:42:27
0001 /* 0002 SPDX-FileCopyrightText: 2023 Wolfgang Reissenberger <sterne-jaeger@openfuture.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "imagemask.h" 0008 #include "cmath" 0009 0010 ImageMask::ImageMask(const uint16_t width, const uint16_t height) 0011 { 0012 m_width = width; 0013 m_height = height; 0014 } 0015 0016 void ImageMask::setImageGeometry(const uint16_t width, const uint16_t height) 0017 { 0018 m_width = width; 0019 m_height = height; 0020 refresh(); 0021 } 0022 0023 bool ImageMask::isVisible(uint16_t posX, uint16_t posY) 0024 { 0025 return posX >= 0 && posX < m_width && posY >= 0 && posY < m_height; 0026 } 0027 0028 uint16_t ImageMask::width() const 0029 { 0030 return m_width; 0031 } 0032 0033 uint16_t ImageMask::height() const 0034 { 0035 return m_height; 0036 } 0037 0038 ImageRingMask::ImageRingMask(const float innerRadius, const float outerRadius, const uint16_t width, 0039 const uint16_t height) : ImageMask(width, height) 0040 { 0041 m_innerRadius = innerRadius; 0042 m_outerRadius = outerRadius; 0043 } 0044 0045 void ImageRingMask::refresh() 0046 { 0047 long const sqDiagonal = (long) (m_width * m_width / 4 + m_height * m_height / 4); 0048 m_InnerRadiusSquare = std::lround(sqDiagonal * innerRadius() * innerRadius()); 0049 m_OuterRadiusSquare = std::lround(sqDiagonal * outerRadius() * outerRadius()); 0050 } 0051 0052 bool ImageRingMask::isVisible(uint16_t posX, uint16_t posY) 0053 { 0054 bool result = ImageMask::isVisible(posX, posY); 0055 // outside of the image? 0056 if (result == false) 0057 return false; 0058 0059 double const x = posX - m_width / 2; 0060 double const y = posY - m_height / 2; 0061 0062 double const sqRadius = x * x + y * y; 0063 0064 return sqRadius >= m_InnerRadiusSquare && sqRadius < m_OuterRadiusSquare; 0065 } 0066 0067 float ImageRingMask::innerRadius() const 0068 { 0069 return m_innerRadius; 0070 } 0071 0072 void ImageRingMask::setInnerRadius(float newInnerRadius) 0073 { 0074 m_innerRadius = newInnerRadius; 0075 refresh(); 0076 } 0077 0078 float ImageRingMask::outerRadius() const 0079 { 0080 return m_outerRadius; 0081 } 0082 0083 void ImageRingMask::setOuterRadius(float newOuterRadius) 0084 { 0085 m_outerRadius = newOuterRadius; 0086 refresh(); 0087 } 0088 0089 ImageMosaicMask::ImageMosaicMask(const uint16_t tileWidth, const uint16_t space, const uint16_t width, 0090 const uint16_t height) : ImageMask(width, height) 0091 { 0092 m_tileWidth = tileWidth; 0093 m_space = space; 0094 // initialize the tiles 0095 for (int i = 0; i < 9; i++) 0096 m_tiles.append(QRect()); 0097 } 0098 0099 bool ImageMosaicMask::isVisible(uint16_t posX, uint16_t posY) 0100 { 0101 for (auto it = m_tiles.begin(); it != m_tiles.end(); it++) 0102 if (it->contains(posX, posY)) 0103 return true; 0104 // no matching tile found 0105 return false; 0106 } 0107 0108 QPointF ImageMosaicMask::translate(QPointF original) 0109 { 0110 int pos = 0; 0111 const auto tileWidth = std::lround(m_width * m_tileWidth / 100); 0112 const float spacex = (m_width - 3 * tileWidth - 2 * m_space) / 2; 0113 const float spacey = (m_height - 3 * tileWidth - 2 * m_space) / 2; 0114 for (QRect tile : m_tiles) 0115 { 0116 // matrix tile position 0117 int posx = pos % 3; 0118 int posy = pos++ / 3; 0119 if (tile.contains(original.x(), original.y())) 0120 return QPointF(original.x() - posx * spacex, original.y() - posy * spacey); 0121 } 0122 // this should not happen for filtered positions 0123 return QPointF(-1, -1); 0124 } 0125 0126 const QVector<QRect> ImageMosaicMask::tiles() 0127 { 0128 return m_tiles; 0129 } 0130 0131 float ImageMosaicMask::tileWidth() const 0132 { 0133 return m_tileWidth; 0134 } 0135 0136 void ImageMosaicMask::setTileWidth(float newTileWidth) 0137 { 0138 m_tileWidth = newTileWidth; 0139 refresh(); 0140 } 0141 0142 uint16_t ImageMosaicMask::space() const 0143 { 0144 return m_space; 0145 } 0146 0147 void ImageMosaicMask::setSpace(uint16_t newSpace) 0148 { 0149 m_space = newSpace; 0150 refresh(); 0151 } 0152 0153 void ImageMosaicMask::refresh() 0154 { 0155 m_tiles.clear(); 0156 uint16_t tileWidth = std::lround(m_width * m_tileWidth / 100); 0157 if (m_width > 0 && m_height > 0) 0158 { 0159 const auto x1 = std::lround((m_width - tileWidth) / 2); 0160 const auto x2 = m_width - tileWidth - 1; 0161 const auto y1 = std::lround((m_height - tileWidth) / 2); 0162 const auto y2 = m_height - tileWidth - 1; 0163 0164 m_tiles.append(QRect(0, 0, tileWidth, tileWidth)); 0165 m_tiles.append(QRect(x1, 0, tileWidth, tileWidth)); 0166 m_tiles.append(QRect(x2, 0, tileWidth, tileWidth)); 0167 m_tiles.append(QRect(0, y1, tileWidth, tileWidth)); 0168 m_tiles.append(QRect(x1, y1, tileWidth, tileWidth)); 0169 m_tiles.append(QRect(x2, y1, tileWidth, tileWidth)); 0170 m_tiles.append(QRect(0, y2, tileWidth, tileWidth)); 0171 m_tiles.append(QRect(x1, y2, tileWidth, tileWidth)); 0172 m_tiles.append(QRect(x2, y2, tileWidth, tileWidth)); 0173 } 0174 }