Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
viewer.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
4/*
5viewer.cpp
6
7Provides a main window for displaying a user-specified original image
8with three color separations in a grid layout.
9
10A main menu provides entries for selecting files, and adjusting the
11brightness of the separations.
12*/
13
14#include <QtWidgets>
15
16#include "finalwidget.h"
17#include "screenwidget.h"
18#include "viewer.h"
19
20/*
21 Constructor: initializes a default value for the brightness, creates
22 the main menu entries, and constructs a central widget that contains
23 enough space for images to be displayed.
24*/
25
27{
28 setWindowTitle(tr("QImage Color Separations"));
29
30 brightness = 255;
31
32 createMenus();
33 setCentralWidget(createCentralWidget());
34}
35
36/*
37 Creates a main menu with two entries: a File menu, to allow the image
38 to be selected, and a Brightness menu to allow the brightness of the
39 separations to be changed.
40
41 Initially, the Brightness menu items are disabled, but the first entry in
42 the menu is checked to reflect the default brightness.
43*/
44
45void Viewer::createMenus()
46{
47 fileMenu = new QMenu(tr("&File"), this);
48 brightnessMenu = new QMenu(tr("&Brightness"), this);
49
50 QAction *openAction = fileMenu->addAction(tr("&Open..."));
51 openAction->setShortcut(QKeySequence("Ctrl+O"));
52 saveAction = fileMenu->addAction(tr("&Save..."));
53 saveAction->setShortcut(QKeySequence("Ctrl+S"));
54 saveAction->setEnabled(false);
55 QAction *quitAction = fileMenu->addAction(tr("E&xit"));
56 quitAction->setShortcut(QKeySequence("Ctrl+Q"));
57
58 QAction *noBrightness = brightnessMenu->addAction(tr("&0%"));
59 noBrightness->setCheckable(true);
60 QAction *quarterBrightness = brightnessMenu->addAction(tr("&25%"));
61 quarterBrightness->setCheckable(true);
62 QAction *halfBrightness = brightnessMenu->addAction(tr("&50%"));
63 halfBrightness->setCheckable(true);
64 QAction *threeQuartersBrightness = brightnessMenu->addAction(tr("&75%"));
65 threeQuartersBrightness->setCheckable(true);
66 QAction *fullBrightness = brightnessMenu->addAction(tr("&100%"));
67 fullBrightness->setCheckable(true);
68
69 menuMap[noBrightness] = None;
70 menuMap[quarterBrightness] = Quarter;
71 menuMap[halfBrightness] = Half;
72 menuMap[threeQuartersBrightness] = ThreeQuarters;
73 menuMap[fullBrightness] = Full;
74
75 currentBrightness = fullBrightness;
76 currentBrightness->setChecked(true);
77 brightnessMenu->setEnabled(false);
78
79 menuBar()->addMenu(fileMenu);
80 menuBar()->addMenu(brightnessMenu);
81
82 connect(openAction, &QAction::triggered, this, &Viewer::chooseFile);
83 connect(saveAction, &QAction::triggered, this, &Viewer::saveImage);
84 connect(quitAction, &QAction::triggered, qApp, QApplication::quit);
85 connect(brightnessMenu, &QMenu::triggered,
86 this, &Viewer::setBrightness);
87}
88
89/*
90 Constructs a central widget for the window consisting of a two-by-two
91 grid of labels, each of which will contain an image. We restrict the
92 size of the labels to 256 pixels, and ensure that the window cannot
93 be resized.
94*/
95
96QFrame* Viewer::createCentralWidget()
97{
98 QFrame* frame = new QFrame(this);
99 grid = new QGridLayout(frame);
100 grid->setSpacing(8);
101
102 layout()->setSizeConstraint(QLayout::SetFixedSize);
103
104 QSize labelSize(256, 256);
105
106 finalWidget = new FinalWidget(frame, tr("Final image"), labelSize);
107
108 cyanWidget = new ScreenWidget(frame, Qt::cyan, tr("Cyan"),
109 ScreenWidget::Cyan, labelSize);
110 magentaWidget = new ScreenWidget(frame, Qt::magenta, tr("Magenta"),
111 ScreenWidget::Magenta, labelSize);
112 yellowWidget = new ScreenWidget(frame, Qt::yellow, tr("Yellow"),
113 ScreenWidget::Yellow, labelSize);
114
115 connect(cyanWidget, &ScreenWidget::imageChanged, this, &Viewer::createImage);
116 connect(magentaWidget, &ScreenWidget::imageChanged, this, &Viewer::createImage);
117 connect(yellowWidget, &ScreenWidget::imageChanged, this, &Viewer::createImage);
118
119 grid->addWidget(finalWidget, 0, 0, Qt::AlignTop | Qt::AlignHCenter);
120 grid->addWidget(cyanWidget, 0, 1, Qt::AlignTop | Qt::AlignHCenter);
121 grid->addWidget(magentaWidget, 1, 0, Qt::AlignTop | Qt::AlignHCenter);
122 grid->addWidget(yellowWidget, 1, 1, Qt::AlignTop | Qt::AlignHCenter);
123
124 return frame;
125}
126
127/*
128 Provides a dialog window to allow the user to specify an image file.
129 If a file is selected, the appropriate function is called to process
130 and display it.
131*/
132
133void Viewer::chooseFile()
134{
135 QString imageFile = QFileDialog::getOpenFileName(this,
136 tr("Choose an image file to open"), path, tr("Images (*.*)"));
137
138 if (!imageFile.isEmpty()) {
139 openImageFile(imageFile);
140 path = imageFile;
141 }
142}
143
144/*
145 Changes the value of the brightness according to the entry selected in the
146 Brightness menu. The selected entry is checked, and the previously selected
147 entry is unchecked.
148
149 The color separations are updated to use the new value for the brightness.
150*/
151
152void Viewer::setBrightness(QAction *action)
153{
154 if (!menuMap.contains(action) || scaledImage.isNull())
155 return;
156
157 Brightness amount = menuMap[action];
158
159 switch (amount) {
160 case None:
161 brightness = 0; break;
162 case Quarter:
163 brightness = 64; break;
164 case Half:
165 brightness = 128; break;
166 case ThreeQuarters:
167 brightness = 191; break;
168 case Full:
169 brightness = 255; break;
170 default: return;
171 }
172
173 currentBrightness->setChecked(false);
174 currentBrightness = action;
175 currentBrightness->setChecked(true);
176
178}
179
180/*
181 Load the image from the file given, and create four pixmaps based
182 on the original image.
183
184 The window caption is set, and the Brightness menu enabled if the image file
185 can be loaded.
186*/
187
188void Viewer::openImageFile(QString &imageFile)
189{
190 QImage originalImage;
191
192 if (originalImage.load(imageFile)) {
193 setWindowTitle(imageFile);
194 //menuBar()->setItemEnabled(brightnessMenuId, true);
195 saveAction->setEnabled(true);
196 brightnessMenu->setEnabled(true);
197
198 /* Note: the ScaleMin value may be different for Qt 4. */
199 scaledImage = originalImage.scaled(256, 256, Qt::KeepAspectRatio);
200
201 cyanWidget->setImage(scaledImage);
202 magentaWidget->setImage(scaledImage);
203 yellowWidget->setImage(scaledImage);
205 }
206 else
207 (void) QMessageBox::warning(this, tr("Cannot open file"),
208 tr("The selected file could not be opened."),
209 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton);
210}
211
212/*
213 Creates an image by combining the contents of the three screens
214 to present a page preview.
215
216 The image associated with each screen is separated into cyan,
217 magenta, and yellow components. We add up the values for each
218 component from the three screen images, and subtract the totals
219 from the maximum value for each corresponding primary color.
220*/
221
223{
224 QImage newImage = scaledImage.copy();
225
226 QImage *image1 = cyanWidget->image();
227 QImage *image2 = magentaWidget->image();
228 QImage *image3 = yellowWidget->image();
229 int darkness = 255 - brightness;
230
231 for (int y = 0; y < newImage.height(); ++y) {
232 for (int x = 0; x < newImage.width(); ++x) {
233
234 // Create three screens, using the quantities of the source
235 // CMY components to determine how much of each of the
236 // inks are to be put on each screen.
237 QRgb p1(image1->pixel(x, y));
238 float cyan1 = 255 - qRed(p1);
239 float magenta1 = 255 - qGreen(p1);
240 float yellow1 = 255 - qBlue(p1);
241
242 QRgb p2(image2->pixel(x, y));
243 float cyan2 = 255 - qRed(p2);
244 float magenta2 = 255 - qGreen(p2);
245 float yellow2 = 255 - qBlue(p2);
246
247 QRgb p3(image3->pixel(x, y));
248 float cyan3 = 255 - qRed(p3);
249 float magenta3 = 255 - qGreen(p3);
250 float yellow3 = 255 - qBlue(p3);
251
252 QColor newColor(
253 qMax(255 - int(cyan1+cyan2+cyan3) - darkness, 0),
254 qMax(255 - int(magenta1+magenta2+magenta3) - darkness, 0),
255 qMax(255 - int(yellow1+yellow2+yellow3) - darkness, 0));
256
257 newImage.setPixel(x, y, newColor.rgb());
258 }
259 }
260
261 finalWidget->setPixmap(QPixmap::fromImage(newImage));
262}
263
264/*
265 Provides a dialog window to allow the user to save the image file.
266*/
267
269{
270 QString imageFile = QFileDialog::getSaveFileName(this,
271 tr("Choose a filename to save the image"), "", tr("Images (*.png)"));
272
273 QFileInfo info(imageFile);
274
275 if (!info.baseName().isEmpty()) {
276 QString newImageFile = QFileInfo(info.absoluteDir(),
277 info.baseName() + ".png").absoluteFilePath();
278
279 if (!finalWidget->pixmap().save(newImageFile, "PNG"))
280 (void) QMessageBox::warning(this, tr("Cannot save file"),
281 tr("The file could not be saved."),
282 QMessageBox::Cancel, QMessageBox::NoButton,
283 QMessageBox::NoButton);
284 }
285 else
286 (void) QMessageBox::warning(this, tr("Cannot save file"),
287 tr("Please enter a valid filename."),
288 QMessageBox::Cancel, QMessageBox::NoButton,
289 QMessageBox::NoButton);
290}
void setBrightness(QAction *action)
Definition viewer.cpp:152
void saveImage()
Definition viewer.cpp:268
Viewer()
Definition viewer.cpp:26
void createImage()
Definition viewer.cpp:222