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 light 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 "exiflight.h" 0016 0017 // C++ includes 0018 0019 #include <cmath> 0020 0021 // Qt includes 0022 0023 #include <QMap> 0024 #include <QGridLayout> 0025 #include <QComboBox> 0026 #include <QApplication> 0027 #include <QStyle> 0028 #include <QDoubleSpinBox> 0029 0030 // KDE includes 0031 0032 #include <klocalizedstring.h> 0033 0034 // Local includes 0035 0036 #include "metadatacheckbox.h" 0037 0038 namespace DigikamGenericMetadataEditPlugin 0039 { 0040 0041 class Q_DECL_HIDDEN FlashMode 0042 { 0043 public: 0044 0045 FlashMode() 0046 : m_id(0) 0047 { 0048 } 0049 FlashMode(int id, const QString& desc) 0050 : m_id (id), 0051 m_desc(desc) 0052 { 0053 } 0054 0055 int id() const 0056 { 0057 return m_id; 0058 } 0059 0060 QString desc() const 0061 { 0062 return m_desc; 0063 } 0064 0065 private: 0066 0067 int m_id; 0068 QString m_desc; 0069 }; 0070 0071 // -------------------------------------------------------------------------- 0072 0073 class Q_DECL_HIDDEN EXIFLight::Private 0074 { 0075 public: 0076 0077 explicit Private() 0078 { 0079 lightSourceCheck = nullptr; 0080 flashModeCheck = nullptr; 0081 flashEnergyCheck = nullptr; 0082 whiteBalanceCheck = nullptr; 0083 lightSourceCB = nullptr; 0084 flashEnergyEdit = nullptr; 0085 flashModeCB = nullptr; 0086 whiteBalanceCB = nullptr; 0087 0088 flashModeMap.insert(0, FlashMode( 0x00, i18n("No flash") )); 0089 flashModeMap.insert(1, FlashMode( 0x01, i18n("Fired") )); 0090 flashModeMap.insert(2, FlashMode( 0x05, i18n("Fired, no strobe return light") )); 0091 flashModeMap.insert(3, FlashMode( 0x07, i18n("Fired, strobe return light") )); 0092 flashModeMap.insert(4, FlashMode( 0x09, i18n("Yes, compulsory") )); 0093 flashModeMap.insert(5, FlashMode( 0x0d, i18n("Yes, compulsory, no return light") )); 0094 flashModeMap.insert(6, FlashMode( 0x0f, i18n("Yes, compulsory, return light") )); 0095 flashModeMap.insert(7, FlashMode( 0x10, i18n("No, compulsory") )); 0096 flashModeMap.insert(8, FlashMode( 0x18, i18n("No, auto") )); 0097 flashModeMap.insert(9, FlashMode( 0x19, i18n("Yes, auto") )); 0098 flashModeMap.insert(10, FlashMode( 0x1d, i18n("Yes, auto, no return light") )); 0099 flashModeMap.insert(11, FlashMode( 0x1f, i18n("Yes, auto, return light") )); 0100 flashModeMap.insert(12, FlashMode( 0x20, i18n("No flash function") )); 0101 flashModeMap.insert(13, FlashMode( 0x41, i18n("Yes, red-eye") )); 0102 flashModeMap.insert(14, FlashMode( 0x45, i18n("Yes, red-eye, no return light") )); 0103 flashModeMap.insert(15, FlashMode( 0x47, i18n("Yes, red-eye, return light") )); 0104 flashModeMap.insert(16, FlashMode( 0x49, i18n("Yes, compulsory, red-eye") )); 0105 flashModeMap.insert(17, FlashMode( 0x4d, i18n("Yes, compulsory, red-eye, no return light") )); 0106 flashModeMap.insert(18, FlashMode( 0x4f, i18n("Yes, compulsory, red-eye, return light") )); 0107 flashModeMap.insert(19, FlashMode( 0x59, i18n("Yes, auto, red-eye") )); 0108 flashModeMap.insert(20, FlashMode( 0x5d, i18n("Yes, auto, red-eye, no return light") )); 0109 flashModeMap.insert(21, FlashMode( 0x5f, i18n("Yes, auto, red-eye, return light") )); 0110 } 0111 0112 typedef QMap<int, FlashMode> FlashModeMap; 0113 0114 FlashModeMap flashModeMap; 0115 0116 QCheckBox* flashEnergyCheck; 0117 0118 QComboBox* lightSourceCB; 0119 QComboBox* flashModeCB; 0120 QComboBox* whiteBalanceCB; 0121 0122 QDoubleSpinBox* flashEnergyEdit; 0123 0124 MetadataCheckBox* lightSourceCheck; 0125 MetadataCheckBox* flashModeCheck; 0126 MetadataCheckBox* whiteBalanceCheck; 0127 }; 0128 0129 // -------------------------------------------------------------------------- 0130 0131 EXIFLight::EXIFLight(QWidget* const parent) 0132 : MetadataEditPage(parent), 0133 d (new Private) 0134 { 0135 QGridLayout* const grid = new QGridLayout(widget()); 0136 0137 // -------------------------------------------------------- 0138 0139 d->lightSourceCheck = new MetadataCheckBox(i18n("Light source:"), this); 0140 d->lightSourceCB = new QComboBox(this); 0141 d->lightSourceCB->insertItem(0, i18nc("light source", "Unknown")); 0142 d->lightSourceCB->insertItem(1, i18nc("light source", "Daylight")); 0143 d->lightSourceCB->insertItem(2, i18nc("light source", "Fluorescent")); 0144 d->lightSourceCB->insertItem(3, i18nc("light source", "Tungsten (incandescent light)")); 0145 d->lightSourceCB->insertItem(4, i18nc("light source", "Flash")); 0146 d->lightSourceCB->insertItem(5, i18nc("light source", "Fine weather")); 0147 d->lightSourceCB->insertItem(6, i18nc("light source", "Cloudy weather")); 0148 d->lightSourceCB->insertItem(7, i18nc("light source", "Shade")); 0149 d->lightSourceCB->insertItem(8, i18nc("light source", "Daylight fluorescent (D 5700 - 7100K)")); 0150 d->lightSourceCB->insertItem(9, i18nc("light source", "Day white fluorescent (N 4600 - 5400K)")); 0151 d->lightSourceCB->insertItem(10, i18nc("light source", "Cool white fluorescent (W 3900 - 4500K)")); 0152 d->lightSourceCB->insertItem(11, i18nc("light source", "White fluorescent (WW 3200 - 3700K)")); 0153 d->lightSourceCB->insertItem(12, i18nc("light source", "Standard light A")); 0154 d->lightSourceCB->insertItem(13, i18nc("light source", "Standard light B")); 0155 d->lightSourceCB->insertItem(14, i18nc("light source", "Standard light C")); 0156 d->lightSourceCB->insertItem(15, i18nc("light source", "D55")); 0157 d->lightSourceCB->insertItem(16, i18nc("light source", "D65")); 0158 d->lightSourceCB->insertItem(17, i18nc("light source", "D75")); 0159 d->lightSourceCB->insertItem(18, i18nc("light source", "D50")); 0160 d->lightSourceCB->insertItem(19, i18nc("light source", "ISO studio tungsten")); 0161 d->lightSourceCB->insertItem(20, i18nc("light source", "Other light source")); 0162 d->lightSourceCB->setWhatsThis(i18n("Select here the kind of light source used " 0163 "to take the picture.")); 0164 0165 // -------------------------------------------------------- 0166 0167 d->flashModeCheck = new MetadataCheckBox(i18n("Flash mode:"), this); 0168 d->flashModeCB = new QComboBox(this); 0169 0170 for (Private::FlashModeMap::Iterator it = d->flashModeMap.begin(); it != d->flashModeMap.end(); ++it ) 0171 d->flashModeCB->addItem(it.value().desc()); 0172 0173 d->flashModeCB->setWhatsThis(i18n("Select here the flash program mode used by the camera " 0174 "to take the picture.")); 0175 0176 // -------------------------------------------------------- 0177 0178 d->flashEnergyCheck = new QCheckBox(i18n("Flash energy (BCPS):"), this); 0179 d->flashEnergyEdit = new QDoubleSpinBox(this); 0180 d->flashEnergyEdit->setRange(1.0, 10000.0); 0181 d->flashEnergyEdit->setSingleStep(1.0); 0182 d->flashEnergyEdit->setValue(1.0); 0183 d->flashEnergyEdit->setDecimals(1); 0184 d->flashEnergyEdit->setWhatsThis(i18n("Set here the flash energy used to take the picture " 0185 "in BCPS units. Beam Candle Power Seconds is the measure " 0186 "of effective intensity of a light source when it is " 0187 "focused into a beam by a reflector or lens. This value " 0188 "is the effective intensity for a period of one second.")); 0189 0190 // -------------------------------------------------------- 0191 0192 d->whiteBalanceCheck = new MetadataCheckBox(i18n("White balance:"), this); 0193 d->whiteBalanceCB = new QComboBox(this); 0194 d->whiteBalanceCB->insertItem(0, i18nc("@item: white balance", "Auto")); 0195 d->whiteBalanceCB->insertItem(1, i18nc("@item: white balance", "Manual")); 0196 d->whiteBalanceCB->setWhatsThis(i18nc("@info", "Select here the white balance mode set by the camera when " 0197 "the picture was taken.")); 0198 0199 // -------------------------------------------------------- 0200 0201 grid->addWidget(d->lightSourceCheck, 0, 0, 1, 1); 0202 grid->addWidget(d->lightSourceCB, 0, 2, 1, 2); 0203 grid->addWidget(d->flashModeCheck, 1, 0, 1, 1); 0204 grid->addWidget(d->flashModeCB, 1, 2, 1, 2); 0205 grid->addWidget(d->flashEnergyCheck, 2, 0, 1, 1); 0206 grid->addWidget(d->flashEnergyEdit, 2, 2, 1, 1); 0207 grid->addWidget(d->whiteBalanceCheck, 3, 0, 1, 1); 0208 grid->addWidget(d->whiteBalanceCB, 3, 2, 1, 1); 0209 grid->setColumnStretch(1, 10); 0210 grid->setRowStretch(4, 10); 0211 0212 int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0213 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); 0214 0215 grid->setContentsMargins(spacing, spacing, spacing, spacing); 0216 grid->setSpacing(spacing); 0217 0218 // -------------------------------------------------------- 0219 0220 connect(d->lightSourceCheck, SIGNAL(toggled(bool)), 0221 d->lightSourceCB, SLOT(setEnabled(bool))); 0222 0223 connect(d->flashModeCheck, SIGNAL(toggled(bool)), 0224 d->flashModeCB, SLOT(setEnabled(bool))); 0225 0226 connect(d->flashEnergyCheck, SIGNAL(toggled(bool)), 0227 d->flashEnergyEdit, SLOT(setEnabled(bool))); 0228 0229 connect(d->whiteBalanceCheck, SIGNAL(toggled(bool)), 0230 d->whiteBalanceCB, SLOT(setEnabled(bool))); 0231 0232 // -------------------------------------------------------- 0233 0234 connect(d->flashEnergyCheck, SIGNAL(toggled(bool)), 0235 this, SIGNAL(signalModified())); 0236 0237 connect(d->lightSourceCheck, SIGNAL(toggled(bool)), 0238 this, SIGNAL(signalModified())); 0239 0240 connect(d->flashModeCheck, SIGNAL(toggled(bool)), 0241 this, SIGNAL(signalModified())); 0242 0243 connect(d->whiteBalanceCheck, SIGNAL(toggled(bool)), 0244 this, SIGNAL(signalModified())); 0245 0246 // -------------------------------------------------------- 0247 0248 connect(d->lightSourceCB, SIGNAL(activated(int)), 0249 this, SIGNAL(signalModified())); 0250 0251 connect(d->flashModeCB, SIGNAL(activated(int)), 0252 this, SIGNAL(signalModified())); 0253 0254 connect(d->whiteBalanceCB, SIGNAL(activated(int)), 0255 this, SIGNAL(signalModified())); 0256 0257 connect(d->flashEnergyEdit, SIGNAL(valueChanged(double)), 0258 this, SIGNAL(signalModified())); 0259 } 0260 0261 EXIFLight::~EXIFLight() 0262 { 0263 delete d; 0264 } 0265 0266 void EXIFLight::readMetadata(const DMetadata& meta) 0267 { 0268 blockSignals(true); 0269 0270 long int num=1, den=1; 0271 long val=0; 0272 0273 d->lightSourceCB->setCurrentIndex(0); 0274 d->lightSourceCheck->setChecked(false); 0275 0276 if (meta.getExifTagLong("Exif.Photo.LightSource", val)) 0277 { 0278 if ((val>=0 && val <=4) || (val> 8 && val <16) || (val> 16 && val <25) || val == 255) 0279 { 0280 if (val > 8 && val < 16) 0281 val = val - 4; 0282 else if (val > 16 && val < 25) 0283 val = val - 5; 0284 else if (val == 255) 0285 val = 20; 0286 0287 d->lightSourceCB->setCurrentIndex(val); 0288 d->lightSourceCheck->setChecked(true); 0289 } 0290 else 0291 { 0292 d->lightSourceCheck->setValid(false); 0293 } 0294 } 0295 0296 d->lightSourceCB->setEnabled(d->lightSourceCheck->isChecked()); 0297 0298 d->flashModeCB->setCurrentIndex(0); 0299 d->flashModeCheck->setChecked(false); 0300 0301 if (meta.getExifTagLong("Exif.Photo.Flash", val)) 0302 { 0303 int item = -1; 0304 0305 for (Private::FlashModeMap::Iterator it = d->flashModeMap.begin(); 0306 it != d->flashModeMap.end(); ++it ) 0307 { 0308 if (it.value().id() == val) 0309 item = it.key(); 0310 } 0311 0312 if (item != -1) 0313 { 0314 d->flashModeCB->setCurrentIndex(item); 0315 d->flashModeCheck->setChecked(true); 0316 } 0317 else 0318 { 0319 d->flashModeCheck->setValid(false); 0320 } 0321 } 0322 0323 d->flashModeCB->setEnabled(d->flashModeCheck->isChecked()); 0324 0325 d->flashEnergyEdit->setValue(1.0); 0326 d->flashEnergyCheck->setChecked(false); 0327 0328 if (meta.getExifTagRational("Exif.Photo.FlashEnergy", num, den)) 0329 { 0330 d->flashEnergyEdit->setValue((double)(num) / (double)(den)); 0331 d->flashEnergyCheck->setChecked(true); 0332 } 0333 0334 d->flashEnergyEdit->setEnabled(d->flashEnergyCheck->isChecked()); 0335 0336 d->whiteBalanceCB->setCurrentIndex(0); 0337 d->whiteBalanceCheck->setChecked(false); 0338 0339 if (meta.getExifTagLong("Exif.Photo.WhiteBalance", val)) 0340 { 0341 if (val>=0 && val<=1) 0342 { 0343 d->whiteBalanceCB->setCurrentIndex(val); 0344 d->whiteBalanceCheck->setChecked(true); 0345 } 0346 else 0347 { 0348 d->whiteBalanceCheck->setValid(false); 0349 } 0350 } 0351 0352 d->whiteBalanceCB->setEnabled(d->whiteBalanceCheck->isChecked()); 0353 0354 blockSignals(false); 0355 } 0356 0357 void EXIFLight::applyMetadata(const DMetadata& meta) 0358 { 0359 long int num=1, den=1; 0360 0361 if (d->lightSourceCheck->isChecked()) 0362 { 0363 long val = d->lightSourceCB->currentIndex(); 0364 0365 if (val > 4 && val < 12) 0366 val = val + 4; 0367 else if (val > 11 && val < 20) 0368 val = val + 5; 0369 else if (val == 20) 0370 val = 255; 0371 0372 meta.setExifTagLong("Exif.Photo.LightSource", val); 0373 } 0374 else if (d->lightSourceCheck->isValid()) 0375 { 0376 meta.removeExifTag("Exif.Photo.LightSource"); 0377 } 0378 0379 if (d->flashModeCheck->isChecked()) 0380 { 0381 long val = d->flashModeCB->currentIndex(); 0382 meta.setExifTagLong("Exif.Photo.Flash", d->flashModeMap[val].id()); 0383 } 0384 else if (d->flashModeCheck->isValid()) 0385 { 0386 meta.removeExifTag("Exif.Photo.Flash"); 0387 } 0388 0389 if (d->flashEnergyCheck->isChecked()) 0390 { 0391 meta.convertToRational(d->flashEnergyEdit->value(), &num, &den, 1); 0392 meta.setExifTagRational("Exif.Photo.FlashEnergy", num, den); 0393 } 0394 else 0395 { 0396 meta.removeExifTag("Exif.Photo.FlashEnergy"); 0397 } 0398 0399 if (d->whiteBalanceCheck->isChecked()) 0400 meta.setExifTagLong("Exif.Photo.WhiteBalance", d->whiteBalanceCB->currentIndex()); 0401 else if (d->whiteBalanceCheck->isValid()) 0402 meta.removeExifTag("Exif.Photo.WhiteBalance"); 0403 } 0404 0405 } // namespace DigikamGenericMetadataEditPlugin 0406 0407 #include "moc_exiflight.cpp"