以编程方式检查 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 元属性。
要以编程方式查看此部分,有几个库可以执行此操作,我使用了 Adobe 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 帮助了我。
我有一种在 Android 上缩小大图像的方法,但是当用户从设备中选择动态 JPEG 或他们使用启用了动态的相机时,它会被阻塞。
我使用 exiftool 查看了文件中运动图像的 exif 数据,我看到了具有以下值的属性:
MicroVideo
MicroVideoVersion
MicroVideoVersionOffset
但我使用 ExifInterface 在 Android 的 EXIF 数据中看不到这些。我查看了所有 mAttributes,但它们不存在。
是否有一种简单的方法来识别这些图像并可能从文件开头提取 jpeg。
事实证明,我学到的关于 jpeg 图像的知识比我想知道的要多得多。我要找的运动值不在 exif 部分,它们是存储在另一个部分的 XMP 元属性。
要以编程方式查看此部分,有几个库可以执行此操作,我使用了 Adobe 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 帮助了我。