我一直在努力从图像中删除Exif元数据,然后再将它们输入到某些ML算法中。
我的示例图片是this one,一个包含超过500kB元数据的小型100x100图片,下载为backpack.jpg
。磁盘上的文件大小为584kB。
首先:只需加载图像,将其保存回磁盘:
open System
open System.Drawing
open System.Drawing.Imaging
// Image from http://www.aedsuperstore.com/assets/images/PAD-BAG-02-T-Thumb.jpg
// downloaded as c:/temp/backpack.jpg, File size 584kB
let img = Bitmap.FromFile "c:/temp/backpack.jpg"
// Saves into a file of 563kB
img.Save "c:/temp/backpack_unchanged.jpg"
很奇怪,文件大小下降了20kB,达到563kB,但我最初忽略了这一点(我指责默认的编码器质量)
图像有一项占用超过500000字节的元数据:
> img.GetPropertyItem 34675;;
val it : PropertyItem =
System.Drawing.Imaging.PropertyItem
{Id = 34675;
Len = 557168;
Type = 1s;
...
要删除元数据,我浏览了所有属性项,并调用了RemovePropertyItem
:
let ids = img.PropertyIdList
for id in ids do
img.RemovePropertyItem id
if img.PropertyIdList.Length <> 0 then
failwith "There are properties left?"
没有抛出任何异常,似乎已删除所有属性。
然后保存到磁盘 - 我得到一个584kB的文件:
// Saves into a file of 584 kB
img.Save("c:/temp/backpack_removed.jpg")
现在有两大问题:
MSDN上有两个相关问题,one with an answer that I found not helpful和one without an answer。 .NET documentation for RemovePropertyItems
也没有具体说明。有一个类似的SO question提供了一种解决方法,但没有解释。
Fwiw,可靠地删除元数据的方法是重新绘制图像,如下所示:
// Saves into a file of 19kB
let reDrawn = new Bitmap(img)
reDrawn.Save("c:/temp/backpack_reDrawn.jpg")
答案 0 :(得分:0)
我也遇到了这个问题。 看来,如果您尝试删除PropertyItems中的所有项目,它们将在内存中被删除一次,但是当您将映像保存到磁盘时,所有属性项目都将返回。 我不知道为什么,但是作为一种解决方法,当您删除项目时,可以保持其中一个不变。 如果您对它的值不满意,可以简单地将其值设置为空白字节[]。
foreach (var prop in bm.PropertyItems)
{
if (prop.Id == 0x10F)//PropertyTagEquipMake
{//I picked 0x10F because I assume it exists in most images.
PropertyItem pi = bm.GetPropertyItem(prop.Id);
pi.Value = new byte[] { 0 };
bm.SetPropertyItem(pi);
}
else
{
bm.RemovePropertyItem(prop.Id);
}
}
但是最后我选择使用与您相同的解决方案,它看起来更可靠,更干净。我对RemovePropertyItem()感到好奇,然后再深入研究。 仅供参考。