1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2007-08-02
7 * Description : save JPEG image options.
8 *
9 * Copyright (C) 2007-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 *
11 * This program is free software; you can redistribute it
12 * and/or modify it under the terms of the GNU General
13 * Public License as published by the Free Software Foundation;
14 * either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * ============================================================ */
23
24 #include "jpegsettings.h"
25
26 // Qt includes
27
28 #include <QApplication>
29 #include <QFrame>
30 #include <QGridLayout>
31 #include <QLabel>
32 #include <QLayout>
33 #include <QString>
34 #include <QComboBox>
35 #include <QStyle>
36
37 // KDE includes
38
39 #include <klocalizedstring.h>
40
41 // Local includes
42
43 #include "dnuminput.h"
44
45 namespace Digikam
46 {
47
48 class Q_DECL_HIDDEN JPEGSettings::Private
49 {
50
51 public:
52
Private()53 explicit Private()
54 : JPEGGrid (nullptr),
55 labelJPEGcompression(nullptr),
56 labelWarning (nullptr),
57 labelSubSampling (nullptr),
58 subSamplingCB (nullptr),
59 JPEGcompression (nullptr)
60 {
61 }
62
63 QGridLayout* JPEGGrid;
64
65 QLabel* labelJPEGcompression;
66 QLabel* labelWarning;
67 QLabel* labelSubSampling;
68
69 QComboBox* subSamplingCB;
70
71 DIntNumInput* JPEGcompression;
72 };
73
JPEGSettings(QWidget * const parent)74 JPEGSettings::JPEGSettings(QWidget* const parent)
75 : QWidget(parent),
76 d (new Private)
77 {
78 setAttribute(Qt::WA_DeleteOnClose);
79
80 const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
81
82 d->JPEGGrid = new QGridLayout(this);
83 d->JPEGcompression = new DIntNumInput(this);
84 d->JPEGcompression->setDefaultValue(75);
85 d->JPEGcompression->setRange(1, 100, 1);
86 d->labelJPEGcompression = new QLabel(i18n("JPEG quality:"), this);
87
88 d->JPEGcompression->setWhatsThis(i18n("<p>The JPEG quality:</p>"
89 "<p><b>1</b>: low quality (high compression and small "
90 "file size)<br/>"
91 "<b>50</b>: medium quality<br/>"
92 "<b>75</b>: good quality (default)<br/>"
93 "<b>100</b>: high quality (no compression and "
94 "large file size)</p>"
95 "<p><b>Note: JPEG always uses lossy compression.</b></p>"));
96
97 d->labelWarning = new QLabel(i18n("<font color='red'><i>"
98 "Warning: <a href='https://en.wikipedia.org/wiki/JPEG'>JPEG</a> is a "
99 "lossy image compression format."
100 "</i></font>"), this);
101
102 d->labelWarning->setOpenExternalLinks(true);
103 d->labelWarning->setFrameStyle(QFrame::Box | QFrame::Plain);
104 d->labelWarning->setLineWidth(1);
105 d->labelWarning->setFrameShape(QFrame::Box);
106
107 d->labelSubSampling = new QLabel(i18n("Chroma subsampling:"), this);
108
109 d->subSamplingCB = new QComboBox(this);
110 d->subSamplingCB->insertItem(0, i18n("4:4:4 (best quality)")); // 1x1, 1x1, 1x1 (4:4:4)
111 d->subSamplingCB->insertItem(1, i18n("4:2:2 (good quality)")); // 2x1, 1x1, 1x1 (4:2:2)
112 d->subSamplingCB->insertItem(2, i18n("4:2:0 (low quality)")); // 2x2, 1x1, 1x1 (4:2:0)
113 d->subSamplingCB->insertItem(3, i18n("4:1:1 (low quality)")); // 4x1, 1x1, 1x1 (4:1:1)
114 d->subSamplingCB->setWhatsThis(i18n("<p>Chroma subsampling reduces file size by taking advantage of the "
115 "eye's lesser sensitivity to color resolution. How perceptible the "
116 "difference is depends on the image - large photos will generally "
117 "show no difference, while sharp, down-scaled pixel graphics may "
118 "lose fine color detail.</p>"
119 "<p><b>4:4:4</b> - No chroma subsampling, highest "
120 "quality but lowest compression.</p>"
121 "<p><b>4:2:2</b> - Chroma halved horizontally, average "
122 "compression, average quality.</p>"
123 "<p><b>4:2:0</b> - Chroma quartered in 2x2 blocks, "
124 "high compression but low quality.</p>"
125 "<p><b>4:1:1</b> - Chroma quartered in 4x1 blocks, "
126 "high compression but low quality.</p>"
127 "<p><b>Note: JPEG always uses lossy compression.</b></p>"));
128
129 d->JPEGGrid->addWidget(d->labelJPEGcompression, 0, 0, 1, 2);
130 d->JPEGGrid->addWidget(d->JPEGcompression, 1, 0, 1, 2);
131 d->JPEGGrid->addWidget(d->labelSubSampling, 2, 0, 1, 2);
132 d->JPEGGrid->addWidget(d->subSamplingCB, 3, 0, 1, 2);
133 d->JPEGGrid->addWidget(d->labelWarning, 4, 0, 1, 1);
134 d->JPEGGrid->setColumnStretch(1, 10);
135 d->JPEGGrid->setRowStretch(5, 10);
136 d->JPEGGrid->setContentsMargins(spacing, spacing, spacing, spacing);
137 d->JPEGGrid->setSpacing(spacing);
138
139 connect(d->JPEGcompression, SIGNAL(valueChanged(int)),
140 this, SIGNAL(signalSettingsChanged()));
141
142 connect(d->subSamplingCB, SIGNAL(activated(int)),
143 this, SIGNAL(signalSettingsChanged()));
144 }
145
~JPEGSettings()146 JPEGSettings::~JPEGSettings()
147 {
148 delete d;
149 }
150
setCompressionValue(int val)151 void JPEGSettings::setCompressionValue(int val)
152 {
153 d->JPEGcompression->setValue(val);
154 }
155
getCompressionValue() const156 int JPEGSettings::getCompressionValue() const
157 {
158 return d->JPEGcompression->value();
159 }
160
setSubSamplingValue(int val)161 void JPEGSettings::setSubSamplingValue(int val)
162 {
163 d->subSamplingCB->setCurrentIndex(val);
164 }
165
getSubSamplingValue() const166 int JPEGSettings::getSubSamplingValue() const
167 {
168 return d->subSamplingCB->currentIndex();
169 }
170
convertCompressionForLibJpeg(int value)171 int JPEGSettings::convertCompressionForLibJpeg(int value)
172 {
173 // JPEG quality slider settings : 1 - 100 ==> libjpeg settings : 25 - 100.
174
175 return ((int)((75.0 / 100.0) * (float)value + 26.0 - (75.0 / 100.0)));
176 }
177
178 } // namespace Digikam
179