2017-08-15 55 views
1

我正在使用提供COM接口的电子软件OMICRON MPD和MI。我正在通过COM Interface提供的方法截图并尝试将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); 

给出同样的错误如上关于无效参数

最终解决

我看一个叫“六角扳手BMP视频:创建位图从零开始“,这帮助我从我得到的数据构建图像。

我接收数据曾在字节的图像数据,在40个字节DIB头,和一些初始27个字节的数据(我不能真正使出来它是什么)。对于这种要被翻译成的图像,它需要在开始时14个字节的文件标头,我手动构造像这样:

byte[] fileHeader = { 0x42, 0x4d, 0x0c, 0xef, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 }; 

注意,在十六进制(0x0c,0xef,为0x82,0×00的文件大小,其等于847760字节的文件大小)是硬编码的(字节很容易变成动态的)。 0x36是实际图像数据开始处的索引54,即十六进制数36。

然后我所附即通过偏移到其中DIB头标开始,其在我的情况是索引27.

下面从我的原始阵列数据是我的原始数据的屏幕截图与初始27个字节未知数据和与DIB头标开始在指数27

enter image description here

enter image description here

以上是我的最终图像十六进制数据的屏幕截图。蓝色是14个字节的文件头,红色是DIB头40个字节,和休息开始绿色是图像数据。用“.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()); 
+0

有没有规范,它会告诉什么是那些二进制数据的格式? –

+0

原始图像是bmp格式,您试图将其保存为jpg。你从bmp转换成jpg的地方? – jdweng

+0

为什么使用ImageConverted而不是Image.FromStream(rawImg); ? – Sorceri

回答

1

尽量只istead你的代码片断是这样的:

byte[] rawImg = ... 

MemoryStream mstream = new MemoryStream(rawImg); 
File.WriteAllBytes("screen.bmp", mstream.ToArray()); 

尝试#2

我的第二个猜测,这可能是一个DIB文件格式,如果它是真的,你应该能够在大多数照片查看器/编辑器(如GIMP或其他)中打开“screen.dib”

byte[] rawImg = array; 

File.WriteAllBytes("screen.dib", rawImg); 
+0

它将其保存为图像文件,但我无法在Windows照片查看器中查看它,当我尝试在GIMP中打开它时,它显示“打开文件失败,不是有效的BMP文件” –

+0

我认为这与@Zergatul所说的一致关于rawImg不是有效的BMP。 –

1

看看记事本++转储它看起来这只是32位每像素或4字节ARGB图像的原始字节。您应该可以使用Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr)构造函数,并只传入原始字节。唯一的问题是计算图像的width,height,stridePixelFormat,但您应该能够通过一点实验来弄清楚。

这里就是我做了一个类似的字节数组,你已经证明一个例子:

byte[] bytes = new byte[] { 
    0,64,128,128, 
    0,64,128,128, 
    0,64,128,128, 
    0,64,128,128, 
    0,64,128,128, 
    0,64,128,128, 
    0,64,128,128, 
    0,64,128,128, 
}; 

unsafe 
{ 
    fixed (byte* pBytes = bytes) 
    { 
     int width = 4; // Your width 
     int height = 2; // Your height 
     int stride = width * 4; // Your stride 
     Bitmap bitmap = new Bitmap(width, height, stride, PixelFormat.Format32bppArgb, new IntPtr(pBytes)); 
     bitmap.Save(@"c:\temp\bitmap.png"); // Could save to another format like .jpg 
    } 
} 
+0

是的,它没有错误的技巧,但从上面的讨论,现在非常清楚,我没有从MPD 600 Com Interface获取不正确的屏幕截图数据。所以图像只是空白! –