2017-08-15 54 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獲取不正確的屏幕截圖數據。所以圖像只是空白! –