Как объединить 2 jpegs без потерь без декодирования с использованием шестнадцатеричного редактора?

Я пытаюсь написать программу (prob в java), чтобы объединить несколько jpeg вместе без потерь без их декодирования.

Я думал, что начну просто, и попытаюсь добавить 2 jpegs того же размера, сжатых с теми же настройками один над другим, используя hex-редактор.

Сначала я извлекаю данные изображения jpeg B и добавляю его в jpeg A. Изменяя размеры, указанные в заголовках, я получаю новое распознаваемое изображение (jpeg A + jpeg B, добавленное по оси y), которое можно разложить. Однако, хотя данные изображения из jpeg B четко распознаются, он, кажется, потерял много информации о цвете и явно неверен.

Итак, мой вопрос - какие шаги я пропустил здесь? Я не думаю, что есть какие-то другие значения заголовка измерения, которые мне нужно изменить, поэтому, возможно, мне нужно, чтобы huffman декодировал данные изображения из обоих jpegs, затем добавлял их вместе, а затем перекодировал лот?

Я потратил некоторое время на чтение jpeg-спецификаций и заголовков и т.д., но, честно говоря, я не в своей глубине и мог бы сделать это с помощью указателя или двух!

Большое спасибо за любую помощь.


Спасибо за все предложения. Да, это определенно возможно, я должен был упомянуть jpegtran в моем первоначальном вопросе. Я в основном пытаюсь воспроизвести этот аспект функции jpegtran, но использовать его в своей собственной программе. Я думаю, я должен посмотреть на источник jpegtran, но я ничего не знаю о C и не очень много о программировании в целом, поэтому обратный инженерный исходный код легче сказать, чем сделать!

Ответ 1

Хорошо, я разработал, где я ошибся.

1) данные сканирования изображения сохраняются в байтах, но фактическая важная информация кодируется как битовые строки переменной длины. Это означает, что конец фактических данных изображения не обязательно попадает на границу байта. Когда jpeg-кодировщик должен отбросить количество бит, чтобы сделать границу байта, он просто добавляет серию из 1s.

2) способ, которым хранится фактическая информация о пикселях, немного сложнее (по крайней мере для меня), чтобы объяснить, но в основном все кодируется в MCU, минимальных единицах кодирования или что-то в этом роде. Они различаются по размеру в зависимости от передискретизации цветности, горизонтального и вертикального размеров - 8 или 16 пикселей. Для каждого MCU есть части постоянного и переменного тока, которые составляют один компонент яркости, Y или цветности, Cb и Cr. Проблема заключалась в том, что компоненты постоянного тока сохраняются как значения по отношению к соответствующему значению постоянного тока предыдущего MCU. Поэтому, когда я добавил новые данные изображения из jpg B, он сохранил свои значения DC по отношению к 0 (потому что не было предыдущих MCU), но необходимо было учитывать конечные значения DC последнего MCU из jpg A. (надеюсь, что это имеет смысл).

Решение:

Вам нужно выполнить начальное декодирование (длина строки Huffman +) данных изображения, чтобы точно определить, где заканчиваются данные изображения, а затем вырезать конечные 1s. Вам также необходимо соответствующим образом изменить начальные значения DC во втором jpg. Затем вам необходимо переписать соответствующие биты, добавить 1s для соответствия байтовой границе, et voila.

Если вы хотите добавить на оси x, это немного сложнее. Вы должны переставить MCU так, чтобы они сканировались в правильном порядке. Jpgs просматриваются слева направо, затем сверху вниз, а затем соответствующим образом корректируют значения DC.

До сих пор я тестировал это только на одном MCU jpg, но теоретически он должен работать и с большими.

BTW Я только проработал это благодаря владельцу этого отличный ресурс/блог, связанный с jpg

Ответ 2

Это очень удобно. Я сделал это на многих фрагментах изображения на карте Google, чтобы присоединиться к ним и сформировать изображение размера плаката. Существует пакет для Unix, называемый JPEG Tools, для выполнения именно этого. Программа называется jpegjoin. Pure C, с доступными двоичные файлы Windows. При компиляции он создает приложение командной строки, которое при запуске объединяет два jpeg-изображения без потерь среди многих других вещей. Он НЕ отменяет сжатие любого изображения, просто объединяет сжатые данные и исправляет заголовок соответственно. Я использовал его для объединения 100 изображений для создания 50 полосок, а затем снова объединил эти полосы для создания большого изображения.

Более подробную информацию можно найти на http://en.wikipedia.org/wiki/Lossy_compression#Lossless_editing

Исходный код

Исходный код библиотеки jpegtran можно найти . Пример script для имитации jpegjoin - здесь.

Ответ 3

jpeg - как mp3 - обычно стабильный, когда вы его сжимаете (используя тот же алгоритм).

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

Ответ 4

Два подхода:

1) декодировать оба изображения исходного JPEG, объединить полученные растровые изображения и снова закодировать как JPEG. Недостатком здесь является повторное сжатие.

2) Убедитесь, что ширина и высота исходного изображения кратно 16, возможно, обрезая изображения. Не декодируйте изображения, а собирайте целевой JPEG из исходных блоков MCU (размер 16 x 16 пикселей, поэтому обрезка).

Ответ 5

Я предлагаю вам рассмотреть маркеры DRI и RSTn, хотя для этого требуется много предварительных условий, но он работает для меня: добавление PPM (формат растрового изображения) в jpeg, который закодирован с использованием DRI и RSTn, оба находятся в одинаковой ширины, и оба они являются кратными MCU.

Я просто вырезал данные jpeg после последнего RSTn-маркера (если есть), декодирует это для PPM и присоединяет два PPM к одной линии MCU, кодирует их с теми же параметрами с исходным jpeg, перестраивает RST в результирующем jpeg в соответствии с исходным jpeg, затем добавив результат к исходному jpeg. Используя этот метод, он не позволяет мне декодировать весь исходный jpeg и кодировать его снова.

Как материал декодирования и кодирования, я использую libjpeg.

Ответ 6

Вместо добавления изображений по горизонтали, возможно, проще поворачивать каждое изображение на 90 градусов, а затем присоединяться к ним по вертикали, а затем поворачивать результирующее изображение назад -90 градусов.

Ответ 7

Операции без потерь JPEG - это в значительной степени оксюморон. Вы можете сделать некоторые обманки, как вращение, но это в значительной степени.

Я предлагаю вам иметь исходные изображения без потерь (TIFF или PNG приходит на ум) или переоценивать требования к качеству изображения - повторная выборка JPEG еще раз, учитывая приличные оригинальные файлы, неотличима подавляющему большинству людей там.

Ответ 8

То, что вы пытаетесь сделать, в принципе невозможно.
Кодировка файла JPEG несколько сложна, и если вы меняете содержимое пикселей, тогда кодировка будет изменена. Вы можете получить изображение меньшего размера или больше суммы двух изображений, которые вы комбинируете. Единственными операциями, которые возможны без потерь, являются те, которые поддерживают взаимно однозначное соответствие пикселям исходного изображения. это в основном сводится к 90 градусам вращения.