我正在使用提供 COM 接口的电子软件 OMICRON MPD 和 MI。我正在通过 COM 接口提供的方法截取屏幕截图,并尝试将 byte[] 保存到图像文件中。
我的代码:
byte[] rawImg = ...
MemoryStream mstream = new MemoryStream(rawImg);
ImageConverter imageConverter = new System.Drawing.ImageConverter();
System.Drawing.Image image = imageConverter.ConvertFrom(rawImg) as System.Drawing.Image; //error line
image.Save(@"path\img.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
我得到错误:
System.ArgumentException' occurred in System.Drawing.dll Parameter is not valid
我检查了字节数组的长度:
rawImg.Length
//897832
我可以使用以下方法将上述内存流保存到文件中:
using (FileStream file = new FileStream(@"path\img.txt", FileMode.Create, FileAccess.Write))
{
mstream.WriteTo(file);
}
我不确定这意味着什么,但我该如何调试呢?错误在哪里?是我收到的数据是错误的还是将其保存为图像的 C# 代码。
根据 COM 接口文档,rawImg 是与设备无关的位图(格式与 .BMP 文件相同)。
失败的尝试 #1
ImageConverter imageConverter = new System.Drawing.ImageConverter();
Image image = imageConverter.ConvertFrom(rawImg) as Image; //error line
image.Save(@"path\img.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
给出与上述无效参数相同的错误
最终解决方案
我观看了一个名为“Hex To BMP: Creating a Bitmap From Scratch”的视频,它帮助我根据获得的数据构建图像。
我收到的数据包含以字节为单位的图像数据、40 字节的 DIB 标头和一些初始的 27 字节数据(我无法真正弄清楚它是什么)。为了将其转换为图像,它需要在开头有一个 14 字节的文件头,我手动构造如下:
byte[] fileHeader = { 0x42, 0x4d, 0x0c, 0xef, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 };
请注意,十六进制的文件大小(0x0c、0xef、0x82、0x00 等于 847760 字节文件大小)是硬编码的(字节可以很容易地变成动态的)。0x36 是实际图像数据开始的位置,索引 54 是十六进制的 36。
然后我只是通过偏移到 DIB Header 开始的位置从我的原始数组中附加该数据,在我的例子中是索引 27。
下面是我的原始数据的屏幕截图,其中包含初始 27 字节的未知数据和从索引 27 开始的 DIB 标头。
以上是我最终图像十六进制数据的屏幕截图。蓝色为 14 字节的文件头,红色为 40 字节的 DIB 头,其余以绿色开头的为图像数据。使用“.bmp”扩展名保存此数据,您将获得图像。
我的代码:
byte[] imgData, newImgData;
byte[] fileHeader = { 0x42, 0x4d, 0x0c, 0xef, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 };
newImgData = new byte[847760];
BinaryFormatter bf = new BinaryFormatter();
string path2 = @"path\myImg.bmp";
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, value);
mgData = ms.ToArray();
}
for(int i = 0; i < fileHeader.Count(); i++)
{
newImgData[i] = fileHeader[i];
}
int indx = 14;
for (int i = 27; i < imgData.Count(); i++)
{
newImgData[indx] = imgData[i];
indx++;
}
System.IO.File.WriteAllBytes(path2, newImgData.ToArray());