编码 JPG 图像的元数据中字符之间的额外空字符



此线程是保存 PNG 图像后元数据中额外字符/字节的延续

但我现在考虑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,作为与PropertyTagImageDescriptionPropertyItem 相关的类型。这些类型以不同的方式存储数据:

PropertyTagExifUserComment 标记中使用的字符代码是 根据开头固定 8 字节区域中的 ID 代码进行识别 标记数据区域。该区域的未使用部分填充为 null 字符 (0)。ID代码通过注册方式分配。 由于类型不是 ASCII,因此无需使用 NULL 终结者。

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

不幸的是,文档相对于PropertyItem.Type值并不简单。这些在gdiplusimaging.h中定义。使用 PropertyItem.Type 说明作为参考。

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

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)

期望这一点,代码保持不变。

相关内容

  • 没有找到相关文章

最新更新