【问题标题】:Extra null Char between characters in metadata encoding a JPG image元数据中编码 JPG 图像的字符之间的额外空字符
【发布时间】:2021-04-21 13:45:19
【问题描述】:

这个话题是Extra characters/bytes in metadata after saving a PNG image的延续

但我现在考虑JPEGfiles,而不是PNG files。

我正在尝试根据名为“sc_status”的参数的值写入元数据。我改编了 Jimi 的提议,该提议非常适用于 PNG 文件:

Imports System.Drawing.Imaging
Imports System.Text

'0x9286 = User Comments
Dim imageDescriptionPropItem = &H9286
' Property Type 2: null-terminated string
Dim PropertyTagTypeASCII As short = 2

Dim encoderParams As New EncoderParameters(1)
Dim ImgCodec = ImageCodecInfo.GetImageEncoders().
               FirstOrDefault(Function(enc) enc.FormatID = ImageFormat.Jpeg.Guid)
If ImgCodec Is Nothing Then
    Throw New FormatException("Invalid format")
End If
encoderParams.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 95L)

Dim imagePath = [Image Source Path]
Dim imageDestinationPath = [Image Destination Path]
Dim imageSourcePath = Image.FromStream(New MemoryStream(File.ReadAllBytes(imageSourcePath)))

Dim propItem As PropertyItem = DirectCast(FormatterServices.GetUninitializedObject(
    GetType(PropertyItem)), PropertyItem)

propItem.Id = imageDescriptionPropItem 
propItem.Type = PropertyTagTypeASCII

Dim description = String.Empty
Select Case sc_status
    Case 3
        description = "HQ" & ChrW(0)
    Case 5
        description = "LQ" & ChrW(0)
    Case Else
        description = "UQ" & ChrW(0)
End Select

' Length of the string including the terminator: mandatory
propItem.Value = Encoding.UTF8.GetBytes(description)
propItem.Len = propItem.Value.Length

imageSource.SetPropertyItem(propItem)
imageSource.Save(imageDestinationPath, ImgCodec, encoderParams)

元数据检查通过以下方式执行:

Dim imageEncoded = Image.FromStream(New MemoryStream(File.ReadAllBytes(imageDestinationPath)))
Dim propItemSaved = imageEncoded.GetPropertyItem(imageDescriptionPropItem)
Dim descr = Encoding.UTF8.GetString(propItemNew.Value).TrimEnd(ChrW(0))

我希望在字节序列中有[72, 81, 0][76, 81, 0][85, 81, 0]。但我得到[72, 0, 81, 0, 0][76, 0, 81, 0, 0][85, 0, 81, 0, 0]。所以每个字符之间多了一个0字节,提供如下字符串:"L" & vbNullChar & "Q" & vbNullChar等。

为什么要插入这些零以及如何摆脱它? 为什么它适用于PNG 图像(使用图像描述道具&H10E)而不是JPEG 图像(使用用户评论道具&H9286)?

非常感谢您的支持。

【问题讨论】:

    标签: vb.net graphics metadata jpeg gdi+


    【解决方案1】:

    您设置了错误的 PropertyItem.Type。
    PropertyTagExifUserComment (0x9286) 将其类型定义为PropertyTagTypeUndefined = 7,而您将其设置为PropertyTagTypeASCII = 2,作为与PropertyTagImageDescription PropertyItem 相关的类型。这些类型不以相同的方式存储数据:

    PropertyTagExifUserComment 标记中使用的字符代码是 基于 ID 代码在一个固定的 8 字节区域的开始识别 标签数据区。该区域的未使用部分用 null 填充 字符 (0)。 ID 代码是通过注册分配的。 因为类型不是 ASCII,所以没有必要使用 NULL 终结者。

    没有必要设置空终止符,但如果你这样做了,那也不是问题。

    不幸的是,文档与 PropertyItem.Type 值的关系并不直接。这些在gdiplusimaging.h 中定义。使用PropertyItem.Type 描述作为参考。

    让我们为这些 PropertyItems 类型定义一个枚举器,以简化其使用:

    Public Enum PropertyItemType As Short
        PropertyTagTypeByte = 1
        PropertyTagTypeASCII = 2
        PropertyTagTypeShort = 3
        PropertyTagTypeLong = 4
        PropertyTagTypeRational = 5
        PropertyTagTypeUndefined = 7
        PropertyTagTypeSLONG = 9
        PropertyTagTypeSRational = 10
    End Enum
    

    因此代码更改为:

    Dim propTagExifUserComment = &H9286
    
    propItem.Id = propTagExifUserComment
    propItem.Type = PropertyItemType.PropertyTagTypeUndefined
    ' [...]
    Dim propItemSaved = imageSaved.GetPropertyItem(propTagExifUserComment)
    

    希望如此,代码保持不变。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 2018-06-29
      • 1970-01-01
      相关资源
      最近更新 更多