C#如何从图像中删除XPKeywords(PropertyItem 0x9c9e)

C#如何从图像中删除XPKeywords(PropertyItem 0x9c9e),c#,image,jpeg,exif,C#,Image,Jpeg,Exif,我在编辑或删除照片中的关键词时遇到困难。以下操作可成功替换关键字: ... string s_keywords = "tag1;tag2;tag3"; PropertyItem item_keyword = (PropertyItem)FormatterServices.GetUninitializedObject(typeof(PropertyItem)); item_keyword.Id = 0x9c9e; // XPKeywords item_keyword.Type = 1; item_

我在编辑或删除照片中的关键词时遇到困难。以下操作可成功替换关键字:

...
string s_keywords = "tag1;tag2;tag3";
PropertyItem item_keyword = (PropertyItem)FormatterServices.GetUninitializedObject(typeof(PropertyItem));
item_keyword.Id = 0x9c9e; // XPKeywords
item_keyword.Type = 1;
item_keyword.Value = System.Text.Encoding.Unicode.GetBytes(s_keywords + "\0");
item_keyword.Len = item_keyword.Value.Length;
image.SetPropertyItem(item_keyword);
...
注意,我的实验表明,
image.RemovePropertyItem(0x9c9e)似乎对保存的图像没有影响。将上述代码与
s_关键字=“一起使用

不要这样做:以下代码可以删除关键字,但会导致jpeg重新编码并失去一些质量(图像文件从4MB变为<2MB,我可以看到一些轻微的视觉差异):

我在设置XPTitle时遇到了类似的问题-设置propertyItem 0x9c9b在保存的图像中似乎没有效果,相反,我必须以BitmapFrame的形式打开文件,提取BitmapMetadata并使用Title属性,然后使用JpegBitmapEncoder构建新的jpeg-从而重新编码并降低图像质量

...
BitmapFrame bf_title = BitmapFrame.Create(new Uri(tmp_file, UriKind.Relative));
BitmapMetadata bmd_title = (BitmapMetadata)bf_title.Metadata.Clone();
bmd_title.Title = new_title;
BitmapFrame bf_new = BitmapFrame.Create(bf_title, bf_title.Thumbnail, bmd_title, bf_title.ColorContexts);
JpegBitmapEncoder je = new JpegBitmapEncoder();
je.Frames.Add(bf_new);
FileStream fs = new FileStream(tmp_file, FileMode.Create);
je.Save(fs);
fs.Close();
...
有关更改标题的正确方法,请参见下面的答案


这让我抓狂,我希望这能帮助其他人…

注意,上面的关键字代码现在可以完美地工作了

我之所以回答这个问题,是因为我在搜索时找不到这样做的示例代码——所以希望其他人会发现这很有用

要更改标题,请使用以下代码。问题是有两个标记会影响windows显示标题的方式-其中一个(0x010e)优先于XPTitle(0xc9b)标记

注意-另一个潜在问题是,您需要将图像保存到新位置。然后,如果需要,可以处理图像并将其复制到原始位置

...
BitmapFrame bf_title = BitmapFrame.Create(new Uri(tmp_file, UriKind.Relative));
BitmapMetadata bmd_title = (BitmapMetadata)bf_title.Metadata.Clone();
bmd_title.Title = new_title;
BitmapFrame bf_new = BitmapFrame.Create(bf_title, bf_title.Thumbnail, bmd_title, bf_title.ColorContexts);
JpegBitmapEncoder je = new JpegBitmapEncoder();
je.Frames.Add(bf_new);
FileStream fs = new FileStream(tmp_file, FileMode.Create);
je.Save(fs);
fs.Close();
...
...
string new_value = "New title for the image";
PropertyItem item_title = (PropertyItem)FormatterServices.GetUninitializedObject(typeof(PropertyItem));
item_title.Id = 0x9c9b; // XPTitle 0x9c9b
item_title.Type = 1;
item_title.Value = System.Text.Encoding.Unicode.GetBytes(new_value + "\0");
item_title.Len = item_title.Value.Length;
image.SetPropertyItem(item_title);
PropertyItem item_title2 = (PropertyItem)FormatterServices.GetUninitializedObject(typeof(PropertyItem));
item_title2.Id = 0x010e; // ImageDescription 0x010e
item_title2.Type = 2;
item_title2.Value = System.Text.Encoding.UTF8.GetBytes(new_value + "\0");
item_title2.Len = item_title2.Value.Length;
image.SetPropertyItem(item_title2);

image.Save("new_filename.jpg", ImageFormat.Jpeg)
image.Dispose();
...