以编程方式检查 Android 上的运动 jpeg 图像

Programmatically check for a motion jpeg image on Android

我有一种在 Android 上缩小大图像的方法,但是当用户从设备中选择动态 JPEG 或他们使用启用了动态的相机时,它会被阻塞。

我使用 exiftool 查看了文件中运动图像的 exif 数据,我看到了具有以下值的属性:

MicroVideo
MicroVideoVersion
MicroVideoVersionOffset

但我使用 ExifInterface 在 Android 的 EXIF 数据中看不到这些。我查看了所有 mAttributes,但它们不存在。

是否有一种简单的方法来识别这些图像并可能从文件开头提取 jpeg。

事实证明,我学到的关于 jpeg 图像的知识比我想知道的要多得多。我要找的运动值不在 exif 部分,它们是存储在另一个部分的 XMP 元属性。

要以编程方式查看此部分,有几个库可以执行此操作,我使用了 Adob​​e XMP Core 库。它是为数不多的允许写 header 的之一。

要从启用运动的文件中仅提取 jpg 图像,类似于 Google 照片中的提取菜单项,可以使用以下代码完成,利用 XMPUtil class 找到 here。所有代码所做的就是读取 XMP header 并获取偏移量。然后它只将 jpeg 部分复制到一个新文件中,然后删除 XMP 值。

        val xmp = XmpUtil()
        val meta = xmp.extractOrCreateXMPMeta(photoFile.absolutePath)

        val haveVideoValue: XMPProperty? = meta.getProperty("http://ns.google.com/photos/1.0/camera/", "MicroVideo")

        val haveVideo = haveVideoValue?.value == "1"

        if (haveVideo) {

            val offsetValue = meta.getProperty("http://ns.google.com/photos/1.0/camera/", "MicroVideoOffset")

            meta.deleteProperty("http://ns.google.com/photos/1.0/camera/", "MicroVideo")
            meta.deleteProperty("http://ns.google.com/photos/1.0/camera/", "MicroVideoOffset")
            meta.deleteProperty("http://ns.google.com/photos/1.0/camera/", "MicroVideoVersion")
            meta.deleteProperty("http://ns.google.com/photos/1.0/camera/", "MicroVideoPresentationTimestampUs")

            val copyBytes = photoFile.length() - offsetValue.value.toLong()

            val tmpImageWithoutVideo = createTmpFile(photoFile.name)

            FileInputStream (photoFile).use { inputStream ->
                FileOutputStream(tmpImageWithoutVideo).use { outputStream ->
                    IOUtils.copyLarge(inputStream, outputStream, 0, copyBytes)
                }
            }

            photoFile.delete()

            // Remove the XMP Motion values
            val newImageFile = createTempFile(photoFile.name)

            FileInputStream(tmpImageWithoutVideo).use { inputStream ->
                FileOutputStream(newImageFile).use { outputStream ->
                    xmp.writeXMPMeta(inputStream, outputStream, meta)
                }
            }

            tmpImageWithoutVideo.delete()

            photoFile = newImageFile
        }

这个 nice page 帮助了我。