.NET Image.RemovePropertyItem 无明显效果

标签 .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")
    

    最佳答案

    我也遇到了这个问题。
    似乎如果您尝试删除 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() 很好奇,然后挖得更深一些。
    仅供引用。

    关于.NET Image.RemovePropertyItem 无明显效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41679087/

    相关文章:

    c# - 如何使用 OnStop 方法终止线程 (C#)

    .net - 在我自己的代码中抛出 AggregateException

    php - 如何创建壁纸

    html - 如何将 HTML 电子邮件中的 GIF 与不支持的客户端的不同图像交换

    vb.net - 带像素化的图像缩放

    .net - 与 Mercurial、MSBuild、ASP.NET 持续集成

    c# - ReliabilityContractAttribute 有什么作用?

    .net - .net中的Tuple(T1)/Singleton的目的是什么?

    java - "light"被视为什么光度值?

    python - 放大图像时控制平移(锚定点)