无论如何,有没有配置十二只猴子JPEGSegmentUtil段阅读器来读取JPEG的所有段

时间:2019-03-25 11:32:36

标签: java jpeg exif twelvemonkeys

我目前正在我要创建的应用程序中制作原型功能,该功能要求具有读取/修改/写入jpeg文件元数据的能力。

我认为可能对此起作用的一种方法是使用十二个猴子Java API读取其中的所有段,修改我感兴趣的那些元数据段,然后将所有段(其中大部分未修改)写回到新文件。

在我的原型制作过程中,我遇到了一个障碍,这引发了一个问题,我不得不承认,我主要直接针对API的作者。如果您(不是作者)还可以提供一些见解,我当然不会将它退后;)

这是我的代码的摘录:

    ImageInputStream streamMoto = ImageIO.createImageInputStream(file1);

    /*
        Prove, for testing/learning purposes, that this is a jpeg file
     */
    streamMoto.mark();
    final int foundFileType = streamMoto.readUnsignedShort();

    if (JPEG_FILE_ID==foundFileType) { // yes, continue... because we have a jpeg file
        streamMoto.reset(); // back to the very start

        // Here, the plan is to get ALL the JPEGSegments, so that we can
        // 1. iterate over each
        // 2. write non-relevant simply to new file (non-meta-data)
        // 3. note the meta-data segments and modify as (per application requirements) necessary (in my case, I want to edit description and tags/labels)
        // 4. after modifying meta-data segments, write the modified metadata segments, appending, to the new file
        // 5. At the end, we should have a new file, pretty much identical to the first (encoding and all) with ONLY meta-data modified
        streamMoto.mark();
        try {
            List<JPEGSegment> allSegments = JPEGSegmentUtil.readSegments(streamMoto, JPEGSegmentUtil.ALL_SEGMENTS);

            // Ahh, but wait! At this stage, in specifying 'ALL_SEGMENTS' I see a discrepancy in what I see in the resulting list of JPEGSegments (only 10 segments)
            // and my, very likely faulty, understanding of what I should see in this list. Namely, a whole bunch of following FF DA, FF C4 segments which I suppose are the 
            // main image data. 
            System.out.println("");

        } finally {
            streamMoto.reset();
        }
    }

xcvxvx

在测试上面的代码时,我看到10个段,列出如下:

FF E0  00 10   the JFIF marker, length 16 decimal
FF E1  07 A2   the Exif marker, length 1954 decimal
FF E1  OC 39   an adobe XMP section, length 3129 decimal
FF ED  00 82   some data in a Photoshop section, length 130 decimal
FF DB  00 43   unknown data; data available
FF DB  00 43   binary
FF C2  00 11   binary
FF C4  00 14   binary
FF C4  00 14   binary
FF DA  00 0c   binary

我已经尝试对JPEG / Exif文件的结构进行了一些研究,并一直在阅读规范。例如,显然图像数据是文件中最后一个'FF D9'标记之前的最后一件事。如何读取(或至少找到)每个标记(各种标记,例如FFE0,FFE1,FFC2等),后跟4个字节,指示该标记段的长度。像这样手动读取文件时(使用Bless Hex编辑器),我读取了与该库相同的所有段....直到

之后是上面列表中显示的最后一个“ FF DA”标记,我(在文件中)看到了一大堆其他标记,我认为(我需要做更多研究)实际的原始图像数据。尽管如此,似乎仍可以分解为不同的部分,可以使用与上述相同的规则(读取标记,读取长度,跳过长度,找到下一个标记)来进行读取,只是“ FF DA”段之后的下一个标记是并不总是紧接在该标记的指定长度之后。 在阅读另一篇stackoverflow文章中的一些建议时(很抱歉,我现在已经丢了它),被告知要简单地向前跳,直到找到下一个“ FFxx”标记(在我的情况下为FFC4)并继续。

现在,我的问题是,如果这些是标记或句段(我仍然对术语感到困惑),为什么图书馆不选择它们?

好吧,我可能会猜出答案;

它们不是通常意义上的标记...。它们是主要的图像数据...这就是原因。

所以我的跟进问题将是

  1. 然后我可以在某个时候(什么时候)只将其余数据视为一个块,并且由于不需要修改它,因此可以在所有段的末尾写出来? / p>

  2. 如何最好地读取数据的末尾块(而不必重置流并从头开始重新读取整个图像?

  3. 我可能正在解决所有错误,但是我一直在寻找一种有效的方法来生成带有修改的元数据的图像文件,而没有其他任何东西!我知道,在使用Java库读取整个文件,然后重新编写文件时,基本上就是在重新编码,并更改整个文件。您可能只是在很小的程度上,但是为了修改元数据而降低了图像文件的质量。我错了吗?我不要那个!必须有更好的方法(不必从头开始编写我自己的图像读取器/写入器)!

谢谢您的建议!

塞恩

1 个答案:

答案 0 :(得分:0)

您面临的问题是,有几种常用的JPEG文件格式,它们以不同的方式存储元数据。原始JPEG标准未定义文件格式。 JFIF的创建是为了填补空白。 Adobe创建了自己的文件格式。然后JPEG引入了SPIFF格式。然后是相机EXIF。