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 - Exif metadata 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 namespace ExifInternal 0027 { 0028 0029 FocusPoint create_af_point(float imageWidth, 0030 float imageHeight, 0031 float af_x_position, 0032 float af_y_position, 0033 float afPointWidth, 0034 float afPointHeight, 0035 MetaEngine::ImageOrientation orientation) 0036 { 0037 QRect region; 0038 region.moveCenter(QPoint(af_x_position, af_y_position)); 0039 region.setSize(QSize(afPointWidth, afPointHeight)); 0040 QSize size = QSize(imageWidth, imageHeight); 0041 0042 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: Exif Subject Area before rotation:" << region; 0043 0044 if ((orientation == MetaEngine::ORIENTATION_ROT_90) || 0045 (orientation == MetaEngine::ORIENTATION_ROT_90_HFLIP) || 0046 (orientation == MetaEngine::ORIENTATION_ROT_90_VFLIP)) 0047 { 0048 region.moveTo(size.height() - region.y() - region.height(), region.x()); 0049 region.setSize(region.size().transposed()); 0050 } 0051 else if (orientation == MetaEngine::ORIENTATION_ROT_180) 0052 { 0053 region.moveTo(size.width() - region.x() - region.width(), 0054 size.height() - region.y() - region.height()); 0055 0056 } 0057 else if (orientation == MetaEngine::ORIENTATION_ROT_270) 0058 { 0059 region.moveTo(region.y(), size.width() - region.x() - region.width()); 0060 region.setSize(region.size().transposed()); 0061 } 0062 0063 if ((orientation == MetaEngine::ORIENTATION_HFLIP) || 0064 (orientation == MetaEngine::ORIENTATION_ROT_90_HFLIP)) 0065 { 0066 region.moveTo(size.width() - region.x() - region.width(), region.y()); 0067 } 0068 else if ((orientation == MetaEngine::ORIENTATION_VFLIP) || 0069 (orientation == MetaEngine::ORIENTATION_ROT_90_VFLIP)) 0070 { 0071 region.moveTo(region.x(), size.height() - region.y() - region.height()); 0072 } 0073 0074 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: Exif Subject Area after rotation:" << region; 0075 0076 FocusPoint fp(region.center().x() / imageWidth, 0077 region.center().y() / imageHeight, 0078 region.width() / imageWidth, 0079 region.height() / imageHeight, 0080 FocusPoint::TypePoint::SelectedInFocus); 0081 0082 return fp; 0083 } 0084 0085 } // namespace ExifInternal 0086 0087 // Main function to extract af point 0088 FocusPointsExtractor::ListAFPoints FocusPointsExtractor::getAFPoints_exif() const 0089 { 0090 // NOTE: See documentation of this tag contents: https://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif/subjectarea.html 0091 0092 QStringList af_info = findValue(QLatin1String("EXIF.ExifIFD.Camera.SubjectArea")).toString() 0093 .split(QLatin1String(" ")); 0094 0095 float af_x_position = 0; 0096 float af_y_position = 0; 0097 float afPointWidth = 0; 0098 float afPointHeight = 0; 0099 0100 switch (af_info.size()) 0101 { 0102 case 4: 0103 { 0104 // Get center coordinates of AF point. 0105 0106 af_x_position = af_info[0].toFloat(); 0107 af_y_position = af_info[1].toFloat(); 0108 0109 // Get size of af area. 0110 0111 afPointWidth = af_info[2].toFloat(); 0112 afPointHeight = af_info[3].toFloat(); 0113 0114 break; 0115 } 0116 0117 case 3: 0118 { 0119 // Get center coordinates of AF point. 0120 0121 af_x_position = af_info[0].toFloat(); 0122 af_y_position = af_info[1].toFloat(); 0123 0124 // Get size of af area (typically a circle transformed as rectangle). 0125 0126 afPointWidth = af_info[3].toFloat(); 0127 afPointHeight = af_info[3].toFloat(); 0128 0129 break; 0130 } 0131 0132 case 2: 0133 { 0134 // Get center coordinates of AF point. 0135 0136 af_x_position = af_info[0].toFloat(); 0137 af_y_position = af_info[1].toFloat(); 0138 0139 // Get size of af area (typically a point transformed an arbritary square of size 120 pixels). 0140 0141 afPointWidth = 120.0F; 0142 afPointHeight = 120.0F; 0143 0144 break; 0145 } 0146 0147 default: // Other sizes are not valid 0148 { 0149 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: Invalid Exif Subject Area."; 0150 0151 // Fail-back to XMP metadata if exists. 0152 0153 return getAFPoints_xmp(); 0154 } 0155 } 0156 0157 QSizeF fs = QSizeF(originalSize()); 0158 0159 qCDebug(DIGIKAM_METAENGINE_LOG) << "FocusPointsExtractor: Exif Subject Area:" << af_info; 0160 0161 ListAFPoints points; 0162 FocusPoint afpoint = ExifInternal::create_af_point( 0163 fs.width(), 0164 fs.height(), 0165 af_x_position, 0166 af_y_position, 0167 afPointWidth, 0168 afPointHeight, 0169 orientation() 0170 ); 0171 0172 if (afpoint.getRect().isValid()) 0173 { 0174 points << afpoint; 0175 } 0176 0177 return points; 0178 } 0179 0180 } // namespace Digikam