反序列化图元文件
我有一个适用于增强型图元文件。
我能够创建它们,将它们以 .emf 格式保存到磁盘,然后再次加载它们,没有问题。
我通过使用 gdi32.dll 方法和 来执行此操作DLLImport 属性。
但是,要启用版本容忍序列化我想要将图元文件与其他数据一起保存在对象中。
这本质上意味着我需要将图元文件数据序列化为字节数组,然后再次反序列化以重建图元文件。
我遇到的问题是,反序列化的数据似乎在某种程度上被损坏,因为我用来重建图元文件的方法引发了“参数无效异常”。
至少像素格式和分辨率发生了变化。
代码使用如下。
[DllImport("gdi32.dll")]
public static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer, byte[] lpbBuffer);
[DllImport("gdi32.dll")]
public static extern IntPtr SetEnhMetaFileBits(uint cbBuffer, byte[] lpBuffer);
[DllImport("gdi32.dll")]
public static extern bool DeleteEnhMetaFile(IntPtr hemf);
该应用程序创建一个图元文件图像并将其传递给下面的方法。
private byte[] ConvertMetaFileToByteArray(Image image)
{
byte[] dataArray = null;
Metafile mf = (Metafile)image;
IntPtr enhMetafileHandle = mf.GetHenhmetafile();
uint bufferSize = GetEnhMetaFileBits(enhMetafileHandle, 0, null);
if (enhMetafileHandle != IntPtr.Zero)
{
dataArray = new byte[bufferSize];
GetEnhMetaFileBits(enhMetafileHandle, bufferSize, dataArray);
}
DeleteEnhMetaFile(enhMetafileHandle);
return dataArray;
}
此时,dataArray 被插入到对象中并使用 BinaryFormatter 进行序列化。
然后使用 BinaryFormatter 和从对象检索的 dataArray 再次对保存的文件进行反序列化。
然后使用 dataArray 使用以下方法重建原始图元文件。
public static Image ConvertByteArrayToMetafile(byte[] data)
{
Metafile mf = null;
try
{
IntPtr hemf = SetEnhMetaFileBits((uint)data.Length, data);
mf = new Metafile(hemf, true);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
return (Image)mf;
}
然后,重建的图元文件作为 .emf(模型)保存到磁盘,此时演示器可以访问它进行显示。
private static void SaveFile(Image image, String filepath)
{
try
{
byte[] buffer = ConvertMetafileToByteArray(image);
File.WriteAllBytes(filepath, buffer); //will overwrite file if it exists
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
问题是保存到磁盘失败。如果在序列化之前使用相同的方法保存原始图元文件,则一切正常。因此,在序列化/反序列化期间数据发生了一些变化。
事实上,如果我在调试器中检查图元文件属性,我可以看到 ImageFlags、PropertyID、分辨率和像素格式发生了变化。
原始 Format32bppRgb 更改为 Format32bppArgb
原始分辨率 81 更改为 96
我已经通过谷歌和 SO 进行了搜索,这帮助我走到了这一步,但我现在陷入困境。
有没有人有足够的图元文件/序列化经验来帮助..?
编辑:如果我直接序列化/反序列化字节数组(不嵌入另一个对象),我会遇到同样的问题。
I have an application that works with Enhanced Metafiles.
I am able to create them, save them to disk as .emf and load them again no problem.
I do this by using the gdi32.dll methods and the DLLImport attribute.
However, to enable Version Tolerant Serialization I want to save the metafile in an object along with other data.
This essentially means that I need to serialize the metafile data as a byte array and then deserialize it again in order to reconstruct the metafile.
The problem I have is that the deserialized data would appear to be corrupted in some way, since the method that I use to reconstruct the Metafile raises a "Parameter not valid exception".
At the very least the pixel format and resolutions have changed.
Code use is below.
[DllImport("gdi32.dll")]
public static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer, byte[] lpbBuffer);
[DllImport("gdi32.dll")]
public static extern IntPtr SetEnhMetaFileBits(uint cbBuffer, byte[] lpBuffer);
[DllImport("gdi32.dll")]
public static extern bool DeleteEnhMetaFile(IntPtr hemf);
The application creates a metafile image and passes it to the method below.
private byte[] ConvertMetaFileToByteArray(Image image)
{
byte[] dataArray = null;
Metafile mf = (Metafile)image;
IntPtr enhMetafileHandle = mf.GetHenhmetafile();
uint bufferSize = GetEnhMetaFileBits(enhMetafileHandle, 0, null);
if (enhMetafileHandle != IntPtr.Zero)
{
dataArray = new byte[bufferSize];
GetEnhMetaFileBits(enhMetafileHandle, bufferSize, dataArray);
}
DeleteEnhMetaFile(enhMetafileHandle);
return dataArray;
}
At this point the dataArray is inserted into an object and serialized using a BinaryFormatter.
The saved file is then deserialized again using a BinaryFormatter and the dataArray retrieved from the object.
The dataArray is then used to reconstruct the original Metafile using the following method.
public static Image ConvertByteArrayToMetafile(byte[] data)
{
Metafile mf = null;
try
{
IntPtr hemf = SetEnhMetaFileBits((uint)data.Length, data);
mf = new Metafile(hemf, true);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
return (Image)mf;
}
The reconstructed metafile is then saved saved to disk as a .emf (Model) at which point it can be accessed by the Presenter for display.
private static void SaveFile(Image image, String filepath)
{
try
{
byte[] buffer = ConvertMetafileToByteArray(image);
File.WriteAllBytes(filepath, buffer); //will overwrite file if it exists
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
The problem is that the save to disk fails. If this same method is used to save the original Metafile before it is serialized everything is OK. So something is happening to the data during serialization/deserializtion.
Indeed if I check the Metafile properties in the debugger I can see that the ImageFlags, PropertyID, resolution and pixelformats change.
Original Format32bppRgb changes to Format32bppArgb
Original Resolution 81 changes to 96
I've trawled though google and SO and this has helped me get this far but Im now stuck.
Does any one have enough experience with Metafiles / serialization to help..?
EDIT: If I serialize/deserialize the byte array directly (without embedding in another object) I get the same problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论