Resource

Resource Basics

Resource Name Remove XMP Properties
Resource Version 1.0
Category Metadata
Downloads 453
Release Date 7/31/2025 3:49:54 PM
 

Resource Details

Description This script allows you to remove individual XMP propertie/properties from the image's XMP.

You can use masks to configure the properties to delete.

Samples:
dc:Subject
crs:Table_*

IMPORTANT; this script permanently removes the selected XMP properties, and that may be synced to your image files. USE WITH CARE.
Installation Instructions None
Usage Instructions 1. Select one or more thumbs
2. Right click on a selected thumb
3. Select Run Script from Repository -> Metadata -> Remove XMP Properties

USE WITH CARE AS YOUR XMP CAN BE PERMANENTLY ALTERED.
Changes in this version na
Special Requirements
 

Author Information

Author Name IDimager Support
 

Available Attachments

Attachment #1 RemoveXMPProperties.png
 

Script

  function IsMatchingMask(AStr, AMask: WideString): Boolean;
  begin
    result := WideMatchesMask(StrTran(AStr, ':', '_'), StrTran(AMask, ':', '_'));
  end;

  procedure DumpParamToStrings(AParam: TMacroParam; AResult: TTntStrings; APrefix: WideString);
  var
    i: Integer;
  begin
    if (AParam.ParamType = ptConstant) or
       (AParam.ParamType = ptVariable) or
       (AParam.ParamType = ptSequence) or
       (AParam.ParamType = ptBag) or
       (AParam.ParamType = ptAlternative)
    then
      AResult.AddObject(APrefix + iif(APrefix = '', '', '.') + AParam.ParamCommand, AParam)
    else if AParam.ParamType = ptStructure then
    begin
      APrefix := APrefix + iif(APrefix = '', '', '.') + AParam.ParamCommand;
      for i := 0 to AParam.CustomParams.Count - 1 do
        DumpParamToStrings(AParam.CustomParams.Items[i], AResult, APrefix);
    end;

    for i := 0 to AParam.SubParams.Count - 1 do
      DumpParamToStrings(AParam.SubParams.Items[i], AResult, APrefix);
  end;

  procedure DumpXMPParamsToStrings(AXmp: TXMP; AResult: TTntStrings);
  var
    i: Integer;
  begin
    for i := 0 to AXmp.XMPDesign.Params.Count - 1 do
      DumpParamToStrings(AXmp.XMPDesign.Params.Items[i], AResult, '');
  end;

  function RemoveProperties(AXmp: TXMP; AXMPProps: TTntStrings): Boolean;
  var
    AXmpDump: TTntStringList;
    i, j: Integer;
    AParamCommand: WideString;
    AParam: TMacroCommand;
    AMatchList: TxomList;
  begin
    result := False;

    AMatchList := TxomList.Create;
    AXmpDump := TTntStringList.Create;
    try
      DumpXMPParamsToStrings(AXmp, AXmpDump);

      for i := 0 to AXmpDump.Count - 1 do
      begin
        AParamCommand := AXmpDump.Strings[i];
        AParam := AXmpDump.Objects[i];

        for j := 0 to AXMPProps.Count - 1 do
        begin
          if IsMatchingMask(AParamCommand, AXMPProps.Strings[j]) then
          begin
            AMatchList.Add(AParam);
            break;
          end;
        end;
      end;

      if AMatchList.Count > 0 then
      begin
        result := True;
        for i := 0 to AMatchList.Count - 1 do
        begin
          AParam := AMatchList.Items[i];
          AParam.Free;
        end;
      end;
    finally
      AXmpDump.Free;
      AMatchList.Free;
    end;
  end;

  function HandleImage(AItem: TImageItem; AXMPProps: TTntStrings): Boolean;
  var
    ACatItem: TCatalogItem;
    AXmp: TXMP;
  begin
    {
      1. Load XMP
      2. Iterate over all properties and remove matches
      3. If handled, save XMP
    }

    result := False;
    ACatItem := TCatalogItem.Create(nil);
    try
      if PublicCatalog.FindImageCombined(AItem, ACatItem, False, vptNone) then
      begin
        AXmp := TXMP.Create(False);
        try
          PublicCatalog.LoadXMPForItem(ACatItem, AXmp, PublicOptions.CachedXMP);

          if RemoveProperties(AXmp, AXMPProps) then
          begin
            // save the XMP again
            PublicCatalog.SaveXMPForItem(ACatItem, AXmp, PublicOptions.CachedXMP);
            result := True;
          end;
        finally
          AXmp.Free;
        end;
      end;
    finally
      ACatItem.Free;
    end;
  end;

var
  AXMPProps: TTntStringList;
  AProperties: WideString;
  AHit: Integer;
begin
  if Selected.Count = 0 then
  begin
    Say('Select at least one file to remove XMP properties from.');
    exit;
  end;

  AProperties := ReadFromRegistry('Scripts\RemoveXMPProp', 'Props', 'crs:Table_*');
  if not AskInput('Remove XMP Properties', 'Enter what XMP properties to remove', 'You can use * (asterisk) as a joker. Comma separate multiple entries.', AProperties, False, nil) then
    exit;

  if Trim(AProperties) = '' then
  begin
    Say('No properties entered');
    exit;
  end;

  if not AskYN('Are you sure that you want to remove these XMP properties for all ' + IntToStrW(Selected.Count) + ' selected images?' + CrLf2W + AProperties) then
    exit;

  WriteToRegistry('Scripts\RemoveXMPProp', 'Props', AProperties);
  AXMPProps := TTntStringList.Create;
  try
    Tokenize(AProperties, ',', AXmpProps);

    AHit := 0;
    for i := 0 to Selected.Count - 1 do
    begin
      if HandleImage(Selected.Items[i], AXmpProps) then
        AHit := AHit + 1;
    end;
  finally
    AXMPProps.Free;
  end;

  if AHit > 0 then
    Say('Removed the properties for ' + IntToStrW(AHit) + ' images.')
  else
    Say('No matching images found with matching properties in the XMP');
end;