Files
PowerToys/src/modules/powerrename/lib/WICMetadataExtractor.cpp

1116 lines
40 KiB
C++
Raw Normal View History

[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "pch.h"
#include "WICMetadataExtractor.h"
#include "MetadataFormatHelper.h"
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cwctype>
#include <comdef.h>
#include <shlwapi.h>
using namespace PowerRenameLib;
namespace
{
// Documentation: https://learn.microsoft.com/en-us/windows/win32/wic/-wic-native-image-format-metadata-queries
// WIC metadata property paths
const std::wstring EXIF_DATE_TAKEN = L"/app1/ifd/exif/{ushort=36867}"; // DateTimeOriginal
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
const std::wstring EXIF_DATE_DIGITIZED = L"/app1/ifd/exif/{ushort=36868}"; // DateTimeDigitized
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
const std::wstring EXIF_DATE_MODIFIED = L"/app1/ifd/{ushort=306}"; // DateTime
const std::wstring EXIF_CAMERA_MAKE = L"/app1/ifd/{ushort=271}"; // Make
const std::wstring EXIF_CAMERA_MODEL = L"/app1/ifd/{ushort=272}"; // Model
const std::wstring EXIF_LENS_MODEL = L"/app1/ifd/exif/{ushort=42036}"; // LensModel
const std::wstring EXIF_ISO = L"/app1/ifd/exif/{ushort=34855}"; // ISOSpeedRatings
const std::wstring EXIF_APERTURE = L"/app1/ifd/exif/{ushort=33437}"; // FNumber
const std::wstring EXIF_SHUTTER_SPEED = L"/app1/ifd/exif/{ushort=33434}"; // ExposureTime
const std::wstring EXIF_FOCAL_LENGTH = L"/app1/ifd/exif/{ushort=37386}"; // FocalLength
const std::wstring EXIF_EXPOSURE_BIAS = L"/app1/ifd/exif/{ushort=37380}"; // ExposureBiasValue
const std::wstring EXIF_FLASH = L"/app1/ifd/exif/{ushort=37385}"; // Flash
const std::wstring EXIF_ORIENTATION = L"/app1/ifd/{ushort=274}"; // Orientation
const std::wstring EXIF_COLOR_SPACE = L"/app1/ifd/exif/{ushort=40961}"; // ColorSpace
const std::wstring EXIF_WIDTH = L"/app1/ifd/exif/{ushort=40962}"; // PixelXDimension - actual image width
const std::wstring EXIF_HEIGHT = L"/app1/ifd/exif/{ushort=40963}"; // PixelYDimension - actual image height
const std::wstring EXIF_ARTIST = L"/app1/ifd/{ushort=315}"; // Artist
const std::wstring EXIF_COPYRIGHT = L"/app1/ifd/{ushort=33432}"; // Copyright
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
// GPS paths for JPEG format
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
const std::wstring GPS_LATITUDE = L"/app1/ifd/gps/{ushort=2}"; // GPSLatitude
const std::wstring GPS_LATITUDE_REF = L"/app1/ifd/gps/{ushort=1}"; // GPSLatitudeRef
const std::wstring GPS_LONGITUDE = L"/app1/ifd/gps/{ushort=4}"; // GPSLongitude
const std::wstring GPS_LONGITUDE_REF = L"/app1/ifd/gps/{ushort=3}"; // GPSLongitudeRef
const std::wstring GPS_ALTITUDE = L"/app1/ifd/gps/{ushort=6}"; // GPSAltitude
const std::wstring GPS_ALTITUDE_REF = L"/app1/ifd/gps/{ushort=5}"; // GPSAltitudeRef
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
// WIC metadata property paths for TIFF/HEIF format (uses /ifd prefix directly)
// HEIF/HEIC images use TIFF-style metadata paths
const std::wstring HEIF_DATE_TAKEN = L"/ifd/exif/{ushort=36867}"; // DateTimeOriginal
const std::wstring HEIF_DATE_DIGITIZED = L"/ifd/exif/{ushort=36868}"; // DateTimeDigitized
const std::wstring HEIF_DATE_MODIFIED = L"/ifd/{ushort=306}"; // DateTime
const std::wstring HEIF_CAMERA_MAKE = L"/ifd/{ushort=271}"; // Make
const std::wstring HEIF_CAMERA_MODEL = L"/ifd/{ushort=272}"; // Model
const std::wstring HEIF_LENS_MODEL = L"/ifd/exif/{ushort=42036}"; // LensModel
const std::wstring HEIF_ISO = L"/ifd/exif/{ushort=34855}"; // ISOSpeedRatings
const std::wstring HEIF_APERTURE = L"/ifd/exif/{ushort=33437}"; // FNumber
const std::wstring HEIF_SHUTTER_SPEED = L"/ifd/exif/{ushort=33434}"; // ExposureTime
const std::wstring HEIF_FOCAL_LENGTH = L"/ifd/exif/{ushort=37386}"; // FocalLength
const std::wstring HEIF_EXPOSURE_BIAS = L"/ifd/exif/{ushort=37380}"; // ExposureBiasValue
const std::wstring HEIF_FLASH = L"/ifd/exif/{ushort=37385}"; // Flash
const std::wstring HEIF_ORIENTATION = L"/ifd/{ushort=274}"; // Orientation
const std::wstring HEIF_COLOR_SPACE = L"/ifd/exif/{ushort=40961}"; // ColorSpace
const std::wstring HEIF_WIDTH = L"/ifd/exif/{ushort=40962}"; // PixelXDimension
const std::wstring HEIF_HEIGHT = L"/ifd/exif/{ushort=40963}"; // PixelYDimension
const std::wstring HEIF_ARTIST = L"/ifd/{ushort=315}"; // Artist
const std::wstring HEIF_COPYRIGHT = L"/ifd/{ushort=33432}"; // Copyright
// GPS paths for TIFF/HEIF format
const std::wstring HEIF_GPS_LATITUDE = L"/ifd/gps/{ushort=2}"; // GPSLatitude
const std::wstring HEIF_GPS_LATITUDE_REF = L"/ifd/gps/{ushort=1}"; // GPSLatitudeRef
const std::wstring HEIF_GPS_LONGITUDE = L"/ifd/gps/{ushort=4}"; // GPSLongitude
const std::wstring HEIF_GPS_LONGITUDE_REF = L"/ifd/gps/{ushort=3}"; // GPSLongitudeRef
const std::wstring HEIF_GPS_ALTITUDE = L"/ifd/gps/{ushort=6}"; // GPSAltitude
const std::wstring HEIF_GPS_ALTITUDE_REF = L"/ifd/gps/{ushort=5}"; // GPSAltitudeRef
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
// Documentation: https://developer.adobe.com/xmp/docs/XMPNamespaces/xmp/
// Based on actual WIC path format discovered through enumeration
// XMP Basic schema - xmp: namespace
const std::wstring XMP_CREATE_DATE = L"/xmp/xmp:CreateDate"; // XMP Create Date
const std::wstring XMP_MODIFY_DATE = L"/xmp/xmp:ModifyDate"; // XMP Modify Date
const std::wstring XMP_METADATA_DATE = L"/xmp/xmp:MetadataDate"; // XMP Metadata Date
const std::wstring XMP_CREATOR_TOOL = L"/xmp/xmp:CreatorTool"; // XMP Creator Tool
// Dublin Core schema - dc: namespace
// Note: For language alternatives like title/description, we need to append /x-default
const std::wstring XMP_DC_TITLE = L"/xmp/dc:title/x-default"; // Title (default language)
const std::wstring XMP_DC_DESCRIPTION = L"/xmp/dc:description/x-default"; // Description (default language)
const std::wstring XMP_DC_CREATOR = L"/xmp/dc:creator"; // Creator/Author
const std::wstring XMP_DC_SUBJECT = L"/xmp/dc:subject"; // Subject/Keywords (array)
// XMP Rights Management schema - xmpRights: namespace
const std::wstring XMP_RIGHTS = L"/xmp/xmpRights:WebStatement"; // Copyright/Rights
// XMP Media Management schema - xmpMM: namespace
const std::wstring XMP_MM_DOCUMENT_ID = L"/xmp/xmpMM:DocumentID"; // Document ID
const std::wstring XMP_MM_INSTANCE_ID = L"/xmp/xmpMM:InstanceID"; // Instance ID
const std::wstring XMP_MM_ORIGINAL_DOCUMENT_ID = L"/xmp/xmpMM:OriginalDocumentID"; // Original Document ID
const std::wstring XMP_MM_VERSION_ID = L"/xmp/xmpMM:VersionID"; // Version ID
std::wstring TrimWhitespace(const std::wstring& value)
{
const auto first = value.find_first_not_of(L" \t\r\n");
if (first == std::wstring::npos)
{
return {};
}
const auto last = value.find_last_not_of(L" \t\r\n");
return value.substr(first, last - first + 1);
}
bool TryParseFixedWidthInt(const std::wstring& source, size_t start, size_t length, int& value)
{
if (start + length > source.size())
{
return false;
}
int result = 0;
for (size_t i = 0; i < length; ++i)
{
const wchar_t ch = source[start + i];
if (ch < L'0' || ch > L'9')
{
return false;
}
result = result * 10 + static_cast<int>(ch - L'0');
}
value = result;
return true;
}
bool ValidateAndBuildSystemTime(int year, int month, int day, int hour, int minute, int second, int milliseconds, SYSTEMTIME& outTime)
{
if (year < 1601 || year > 9999 ||
month < 1 || month > 12 ||
day < 1 || day > 31 ||
hour < 0 || hour > 23 ||
minute < 0 || minute > 59 ||
second < 0 || second > 59 ||
milliseconds < 0 || milliseconds > 999)
{
return false;
}
SYSTEMTIME candidate{};
candidate.wYear = static_cast<WORD>(year);
candidate.wMonth = static_cast<WORD>(month);
candidate.wDay = static_cast<WORD>(day);
candidate.wHour = static_cast<WORD>(hour);
candidate.wMinute = static_cast<WORD>(minute);
candidate.wSecond = static_cast<WORD>(second);
candidate.wMilliseconds = static_cast<WORD>(milliseconds);
FILETIME fileTime{};
if (!SystemTimeToFileTime(&candidate, &fileTime))
{
return false;
}
outTime = candidate;
return true;
}
std::optional<SYSTEMTIME> ParseExifDateTime(const std::wstring& date)
{
if (date.size() < 19)
{
return std::nullopt;
}
if (date[4] != L':' || date[7] != L':' ||
(date[10] != L' ' && date[10] != L'T') ||
date[13] != L':' || date[16] != L':')
{
return std::nullopt;
}
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minute = 0;
int second = 0;
if (!TryParseFixedWidthInt(date, 0, 4, year) ||
!TryParseFixedWidthInt(date, 5, 2, month) ||
!TryParseFixedWidthInt(date, 8, 2, day) ||
!TryParseFixedWidthInt(date, 11, 2, hour) ||
!TryParseFixedWidthInt(date, 14, 2, minute) ||
!TryParseFixedWidthInt(date, 17, 2, second))
{
return std::nullopt;
}
int milliseconds = 0;
size_t pos = 19;
if (pos < date.size() && (date[pos] == L'.' || date[pos] == L','))
{
++pos;
int digits = 0;
while (pos < date.size() && std::iswdigit(date[pos]) && digits < 3)
{
milliseconds = milliseconds * 10 + static_cast<int>(date[pos] - L'0');
++pos;
++digits;
}
while (digits > 0 && digits < 3)
{
milliseconds *= 10;
++digits;
}
}
SYSTEMTIME result{};
if (!ValidateAndBuildSystemTime(year, month, day, hour, minute, second, milliseconds, result))
{
return std::nullopt;
}
return result;
}
std::optional<SYSTEMTIME> ParseIso8601DateTime(const std::wstring& date)
{
if (date.size() < 19)
{
return std::nullopt;
}
size_t separator = date.find(L'T');
if (separator == std::wstring::npos)
{
separator = date.find(L' ');
}
if (separator == std::wstring::npos)
{
return std::nullopt;
}
int year = 0;
int month = 0;
int day = 0;
if (!TryParseFixedWidthInt(date, 0, 4, year) ||
date[4] != L'-' ||
!TryParseFixedWidthInt(date, 5, 2, month) ||
date[7] != L'-' ||
!TryParseFixedWidthInt(date, 8, 2, day))
{
return std::nullopt;
}
size_t timePos = separator + 1;
if (timePos + 7 >= date.size())
{
return std::nullopt;
}
int hour = 0;
int minute = 0;
int second = 0;
if (!TryParseFixedWidthInt(date, timePos, 2, hour) ||
date[timePos + 2] != L':' ||
!TryParseFixedWidthInt(date, timePos + 3, 2, minute) ||
date[timePos + 5] != L':' ||
!TryParseFixedWidthInt(date, timePos + 6, 2, second))
{
return std::nullopt;
}
size_t pos = timePos + 8;
int milliseconds = 0;
if (pos < date.size() && (date[pos] == L'.' || date[pos] == L','))
{
++pos;
int digits = 0;
while (pos < date.size() && std::iswdigit(date[pos]) && digits < 3)
{
milliseconds = milliseconds * 10 + static_cast<int>(date[pos] - L'0');
++pos;
++digits;
}
while (pos < date.size() && std::iswdigit(date[pos]))
{
++pos;
}
while (digits > 0 && digits < 3)
{
milliseconds *= 10;
++digits;
}
}
bool hasOffset = false;
int offsetMinutes = 0;
if (pos < date.size())
{
const wchar_t tzIndicator = date[pos];
if (tzIndicator == L'Z' || tzIndicator == L'z')
{
hasOffset = true;
offsetMinutes = 0;
++pos;
}
else if (tzIndicator == L'+' || tzIndicator == L'-')
{
hasOffset = true;
const int sign = (tzIndicator == L'-') ? -1 : 1;
++pos;
int offsetHours = 0;
int offsetMins = 0;
if (!TryParseFixedWidthInt(date, pos, 2, offsetHours))
{
return std::nullopt;
}
pos += 2;
if (pos < date.size() && date[pos] == L':')
{
++pos;
}
if (pos + 1 < date.size() && std::iswdigit(date[pos]) && std::iswdigit(date[pos + 1]))
{
if (!TryParseFixedWidthInt(date, pos, 2, offsetMins))
{
return std::nullopt;
}
pos += 2;
}
if (offsetHours < 0 || offsetHours > 23 || offsetMins < 0 || offsetMins > 59)
{
return std::nullopt;
}
offsetMinutes = sign * (offsetHours * 60 + offsetMins);
}
while (pos < date.size() && std::iswspace(date[pos]))
{
++pos;
}
if (pos != date.size())
{
return std::nullopt;
}
}
SYSTEMTIME baseTime{};
if (!ValidateAndBuildSystemTime(year, month, day, hour, minute, second, milliseconds, baseTime))
{
return std::nullopt;
}
if (!hasOffset)
{
return baseTime;
}
FILETIME utcFileTime{};
if (!SystemTimeToFileTime(&baseTime, &utcFileTime))
{
return std::nullopt;
}
ULARGE_INTEGER timeValue{};
timeValue.LowPart = utcFileTime.dwLowDateTime;
timeValue.HighPart = utcFileTime.dwHighDateTime;
constexpr long long TicksPerMinute = 60LL * 10000000LL;
timeValue.QuadPart -= static_cast<long long>(offsetMinutes) * TicksPerMinute;
FILETIME adjustedUtc{};
adjustedUtc.dwLowDateTime = timeValue.LowPart;
adjustedUtc.dwHighDateTime = timeValue.HighPart;
FILETIME localFileTime{};
if (!FileTimeToLocalFileTime(&adjustedUtc, &localFileTime))
{
return std::nullopt;
}
SYSTEMTIME localTime{};
if (!FileTimeToSystemTime(&localFileTime, &localTime))
{
return std::nullopt;
}
return localTime;
}
// Global WIC factory management with thread-safe access
CComPtr<IWICImagingFactory> g_wicFactory;
std::once_flag g_wicInitFlag;
std::mutex g_wicFactoryMutex; // Protect access to g_wicFactory
}
WICMetadataExtractor::WICMetadataExtractor()
{
InitializeWIC();
}
WICMetadataExtractor::~WICMetadataExtractor()
{
// WIC cleanup handled statically
}
void WICMetadataExtractor::InitializeWIC()
{
std::call_once(g_wicInitFlag, []() {
// Don't initialize COM in library code - assume caller has done it
// Just create the WIC factory
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
reinterpret_cast<LPVOID*>(&g_wicFactory)
);
if (FAILED(hr))
{
g_wicFactory = nullptr;
}
});
}
CComPtr<IWICImagingFactory> WICMetadataExtractor::GetWICFactory()
{
std::lock_guard<std::mutex> lock(g_wicFactoryMutex);
return g_wicFactory;
}
bool WICMetadataExtractor::ExtractEXIFMetadata(
const std::wstring& filePath,
EXIFMetadata& outMetadata)
{
return cache.GetOrLoadEXIF(filePath, outMetadata, [this, &filePath](EXIFMetadata& metadata) {
return LoadEXIFMetadata(filePath, metadata);
});
}
bool WICMetadataExtractor::LoadEXIFMetadata(
const std::wstring& filePath,
EXIFMetadata& outMetadata)
{
CComPtr<IWICMetadataQueryReader> reader;
if (!PathFileExistsW(filePath.c_str()))
{
#ifdef _DEBUG
std::wstring msg = L"[PowerRename] EXIF metadata extraction failed: File not found - " + filePath + L"\n";
OutputDebugStringW(msg.c_str());
#endif
return false;
}
auto decoder = CreateDecoder(filePath);
if (!decoder)
{
#ifdef _DEBUG
std::wstring msg = L"[PowerRename] EXIF metadata extraction: Unsupported format or unable to create decoder - " + filePath + L"\n";
OutputDebugStringW(msg.c_str());
#endif
return false;
}
CComPtr<IWICBitmapFrameDecode> frame;
if (FAILED(decoder->GetFrame(0, &frame)))
{
#ifdef _DEBUG
std::wstring msg = L"[PowerRename] EXIF metadata extraction failed: WIC decoder error - " + filePath + L"\n";
OutputDebugStringW(msg.c_str());
#endif
return false;
}
reader = GetMetadataReader(decoder);
if (!reader)
{
// No metadata is not necessarily an error - just means the file has no EXIF data
return false;
}
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
// Detect container format to determine correct metadata paths
MetadataPathFormat pathFormat = GetMetadataPathFormatFromDecoder(decoder);
ExtractAllEXIFFields(reader, outMetadata, pathFormat);
ExtractGPSData(reader, outMetadata, pathFormat);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
return true;
}
void WICMetadataExtractor::ClearCache()
{
cache.ClearAll();
}
CComPtr<IWICBitmapDecoder> WICMetadataExtractor::CreateDecoder(const std::wstring& filePath)
{
auto factory = GetWICFactory();
if (!factory)
{
return nullptr;
}
CComPtr<IWICBitmapDecoder> decoder;
HRESULT hr = factory->CreateDecoderFromFilename(
filePath.c_str(),
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&decoder
);
if (FAILED(hr))
{
return nullptr;
}
return decoder;
}
CComPtr<IWICMetadataQueryReader> WICMetadataExtractor::GetMetadataReader(IWICBitmapDecoder* decoder)
{
if (!decoder)
{
return nullptr;
}
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
CComPtr<IWICBitmapFrameDecode> frame;
if (FAILED(decoder->GetFrame(0, &frame)))
{
return nullptr;
}
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
CComPtr<IWICMetadataQueryReader> reader;
frame->GetMetadataQueryReader(&reader);
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
return reader;
}
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
MetadataPathFormat WICMetadataExtractor::GetMetadataPathFormatFromDecoder(IWICBitmapDecoder* decoder)
{
if (!decoder)
{
return MetadataPathFormat::JPEG;
}
GUID containerFormat;
if (SUCCEEDED(decoder->GetContainerFormat(&containerFormat)))
{
// HEIF and TIFF use /ifd/... paths directly
if (containerFormat == GUID_ContainerFormatHeif ||
containerFormat == GUID_ContainerFormatTiff)
{
return MetadataPathFormat::IFD;
}
}
// JPEG and other formats use /app1/ifd/... paths
return MetadataPathFormat::JPEG;
}
void WICMetadataExtractor::ExtractAllEXIFFields(IWICMetadataQueryReader* reader, EXIFMetadata& metadata, MetadataPathFormat pathFormat)
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
{
if (!reader)
return;
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
// Select the correct paths based on container format
const bool useIfdPaths = (pathFormat == MetadataPathFormat::IFD);
// Date/time paths
const auto& dateTakenPath = useIfdPaths ? HEIF_DATE_TAKEN : EXIF_DATE_TAKEN;
const auto& dateDigitizedPath = useIfdPaths ? HEIF_DATE_DIGITIZED : EXIF_DATE_DIGITIZED;
const auto& dateModifiedPath = useIfdPaths ? HEIF_DATE_MODIFIED : EXIF_DATE_MODIFIED;
// Camera info paths
const auto& cameraMakePath = useIfdPaths ? HEIF_CAMERA_MAKE : EXIF_CAMERA_MAKE;
const auto& cameraModelPath = useIfdPaths ? HEIF_CAMERA_MODEL : EXIF_CAMERA_MODEL;
const auto& lensModelPath = useIfdPaths ? HEIF_LENS_MODEL : EXIF_LENS_MODEL;
// Shooting parameter paths
const auto& isoPath = useIfdPaths ? HEIF_ISO : EXIF_ISO;
const auto& aperturePath = useIfdPaths ? HEIF_APERTURE : EXIF_APERTURE;
const auto& shutterSpeedPath = useIfdPaths ? HEIF_SHUTTER_SPEED : EXIF_SHUTTER_SPEED;
const auto& focalLengthPath = useIfdPaths ? HEIF_FOCAL_LENGTH : EXIF_FOCAL_LENGTH;
const auto& exposureBiasPath = useIfdPaths ? HEIF_EXPOSURE_BIAS : EXIF_EXPOSURE_BIAS;
const auto& flashPath = useIfdPaths ? HEIF_FLASH : EXIF_FLASH;
// Image property paths
const auto& widthPath = useIfdPaths ? HEIF_WIDTH : EXIF_WIDTH;
const auto& heightPath = useIfdPaths ? HEIF_HEIGHT : EXIF_HEIGHT;
const auto& orientationPath = useIfdPaths ? HEIF_ORIENTATION : EXIF_ORIENTATION;
const auto& colorSpacePath = useIfdPaths ? HEIF_COLOR_SPACE : EXIF_COLOR_SPACE;
// Author info paths
const auto& artistPath = useIfdPaths ? HEIF_ARTIST : EXIF_ARTIST;
const auto& copyrightPath = useIfdPaths ? HEIF_COPYRIGHT : EXIF_COPYRIGHT;
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
// Extract date/time fields
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
metadata.dateTaken = ReadDateTime(reader, dateTakenPath);
metadata.dateDigitized = ReadDateTime(reader, dateDigitizedPath);
metadata.dateModified = ReadDateTime(reader, dateModifiedPath);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
// Extract camera information
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
metadata.cameraMake = ReadString(reader, cameraMakePath);
metadata.cameraModel = ReadString(reader, cameraModelPath);
metadata.lensModel = ReadString(reader, lensModelPath);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
// Extract shooting parameters
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
metadata.iso = ReadInteger(reader, isoPath);
metadata.aperture = ReadDouble(reader, aperturePath);
metadata.shutterSpeed = ReadDouble(reader, shutterSpeedPath);
metadata.focalLength = ReadDouble(reader, focalLengthPath);
metadata.exposureBias = ReadDouble(reader, exposureBiasPath);
metadata.flash = ReadInteger(reader, flashPath);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
// Extract image properties
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
metadata.width = ReadInteger(reader, widthPath);
metadata.height = ReadInteger(reader, heightPath);
metadata.orientation = ReadInteger(reader, orientationPath);
metadata.colorSpace = ReadInteger(reader, colorSpacePath);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
// Extract author information
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
metadata.author = ReadString(reader, artistPath);
metadata.copyright = ReadString(reader, copyrightPath);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
}
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
void WICMetadataExtractor::ExtractGPSData(IWICMetadataQueryReader* reader, EXIFMetadata& metadata, MetadataPathFormat pathFormat)
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
{
if (!reader)
{
return;
}
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
// Select the correct paths based on container format
const bool useIfdPaths = (pathFormat == MetadataPathFormat::IFD);
const auto& latitudePath = useIfdPaths ? HEIF_GPS_LATITUDE : GPS_LATITUDE;
const auto& longitudePath = useIfdPaths ? HEIF_GPS_LONGITUDE : GPS_LONGITUDE;
const auto& latitudeRefPath = useIfdPaths ? HEIF_GPS_LATITUDE_REF : GPS_LATITUDE_REF;
const auto& longitudeRefPath = useIfdPaths ? HEIF_GPS_LONGITUDE_REF : GPS_LONGITUDE_REF;
const auto& altitudePath = useIfdPaths ? HEIF_GPS_ALTITUDE : GPS_ALTITUDE;
auto lat = ReadMetadata(reader, latitudePath);
auto lon = ReadMetadata(reader, longitudePath);
auto latRef = ReadMetadata(reader, latitudeRefPath);
auto lonRef = ReadMetadata(reader, longitudeRefPath);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
if (lat && lon)
{
PropVariantValue emptyLatRef;
PropVariantValue emptyLonRef;
const PROPVARIANT& latRefVar = latRef ? latRef->Get() : emptyLatRef.Get();
const PROPVARIANT& lonRefVar = lonRef ? lonRef->Get() : emptyLonRef.Get();
auto coords = MetadataFormatHelper::ParseGPSCoordinates(
lat->Get(),
lon->Get(),
latRefVar,
lonRefVar);
metadata.latitude = coords.first;
metadata.longitude = coords.second;
}
Add HEIF/AVIF EXIF metadata extraction and UI support (#44466) - Support EXIF extraction from HEIF/HEIC and AVIF images by detecting container format and using correct WIC metadata paths. - Extend supported file extensions to include .heic, .heif, and .avif. - Add unit tests and test data for HEIF/AVIF extraction, with graceful handling if required Windows Store extensions are missing. - Update PowerRename settings UI to show HEIF/AVIF extension status and provide install buttons. - Extend ViewModel to detect/install required extensions and expose status for binding. <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #43758 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-01-08 11:18:47 +08:00
auto alt = ReadMetadata(reader, altitudePath);
[PowerRename] Support using photo metadata to replace in the PowerRename (#41728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request 1. Introduce WIC for power rename and add new class WICMetadataExtractor to use WIC to extract metadata. 2. Add some patterns for metadata extract. 3. Support XMP and EXIF metadata extract. 4. Add test data for xmp and exif extractor 5. Add attribution for the test data uploader. UI: <img width="2052" height="1415" alt="image" src="https://github.com/user-attachments/assets/9051b12e-4e66-4fdc-a4d4-3bada661c235" /> <img width="284" height="170" alt="image" src="https://github.com/user-attachments/assets/2fd67193-77a7-48f0-a5ac-08a69fe64e55" /> <img width="715" height="1160" alt="image" src="https://github.com/user-attachments/assets/5fa68a8c-d129-44dd-b747-099dfbcded12" /> demo: https://github.com/user-attachments/assets/e90bc206-62e5-4101-ada2-3187ee7e2039 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #5612 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Yu Leng <yuleng@microsoft.com>
2025-11-04 09:27:16 +08:00
if (alt)
{
metadata.altitude = MetadataFormatHelper::ParseGPSRational(alt->Get());
}
}
std::optional<SYSTEMTIME> WICMetadataExtractor::ReadDateTime(IWICMetadataQueryReader* reader, const std::wstring& path)
{
auto propVar = ReadMetadata(reader, path);
if (!propVar)
{
return std::nullopt;
}
std::wstring rawValue;
const PROPVARIANT& variant = propVar->Get();
switch (variant.vt)
{
case VT_LPWSTR:
if (variant.pwszVal)
{
rawValue = variant.pwszVal;
}
break;
case VT_BSTR:
if (variant.bstrVal)
{
rawValue = variant.bstrVal;
}
break;
case VT_LPSTR:
if (variant.pszVal)
{
const int size = MultiByteToWideChar(CP_UTF8, 0, variant.pszVal, -1, nullptr, 0);
if (size > 1)
{
rawValue.resize(static_cast<size_t>(size) - 1);
MultiByteToWideChar(CP_UTF8, 0, variant.pszVal, -1, &rawValue[0], size);
}
}
break;
default:
break;
}
if (rawValue.empty())
{
return std::nullopt;
}
const std::wstring normalized = TrimWhitespace(rawValue);
if (normalized.empty())
{
return std::nullopt;
}
if (auto exifDate = ParseExifDateTime(normalized))
{
return exifDate;
}
if (auto isoDate = ParseIso8601DateTime(normalized))
{
return isoDate;
}
return std::nullopt;
}
std::optional<std::wstring> WICMetadataExtractor::ReadString(IWICMetadataQueryReader* reader, const std::wstring& path)
{
auto propVar = ReadMetadata(reader, path);
if (!propVar.has_value())
return std::nullopt;
std::wstring result;
switch (propVar->Get().vt)
{
case VT_LPWSTR:
if (propVar->Get().pwszVal)
result = propVar->Get().pwszVal;
break;
case VT_BSTR:
if (propVar->Get().bstrVal)
result = propVar->Get().bstrVal;
break;
case VT_LPSTR:
if (propVar->Get().pszVal)
{
int size = MultiByteToWideChar(CP_UTF8, 0, propVar->Get().pszVal, -1, nullptr, 0);
if (size > 1)
{
result.resize(static_cast<size_t>(size) - 1);
MultiByteToWideChar(CP_UTF8, 0, propVar->Get().pszVal, -1, &result[0], size);
}
}
break;
}
// Trim whitespace from both ends
if (!result.empty())
{
size_t start = result.find_first_not_of(L" \t\r\n");
size_t end = result.find_last_not_of(L" \t\r\n");
if (start != std::wstring::npos && end != std::wstring::npos)
{
result = result.substr(start, end - start + 1);
}
else if (start == std::wstring::npos)
{
result.clear();
}
}
return result.empty() ? std::nullopt : std::make_optional(result);
}
std::optional<int64_t> WICMetadataExtractor::ReadInteger(IWICMetadataQueryReader* reader, const std::wstring& path)
{
auto propVar = ReadMetadata(reader, path);
if (!propVar.has_value())
return std::nullopt;
int64_t result = 0;
switch (propVar->Get().vt)
{
case VT_I1: result = propVar->Get().cVal; break;
case VT_I2: result = propVar->Get().iVal; break;
case VT_I4: result = propVar->Get().lVal; break;
case VT_I8: result = propVar->Get().hVal.QuadPart; break;
case VT_UI1: result = propVar->Get().bVal; break;
case VT_UI2: result = propVar->Get().uiVal; break;
case VT_UI4: result = propVar->Get().ulVal; break;
case VT_UI8: result = static_cast<int64_t>(propVar->Get().uhVal.QuadPart); break;
default:
return std::nullopt;
}
return result;
}
std::optional<double> WICMetadataExtractor::ReadDouble(IWICMetadataQueryReader* reader, const std::wstring& path)
{
auto propVar = ReadMetadata(reader, path);
if (!propVar.has_value())
return std::nullopt;
double result = 0.0;
switch (propVar->Get().vt)
{
case VT_R4:
result = static_cast<double>(propVar->Get().fltVal);
break;
case VT_R8:
result = propVar->Get().dblVal;
break;
case VT_UI1 | VT_VECTOR:
case VT_UI4 | VT_VECTOR:
// Handle rational number (common for EXIF values)
// Rational data is stored as 8 bytes: 4-byte numerator + 4-byte denominator
if (propVar->Get().caub.cElems >= 8)
{
// ExposureBias (EXIF tag 37380) uses SRATIONAL type (signed rational)
// which can represent negative values like -0.33 EV for exposure compensation.
// Most other EXIF fields use RATIONAL type (unsigned) for values like aperture, shutter speed.
if (path == EXIF_EXPOSURE_BIAS)
{
// Parse as signed rational: int32_t / int32_t
result = MetadataFormatHelper::ParseSingleSRational(propVar->Get().caub.pElems, 0);
break;
}
else
{
// Parse as unsigned rational: uint32_t / uint32_t
// First check if denominator is valid (non-zero) to avoid division by zero
const uint8_t* bytes = propVar->Get().caub.pElems;
uint32_t denominator = static_cast<uint32_t>(bytes[4]) |
(static_cast<uint32_t>(bytes[5]) << 8) |
(static_cast<uint32_t>(bytes[6]) << 16) |
(static_cast<uint32_t>(bytes[7]) << 24);
if (denominator != 0)
{
result = MetadataFormatHelper::ParseSingleRational(propVar->Get().caub.pElems, 0);
break;
}
}
}
return std::nullopt;
default:
// Try integer conversion
switch (propVar->Get().vt)
{
case VT_I1: result = static_cast<double>(propVar->Get().cVal); break;
case VT_I2: result = static_cast<double>(propVar->Get().iVal); break;
case VT_I4: result = static_cast<double>(propVar->Get().lVal); break;
case VT_I8:
{
// ExposureBias (EXIF tag 37380) may be stored as VT_I8 in some WIC implementations
// It represents a signed rational (SRATIONAL) packed into a 64-bit integer
if (path == EXIF_EXPOSURE_BIAS)
{
// Parse signed rational from int64: low 32 bits = numerator, high 32 bits = denominator
// Some implementations may reverse the order, so we try both
int32_t numerator = static_cast<int32_t>(propVar->Get().hVal.QuadPart & 0xFFFFFFFF);
int32_t denominator = static_cast<int32_t>(propVar->Get().hVal.QuadPart >> 32);
if (denominator != 0)
{
result = static_cast<double>(numerator) / static_cast<double>(denominator);
}
else
{
// Try reversed order: high 32 bits = numerator, low 32 bits = denominator
numerator = static_cast<int32_t>(propVar->Get().hVal.QuadPart >> 32);
denominator = static_cast<int32_t>(propVar->Get().hVal.QuadPart & 0xFFFFFFFF);
if (denominator != 0)
{
result = static_cast<double>(numerator) / static_cast<double>(denominator);
}
else
{
result = 0.0; // Default to 0 if both attempts fail
}
}
}
else
{
// For other fields, treat VT_I8 as a simple 64-bit integer
result = static_cast<double>(propVar->Get().hVal.QuadPart);
}
}
break;
case VT_UI1: result = static_cast<double>(propVar->Get().bVal); break;
case VT_UI2: result = static_cast<double>(propVar->Get().uiVal); break;
case VT_UI4: result = static_cast<double>(propVar->Get().ulVal); break;
case VT_UI8:
{
// ExposureBias (EXIF tag 37380) may be stored as VT_UI8 in some WIC implementations
// Even though it's unsigned, we need to reinterpret it as signed for SRATIONAL
if (path == EXIF_EXPOSURE_BIAS)
{
// Parse signed rational from uint64 (reinterpret as signed)
// Low 32 bits = numerator, high 32 bits = denominator
int32_t numerator = static_cast<int32_t>(propVar->Get().uhVal.QuadPart & 0xFFFFFFFF);
int32_t denominator = static_cast<int32_t>(propVar->Get().uhVal.QuadPart >> 32);
if (denominator != 0)
{
result = static_cast<double>(numerator) / static_cast<double>(denominator);
}
else
{
// Try reversed order: high 32 bits = numerator, low 32 bits = denominator
numerator = static_cast<int32_t>(propVar->Get().uhVal.QuadPart >> 32);
denominator = static_cast<int32_t>(propVar->Get().uhVal.QuadPart & 0xFFFFFFFF);
if (denominator != 0)
{
result = static_cast<double>(numerator) / static_cast<double>(denominator);
}
else
{
result = 0.0; // Default to 0 if both attempts fail
}
}
}
else
{
// For other EXIF rational fields (unsigned), try both byte orders to handle different encodings
// First try: low 32 bits = numerator, high 32 bits = denominator
uint32_t numerator = static_cast<uint32_t>(propVar->Get().uhVal.QuadPart & 0xFFFFFFFF);
uint32_t denominator = static_cast<uint32_t>(propVar->Get().uhVal.QuadPart >> 32);
if (denominator != 0)
{
result = static_cast<double>(numerator) / static_cast<double>(denominator);
}
else
{
// Second try: high 32 bits = numerator, low 32 bits = denominator
numerator = static_cast<uint32_t>(propVar->Get().uhVal.QuadPart >> 32);
denominator = static_cast<uint32_t>(propVar->Get().uhVal.QuadPart & 0xFFFFFFFF);
if (denominator != 0)
{
result = static_cast<double>(numerator) / static_cast<double>(denominator);
}
else
{
// Fall back to treating as regular integer if denominator is 0
result = static_cast<double>(propVar->Get().uhVal.QuadPart);
}
}
}
}
break;
default:
return std::nullopt;
}
}
return result;
}
std::optional<PropVariantValue> WICMetadataExtractor::ReadMetadata(IWICMetadataQueryReader* reader, const std::wstring& path)
{
if (!reader)
return std::nullopt;
PropVariantValue value;
HRESULT hr = reader->GetMetadataByName(path.c_str(), value.GetAddressOf());
if (SUCCEEDED(hr))
{
return std::optional<PropVariantValue>(std::move(value));
}
return std::nullopt;
}
// GPS parsing functions have been moved to MetadataFormatHelper for better testability
bool WICMetadataExtractor::ExtractXMPMetadata(
const std::wstring& filePath,
XMPMetadata& outMetadata)
{
return cache.GetOrLoadXMP(filePath, outMetadata, [this, &filePath](XMPMetadata& metadata) {
return LoadXMPMetadata(filePath, metadata);
});
}
bool WICMetadataExtractor::LoadXMPMetadata(
const std::wstring& filePath,
XMPMetadata& outMetadata)
{
if (!PathFileExistsW(filePath.c_str()))
{
#ifdef _DEBUG
std::wstring msg = L"[PowerRename] XMP metadata extraction failed: File not found - " + filePath + L"\n";
OutputDebugStringW(msg.c_str());
#endif
return false;
}
auto decoder = CreateDecoder(filePath);
if (!decoder)
{
#ifdef _DEBUG
std::wstring msg = L"[PowerRename] XMP metadata extraction: Unsupported format or unable to create decoder - " + filePath + L"\n";
OutputDebugStringW(msg.c_str());
#endif
return false;
}
CComPtr<IWICBitmapFrameDecode> frame;
if (FAILED(decoder->GetFrame(0, &frame)))
{
#ifdef _DEBUG
std::wstring msg = L"[PowerRename] XMP metadata extraction failed: WIC decoder error - " + filePath + L"\n";
OutputDebugStringW(msg.c_str());
#endif
return false;
}
CComPtr<IWICMetadataQueryReader> rootReader;
if (FAILED(frame->GetMetadataQueryReader(&rootReader)))
{
// No metadata is not necessarily an error - just means the file has no XMP data
return false;
}
ExtractAllXMPFields(rootReader, outMetadata);
return true;
}
// Batch extraction method implementations
void WICMetadataExtractor::ExtractAllXMPFields(IWICMetadataQueryReader* reader, XMPMetadata& metadata)
{
if (!reader)
return;
// XMP Basic schema - xmp: namespace
metadata.creatorTool = ReadString(reader, XMP_CREATOR_TOOL);
metadata.createDate = ReadDateTime(reader, XMP_CREATE_DATE);
metadata.modifyDate = ReadDateTime(reader, XMP_MODIFY_DATE);
metadata.metadataDate = ReadDateTime(reader, XMP_METADATA_DATE);
// Dublin Core schema - dc: namespace
metadata.title = ReadString(reader, XMP_DC_TITLE);
metadata.description = ReadString(reader, XMP_DC_DESCRIPTION);
metadata.creator = ReadString(reader, XMP_DC_CREATOR);
// For dc:subject, we need to handle the array structure
// Try to read individual elements
// XMP allows for large arrays, but we limit to a reasonable number to avoid performance issues
constexpr int MAX_XMP_SUBJECTS = 50;
std::vector<std::wstring> subjects;
for (int i = 0; i < MAX_XMP_SUBJECTS; ++i)
{
std::wstring subjectPath = L"/xmp/dc:subject/{ulong=" + std::to_wstring(i) + L"}";
auto subject = ReadString(reader, subjectPath);
if (subject.has_value())
{
subjects.push_back(subject.value());
}
else
{
break; // No more subjects
}
}
if (!subjects.empty())
{
metadata.subject = subjects;
}
// XMP Rights Management schema
metadata.rights = ReadString(reader, XMP_RIGHTS);
// XMP Media Management schema - xmpMM: namespace
metadata.documentID = ReadString(reader, XMP_MM_DOCUMENT_ID);
metadata.instanceID = ReadString(reader, XMP_MM_INSTANCE_ID);
metadata.originalDocumentID = ReadString(reader, XMP_MM_ORIGINAL_DOCUMENT_ID);
metadata.versionID = ReadString(reader, XMP_MM_VERSION_ID);
}