Независимый от устройства байтовый массив для изображения: параметр недействителен
Я работаю с электронным программным обеспечением OMICRON MPD и MI, которое обеспечивает интерфейс COM. Я делаю снимок экрана с помощью методов, предоставляемых COM-интерфейсом, и пытаюсь сохранить байт [] в файл изображения.
Мой код:
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: Создание растрового изображения с нуля", которое помогло мне построить изображение на основе полученных данных.
Я получал данные, которые содержали данные изображения в байтах, 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());
2 ответа
Глядя на дамп 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, если это правда, вы должны иметь возможность открывать "screen.dib" в большинстве средств просмотра / редактирования фотографий (например, GIMP или другие)
byte[] rawImg = array;
File.WriteAllBytes("screen.dib", rawImg);