为什么C#中的Image.Save()并不总是给出相同的序列化结果,以及如何以确定性的方式序列化图像



我使用以下代码序列化图像:

public static string SerializeImage(Image image)
{
using (MemoryStream memoryStream = new MemoryStream())
{
image.Save(memoryStream, image.RawFormat);
return Convert.ToBase64String(memoryStream.ToArray());
}
}

并通过执行以下对图像进行反序列化

public static Image DeserializeImage(string serializedImage)
{
byte[] imageAsBytes = Convert.FromBase64String(serializedImage);
using (MemoryStream memoryStream = new MemoryStream(imageAsBytes, 0, imageAsBytes.Length))
{
memoryStream.Write(imageAsBytes, 0, imageAsBytes.Length);
return Image.FromStream(memoryStream, true);
}
}

如果我有一个图像和

string serializedImage1 = SerializeImage(image);
Image deserializedImage = DeserializeImage(serializedImage1);
string serializedImage2 = SerializeImage(deserializedImage );

然后

serializedImage1 == serializedImage2;

正如预期的那样但情况并非总是如此。

如果我在进程1上序列化一个映像,然后在进程2上重新序列化并重新序列化它,那么进程2上的重新序列化结果与进程1上的结果不同。一切正常,但序列化开始时的几个字节不同。

最糟糕的是,如果我在两个不同的dll(或线程,我不确定(上做同样的事情,序列化结果似乎也不一样。同样,序列化/反序列化是有效的,但有几个字节是不同的。

第一次加载的图像具有以下功能:

public static Image GetImageFromFilePath(string filePath)
{
var uri = new Uri(filePath);
var bitmapImage = new BitmapImage(uri);
bitmapImage.Freeze();
using (var memoryStream = new MemoryStream())
{
var pngBitmapEncoder = new PngBitmapEncoder();
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(bitmapImage));
pngBitmapEncoder.Save(memoryStream);
Image image = Image.FromStream(memoryStream);
return image;
}
}

但是请注意,即使使用DeserializeImage((函数加载图像两次,也会发生这种情况。

我做的测试是ImageFormat.Jpeg和ImageFormat.Png.

第一个问题,它为什么这么做?我本以为结果总是一样的,但我想在执行Image.Save((.时使用了一些盐

第二个问题:我希望有一种确定性的方法来序列化图像,保持图像格式不变。目标是将图像保存在数据库中,并比较序列化的图像,以了解它是否已经存在于使用此功能的系统中。

好吧,我在试图解决这个问题时发现,C#中的png或jpeg图像对象有一些元数据与之相关,而我所做的并不是比较图像的可靠方法。

我使用的解决方案来自这个链接

https://insertcode.wordpress.com/2014/05/13/compare-content-of-two-files-images-in-c/

因此,我最后要做的是用前面描述的SerializeImage(Image image)函数将图像保存在系统内部,当我想使用它时,我用前面描述过的DeserializeImage(string serializedImage)函数对它进行反序列化。但是当我想比较图像时,我使用以下功能

public static bool ImagesAreEqual(Image image1, Image image2)
{
string image1Base64Bitmap = GetImageAsBase64Bitmap(image1);
string image2Base64Bitmap = GetImageAsBase64Bitmap(image2);
return image1Base64Bitmap.Equals(image2Base64Bitmap);
}
public static string GetImageAsBase64Bitmap(Image image)
{
using (var memoryStream = new MemoryStream())
{
using (var bitmap = new Bitmap(image))
{
bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp);
}
return Convert.ToBase64String(memoryStream.ToArray());
}
}

将图像转换为原始位图,然后再进行比较。

在所有需要的情况下,这对我来说都是完美的:图像的格式都被正确地保存/恢复了,我可以在它们之间进行比较,以检查它们是否相同,而不必担心可能不同的序列化。

最新更新