Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_wdg_options_heightmap.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Victor Wåhlström <victor.wahlstrom@initiali.se>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6
8
9#include <QtMath>
10#include <QToolTip>
11
12#include <kis_assert.h>
13#include <kis_paint_layer.h>
14
15static constexpr quint32 nextPow2(quint32 n)
16{
17 return ((((((n - 1) | n >> 1) | n >> 2) | n >> 4) | n >> 8) | n >> 16) + 1 + (quint32)(n == 0);
18}
19
20static constexpr quint32 prevPow2(quint32 n)
21{
22 return nextPow2(n) >> 1;
23}
24
25static void showErrorTooltip(const QString &msg)
26{
27 QToolTip::showText(QCursor::pos(), i18n("Error: ") + msg);
28}
29
34
35KisWdgOptionsHeightmap::KisWdgOptionsHeightmap(QWidget *parent, bool export_mode)
36 : KisConfigWidget(parent)
37 , m_exportMode(export_mode)
38{
39 setupUi(this);
40
41 if (m_exportMode) {
42 dimensionsGroupBox->setVisible(false);
43 fileSizeDescLabel->setVisible(false);
44 fileSizeLabel->setVisible(false);
45 bppDescLabel->setVisible(false);
46 bppLabel->setVisible(false);
47 }
48 else {
49 connect(guessButton, SIGNAL(clicked(bool)), this, SLOT(guessDimensions()));
50 connect(widthInput, SIGNAL(valueChanged(int)), this, SLOT(widthChanged(int)));
51 connect(heightInput, SIGNAL(valueChanged(int)), this, SLOT(heightChanged(int)));
52 }
53}
54
56{
57 int endianness = cfg->getInt("endianness", 1);
58 if (endianness == 0) {
59 radioBig->setChecked(true);
60 }
61 else {
62 radioLittle->setChecked(true);
63 }
64}
65
67{
69 if (radioBig->isChecked()) {
70 cfg->setProperty("endianness", 0);
71 }
72 else {
73 cfg->setProperty("endianness", 1);
74 }
75 return cfg;
76}
77
78void KisWdgOptionsHeightmap::showEvent(QShowEvent *event)
79{
81 QWidget::showEvent(event);
82}
83
85{
86 if (m_exportMode)
87 return;
88 bool ok;
89 int fileSize = fileSizeLabel->text().toInt(&ok);
91 KIS_ASSERT_RECOVER_RETURN(fileSize > 0);
92 int w = widthInput->value();
93 int h = heightInput->value();
94
95 quint32 depth = bppLabel->text().toUInt(&ok);
97
98 QString old_status = statusLabel->text();
99
100 int bytesPerPixel = depth / 8;
101 int dataSize = w * h * bytesPerPixel;
102
103 bool status_ok = false;
104
105 QString fileMismatch = i18n("Input does not match file size");
106 if (w == 0 && h == 0) {
107 statusLabel->setText(i18n("Please specify width and height"));
108 }
109 else if (w == 0) {
110 statusLabel->setText(i18n("Please specify width"));
111 }
112 else if (h == 0) {
113 statusLabel->setText(i18n("Please specify height"));
114 }
115 else if (dataSize != fileSize) {
116 statusLabel->setText(fileMismatch);
117 }
118 else {
119 statusLabel->setText("");
120 status_ok = true;
121 }
122
123 if (old_status.compare(statusLabel->text()) != 0) {
124 Q_EMIT statusUpdated(status_ok);
125 }
126}
127
129{
130 Q_UNUSED(i);
131 updateStatus();
132}
133
135{
136 Q_UNUSED(i);
137 updateStatus();
138}
139
141{
142 quint32 w = widthInput->value();
143 quint32 h = heightInput->value();
144
145 bool ok;
146 quint32 fileSize = fileSizeLabel->text().toUInt(&ok);
148
149 quint32 depth = bppLabel->text().toUInt(&ok);
151
152 quint32 bytesPerPixel = depth / 8;
153
154 w = widthInput->text().toUInt(&ok);
156
157 h = heightInput->text().toUInt(&ok);
159
160 quint32 dimensions = fileSize / bytesPerPixel;
161
162 if (w > 0 && h > 0) {
163 if (w * h == dimensions) {
164 // toggle landscape/portrait orientation
165 widthInput->setValue(h);
166 heightInput->setValue(w);
167 }
168 }
169 else if (w == 0 && h == 0) {
170 quint32 r = (quint32)(qFloor(qSqrt(dimensions) + 0.5));
171
172 // First guess, square image?
173 if (r*r == dimensions) {
174 widthInput->setValue(r);
175 heightInput->setValue(r);
176 }
177 else {
178 // second guess, power of two?
179 w = prevPow2(r);
180 h = dimensions / w + (dimensions % w);
181 if (w * h != dimensions) {
182 showErrorTooltip(i18n("Too many possible combinations. Input a width or height and try again."));
183 return;
184 }
185
186 // prefer landscape orientation
187 widthInput->setValue(w > h ? w : h);
188 heightInput->setValue(w > h ? h : w);
189
190 // TODO: cycle through other pow2 combinations if called multiple times?
191 }
192 }
193 else if (w > 0) {
194 if (w > dimensions) {
195 showErrorTooltip(i18n("Width exceeds available pixels."));
196 return;
197 }
198 h = dimensions / w + (dimensions % w);
199 if (w * h != dimensions) {
200 showErrorTooltip(i18n("Unable to calculate an appropriate height. File does not contain enough pixels to form a rectangle."));
201 return;
202 }
203 heightInput->setValue(h);
204 }
205 else {
206 if (h > dimensions) {
207 showErrorTooltip(i18n("Height exceeds available pixels."));
208 return;
209 }
210 w = dimensions / h + (dimensions % h);
211 if (w * h != dimensions) {
212 showErrorTooltip(i18n("Unable to calculate an appropriate width. File does not contain enough pixels to form a rectangle."));
213 return;
214 }
215 widthInput->setValue(w);
216 }
217}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KisPropertiesConfigurationSP configuration() const override
void statusUpdated(bool status)
void setConfiguration(const KisPropertiesConfigurationSP cfg) override
void showEvent(QShowEvent *event) override
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
static void showErrorTooltip(const QString &msg)
static constexpr quint32 prevPow2(quint32 n)
static constexpr quint32 nextPow2(quint32 n)