编码 JPG 图像的元数据中字符之间的额外空字符
Extra null Char between characters in metadata encoding a JPG image
此线程是
的延续
但我现在考虑 JPEG
个文件,而不是 PNG
个文件。
我正在尝试根据名为 '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
)?
非常感谢您的支持。
你设置错了PropertyItem.Type。
PropertyTagExifUserComment (0x9286
) 将其类型定义为 PropertyTagTypeUndefined = 7
,而您将其设置为 PropertyTagTypeASCII = 2
,作为与 PropertyTagImageDescription
PropertyItem 相关的类型。这些类型不以相同的方式存储数据:
The character code used in the PropertyTagExifUserComment tag is
identified based on an ID code in a fixed 8-byte area at the start of
the tag data area. The unused portion of the area is padded with null
characters (0). ID codes are assigned by means of registration.
Because the type is not ASCII, it is not necessary to use a NULL
terminator.
不需要设置空终止符,但如果你这样做了,那也不是问题。
不幸的是,与 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)
期待这一点,代码保持不变。
此线程是
但我现在考虑 JPEG
个文件,而不是 PNG
个文件。
我正在尝试根据名为 '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
)?
非常感谢您的支持。
你设置错了PropertyItem.Type。
PropertyTagExifUserComment (0x9286
) 将其类型定义为 PropertyTagTypeUndefined = 7
,而您将其设置为 PropertyTagTypeASCII = 2
,作为与 PropertyTagImageDescription
PropertyItem 相关的类型。这些类型不以相同的方式存储数据:
The character code used in the PropertyTagExifUserComment tag is identified based on an ID code in a fixed 8-byte area at the start of the tag data area. The unused portion of the area is padded with null characters (0). ID codes are assigned by means of registration. Because the type is not ASCII, it is not necessary to use a NULL terminator.
不需要设置空终止符,但如果你这样做了,那也不是问题。
不幸的是,与 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)
期待这一点,代码保持不变。