读取JPG文件的XMP元数据 [英] Reading JPG file's XMP metadata

查看:4747
本文介绍了读取JPG文件的XMP元数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发的应该充分利用谷歌相机的新的深度图生成功能的Andr​​oid应用程序。

基本上谷歌已经说明使用的元数据这里

我可以访问大部分的元数据,但不幸的是最重要的数据是EN $ C $光盘作为extendedXmp,我不能得到任何XMP解析库正确解析吧!

我试过用CC-成像,元数据提取以及最近坯XMPCore

XMPCore也许能处理扩展版本,但没有文件我怎样才能得到它来解析从JPG文件中的数据,其假设的原始数据XMP要传递

有没有正确执行XMP解析,包括的JPG文件扩展部件或我只是做错了什么?

下面是我的尝试:

随着公地成像:

  {尝试
                    。串imageParser =新JpegImageParser()getXmpXml(新ByteSourceInputStream(的ImageStreamimg.jpg),新的HashMap&下;串,对象>());                    Log.v(TAG,imageParser);                }赶上(ImageReadException E1){
                    // TODO自动生成catch块
                    e1.printStackTrace();
                }

使用元数据提取

 元数据元数据= ImageMetadataReader.readMetadata(
                        新的BufferedInputStream(的ImageStream),FALSE);
                XmpDirectory XMP元数据=
                        .getDirectory(XmpDirectory.class);
                XMPMeta xmpMeta = xmp.getXMPMeta();                字符串URI =htt​​p://ns.google.com/photos/1.0/depthmap/;                Log.v(TAG,xmpMeta.doesPropertyExist(URI,GDepth:格式)+);                尝试{
                    XMPProperty hasExtendedXMP = xmpMeta.getProperty(http://ns.adobe.com/xmp/note/,xmpNote:HasExtendedXMP);                    Log.v(。TAG,hasExtendedXMP.getValue()的toString()++新的String(Base64.de code(hasExtendedXMP.getValue()的toString(),Base64.DEFAULT)));                }赶上(XMPException E){
                    e.printStackTrace();
                }


解决方案

起初,Adobe公司没想到的XMP数据长度将超过一JPEG段(约64K)和XMP规格的限制规定的XMP数据必须符合成一个。后,当他们发现单个JPEG APP1段是没有大到足以容纳XMP数据,他们改变了规范以允许整个XMP数据的多个APP1段。数据被分为两部分:标准的XMP和ExtendedXMP。标准XMP部分是一个正常的XMP结构与包包装而ExtendedXMP部分不具有包包装。所述ExtendedXMP数据可以进一步划分,以适应成多个APP1

下面的报价是从Adobe XMP规范第3部分为ExtendedXMP块为JPEG APP1:


  

每个块被写入到JPEG文件的单独APP1标记内
  分割。每个ExtendedXMP标记段包括:


  
  

      
  • http://ns.adobe.com/xmp/extension空结尾的署名字符串/

  •   
  • 存储为一个32字节的ASCII十六进制字符串的128位GUID,大写字母A-F,无空终止。 GUID是完整的一个128位的MD5摘要
      ExtendedXMP系列化。

  •   
  • 的ExtendedXMP序列全长为32位无符号整数

  •   
  • 这部分作为一个32位无符号整数的偏移量。

  •   
  • 的ExtendedXMP的部分

  •   

我们可以除了空值终止字符串作为ExtendedXMP数据的ID看,还有一个GUID应该是相同的值作为一个在标准的XMP部分找到。所以对于ExtendedXMP APP1序列甚至可能不是为了 - 是用来加入ExtendedXMP的不同部分的偏移量。然后来的实际数据的一部分,这就是为什么@马特的答案需要一些方法来解决这个字符串。还有另外一个值 - ExtendedXMP系列化这有两个目的的全长:检查数据的完整性以及用于接合所述数据提供的缓冲区大小

当我们发现了一个ExtendedXMP段,我们需要加入与其他ExtendedXMP段目前的数据,最终得到了整个ExtendedXMP数据。然后,我们加入这两个XML树在一起(从标准XMP中卸下GUID以及)检索整个XMP数据。

我有codeD 的东西在Java中提取和插入XMP以及ExtendedXMP 。一项所述的用例的ExtendedXMP的是谷歌的深度图数据这实际上是隐蔽的实际图像作为元数据内的灰度图像,并以JPEG的情况下,作为XMP数据。深度图图像可以被用于例如​​模糊原始图像。深度图数据通常是大而不得不被分成标准和扩展的XMP份。整个数据的Base64 EN codeD和可能是PNG格式。

