File indexing completed on 2025-01-19 03:51:22
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2006-10-18 0007 * Description : EXIF lens settings page. 0008 * 0009 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "exiflens.h" 0016 0017 // C++ includes 0018 0019 #include <cmath> 0020 0021 // Qt includes 0022 0023 #include <QGridLayout> 0024 #include <QApplication> 0025 #include <QStyle> 0026 #include <QComboBox> 0027 #include <QSpinBox> 0028 0029 // KDE includes 0030 0031 #include <klocalizedstring.h> 0032 0033 // Local includes 0034 0035 #include "metadatacheckbox.h" 0036 0037 namespace DigikamGenericMetadataEditPlugin 0038 { 0039 0040 class Q_DECL_HIDDEN EXIFLens::Private 0041 { 0042 public: 0043 0044 explicit Private() 0045 { 0046 apertureCheck = nullptr; 0047 maxApertureCheck = nullptr; 0048 focalLength35mmCheck = nullptr; 0049 focalLengthCheck = nullptr; 0050 digitalZoomRatioCheck = nullptr; 0051 apertureCB = nullptr; 0052 maxApertureCB = nullptr; 0053 focalLength35mmEdit = nullptr; 0054 focalLengthEdit = nullptr; 0055 digitalZoomRatioEdit = nullptr; 0056 0057 apertureValues.append(QLatin1String("f/1.0")); 0058 apertureValues.append(QLatin1String("f/1.1")); 0059 apertureValues.append(QLatin1String("f/1.2")); 0060 apertureValues.append(QLatin1String("f/1.3")); 0061 apertureValues.append(QLatin1String("f/1.4")); 0062 apertureValues.append(QLatin1String("f/1.6")); 0063 apertureValues.append(QLatin1String("f/1.8")); 0064 apertureValues.append(QLatin1String("f/2.0")); 0065 apertureValues.append(QLatin1String("f/2.2")); 0066 apertureValues.append(QLatin1String("f/2.5")); 0067 apertureValues.append(QLatin1String("f/2.8")); 0068 apertureValues.append(QLatin1String("f/3.2")); 0069 apertureValues.append(QLatin1String("f/3.5")); 0070 apertureValues.append(QLatin1String("f/3.6")); 0071 apertureValues.append(QLatin1String("f/4.0")); 0072 apertureValues.append(QLatin1String("f/4.5")); 0073 apertureValues.append(QLatin1String("f/4.9")); 0074 apertureValues.append(QLatin1String("f/5.0")); 0075 apertureValues.append(QLatin1String("f/5.6")); 0076 apertureValues.append(QLatin1String("f/5.7")); 0077 apertureValues.append(QLatin1String("f/6.3")); 0078 apertureValues.append(QLatin1String("f/7.0")); 0079 apertureValues.append(QLatin1String("f/7.1")); 0080 apertureValues.append(QLatin1String("f/8.0")); 0081 apertureValues.append(QLatin1String("f/9.0")); 0082 apertureValues.append(QLatin1String("f/10.0")); 0083 apertureValues.append(QLatin1String("f/10.1")); 0084 apertureValues.append(QLatin1String("f/11.0")); 0085 apertureValues.append(QLatin1String("f/11.3")); 0086 apertureValues.append(QLatin1String("f/12.0")); 0087 apertureValues.append(QLatin1String("f/12.7")); 0088 apertureValues.append(QLatin1String("f/13.0")); 0089 apertureValues.append(QLatin1String("f/14.0")); 0090 apertureValues.append(QLatin1String("f/14.3")); 0091 apertureValues.append(QLatin1String("f/16.0")); 0092 apertureValues.append(QLatin1String("f/18.0")); 0093 apertureValues.append(QLatin1String("f/20.0")); 0094 apertureValues.append(QLatin1String("f/20.2")); 0095 apertureValues.append(QLatin1String("f/22.0")); 0096 apertureValues.append(QLatin1String("f/22.6")); 0097 apertureValues.append(QLatin1String("f/25.0")); 0098 apertureValues.append(QLatin1String("f/25.4")); 0099 apertureValues.append(QLatin1String("f/28.5")); 0100 apertureValues.append(QLatin1String("f/29.0")); 0101 apertureValues.append(QLatin1String("f/32.0")); 0102 apertureValues.append(QLatin1String("f/35.9")); 0103 apertureValues.append(QLatin1String("f/36.0")); 0104 apertureValues.append(QLatin1String("f/40.0")); 0105 apertureValues.append(QLatin1String("f/40.3")); 0106 apertureValues.append(QLatin1String("f/45.0")); 0107 apertureValues.append(QLatin1String("f/45.3")); 0108 apertureValues.append(QLatin1String("f/50.8")); 0109 apertureValues.append(QLatin1String("f/51.0")); 0110 apertureValues.append(QLatin1String("f/57.0")); 0111 apertureValues.append(QLatin1String("f/64.0")); 0112 apertureValues.append(QLatin1String("f/72.0")); 0113 apertureValues.append(QLatin1String("f/81.0")); 0114 apertureValues.append(QLatin1String("f/91.0")); 0115 } 0116 0117 QStringList apertureValues; 0118 0119 QCheckBox* focalLength35mmCheck; 0120 QCheckBox* focalLengthCheck; 0121 QCheckBox* digitalZoomRatioCheck; 0122 0123 QComboBox* apertureCB; 0124 QComboBox* maxApertureCB; 0125 0126 QSpinBox* focalLength35mmEdit; 0127 0128 QDoubleSpinBox* focalLengthEdit; 0129 QDoubleSpinBox* digitalZoomRatioEdit; 0130 0131 MetadataCheckBox* apertureCheck; 0132 MetadataCheckBox* maxApertureCheck; 0133 }; 0134 0135 EXIFLens::EXIFLens(QWidget* const parent) 0136 : MetadataEditPage(parent), 0137 d (new Private) 0138 { 0139 QGridLayout* const grid = new QGridLayout(widget()); 0140 0141 // -------------------------------------------------------- 0142 0143 d->focalLengthCheck = new QCheckBox(i18n("Focal length (mm):"), this); 0144 d->focalLengthEdit = new QDoubleSpinBox(this); 0145 d->focalLengthEdit->setRange(1.0, 10000.0); 0146 d->focalLengthEdit->setSingleStep(1.0); 0147 d->focalLengthEdit->setValue(50.0); 0148 d->focalLengthEdit->setDecimals(1); 0149 d->focalLengthEdit->setWhatsThis(i18n("Set here the lens focal length in millimeters " 0150 "used by camera to take the picture.")); 0151 0152 // -------------------------------------------------------- 0153 0154 d->focalLength35mmCheck = new QCheckBox(i18n("Focal length in 35mm film (mm):"), this); 0155 d->focalLength35mmEdit = new QSpinBox(this); 0156 d->focalLength35mmEdit->setMinimum(1); 0157 d->focalLength35mmEdit->setMaximum(10000); 0158 d->focalLength35mmEdit->setSingleStep(1); 0159 d->focalLength35mmEdit->setValue(1); 0160 d->focalLength35mmEdit->setWhatsThis(i18n("Set here equivalent focal length assuming " 0161 "a 35mm film camera, in mm. A value of 0 means the focal " 0162 "length is unknown.")); 0163 0164 // -------------------------------------------------------- 0165 0166 d->digitalZoomRatioCheck = new QCheckBox(i18n("Digital zoom ratio:"), this); 0167 d->digitalZoomRatioEdit = new QDoubleSpinBox(this); 0168 d->digitalZoomRatioEdit->setRange(0.0, 100.0); 0169 d->digitalZoomRatioEdit->setSingleStep(0.1); 0170 d->digitalZoomRatioEdit->setValue(1.0); 0171 d->digitalZoomRatioEdit->setDecimals(1); 0172 d->digitalZoomRatioEdit->setWhatsThis(i18n("Set here the digital zoom ratio " 0173 "used by camera to take the picture.")); 0174 0175 // -------------------------------------------------------- 0176 0177 d->apertureCheck = new MetadataCheckBox(i18n("Lens aperture (f-number):"), this); 0178 d->apertureCB = new QComboBox(this); 0179 d->apertureCB->insertItems(0, d->apertureValues); 0180 d->apertureCB->setWhatsThis(i18n("Select here the lens aperture used by camera " 0181 "to take the picture.")); 0182 0183 // -------------------------------------------------------- 0184 0185 d->maxApertureCheck = new MetadataCheckBox(i18n("Max. lens aperture (f-number):"), this); 0186 d->maxApertureCB = new QComboBox(this); 0187 d->maxApertureCB->insertItems(0, d->apertureValues); 0188 d->maxApertureCB->setWhatsThis(i18n("Select here the smallest aperture of the lens used by camera " 0189 "to take the picture.")); 0190 0191 grid->addWidget(d->focalLengthCheck, 0, 0, 1, 1); 0192 grid->addWidget(d->focalLengthEdit, 0, 2, 1, 1); 0193 grid->addWidget(d->focalLength35mmCheck, 1, 0, 1, 1); 0194 grid->addWidget(d->focalLength35mmEdit, 1, 2, 1, 1); 0195 grid->addWidget(d->digitalZoomRatioCheck, 2, 0, 1, 1); 0196 grid->addWidget(d->digitalZoomRatioEdit, 2, 2, 1, 1); 0197 grid->addWidget(d->apertureCheck, 3, 0, 1, 1); 0198 grid->addWidget(d->apertureCB, 3, 2, 1, 1); 0199 grid->addWidget(d->maxApertureCheck, 4, 0, 1, 1); 0200 grid->addWidget(d->maxApertureCB, 4, 2, 1, 1); 0201 grid->setColumnStretch(1, 10); 0202 grid->setRowStretch(5, 10); 0203 0204 int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0205 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); 0206 0207 grid->setContentsMargins(spacing, spacing, spacing, spacing); 0208 grid->setSpacing(spacing); 0209 0210 // -------------------------------------------------------- 0211 0212 connect(d->focalLengthCheck, SIGNAL(toggled(bool)), 0213 d->focalLengthEdit, SLOT(setEnabled(bool))); 0214 0215 connect(d->focalLength35mmCheck, SIGNAL(toggled(bool)), 0216 d->focalLength35mmEdit, SLOT(setEnabled(bool))); 0217 0218 connect(d->digitalZoomRatioCheck, SIGNAL(toggled(bool)), 0219 d->digitalZoomRatioEdit, SLOT(setEnabled(bool))); 0220 0221 connect(d->apertureCheck, SIGNAL(toggled(bool)), 0222 d->apertureCB, SLOT(setEnabled(bool))); 0223 0224 connect(d->maxApertureCheck, SIGNAL(toggled(bool)), 0225 d->maxApertureCB, SLOT(setEnabled(bool))); 0226 0227 // -------------------------------------------------------- 0228 0229 connect(d->focalLength35mmCheck, SIGNAL(toggled(bool)), 0230 this, SIGNAL(signalModified())); 0231 0232 connect(d->focalLengthCheck, SIGNAL(toggled(bool)), 0233 this, SIGNAL(signalModified())); 0234 0235 connect(d->digitalZoomRatioCheck, SIGNAL(toggled(bool)), 0236 this, SIGNAL(signalModified())); 0237 0238 connect(d->apertureCheck, SIGNAL(toggled(bool)), 0239 this, SIGNAL(signalModified())); 0240 0241 connect(d->maxApertureCheck, SIGNAL(toggled(bool)), 0242 this, SIGNAL(signalModified())); 0243 0244 // -------------------------------------------------------- 0245 0246 connect(d->apertureCB, SIGNAL(activated(int)), 0247 this, SIGNAL(signalModified())); 0248 0249 connect(d->maxApertureCB, SIGNAL(activated(int)), 0250 this, SIGNAL(signalModified())); 0251 0252 connect(d->focalLength35mmEdit, SIGNAL(valueChanged(int)), 0253 this, SIGNAL(signalModified())); 0254 0255 connect(d->focalLengthEdit, SIGNAL(valueChanged(double)), 0256 this, SIGNAL(signalModified())); 0257 0258 connect(d->digitalZoomRatioEdit, SIGNAL(valueChanged(double)), 0259 this, SIGNAL(signalModified())); 0260 } 0261 0262 EXIFLens::~EXIFLens() 0263 { 0264 delete d; 0265 } 0266 0267 void EXIFLens::readMetadata(const DMetadata& meta) 0268 { 0269 blockSignals(true); 0270 0271 long int num=1, den=1; 0272 long val=0; 0273 0274 d->focalLengthEdit->setValue(50.0); 0275 d->focalLengthCheck->setChecked(false); 0276 0277 if (meta.getExifTagRational("Exif.Photo.FocalLength", num, den)) 0278 { 0279 d->focalLengthEdit->setValue((double)(num) / (double)(den)); 0280 d->focalLengthCheck->setChecked(true); 0281 } 0282 0283 d->focalLengthEdit->setEnabled(d->focalLengthCheck->isChecked()); 0284 0285 d->focalLength35mmEdit->setValue(10); 0286 d->focalLength35mmCheck->setChecked(false); 0287 0288 if (meta.getExifTagLong("Exif.Photo.FocalLengthIn35mmFilm", val)) 0289 { 0290 d->focalLength35mmEdit->setValue(val); 0291 d->focalLength35mmCheck->setChecked(true); 0292 } 0293 0294 d->focalLength35mmEdit->setEnabled(d->focalLength35mmCheck->isChecked()); 0295 0296 d->digitalZoomRatioEdit->setValue(1.0); 0297 d->digitalZoomRatioCheck->setChecked(false); 0298 0299 if (meta.getExifTagRational("Exif.Photo.DigitalZoomRatio", num, den)) 0300 { 0301 d->digitalZoomRatioEdit->setValue((num == 0) ? 0.0 : (double)(num) / (double)(den)); 0302 d->digitalZoomRatioCheck->setChecked(true); 0303 } 0304 0305 d->digitalZoomRatioEdit->setEnabled(d->digitalZoomRatioCheck->isChecked()); 0306 0307 d->apertureCB->setCurrentIndex(0); 0308 d->apertureCheck->setChecked(false); 0309 0310 if (meta.getExifTagRational("Exif.Photo.FNumber", num, den)) 0311 { 0312 QString fnumber = QString::number((double)(num)/(double)(den), 'f', 1); 0313 int item = -1; 0314 0315 for (int i = 0 ; i < d->apertureCB->count() ; ++i) 0316 { 0317 if (d->apertureCB->itemText(i).remove(0, 2) == fnumber) 0318 item = i; 0319 } 0320 0321 if (item != -1) 0322 { 0323 d->apertureCB->setCurrentIndex(item); 0324 d->apertureCheck->setChecked(true); 0325 } 0326 } 0327 else if (meta.getExifTagRational("Exif.Photo.ApertureValue", num, den)) 0328 { 0329 double aperture = std::pow(2.0, ((double)(num)/(double)(den))/2.0); 0330 QString fnumber = QString::number(aperture, 'f', 1); 0331 int item = -1; 0332 0333 for (int i = 0 ; i < d->apertureCB->count() ; ++i) 0334 { 0335 if (d->apertureCB->itemText(i).remove(0, 2) == fnumber) 0336 item = i; 0337 } 0338 0339 if (item != -1) 0340 { 0341 d->apertureCB->setCurrentIndex(item); 0342 d->apertureCheck->setChecked(true); 0343 } 0344 else 0345 d->apertureCheck->setValid(false); 0346 } 0347 d->apertureCB->setEnabled(d->apertureCheck->isChecked()); 0348 0349 d->maxApertureCB->setCurrentIndex(0); 0350 d->maxApertureCheck->setChecked(false); 0351 0352 if (meta.getExifTagRational("Exif.Photo.MaxApertureValue", num, den)) 0353 { 0354 double maxAperture = std::pow(2.0, ((double)(num)/(double)(den))/2.0); 0355 QString fnumber = QString::number(maxAperture, 'f', 1); 0356 int item = -1; 0357 0358 for (int i = 0 ; i < d->apertureCB->count() ; ++i) 0359 { 0360 if (d->maxApertureCB->itemText(i).remove(0, 2) == fnumber) 0361 item = i; 0362 } 0363 0364 if (item != -1) 0365 { 0366 d->maxApertureCB->setCurrentIndex(item); 0367 d->maxApertureCheck->setChecked(true); 0368 } 0369 else 0370 { 0371 d->maxApertureCheck->setValid(false); 0372 } 0373 } 0374 0375 d->maxApertureCB->setEnabled(d->maxApertureCheck->isChecked()); 0376 0377 blockSignals(false); 0378 } 0379 0380 void EXIFLens::applyMetadata(const DMetadata& meta) 0381 { 0382 long int num=1, den=1; 0383 0384 if (d->focalLengthCheck->isChecked()) 0385 { 0386 meta.convertToRational(d->focalLengthEdit->value(), &num, &den, 1); 0387 meta.setExifTagRational("Exif.Photo.FocalLength", num, den); 0388 } 0389 else 0390 meta.removeExifTag("Exif.Photo.FocalLength"); 0391 0392 if (d->focalLength35mmCheck->isChecked()) 0393 meta.setExifTagLong("Exif.Photo.FocalLengthIn35mmFilm", d->focalLength35mmEdit->value()); 0394 else 0395 meta.removeExifTag("Exif.Photo.FocalLengthIn35mmFilm"); 0396 0397 if (d->digitalZoomRatioCheck->isChecked()) 0398 { 0399 meta.convertToRational(d->digitalZoomRatioEdit->value(), &num, &den, 1); 0400 meta.setExifTagRational("Exif.Photo.DigitalZoomRatio", num, den); 0401 } 0402 else 0403 meta.removeExifTag("Exif.Photo.DigitalZoomRatio"); 0404 0405 if (d->apertureCheck->isChecked()) 0406 { 0407 meta.convertToRational(d->apertureCB->currentText().remove(0, 2).toDouble(), &num, &den, 1); 0408 meta.setExifTagRational("Exif.Photo.FNumber", num, den); 0409 0410 double fnumber = d->apertureCB->currentText().remove(0, 2).toDouble(); 0411 double aperture = 2.0*(std::log(fnumber)/std::log(2.0)); 0412 meta.convertToRational(aperture, &num, &den, 8); 0413 meta.setExifTagRational("Exif.Photo.ApertureValue", num, den); 0414 } 0415 else if (d->apertureCheck->isValid()) 0416 { 0417 meta.removeExifTag("Exif.Photo.FNumber"); 0418 meta.removeExifTag("Exif.Photo.ApertureValue"); 0419 } 0420 0421 if (d->maxApertureCheck->isChecked()) 0422 { 0423 double fnumber = d->maxApertureCB->currentText().remove(0, 2).toDouble(); 0424 double aperture = 2.0*(std::log(fnumber)/std::log(2.0)); 0425 meta.convertToRational(aperture, &num, &den, 8); 0426 meta.setExifTagRational("Exif.Photo.MaxApertureValue", num, den); 0427 } 0428 else if (d->maxApertureCheck->isValid()) 0429 meta.removeExifTag("Exif.Photo.MaxApertureValue"); 0430 } 0431 0432 } // namespace DigikamGenericMetadataEditPlugin 0433 0434 #include "moc_exiflens.cpp"