[英]Device Independent Bitmap Byte Array to Image : Parameter is not valid
我正在使用提供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);
對於無效參數給出與上述相同的錯誤
最終解決方案
我觀看了一個名為“十六進制到BMP:從頭開始創建位圖”的視頻,該視頻幫助我從獲取的數據中構建了圖像。
我收到的數據包含以字節為單位的圖像數據,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頭開始的位置(在我的情況下為索引27)將原始數組中的數據附加到了該位置。
以下是我的原始數據的屏幕截圖,其中包含初始27個字節的未知數據,並且DIB標頭從索引27開始。
上面是我最終圖像十六進制數據的屏幕截圖。 藍色是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());
查看Notepad ++轉儲,似乎這只是32位每像素或4字節ARGB圖像的原始字節。 您應該能夠使用Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr)
構造函數,並且只需傳入原始字節即可。 唯一的問題是弄清楚圖像的width
, height
, stride
和PixelFormat
,但是您只需做一點點試驗就可以弄清楚。
這是一個示例,其中我制作了一個與您顯示的字節數組類似的字節數組:
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
}
}
嘗試而不是像以下代碼片段那樣嘗試:
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.