diff / patch для изображений - PullRequest
7 голосов
/ 07 июля 2011

Я пишу проект, в котором мне нужно передать набор похожих изображений по сети.Чтобы ускорить процесс, я подумал о том, чтобы делать то, что делают большинство кодеков фильмов.имея ключевые кадры, а затем просто отправляю изменения.

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

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

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

Редактировать: мне нужно передать это изображения.Edit2: Дело не столько в специфике реализации, сколько в том, что является наиболее эффективной идеей для алгоритма.Как работать только с кусками 5px и не игнорировать пиксель, если он только изменился, поэтому глаз не заметит (я могу жить с некоторой потерей качества)

Ответы [ 6 ]

5 голосов
/ 19 августа 2011

Упрощенным подходом было бы сделать эквивалент операции XOR на двух изображениях.Это покажет пиксели, которые идентичны (будут равны нулю), и пиксели, которые изменились (не равны нулю).

Если вам не нужны почти незаметные различия, в качестве альтернативы, используйте смесь «вычитать»затем сдвиг вправо, чтобы отбросить разницу в один или два бита.

Затем можно вычислить границы (возможно, простой прямоугольник) и передать только дельту.Дельта, скорее всего, будет содержать множество нулей или не более байтов с несколькими правыми битами разницы, т. Е. Будет иметь низкую «энтропию», что означает, что она теоретически должна быть в высокой степени сжимаемой с использованием современных алгоритмов сжатия.Получив конец, обратный процесс так же прост.Учитывая дельту и ограничивающий прямоугольник, разархивируйте дельту, затем примените ее (XOR или добавление влево, затем добавьте) к затронутой области предыдущего / существующего изображения.

Для более изощренного подхода без потерь,Посмотрите, как анимированы GIF / PNG и какие алгоритмы используются для вычисления / кодирования дельта-информации между кадрами.См., Например, Какой лучший способ сделать анимированный GIF-файл с использованием алгоритма?

Для еще более изощренного подхода при работе с изображениями реального мира и при желанииидти по пути с потерями - тогда вы уже намекали на это.Посмотрите, как видеокодеки кодируют / передают кадры, например, MPEG Video Encoding .

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

3 голосов
/ 07 июля 2011

Вы можете перебрать все пиксели BufferedImage, используя getRGB(int x, int y).

for (int x = 0; x < img.getWidth(); ++x)
{
    for (int y = 0; y < img.getHeight(); ++y)
    {
        int oldARGB = oldImg.getRGB(x, y);
        int newARGB = img.getRGB(x, y);
        if (oldARGB != newARGB)
        {
            // handle the diffrence
        }
    }

}
2 голосов
/ 22 декабря 2014

У меня есть идея, на самом деле это очень просто. Сравнить пиксель один за другим

Если пиксель равен, то сохранить как RGBA (0, 0, 0, 0). Затем сохраните разницу как PNG.

Это демонстрационный результат. разница очень маленькая.

Переполнение стека скажет you need at least 10 reputation to post images. Так что я могу разместить здесь только адрес изображения.

http://oi61.tinypic.com/2vs5ifl.jpg

0 голосов
/ 09 июля 2016

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

0 голосов
/ 19 августа 2011

Ваше время, вероятно, лучше потратить на разработку приложения, а затем на оценку улучшения производительности, если это проблема.Я предполагаю, что все это будет YAGNI.

Чтобы ускорить процесс, я подумал о выполнении ...

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

0 голосов
/ 07 июля 2011

В зависимости от объема работы, которую вы хотите инвестировать, я бы предложил довольно простое решение: сохранить эти изображения в виде растровых изображений и позволить 7z сжимать их.Затем отправьте архив.

...