Повторная загрузка и сохранение одного и того же изображения в файловую систему изменяет данные изображения - PullRequest
0 голосов
/ 29 марта 2020

Повторное сохранение и загрузка идентичного изображения из файловой системы приводит к изменению данных и, следовательно, к измененной сумме га sh (что мне нужно).

Моя программа выполняет следующие шаги:

1. Создайте BufferedImage

BufferedImage bufferedImage = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = bufferedImage.createGraphics();
graphics.setColor(Color.RED);
graphics.fillRect(100, 100, 200, 200);
graphics.dispose();

2. Вычислить MD5 га sh от созданного BufferedImage

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", baos);
byte[] bytesOfImage = baos.toByteArray();
DigestUtils.md5Hex(bytesOfImage); // => bebc7da469524057926f3871bdb07a6a

3. Сохранить BufferedImage в файловую систему

Path tempFile = Files.createTempFile(null, "jpg");
ImageIO.write(bufferedImage, "jpg", tempFile.toFile());

4. Расчет MD5 га sh файла

byte[] bytesOfFile = Files.readAllBytes(tempFile);
DigestUtils.md5Hex(bytesOfFile); // => bebc7da469524057926f3871bdb07a6a

5. Загрузить изображение из файловой системы

BufferedImage bufferedImageFromFilesystem = ImageIO.read(tempFile.toFile());

6. Вычислить MD5 га sh изображения, загруженного из файловой системы

ByteArrayOutputStream baosFS = new ByteArrayOutputStream();
ImageIO.write(bufferedImageFromFilesystem, "jpg", baosFS);
byte[] bytesOfImageFromFilesystem = baosFS.toByteArray();
DigestUtils.md5Hex(bytesOfImageFromFilesystem); // => 11dc0e49342a1ad15ab1b5a7f8bc271e

(Повторите шаги с 3 по 6, но повторно используйте изображение с шага 5:)
7. Сохранить BufferedImage для файловой системы

Path tempFile2 = Files.createTempFile(null, "jpg");
ImageIO.write(bufferedImageFromFilesystem, "jpg", tempFile2.toFile());

8. Рассчитать MD5 га sh файла

byte[] bytesOfFile2 = Files.readAllBytes(tempFile2);
DigestUtils.md5Hex(bytesOfFile2);// => 11dc0e49342a1ad15ab1b5a7f8bc271e

9. Загрузить изображение из файловой системы

BufferedImage bufferedImageFromFilesystem2 = ImageIO.read(tempFile2.toFile());

10. Вычислить MD5 га sh изображения, загруженного из файловой системы

ByteArrayOutputStream baosFS2 = new ByteArrayOutputStream();
ImageIO.write(bufferedImageFromFilesystem2, "jpg", baosFS2);
byte[] bytesOfImageFromFilesystem2 = baosFS2.toByteArray();
DigestUtils.md5Hex(bytesOfImageFromFilesystem2); // => d1102e4b7efef384623cac915a21e1c2

(org. apache .commons.code c .digest.DigestUtils используется для расчета MD5)

Каждый раз, когда я сохраняю одно и то же изображение в файловой системе, используя фрагмент кода # 3. , и загружаю одно и то же изображение, используя отрыванный код # 5. из файловой системы, данные изображения изменяются. Размер изображения уменьшается на несколько байтов. Изображение все еще может быть открыто стандартным windows средством просмотра изображений и, кажется, все еще действует.

Я уже проверил, вызвана ли проблема метаданными изображения. Сравнение метаданных файлов jpg с соответствующей программой не показывает никакой разницы метаданных.

Как я могу убедиться, что загрузка и сохранение идентичного изображения не изменяет файл?

1 Ответ

2 голосов
/ 29 марта 2020

Вы сохраняете jpeg, формат сжатия сжатых изображений с потерями , а не необработанный буфер. Потеря означает, что процесс не может быть отменен, потому что информация теряется в процессе. Сохранение его в формате jpeg использует эвристику для сжатия байтового массива с целью уменьшения его размера. Таким образом, когда вы загружаете его обратно, это приводит к тому, что массив байтов отличается от исходного, следовательно, изменяется ha sh Затем вы сохраняете его снова, что снова сжимает его, приводя к новому значению ha sh при загрузке. Я подозреваю, что если бы вы сделали это миллион раз, изображение превратилось бы в один серый пиксель, и ха sh перестал бы меняться.

...