.NET Image.RemovePropertyItem没有明显的效果

时间:2017-01-16 14:52:39

标签: .net image

我一直在努力从图像中删除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")

现在有两大问题:

  • 为什么删除属性项没有任何明显的效果?我可以做任何事情来使它产生影响吗?
  • 为什么第二次保存时,磁盘上的图像尺寸会恢复到原来的584kB?

MSDN上有两个相关问题,one with an answer that I found not helpfulone 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")

1 个答案:

答案 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()感到好奇,然后再深入研究。 仅供参考。