Enhanced Metafilesで動作するアプリケーションがあります。
それらを作成し、.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 (モデル) としてディスクに保存されます。この時点で、Presenter がアクセスして表示できます。
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をトロールしましたが、これは私がここまで到達するのに役立ちましたが、今は立ち往生しています。
メタファイル/シリアライゼーションで十分な経験を持っている人はいますか..?
編集:バイト配列を(別のオブジェクトに埋め込まずに)直接シリアライズ/デシリアライズすると、同じ問題が発生します。