source: trunk/doc/src/snippets/separations/viewer.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 11.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41/*
42viewer.cpp
43
44Provides a main window for displaying a user-specified original image
45with three color separations in a grid layout.
46
47A main menu provides entries for selecting files, and adjusting the
48brightness of the separations.
49*/
50
51#include <QtGui>
52
53#include "finalwidget.h"
54#include "screenwidget.h"
55#include "viewer.h"
56
57/*
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.
61*/
62
63Viewer::Viewer()
64{
65 setWindowTitle(tr("QImage Color Separations"));
66
67 brightness = 255;
68
69 createMenus();
70 setCentralWidget(createCentralWidget());
71}
72
73/*
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.
77
78 Initially, the Brightness menu items are disabled, but the first entry in
79 the menu is checked to reflect the default brightness.
80*/
81
82void Viewer::createMenus()
83{
84 fileMenu = new QMenu(tr("&File"), this);
85 brightnessMenu = new QMenu(tr("&Brightness"), this);
86
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"));
94
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);
105
106 menuMap[noBrightness] = None;
107 menuMap[quarterBrightness] = Quarter;
108 menuMap[halfBrightness] = Half;
109 menuMap[threeQuartersBrightness] = ThreeQuarters;
110 menuMap[fullBrightness] = Full;
111
112 currentBrightness = fullBrightness;
113 currentBrightness->setChecked(true);
114 brightnessMenu->setEnabled(false);
115
116 menuBar()->addMenu(fileMenu);
117 menuBar()->addMenu(brightnessMenu);
118
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 *)));
124}
125
126/*
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
130 be resized.
131*/
132
133QFrame* Viewer::createCentralWidget()
134{
135 QFrame* frame = new QFrame(this);
136 grid = new QGridLayout(frame);
137 grid->setSpacing(8);
138 grid->setMargin(4);
139
140 layout()->setSizeConstraint(QLayout::SetFixedSize);
141
142 QSize labelSize(256, 256);
143
144 finalWidget = new FinalWidget(frame, tr("Final image"), labelSize);
145
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);
152
153 connect(cyanWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
154 connect(magentaWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
155 connect(yellowWidget, SIGNAL(imageChanged()), this, SLOT(createImage()));
156
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);
161
162 return frame;
163}
164
165/*
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
168 and display it.
169*/
170
171void Viewer::chooseFile()
172{
173 QString imageFile = QFileDialog::getOpenFileName(this,
174 tr("Choose an image file to open"), path, tr("Images (*.*)"));
175
176 if (!imageFile.isEmpty()) {
177 openImageFile(imageFile);
178 path = imageFile;
179 }
180}
181
182/*
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
185 entry is unchecked.
186
187 The color separations are updated to use the new value for the brightness.
188*/
189
190void Viewer::setBrightness(QAction *action)
191{
192 if (!menuMap.contains(action) || scaledImage.isNull())
193 return;
194
195 Brightness amount = menuMap[action];
196
197 switch (amount) {
198 case None:
199 brightness = 0; break;
200 case Quarter:
201 brightness = 64; break;
202 case Half:
203 brightness = 128; break;
204 case ThreeQuarters:
205 brightness = 191; break;
206 case Full:
207 brightness = 255; break;
208 default: return;
209 }
210
211 currentBrightness->setChecked(false);
212 currentBrightness = action;
213 currentBrightness->setChecked(true);
214
215 createImage();
216}
217
218/*
219 Load the image from the file given, and create four pixmaps based
220 on the original image.
221
222 The window caption is set, and the Brightness menu enabled if the image file
223 can be loaded.
224*/
225
226void Viewer::openImageFile(QString &imageFile)
227{
228 QImage originalImage;
229
230 if (originalImage.load(imageFile)) {
231 setWindowTitle(imageFile);
232 //menuBar()->setItemEnabled(brightnessMenuId, true);
233 saveAction->setEnabled(true);
234 brightnessMenu->setEnabled(true);
235
236 /* Note: the ScaleMin value may be different for Qt 4. */
237 scaledImage = originalImage.scaled(256, 256, Qt::KeepAspectRatio);
238
239 cyanWidget->setImage(scaledImage);
240 magentaWidget->setImage(scaledImage);
241 yellowWidget->setImage(scaledImage);
242 createImage();
243 }
244 else
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);
248}
249
250/*
251 Creates an image by combining the contents of the three screens
252 to present a page preview.
253
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.
258*/
259
260void Viewer::createImage()
261{
262 QImage newImage = scaledImage.copy();
263
264 QImage *image1 = cyanWidget->image();
265 QImage *image2 = magentaWidget->image();
266 QImage *image3 = yellowWidget->image();
267 int darkness = 255 - brightness;
268
269 for (int y = 0; y < newImage.height(); ++y) {
270 for (int x = 0; x < newImage.width(); ++x) {
271
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);
279
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);
284
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);
289
290 QColor newColor(
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));
294
295 newImage.setPixel(x, y, newColor.rgb());
296 }
297 }
298
299 finalWidget->setPixmap(QPixmap::fromImage(newImage));
300}
301
302/*
303 Provides a dialog window to allow the user to save the image file.
304*/
305
306void Viewer::saveImage()
307{
308 QString imageFile = QFileDialog::getSaveFileName(this,
309 tr("Choose a filename to save the image"), "", tr("Images (*.png)"));
310
311 QFileInfo info(imageFile);
312
313 if (!info.baseName().isEmpty()) {
314 QString newImageFile = QFileInfo(info.absoluteDir(),
315 info.baseName() + ".png").absoluteFilePath();
316
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);
322 }
323 else
324 (void) QMessageBox::warning(this, tr("Cannot save file"),
325 tr("Please enter a valid filename."),
326 QMessageBox::Cancel, QMessageBox::NoButton,
327 QMessageBox::NoButton);
328}
Note: See TracBrowser for help on using the repository browser.