重复加载相同图像并将其保存到文件系统会改变图像数据
Repeated loading and saving the same image to file system alters data of image
从文件系统反复保存和加载相同的图像会导致数据发生变化,从而导致哈希和发生变化(我需要)。
我的程序执行以下步骤:
1.创建一个缓冲图像
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。计算创建的BufferedImage
的MD5 hash
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 散列
byte[] bytesOfFile = Files.readAllBytes(tempFile);
DigestUtils.md5Hex(bytesOfFile); // => bebc7da469524057926f3871bdb07a6a
5.从文件系统加载图像
BufferedImage bufferedImageFromFilesystem = ImageIO.read(tempFile.toFile());
6.计算从文件系统加载的图像的 MD5 哈希
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散列
byte[] bytesOfFile2 = Files.readAllBytes(tempFile2);
DigestUtils.md5Hex(bytesOfFile2);// => 11dc0e49342a1ad15ab1b5a7f8bc271e
9.从文件系统加载图像
BufferedImage bufferedImageFromFilesystem2 = ImageIO.read(tempFile2.toFile());
10。计算从文件系统加载的图像的 MD5 哈希
ByteArrayOutputStream baosFS2 = new ByteArrayOutputStream();
ImageIO.write(bufferedImageFromFilesystem2, "jpg", baosFS2);
byte[] bytesOfImageFromFilesystem2 = baosFS2.toByteArray();
DigestUtils.md5Hex(bytesOfImageFromFilesystem2); // => d1102e4b7efef384623cac915a21e1c2
(org.apache.commons.codec.digest.DigestUtils用于MD5计算)
每次我使用代码片段 #3. 在文件系统上保存相同的图像并使用代码片段 #5 加载相同的图像。 从文件系统中,图像数据被更改。图像的大小缩小了几个字节。该图像仍然可以通过标准 windows 图像查看器打开,并且似乎仍然有效。
我已经检查了问题是否是由图像的元数据引起的。将 jpg 文件的元数据与适当的程序进行比较不会显示元数据有任何差异。
如何确保加载和保存相同的图像不会更改文件?
您保存的是 jpeg,这是一种有损 压缩图像格式,而不是原始缓冲区。有损意味着这个过程不能逆转,因为信息在这个过程中丢失了。将其保存为 jpeg 使用启发式方法压缩字节数组以减小其大小。因此,当您将其加载回来时,它会产生与原始字节数组不同的字节数组,因此会更改哈希。然后你再次保存它,再次压缩它,当你加载它时再次导致不同的散列。我怀疑如果你这样做一百万次图像会变成一个灰色像素并且散列将停止改变。
从文件系统反复保存和加载相同的图像会导致数据发生变化,从而导致哈希和发生变化(我需要)。
我的程序执行以下步骤:
1.创建一个缓冲图像
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。计算创建的BufferedImage
的MD5 hashByteArrayOutputStream 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 散列
byte[] bytesOfFile = Files.readAllBytes(tempFile);
DigestUtils.md5Hex(bytesOfFile); // => bebc7da469524057926f3871bdb07a6a
5.从文件系统加载图像
BufferedImage bufferedImageFromFilesystem = ImageIO.read(tempFile.toFile());
6.计算从文件系统加载的图像的 MD5 哈希
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散列
byte[] bytesOfFile2 = Files.readAllBytes(tempFile2);
DigestUtils.md5Hex(bytesOfFile2);// => 11dc0e49342a1ad15ab1b5a7f8bc271e
9.从文件系统加载图像
BufferedImage bufferedImageFromFilesystem2 = ImageIO.read(tempFile2.toFile());
10。计算从文件系统加载的图像的 MD5 哈希
ByteArrayOutputStream baosFS2 = new ByteArrayOutputStream();
ImageIO.write(bufferedImageFromFilesystem2, "jpg", baosFS2);
byte[] bytesOfImageFromFilesystem2 = baosFS2.toByteArray();
DigestUtils.md5Hex(bytesOfImageFromFilesystem2); // => d1102e4b7efef384623cac915a21e1c2
(org.apache.commons.codec.digest.DigestUtils用于MD5计算)
每次我使用代码片段 #3. 在文件系统上保存相同的图像并使用代码片段 #5 加载相同的图像。 从文件系统中,图像数据被更改。图像的大小缩小了几个字节。该图像仍然可以通过标准 windows 图像查看器打开,并且似乎仍然有效。
我已经检查了问题是否是由图像的元数据引起的。将 jpg 文件的元数据与适当的程序进行比较不会显示元数据有任何差异。
如何确保加载和保存相同的图像不会更改文件?
您保存的是 jpeg,这是一种有损 压缩图像格式,而不是原始缓冲区。有损意味着这个过程不能逆转,因为信息在这个过程中丢失了。将其保存为 jpeg 使用启发式方法压缩字节数组以减小其大小。因此,当您将其加载回来时,它会产生与原始字节数组不同的字节数组,因此会更改哈希。然后你再次保存它,再次压缩它,当你加载它时再次导致不同的散列。我怀疑如果你这样做一百万次图像会变成一个灰色像素并且散列将停止改变。