File indexing completed on 2025-01-05 03:56:31
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 28/08/2021 0007 * Description : Extraction of focus points by exiftool data - Canon devices 0008 * 0009 * SPDX-FileCopyrightText: 2021-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2021 by Phuoc Khanh Le <phuockhanhnk94 at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "focuspoints_extractor.h" 0017 0018 // Local includes 0019 0020 #include "digikam_debug.h" 0021 0022 namespace Digikam 0023 { 0024 0025 // Internal function to create af point from meta data 0026 0027 namespace CanonInternal 0028 { 0029 0030 void set_point_position(FocusPoint& point, 0031 float imageWidth, 0032 float imageHeight, 0033 float af_x_position, 0034 float af_y_position, 0035 int yDirection) 0036 { 0037 point.setCenterPosition(0.5 + af_x_position / imageWidth, 0038 0.5 + af_y_position * yDirection / imageHeight); 0039 } 0040 0041 void set_point_size(FocusPoint& point, 0042 float imageWidth, 0043 float imageHeight, 0044 float afPointWidth, 0045 float afPointHeight) 0046 { 0047 point.setSize(afPointWidth / imageWidth, afPointHeight / imageHeight); 0048 } 0049 0050 void set_point_type(FocusPoint& point, 0051 const QStringList& af_selected, 0052 const QStringList& af_infocus, 0053 int index) 0054 { 0055 point.setType(FocusPoint::TypePoint::Inactive); 0056 0057 if (af_infocus.isEmpty() && af_selected.contains(QString::number(index))) 0058 { 0059 point.setType(FocusPoint::TypePoint::Selected); 0060 } 0061 0062 if (af_infocus.contains(QString::number(index))) 0063 { 0064 point.setType(FocusPoint::TypePoint::SelectedInFocus); 0065 } 0066 } 0067 0068 FocusPoint create_af_point(float imageWidth, 0069 float imageHeight, 0070 float afPointWidth, 0071 float afPointHeight, 0072 float af_x_position, 0073 float af_y_position, 0074 const QStringList& af_selected, 0075 const QStringList& af_infocus, 0076 int yDirection, 0077 int index) 0078 { 0079 FocusPoint point; 0080 0081 set_point_position(point, 0082 imageWidth, 0083 imageHeight, 0084 af_x_position, 0085 af_y_position, 0086 yDirection); 0087 0088 set_point_size(point, 0089 imageWidth, 0090 imageHeight, 0091 afPointWidth, 0092 afPointHeight); 0093 0094 set_point_type(point, 0095 af_selected, 0096 af_infocus, 0097 index); 0098 0099 return point; 0100 } 0101 0102 } // namespace CanonInternal 0103 0104 // Main function to extract af point 0105 FocusPointsExtractor::ListAFPoints FocusPointsExtractor::getAFPoints_canon() const 0106 { 0107 QString TagNameRoot = QLatin1String("MakerNotes.Canon.Camera"); 0108 0109 // Get size image 0110 0111 QString model = findValue(QLatin1String("EXIF.IFD0.Camera.Make")).toString(); 0112 0113 QVariant imageWidth, imageHeight; 0114 0115 if (model.toLower() == QLatin1String("canon eos 5d")) 0116 { 0117 imageWidth = findValueFirstMatch(QStringList() 0118 << QLatin1String("MakerNotes.Canon.Image.CanonImageWidth") 0119 << QLatin1String("EXIF.ExifIFD.Image.ExifImageWidth") 0120 ); 0121 0122 imageHeight = findValueFirstMatch(QStringList() 0123 << QLatin1String("MakerNotes.Canon.Image.CanonImageHeight") 0124 << QLatin1String("EXIF.ExifIFD.Image.ExifImageHeight") 0125 ); 0126 } 0127 else 0128 { 0129 imageWidth = findValueFirstMatch(QStringList() 0130 << QLatin1String("MakerNotes.Canon.Camera.AFImageWidth") 0131 << QLatin1String("EXIF.ExifIFD.Image.ExifImageWidth") 0132 ); 0133 0134 imageHeight = findValueFirstMatch(QStringList() 0135 << QLatin1String("MakerNotes.Canon.Camera.AFImageHeight") 0136 << QLatin1String("EXIF.ExifIFD.Image.ExifImageHeight") 0137 ); 0138 } 0139 0140 if (imageWidth.isNull() || imageHeight.isNull()) 0141 { 0142 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: invalid Canon Camera image sizes."; 0143 0144 return getAFPoints_exif(); 0145 } 0146 0147 setOriginalSize(QSize(imageWidth.toInt(), imageHeight.toInt())); 0148 0149 // Get size of af points 0150 0151 QVariant afPointWidth = findValue(TagNameRoot, QLatin1String("AFAreaWidth")); 0152 QVariant afPointHeight = findValue(TagNameRoot, QLatin1String("AFAreaHeight")); 0153 QStringList afPointWidths = findValue(TagNameRoot, QLatin1String("AFAreaWidths"), true).toStringList(); 0154 QStringList afPointHeights = findValue(TagNameRoot, QLatin1String("AFAreaHeights"), true).toStringList(); 0155 0156 if (((afPointWidth.isNull()) || (afPointHeight.isNull())) && 0157 ((afPointWidths.isEmpty()) || (afPointHeights.isEmpty()))) 0158 { 0159 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: invalid sizes from Canon makernotes."; 0160 0161 return getAFPoints_exif(); 0162 } 0163 0164 // Get coordinate of af points 0165 0166 QStringList af_x_positions = findValue(TagNameRoot, QLatin1String("AFAreaXPositions"), true).toStringList(); 0167 QStringList af_y_positions = findValue(TagNameRoot, QLatin1String("AFAreaYPositions"), true).toStringList(); 0168 0169 if (af_x_positions.isEmpty() || af_y_positions.isEmpty()) 0170 { 0171 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: invalid positions from Canon makernotes."; 0172 0173 return getAFPoints_exif(); 0174 } 0175 0176 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: Canon makernotes focus Xs/Ys size:" << af_x_positions.size() 0177 << af_y_positions.size(); 0178 0179 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: Canon makernotes focus W/H value :" << afPointWidth 0180 << afPointHeight; 0181 0182 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: Canon makernotes focus Ws/Hs size:" << afPointWidths.size() 0183 << afPointHeights.size(); 0184 0185 // Get type of af points 0186 0187 QStringList af_selected = findValueFirstMatch(TagNameRoot, QStringList() << QLatin1String("AFPointsSelected") 0188 << QLatin1String("AFPointsInFocus"), 0189 true).toStringList(); 0190 QStringList af_infocus = findValue(TagNameRoot, QLatin1String("AFPointsInFocus"), true).toStringList(); 0191 0192 // Check and remove possible (none) keyword 0193 0194 if (af_infocus.size() == 1) 0195 { 0196 bool ok = false; 0197 int afPoint = af_infocus.first().toInt(&ok); 0198 0199 if ((afPoint == 0) && !ok) 0200 { 0201 af_infocus.clear(); 0202 } 0203 } 0204 0205 // If we have focus points in AFPointsInFocus, 0206 // remove them from AFPointsSelected 0207 0208 Q_FOREACH (const QString& key, af_infocus) 0209 { 0210 af_selected.removeAll(key); 0211 } 0212 0213 // Get direction 0214 0215 QString cameraType = findValue(TagNameRoot, QLatin1String("CameraType")).toString().toUpper(); 0216 0217 int yDirection = 1; 0218 0219 if ((cameraType == QLatin1String("COMPACT")) || 0220 (cameraType == QLatin1String("EOS HIGH-END"))) 0221 { 0222 yDirection = -1; 0223 } 0224 0225 ListAFPoints points; 0226 0227 for (int i = 0 ; i < af_x_positions.count() ; ++i) 0228 { 0229 float afPointWidthUsed = (afPointWidths.isEmpty()) ? afPointWidth.toFloat() 0230 : afPointWidths[i].toFloat(); 0231 0232 float afPointHeightUsed = (afPointWidths.isEmpty()) ? afPointHeight.toFloat() 0233 : afPointWidths[i].toFloat(); 0234 0235 FocusPoint point = CanonInternal::create_af_point( 0236 imageWidth.toFloat(), 0237 imageHeight.toFloat(), 0238 afPointWidthUsed, 0239 afPointHeightUsed, 0240 af_x_positions[i].toFloat(), 0241 af_y_positions[i].toFloat(), 0242 af_selected, 0243 af_infocus, 0244 yDirection, 0245 i 0246 ); 0247 0248 if (!point.getRect().isValid()) 0249 { 0250 continue; 0251 } 0252 0253 points.append(point); 0254 } 0255 0256 return points; 0257 } 0258 0259 } // namespace Digikam