System.Drawing.Image 保存的输出与输入 Image.FromStream 的输出不同
Output of System.Drawing.Image Save is not the same as what fed into Image.FromStream
我正在尝试验证以 Base64 字符串格式提交给后端的图像,方法是将其解析为 Image 对象,从同一 Image 对象中提取它,最后比较输入字节数组和输出字节数组,假设这两个应该是相同或输入图像有问题。这是代码:
private void UpdatePhoto(string photoBase64)
{
var imageDataInBytes = Convert.FromBase64String(photoBase64);
ValidateImageContent(imageDataInBytes);
}
private void ValidateImageContent(byte[] imageDataInBytes)
{
using (var inputMem = new MemoryStream(imageDataInBytes))
{
var img = Image.FromStream(inputMem, false, true);
using (MemoryStream outputMemStream = new MemoryStream())
{
img.Save(outputMemStream, img.RawFormat);
var outputSerialized = outputMemStream.ToArray();
if (!outputSerialized.SequenceEqual(imageDataInBytes))
throw new Exception("Invalid image. Identified extra data in the input. Please upload another photo.");
}
}
}
它在一张我知道是有效的图像上失败了。
我认为 Image.Save 的输出必须与 Image.FromStream 的输入相同的假设是错误的吗?有没有办法纠正这个逻辑以正确实现这种验证方式?
如果将原始图像与创建的图像进行比较,您会注意到元数据中的一些差异:对于我的示例图像,我可以观察到一些元数据被剥离(XMP 数据被完全删除)。此外,在保留 EXIF 数据的同时,写入的 endianness 从小端倒转为大端。这本身就解释了为什么数据不匹配。
在我的示例中,实际图像数据是相同的,但您无法仅通过查看字节来轻易分辨。
如果您想生成与源相同的结果,则必须以与源完全相同的方式生成元数据。如果不仔细查看原始照片的元数据,您将无法做到这一点。 .NET 的 Image
根本无法包含文件可能包含的所有元数据。即使您能够提取所有元数据并再次以正确的格式存储它,元数据序列化程序之间也存在许多细微差别,因此很难产生完全相同的结果。
所以如果你想比较图像,你应该去掉元数据,只比较图像数据。但是,当您考虑如何保存图像 (Raw
) 时,您将再次获得完全相同的数据块,所以我不希望那里有差异。
我正在尝试验证以 Base64 字符串格式提交给后端的图像,方法是将其解析为 Image 对象,从同一 Image 对象中提取它,最后比较输入字节数组和输出字节数组,假设这两个应该是相同或输入图像有问题。这是代码:
private void UpdatePhoto(string photoBase64)
{
var imageDataInBytes = Convert.FromBase64String(photoBase64);
ValidateImageContent(imageDataInBytes);
}
private void ValidateImageContent(byte[] imageDataInBytes)
{
using (var inputMem = new MemoryStream(imageDataInBytes))
{
var img = Image.FromStream(inputMem, false, true);
using (MemoryStream outputMemStream = new MemoryStream())
{
img.Save(outputMemStream, img.RawFormat);
var outputSerialized = outputMemStream.ToArray();
if (!outputSerialized.SequenceEqual(imageDataInBytes))
throw new Exception("Invalid image. Identified extra data in the input. Please upload another photo.");
}
}
}
它在一张我知道是有效的图像上失败了。
我认为 Image.Save 的输出必须与 Image.FromStream 的输入相同的假设是错误的吗?有没有办法纠正这个逻辑以正确实现这种验证方式?
如果将原始图像与创建的图像进行比较,您会注意到元数据中的一些差异:对于我的示例图像,我可以观察到一些元数据被剥离(XMP 数据被完全删除)。此外,在保留 EXIF 数据的同时,写入的 endianness 从小端倒转为大端。这本身就解释了为什么数据不匹配。
在我的示例中,实际图像数据是相同的,但您无法仅通过查看字节来轻易分辨。
如果您想生成与源相同的结果,则必须以与源完全相同的方式生成元数据。如果不仔细查看原始照片的元数据,您将无法做到这一点。 .NET 的 Image
根本无法包含文件可能包含的所有元数据。即使您能够提取所有元数据并再次以正确的格式存储它,元数据序列化程序之间也存在许多细微差别,因此很难产生完全相同的结果。
所以如果你想比较图像,你应该去掉元数据,只比较图像数据。但是,当您考虑如何保存图像 (Raw
) 时,您将再次获得完全相同的数据块,所以我不希望那里有差异。