1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the documentation of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:BSD$
9
** You may use this file under the terms of the BSD license as follows:
11
** "Redistribution and use in source and binary forms, with or without
12
** modification, are permitted provided that the following conditions are
14
** * Redistributions of source code must retain the above copyright
15
** notice, this list of conditions and the following disclaimer.
16
** * Redistributions in binary form must reproduce the above copyright
17
** notice, this list of conditions and the following disclaimer in
18
** the documentation and/or other materials provided with the
20
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21
** of its contributors may be used to endorse or promote products derived
22
** from this software without specific prior written permission.
25
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39
****************************************************************************/
44
Provides a main window for displaying a user-specified original image
45
with three color separations in a grid layout.
47
A main menu provides entries for selecting files, and adjusting the
48
brightness of the separations.
53
#include "finalwidget.h"
54
#include "screenwidget.h"
58
Constructor: initializes a default value for the brightness, creates
59
the main menu entries, and constructs a central widget that contains
60
enough space for images to be displayed.
65
setWindowTitle(tr("QImage Color Separations"));
70
setCentralWidget(createCentralWidget());
74
Creates a main menu with two entries: a File menu, to allow the image
75
to be selected, and a Brightness menu to allow the brightness of the
76
separations to be changed.
78
Initially, the Brightness menu items are disabled, but the first entry in
79
the menu is checked to reflect the default brightness.
82
void Viewer::createMenus()
84
fileMenu = new QMenu(tr("&File"), this);
85
brightnessMenu = new QMenu(tr("&Brightness"), this);
87
QAction *openAction = fileMenu->addAction(tr("&Open..."));
88
openAction->setShortcut(QKeySequence("Ctrl+O"));
89
saveAction = fileMenu->addAction(tr("&Save..."));
90
saveAction->setShortcut(QKeySequence("Ctrl+S"));
91
saveAction->setEnabled(false);
92
QAction *quitAction = fileMenu->addAction(tr("E&xit"));
93
quitAction->setShortcut(QKeySequence("Ctrl+Q"));
95
QAction *noBrightness = brightnessMenu->addAction(tr("&0%"));
96
noBrightness->setCheckable(true);
97
QAction *quarterBrightness = brightnessMenu->addAction(tr("&25%"));
98
quarterBrightness->setCheckable(true);
99
QAction *halfBrightness = brightnessMenu->addAction(tr("&50%"));
100
halfBrightness->setCheckable(true);
101
QAction *threeQuartersBrightness = brightnessMenu->addAction(tr("&75%"));
102
threeQuartersBrightness->setCheckable(true);
103
QAction *fullBrightness = brightnessMenu->addAction(tr("&100%"));
104
fullBrightness->setCheckable(true);
106
menuMap[noBrightness] = None;
107
menuMap[quarterBrightness] = Quarter;
108
menuMap[halfBrightness] = Half;
109
menuMap[threeQuartersBrightness] = ThreeQuarters;
110
menuMap[fullBrightness] = Full;
112
currentBrightness = fullBrightness;
113
currentBrightness->setChecked(true);
114
brightnessMenu->setEnabled(false);
116
menuBar()->addMenu(fileMenu);
117
menuBar()->addMenu(brightnessMenu);
119
connect(openAction, SIGNAL(triggered()), this, SLOT(chooseFile()));
120
connect(saveAction, SIGNAL(triggered()), this, SLOT(saveImage()));
121
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
122
connect(brightnessMenu, SIGNAL(triggered(QAction *)), this,
123
SLOT(setBrightness(QAction *)));
127
Constructs a central widget for the window consisting of a two-by-two
128
grid of labels, each of which will contain an image. We restrict the
129
size of the labels to 256 pixels, and ensure that the window cannot
133
QFrame* Viewer::createCentralWidget()
135
QFrame* frame = new QFrame(this);
136
grid = new QGridLayout(frame);
140
layout()->setSizeConstraint(QLayout::SetFixedSize);
142
QSize labelSize(256, 256);
144
finalWidget = new FinalWidget(frame, tr("Final image"), labelSize);
146
cyanWidget = new ScreenWidget(frame, Qt::cyan, tr("Cyan"),
147
ScreenWidget::Cyan, labelSize);
148
magentaWidget = new ScreenWidget(frame, Qt::magenta, tr("Magenta"),
149
ScreenWidget::Magenta, labelSize);
150
yellowWidget = new ScreenWidget(frame, Qt::yellow, tr("Yellow"),
151
ScreenWidget::Yellow, labelSize);
153
connect(cyanWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
154
connect(magentaWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
155
connect(yellowWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
157
grid->addWidget(finalWidget, 0, 0, Qt::AlignTop | Qt::AlignHCenter);
158
grid->addWidget(cyanWidget, 0, 1, Qt::AlignTop | Qt::AlignHCenter);
159
grid->addWidget(magentaWidget, 1, 0, Qt::AlignTop | Qt::AlignHCenter);
160
grid->addWidget(yellowWidget, 1, 1, Qt::AlignTop | Qt::AlignHCenter);
166
Provides a dialog window to allow the user to specify an image file.
167
If a file is selected, the appropriate function is called to process
171
void Viewer::chooseFile()
173
QString imageFile = QFileDialog::getOpenFileName(this,
174
tr("Choose an image file to open"), path, tr("Images (*.*)"));
176
if (!imageFile.isEmpty()) {
177
openImageFile(imageFile);
183
Changes the value of the brightness according to the entry selected in the
184
Brightness menu. The selected entry is checked, and the previously selected
187
The color separations are updated to use the new value for the brightness.
190
void Viewer::setBrightness(QAction *action)
192
if (!menuMap.contains(action) || scaledImage.isNull())
195
Brightness amount = menuMap[action];
199
brightness = 0; break;
201
brightness = 64; break;
203
brightness = 128; break;
205
brightness = 191; break;
207
brightness = 255; break;
211
currentBrightness->setChecked(false);
212
currentBrightness = action;
213
currentBrightness->setChecked(true);
219
Load the image from the file given, and create four pixmaps based
220
on the original image.
222
The window caption is set, and the Brightness menu enabled if the image file
226
void Viewer::openImageFile(QString &imageFile)
228
QImage originalImage;
230
if (originalImage.load(imageFile)) {
231
setWindowTitle(imageFile);
232
//menuBar()->setItemEnabled(brightnessMenuId, true);
233
saveAction->setEnabled(true);
234
brightnessMenu->setEnabled(true);
236
/* Note: the ScaleMin value may be different for Qt 4. */
237
scaledImage = originalImage.scaled(256, 256, Qt::KeepAspectRatio);
239
cyanWidget->setImage(scaledImage);
240
magentaWidget->setImage(scaledImage);
241
yellowWidget->setImage(scaledImage);
245
(void) QMessageBox::warning(this, tr("Cannot open file"),
246
tr("The selected file could not be opened."),
247
QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton);
251
Creates an image by combining the contents of the three screens
252
to present a page preview.
254
The image associated with each screen is separated into cyan,
255
magenta, and yellow components. We add up the values for each
256
component from the three screen images, and subtract the totals
257
from the maximum value for each corresponding primary color.
260
void Viewer::createImage()
262
QImage newImage = scaledImage.copy();
264
QImage *image1 = cyanWidget->image();
265
QImage *image2 = magentaWidget->image();
266
QImage *image3 = yellowWidget->image();
267
int darkness = 255 - brightness;
269
for (int y = 0; y < newImage.height(); ++y) {
270
for (int x = 0; x < newImage.width(); ++x) {
272
// Create three screens, using the quantities of the source
273
// CMY components to determine how much of each of the
274
// inks are to be put on each screen.
275
QRgb p1(image1->pixel(x, y));
276
float cyan1 = 255 - qRed(p1);
277
float magenta1 = 255 - qGreen(p1);
278
float yellow1 = 255 - qBlue(p1);
280
QRgb p2(image2->pixel(x, y));
281
float cyan2 = 255 - qRed(p2);
282
float magenta2 = 255 - qGreen(p2);
283
float yellow2 = 255 - qBlue(p2);
285
QRgb p3(image3->pixel(x, y));
286
float cyan3 = 255 - qRed(p3);
287
float magenta3 = 255 - qGreen(p3);
288
float yellow3 = 255 - qBlue(p3);
291
qMax(255 - int(cyan1+cyan2+cyan3) - darkness, 0),
292
qMax(255 - int(magenta1+magenta2+magenta3) - darkness, 0),
293
qMax(255 - int(yellow1+yellow2+yellow3) - darkness, 0));
295
newImage.setPixel(x, y, newColor.rgb());
299
finalWidget->setPixmap(QPixmap::fromImage(newImage));
303
Provides a dialog window to allow the user to save the image file.
306
void Viewer::saveImage()
308
QString imageFile = QFileDialog::getSaveFileName(this,
309
tr("Choose a filename to save the image"), "", tr("Images (*.png)"));
311
QFileInfo info(imageFile);
313
if (!info.baseName().isEmpty()) {
314
QString newImageFile = QFileInfo(info.absoluteDir(),
315
info.baseName() + ".png").absoluteFilePath();
317
if (!finalWidget->pixmap()->save(newImageFile, "PNG"))
318
(void) QMessageBox::warning(this, tr("Cannot save file"),
319
tr("The file could not be saved."),
320
QMessageBox::Cancel, QMessageBox::NoButton,
321
QMessageBox::NoButton);
324
(void) QMessageBox::warning(this, tr("Cannot save file"),
325
tr("Please enter a valid filename."),
326
QMessageBox::Cancel, QMessageBox::NoButton,
327
QMessageBox::NoButton);