【问题标题】:Write metadata to PNG image in .NET在 .NET 中将元数据写入 PNG 图像
【发布时间】:2010-07-22 21:05:48
【问题描述】:

我看到很多问题询问如何从图像中读取元数据,但我还没有看到很多问题询问如何写入元数据。基本上,我需要将一项元数据(“ImageDescription”)添加到我动态生成的 PNG 图像(创建一个 Bitmap 对象并以程序方式生成其中的所有内容)。

在将文件写入磁盘之前或之后使用 .NET 将元数据添加到图像的最佳方法是什么?

【问题讨论】:

    标签: .net vb.net png metadata system.drawing


    【解决方案1】:

    您可以使用FreeImage.NET library,我相信它可以读写PNG文件及其元数据。

    【讨论】:

    • 谢谢,这似乎应该可以工作.. 如果我能让它看起来写我想要它写的标签
    【解决方案2】:

    您可以使用 System.Windows.Media.Imaging 中的 BitmapMetadata 来写入 iTXt 值。 VB 示例:

    ' Imports System.Windows.Media.Imaging
    ' Imports System.Windows.Media
    
    Dim width = 256
    Dim height = 256
    Dim pngMetadata = New BitmapMetadata("png")
    
    ' PNG spec: http://www.libpng.org/pub/png/book/chapter11.html - Info on the iTXt chunk (and other custom metadata tags). 
    
    pngMetadata.SetQuery("/iTXt/Keyword", "SomeKeyword".ToCharArray())
    pngMetadata.SetQuery("/iTXt/TextEntry", "SomeValue")
    
    Dim bitmap = New WriteableBitmap(width, height, 96, 96, PixelFormats.Gray8, Nothing)
    Dim pixels = New Byte(width * height - 1) {}
    For y = 0 To height - 1
        For x = 0 To width - 1
            pixels(y * width + x) = CByte(x)
        Next
    Next
    
    bitmap.WritePixels(New Int32Rect(0, 0, width, height), pixels, width, 0)
    Dim encoder = New PngBitmapEncoder()
    encoder.Frames.Add(BitmapFrame.Create(bitmap, Nothing, pngMetadata, Nothing))
    
    Using stream = File.Create("c:\pngWithMetaData.png")
        encoder.Save(stream)
    End Using
    

    【讨论】:

      【解决方案3】:

      需要将一些简单的元数据写入至少 .png 和 .jpg 并且不必将另一个 3rd 方库拖到我的程序中。几个小时后似乎没有任何效果,即使所有文件类型都不同等等。

      考虑只存储在图像旁边的文件中,或者保留一个小的文件“数据库”和我需要的数据。

      对我来说,我只是在重新加载图像时再次需要数据。数据包含一个转换因子,它告诉我有多少像素 = 1mm。

      剧透...如果您不喜欢黑客,请立即离开。

      基本上在我用二进制“@Conv=”写的文件末尾,后跟该值的 8 字节双精度值。

      我的程序在二进制读取中打开图像...寻找到最后减去我的“hack”中的总字节数并寻找“@Conv=”。如果找到它,它会读取值。一旦确定了比例因子,程序就可以选择保存,而不必每次打开时都测量并输入一个值。

      我有读取/查询、更新和添加数据的代码。

      适用于 .png、.jpg 和可能的其他类型。

      我这样做的文件被复制并且是本地的。显然,如果文件是从其他应用程序重写的,数据将会丢失,但对于许多应用程序的任何元数据来说,这可能都是正确的。

      我最终存储了一些数据项,包括“原点”位置(以像素为单位)和图像的首选旋转 (0,90,180,270)。

      一些 vbcode 只是为了好玩。

      Shared arr_magic As Byte() = {CByte(AscW("@"c)), CByte(AscW("C"c)), CByte(AscW("o"c)), CByte(AscW("n"c)), CByte(AscW("v"c)), CByte(AscW("2"c)), CByte(AscW("="c))}
      
      Const metaSize As Integer = 8 + 4 + 4 + 4
      Function FileCheckScale(fn As String, ByRef origin As Point, ByRef angle As Integer, update As Boolean) As Double
          Dim fr = New IO.StreamReader(fn)
      
          Dim br As New IO.BinaryReader(fr.BaseStream)
      
          fr.BaseStream.Seek(-(metaSize + arr_magic.Length), IO.SeekOrigin.End)
      
          For i = 0 To arr_magic.Length - 1
              If br.ReadByte() <> arr_magic(i) Then
                  fr.Close()
                  Return 0.0 ' <= 0 means not found
              End If
          Next
      
          Dim v As Double = br.ReadDouble
      
          If update Then
              origin.X = br.ReadInt32
              origin.Y = br.ReadInt32
              angle = br.ReadInt32
          End If
      
          fr.Close()
      
          Return v
      End Function
      
      
      Sub FileUpdateScale(fn As String, v As Double, origin As Point, angle As Integer)
          Dim fr = New IO.FileStream(fn, IO.FileMode.Open, IO.FileAccess.Write)
      
          Dim br As New IO.BinaryWriter(fr)
      
          fr.Seek(-(metaSize + arr_magic.Length), IO.SeekOrigin.End)
      
          br.Write(arr_magic)
          br.Write(v)
          br.Write(origin.X)
          br.Write(origin.Y)
          br.Write(angle)
      
          fr.Close()
      End Sub
      
      Sub FileAddScale(fn As String, v As Double, origin As Point, angle As Integer)
          Dim fr = New IO.StreamWriter(fn, True)
          Dim br As New IO.BinaryWriter(fr.BaseStream)
      
          fr.BaseStream.Seek(0, IO.SeekOrigin.End)
      
          br.Write(arr_magic)
          br.Write(v)
          br.Write(origin.X)
          br.Write(origin.Y)
          br.Write(angle)
      
          fr.Close()
      End Sub
      

      【讨论】:

        猜你喜欢
        • 2014-03-17
        • 2011-07-16
        • 2013-02-19
        • 1970-01-01
        • 2017-09-15
        • 2013-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多