MauiKit Image Tools

imagedocument.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2020 Carl Schwan <carl@carlschwan.eu>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6
7#include "imagedocument.h"
8
9#include "commands/cropcommand.h"
10#include "commands/mirrorcommand.h"
11#include "commands/resizecommand.h"
12#include "commands/rotatecommand.h"
13#include "commands/colorcommands.h"
14#include <QDebug>
15
16ImageDocument::ImageDocument(QObject *parent)
17 : QObject(parent)
18{
19 m_changesApplied = true;
20
21 connect(this, &ImageDocument::pathChanged, this, [this](const QUrl &url) {
22 m_image = QImage(url.isLocalFile() ? url.toLocalFile() : url.toString());
23 m_originalImage = m_image;
24 m_edited = false;
25 Q_EMIT editedChanged();
26 Q_EMIT imageChanged();
27 });
28}
29
31{
32 while (!m_undos.empty()) {
33 const auto command = m_undos.pop();
34 if(m_undos.isEmpty())
35 m_image = command->undo(m_image);
36 delete command;
37 }
38
39 resetValues();
40 setEdited(false);
41 Q_EMIT imageChanged();
42}
43
44QImage ImageDocument::image() const
45{
46 return m_image;
47}
48
49bool ImageDocument::edited() const
50{
51 return m_edited;
52}
53
55{
56 if(m_undos.empty())
57 {
58 qDebug() << "No more commands to undo";
59 return;
60 }
61
62 const auto command = m_undos.pop();
63 m_image = command->undo();
64 m_originalImage = m_image;
65 delete command;
66 Q_EMIT imageChanged();
67 if (m_undos.empty()) {
68 setEdited(false);
69 }
70}
71
72void ImageDocument::crop(int x, int y, int width, int height)
73{
74 const auto command = new CropCommand(QRect(x, y, width, height));
75 m_image = command->redo(m_image);
76 m_undos.append(command);
77 setEdited(true);
78 Q_EMIT imageChanged();
79}
80
81void ImageDocument::resize(int width, int height)
82{
83 const auto command = new ResizeCommand(QSize(width, height));
84 m_image = command->redo(m_image);
85 m_undos.append(command);
86 setEdited(true);
87 Q_EMIT imageChanged();
88}
89
90void ImageDocument::mirror(bool horizontal, bool vertical)
91{
92 const auto command = new MirrorCommand(horizontal, vertical);
93 m_image = command->redo(m_image);
94
95 m_undos.append(command);
96 setEdited(true);
97 Q_EMIT imageChanged();
98}
99
101{
102 QTransform transform;
103 transform.rotate(angle);
104 const auto command = new RotateCommand(transform);
105 m_image = command->redo(m_image);
106 m_undos.append(command);
107 setEdited(true);
108 Q_EMIT imageChanged();
109}
110
112{
113
114
115
116 m_changesApplied = !value;
117 Q_EMIT changesAppliedChanged();
118
119 if (m_edited == value) {
120 return;
121 }
122 m_edited = value;
123 Q_EMIT editedChanged();
124}
125
127{
128 return m_originalImage.save(m_path.isLocalFile() ? m_path.toLocalFile() : m_path.toString());
129}
130
131bool ImageDocument::saveAs(const QUrl &location)
132{
133 return m_originalImage.save(location.isLocalFile() ? location.toLocalFile() : location.toString());
134}
135
136void ImageDocument::adjustBrightness(int value)
137{
138 if(value == m_brightness)
139 return;
140
141 auto oldBrightness = m_brightness;
142 m_brightness = value;
143 const auto command = new ColorCommands::Brightness(m_image, m_brightness, [this, oldBrightness]()
144 {
145 this->m_brightness = oldBrightness;
146 Q_EMIT brightnessChanged();
147 });
148 // command->setArea({0,0, 200, 200});
149 m_image = command->redo(m_originalImage);
150 m_undos.append(command);
151 Q_EMIT brightnessChanged();
152 setEdited(true);
153 Q_EMIT imageChanged();
154}
155
156void ImageDocument::adjustContrast(int value)
157{
158 if(value == m_contrast)
159 return;
160
161 auto oldContrast = m_contrast;
162 m_contrast = value;
163 const auto command = new ColorCommands::Contrast(m_image, m_contrast, [this, oldContrast]()
164 {
165 this->m_contrast = oldContrast;
166 Q_EMIT contrastChanged();
167 });
168
169 m_image = command->redo(m_originalImage);
170 m_undos.append(command);
171 setEdited(true);
172 Q_EMIT contrastChanged();
173 Q_EMIT imageChanged();
174}
175
176void ImageDocument::adjustSaturation(int value)
177{
178 if(m_image.isGrayscale())
179 return;
180
181 if(value == m_saturation)
182 return;
183
184 auto oldSaturation = m_saturation;
185 m_saturation = value;
186 const auto command = new ColorCommands::Saturation(m_image, m_saturation, [this, oldSaturation]()
187 {
188 this->m_saturation = oldSaturation;
189 Q_EMIT saturationChanged();
190 });
191
192 m_image = command->redo(m_originalImage);
193 m_undos.append(command);
194 setEdited(true);
195 Q_EMIT imageChanged();
196 Q_EMIT saturationChanged();
197}
198
199void ImageDocument::adjustHue(int value)
200{
201 qDebug() << "adjust HUE DOCUMENT" << value;
202 if(m_image.isGrayscale())
203 return;
204
205 if(value == m_hue)
206 return;
207
208 auto oldValue = m_hue;
209 m_hue = value;
210 const auto command = new ColorCommands::Hue(m_image, m_hue, [this, oldValue]()
211 {
212 this->m_hue = oldValue;
213 Q_EMIT hueChanged();
214 });
215
216 m_image = command->redo(m_originalImage);
217 m_undos.append(command);
218 setEdited(true);
219 Q_EMIT imageChanged();
220 Q_EMIT saturationChanged();
221}
222
223void ImageDocument::applyChanges()
224{
225 resetValues();
226
227 m_originalImage = m_image;
228 m_changesApplied = true;
229 Q_EMIT changesAppliedChanged();
230}
231
232int ImageDocument::brightness() const
233{
234 return m_brightness;
235}
236
237int ImageDocument::contrast() const
238{
239 return m_contrast;
240}
241
242int ImageDocument::saturation() const
243{
244 return m_saturation;
245}
246
247int ImageDocument::hue() const
248{
249 return m_hue;
250}
251
252QUrl ImageDocument::path() const
253{
254 return m_path;
255}
256
257void ImageDocument::setPath(const QUrl &path)
258{
259 m_path = path;
260 Q_EMIT pathChanged(path);
261}
262
263// #include "moc_imagedocument.cpp"
264
265QRectF ImageDocument::area() const
266{
267 return m_area;
268}
269
270void ImageDocument::setArea(const QRectF &newArea)
271{
272 if (m_area == newArea)
273 return;
274 m_area = newArea;
275 Q_EMIT areaChanged();
276}
277
278void ImageDocument::resetArea()
279{
280 setArea({}); // TODO: Adapt to use your actual default value
281}
282
283void ImageDocument::resetValues()
284{
285 m_contrast = 0;
286 m_brightness = 0;
287 m_saturation = 0;
288 m_hue = 0;
289 Q_EMIT hueChanged();
290 Q_EMIT saturationChanged();
291 Q_EMIT brightnessChanged();
292 Q_EMIT contrastChanged();
293}
294
295bool ImageDocument::changesApplied() const
296{
297 return m_changesApplied;
298}
CropCommand that crop the current image.
Definition cropcommand.h:18
Q_INVOKABLE void undo()
Undo the last edit on the images.
Q_INVOKABLE void rotate(int angle)
Rotate the image.
Q_INVOKABLE bool saveAs(const QUrl &location)
Save current edited image as a new image.
Q_INVOKABLE bool save()
Save current edited image in place.
Q_INVOKABLE void mirror(bool horizontal, bool vertical)
Mirror the image.
Q_INVOKABLE void crop(int x, int y, int width, int height)
Crop the image.
Q_INVOKABLE void cancel()
Cancel all the edit.
void setEdited(bool value)
Change the edited value.
Q_INVOKABLE void resize(int width, int height)
Resize the image.
MirrorCommand that mirror an image horizontally or vertically.
ResizeCommand that resizes the current image.
RotateCommand that rotates the current image.
Q_EMITQ_EMIT
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool isLocalFile() const const
QString toLocalFile() const const
QString toString(FormattingOptions options) const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:57:09 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.