【问题标题】:Using MetaDataExtractor to add EXIF back to resized image使用 MetaDataExtractor 将 EXIF 添加回调整大小的图像
【发布时间】:2018-03-12 07:23:08
【问题描述】:

使用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 桌面应用程序中找到它并旋转它)。知道我现在做错了什么吗?

【问题讨论】:

    标签: .net exif metadata-extractor


    【解决方案1】:

    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);
    

    请注意,subIfdorientation 都可以为空,具体取决于图像。

    这是 C#,因为我不知道 VB.NET,抱歉。希望这对您来说是一个简单的转换。

    【讨论】:

    • 我查看了此链接drewnoakes.com/code/exif/sampleUsage.html 以获取更多信息,但我仍然无法在 MetadataExtractor 下找到 JpegSegmentReader - 它是否隐藏在另一个类名下?
    • 它在 MetadataExtractor.Formats.Jpeg 命名空间中。
    • 我只是在返回这里之前通过反复试验发现。在您的示例代码“Dim segmentReader As New JpegSegmentReader(jpegFile)”中,它用“没有新的可访问”来抛出玩具什么类元数据在“将元数据作为新元数据()吗?”
    • Metadata 是 Java 实现中的一个类(您在第一条评论中发布的链接通常与此相关)。 JpegSegmentReader 是一个静态类。您必须使用它的静态成员。正如编译器所说,您不能新建它的实例。
    • 我决定从不同的角度来解决这个问题——将 EXIF 数据返回到字符串并与图像分开保存。我还需要获取方向编号。如果它是 6 或 8,我们可以旋转新图像,但它会返回字符串“Exif IFD0 Orientation Right side, top (Rotate 90 CW)”。我如何获得号码?感谢您的耐心等待:-)
    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    相关资源
    最近更新 更多