Есть ли в любом случае настроить обезьяны JPEGSegmentUtil двенадцать обезьяны для чтения всех сегментов JPEG - PullRequest
0 голосов
/ 25 марта 2019

В настоящее время я работаю над созданием прототипов в приложении, которое хочу создать, для чего требуется возможность считывать / изменять / записывать метаданные файла 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. Могу ли я затем, в какой-то момент (в какой-то момент), просто рассмотреть оставшиеся данные одним блоком, и так как яне нужно его модифицировать, записать его в конце всех сегментов?

  2. Как мне лучше прочитать этот конечный блок данных (без необходимости сбрасывать поток и читатьэто все изображение снова с самого начала?

  3. Я, наверное, все об этом ошибаюсь, но я искал эффективный способ создания файла изображения с измененными метаданными и ничего большеЯ знаю, что при чтении с java-библиотеками всего файла, а затем перезаписи его, вы в основном перекодируете и меняете весь файл. Вы, возможно, только в небольшой степени, но, тем не менее,ухудшено качество файла изображения только для изменения метаданных. Я ошибаюсь? Я не хочу этого! Должен быть лучший способ (без необходимости писать собственный читатель / писатель изображений с нуля)!

Спасибоза любой совет!

Шон

1 Ответ

0 голосов
/ 27 марта 2019

Проблема, с которой вы сталкиваетесь, заключается в том, что существует несколько широко используемых форматов файлов JPEG, и они хранят метаданные по-разному. Исходный стандарт JPEG не определял формат файла. JFIF был создан, чтобы заполнить пробелы. Adobe создала собственный формат файлов. Затем JPEG представил формат SPIFF. Затем появился EXIF ​​для камер.

...