下面是一个实例图像和所提取的深度图:

原始图像来自 rel=\"nofollow\">。

I am developing Android application that's supposed to make use of Google Camera's new depth map generation feature.

Basically Google has described the meta data used here

I can access to most of the metadata, but unfortunately the most important data is encoded as extendedXmp, and I can't get any XMP parsing library to parse it correctly!

I've tried Commons-Imaging, metadata-extractor and most recently Adobes XMPCore

XMPCore might be able to handle the extended version, but there's no documentation how can I get it to parse the data from JPG file, its assuming raw XMP data to be passed

Is there any correct implementation of XMP parsing that includes the extended parts of JPG files or am I just doing something wrong?

Here's my tries:

With Commons-Imaging:

                try {
                    String imageParser = new JpegImageParser().getXmpXml(new ByteSourceInputStream(imageStream, "img.jpg"), new HashMap<String, Object>());

                    Log.v(TAG, imageParser);

                } catch (ImageReadException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

With metadata-extractor

                Metadata metadata = ImageMetadataReader.readMetadata(
                        new BufferedInputStream(imageStream), false);


                XmpDirectory xmp = metadata
                        .getDirectory(XmpDirectory.class);
                XMPMeta xmpMeta = xmp.getXMPMeta();



                String uri = "http://ns.google.com/photos/1.0/depthmap/";

                Log.v(TAG, xmpMeta.doesPropertyExist(uri, "GDepth:Format") + " " );

                try {
                    XMPProperty hasExtendedXMP = xmpMeta.getProperty("http://ns.adobe.com/xmp/note/", "xmpNote:HasExtendedXMP");

                    Log.v(TAG, hasExtendedXMP.getValue().toString() + " " + new String(Base64.decode(hasExtendedXMP.getValue().toString(), Base64.DEFAULT)));

                } catch (XMPException e) {
                    e.printStackTrace();
                }

解决方案

Initially, Adobe didn't expect the XMP data length would exceed the limit of one JPEG segment (about 64K) and their XMP specification stated the XMP data must fit into one. Later when they found a single JPEG APP1 segment is not large enough to hold the XMP data, they changed their specification to allow for multiple APP1 segments for the whole XMP data. The data is split into two parts: the standard XMP and the ExtendedXMP. The standard XMP part is a "normal" XMP structure with a package wrapper while the ExtendedXMP part doesn't have a package wrapper. The ExtendedXMP data can be further divided to fit into multiple APP1.

The following quote is from Adobe XMP specification Part 3 for ExtendedXMP chunks as JPEG APP1:

Each chunk is written into the JPEG file within a separate APP1 marker segment. Each ExtendedXMP marker segment contains:

  • A null-terminated signature string of "http://ns.adobe.com/xmp/extension/".
  • A 128-bit GUID stored as a 32-byte ASCII hex string, capital A-F, no null termination. The GUID is a 128-bit MD5 digest of the full ExtendedXMP serialization.
  • The full length of the ExtendedXMP serialization as a 32-bit unsigned integer
  • The offset of this portion as a 32-bit unsigned integer.
  • The portion of the ExtendedXMP

We can see besides the null-terminated string as an id for the ExtendedXMP data, there is also a GUID which should be the same value as the one found in the standard XMP part. The offset is used to join the different parts of the ExtendedXMP - so the sequence for the ExtendedXMP APP1 may not even be in order. Then come the actual data part and this is why @Matt's answer need some way to fix the string. There is another value - full length of the ExtendedXMP serialization which serves two purposes: check the integrity of the data as well as provides the buffer size for joining the data.

When we found a ExtendedXMP segment, we need to join the current data with the other ExtendedXMP segments and finally got the whole ExtendedXMP data. We then join the two XML tree together (removing the GUID from the standard XMP part as well) to retrieve the entire XMP data.

I have coded something in Java to extract and insert XMP as well as ExtendedXMP. One of the usecase for the ExtendedXMP is for Google's depth map data which in fact is a grayscale image hidden inside the actual image as a metadata, and in the case of JPEG, as XMP data. The depth map image could be used for example to blur the original image. The depth map data are usually large and have to be split into standard and extended XMP parts. The whole data is Base64 encoded and could be in PNG format.

The following is an example image and the extracted depth map:

The original image comes from here.

这篇关于读取JPG文件的XMP元数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