簡體   English   中英

與設備無關的位圖字節數組到圖像:參數無效

[英]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)構造函數,並且只需傳入原始字節即可。 唯一的問題是弄清楚圖像的widthheightstridePixelFormat ,但是您只需做一點點試驗就可以弄清楚。

這是一個示例,其中我制作了一個與您顯示的字節數組類似的字節數組:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM