使用 MetaDataExtractor 将 EXIF 添加回调整大小的图像
Using MetaDataExtractor to add EXIF back to resized image
使用 MVC 应用程序上传图像,我们需要在保存到数据库之前减小文件大小,但又想保留 EXIF 数据...我能想到的唯一方法是从原始上传的图像,然后使用 MetadataExtractor
将其添加到调整后的图像
我们可以这样获取元数据
Dim vMetadata As IEnumerable(Of System.IO.Directory) = MetadataExtractor.ImageMetadataReader.ReadMetadata(file.InputStream)
然后像这样调整图像大小
fext = IO.Path.GetExtension(file.FileName).ToLower
Dim vLen As Integer = file.ContentLength
Dim vData(vLen - 1) As Byte
Dim image_file As System.Drawing.Image = System.Drawing.Image.FromStream(file.InputStream)
Dim image_height As Integer = image_file.Height
Dim image_width As Integer = image_file.Width
Dim max_height As Integer = 240
Dim max_width As Integer = 320
image_height = (image_height * max_width) / image_width
image_width = max_width
If image_height > max_height Then
image_width = (image_width * max_height) / image_height
image_height = max_height
End If
Dim bitmap_file As New System.Drawing.Bitmap(image_file, image_width, image_height)
Using vStream As New IO.MemoryStream
Select Case fext
Case ".jpg"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case ".jpeg"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case ".png"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Png)
Case ".gif"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Gif)
Case Else
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
End Select
vStream.Position = 0
vStream.Read(vData, 0, vStream.Length)
vImageFile = vData
vData = Nothing
End Using
所以我们将元数据保存为字典,将缩小尺寸的图像文件保存为我们现在可以保存的变量 vImageFile...
问题是 - 我们如何将该元数据添加回新文件?
谢谢
--------------------编辑于 2017 年 10 月 1 日添加--------------------
我已经添加了这段代码
Dim vOrientationNumber As Integer = 1
Dim vEXIF As String = ""
Dim vDirectories = ImageMetadataReader.ReadMetadata(file.InputStream)
Dim vSub = vDirectories.OfType(Of ExifSubIfdDirectory)().FirstOrDefault
If Not vSub Is Nothing Then
Dim vOrientationObj = vSub.GetObject(ExifDirectoryBase.TagOrientation)
If Not vOrientationObj Is Nothing Then
If Not vOrientationObj.Equals(DBNull.Value) Then
vOrientationNumber = Convert.ToInt16(vOrientationObj)
End If
End If
End If
For Each vDirectory In vDirectories
For Each Tag In vDirectory.Tags
vEXIF += vDirectory.Name & " " & Tag.Name & " " & Tag.Description & Environment.NewLine
Next
Next
获取方向编号的句柄,但变量 vSub 始终为 Nothing。我知道这个图像的方向编号在那里(因为它在主 WPF 桌面应用程序中找到它并旋转它)。知道我现在可能做错了什么吗?
MetadataExtractor 不支持将元数据写入文件。这是一个受欢迎的功能请求,但要正确执行(这显然是必不可少的,因为人们可能会覆盖他们的文件)需要一些工作。
不过,只要您处理的是 JPEG 文件,该库确实提供了一些可能有用的代码。
JPEG 文件基本上是所谓的 JPEG 片段的列表。 Exif 数据存在于其中一个片段中。因此,如果您在原始图像中隔离该片段,则可以在调整大小后替换它。
很遗憾,我没有这方面的任何代码。您可以使用 JpegSegmentReader
来提取您需要的片段(Exif 在 JpegSegmentType.App1
中),这应该让您开始。
您看到的字符串值是一个描述。要访问原始方向值,请使用如下代码:
var directories = ImageMetadataReader.ReadMetadata(imagePath);
var subIfd = directories.OfType<ExifIfd0Directory>().FirstOrDefault();
int? orientation = subIfd?.GetObject(ExifDirectoryBase.TagOrientation);
请注意,subIfd
和 orientation
都可以为空,具体取决于图像。
这是 C#,我不知道 VB.NET,抱歉。希望这对您来说是一个简单的转换。
使用 MVC 应用程序上传图像,我们需要在保存到数据库之前减小文件大小,但又想保留 EXIF 数据...我能想到的唯一方法是从原始上传的图像,然后使用 MetadataExtractor
将其添加到调整后的图像我们可以这样获取元数据
Dim vMetadata As IEnumerable(Of System.IO.Directory) = MetadataExtractor.ImageMetadataReader.ReadMetadata(file.InputStream)
然后像这样调整图像大小
fext = IO.Path.GetExtension(file.FileName).ToLower
Dim vLen As Integer = file.ContentLength
Dim vData(vLen - 1) As Byte
Dim image_file As System.Drawing.Image = System.Drawing.Image.FromStream(file.InputStream)
Dim image_height As Integer = image_file.Height
Dim image_width As Integer = image_file.Width
Dim max_height As Integer = 240
Dim max_width As Integer = 320
image_height = (image_height * max_width) / image_width
image_width = max_width
If image_height > max_height Then
image_width = (image_width * max_height) / image_height
image_height = max_height
End If
Dim bitmap_file As New System.Drawing.Bitmap(image_file, image_width, image_height)
Using vStream As New IO.MemoryStream
Select Case fext
Case ".jpg"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case ".jpeg"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case ".png"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Png)
Case ".gif"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Gif)
Case Else
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
End Select
vStream.Position = 0
vStream.Read(vData, 0, vStream.Length)
vImageFile = vData
vData = Nothing
End Using
所以我们将元数据保存为字典,将缩小尺寸的图像文件保存为我们现在可以保存的变量 vImageFile...
问题是 - 我们如何将该元数据添加回新文件?
谢谢
--------------------编辑于 2017 年 10 月 1 日添加--------------------
我已经添加了这段代码
Dim vOrientationNumber As Integer = 1
Dim vEXIF As String = ""
Dim vDirectories = ImageMetadataReader.ReadMetadata(file.InputStream)
Dim vSub = vDirectories.OfType(Of ExifSubIfdDirectory)().FirstOrDefault
If Not vSub Is Nothing Then
Dim vOrientationObj = vSub.GetObject(ExifDirectoryBase.TagOrientation)
If Not vOrientationObj Is Nothing Then
If Not vOrientationObj.Equals(DBNull.Value) Then
vOrientationNumber = Convert.ToInt16(vOrientationObj)
End If
End If
End If
For Each vDirectory In vDirectories
For Each Tag In vDirectory.Tags
vEXIF += vDirectory.Name & " " & Tag.Name & " " & Tag.Description & Environment.NewLine
Next
Next
获取方向编号的句柄,但变量 vSub 始终为 Nothing。我知道这个图像的方向编号在那里(因为它在主 WPF 桌面应用程序中找到它并旋转它)。知道我现在可能做错了什么吗?
MetadataExtractor 不支持将元数据写入文件。这是一个受欢迎的功能请求,但要正确执行(这显然是必不可少的,因为人们可能会覆盖他们的文件)需要一些工作。
不过,只要您处理的是 JPEG 文件,该库确实提供了一些可能有用的代码。
JPEG 文件基本上是所谓的 JPEG 片段的列表。 Exif 数据存在于其中一个片段中。因此,如果您在原始图像中隔离该片段,则可以在调整大小后替换它。
很遗憾,我没有这方面的任何代码。您可以使用 JpegSegmentReader
来提取您需要的片段(Exif 在 JpegSegmentType.App1
中),这应该让您开始。
您看到的字符串值是一个描述。要访问原始方向值,请使用如下代码:
var directories = ImageMetadataReader.ReadMetadata(imagePath);
var subIfd = directories.OfType<ExifIfd0Directory>().FirstOrDefault();
int? orientation = subIfd?.GetObject(ExifDirectoryBase.TagOrientation);
请注意,subIfd
和 orientation
都可以为空,具体取决于图像。
这是 C#,我不知道 VB.NET,抱歉。希望这对您来说是一个简单的转换。