我读了很多问题和答案,大多数建议:
byte[] byteArray; //(contains image data)
MemoryStream stream = new MemoryStream(byteArray);
Bitmap image = new Bitmap(stream);
pictureBox.Image = image;
或更直接:
pictureBox.Image = Image.FromStream(stream);
我总是得到:“System.Drawing.dll中发生了'System.ArgumentException'类型的未处理异常
附加信息:参数无效。“
关于stream参数。
即使在以下情况下:
byte[] byteArray = new byte[1];
byteArray[0] = 255;
我无法弄清楚原因。
编辑:
我从这样的文件中获取数据:
//byteArray is defined as List<byte> byteArray = new List<byte>();
TextReader tr = new StreamReader(file);
string File = tr.ReadToEnd();
string[] bits = File.Split('\t');
List<string> image = new List<string>(bits);
height = int.Parse(bits[0]);
width = int.Parse(bits[1]);
image.RemoveRange(0, 2);
image.RemoveAt(image.Count - 1);
foreach (string s in image)
{
byteArray.Add(byte.Parse(s));
}
return byteArray //(i do .ToArray() in the MemoryStream call);
在调试器中,我看到,即byteArray是好的,count = 2244,值到处都是等等。
编辑#2:样本数据文件(第一个字节[0]是高度,第二个字节[1]是宽度,其余是RGB数据)
47 15 12 55 25 52 55 25 52 55 25 52 55 25 52 55
25 52 55 25 52 55 25 52 55 25 52 55 25 52 55 25
52 55 25 52 55 25 52 55 25 52 55 25 52 55 25 52
55 25 52 55 25 52 55 25 52 55 25 52 55 25 52 55
25 52 51 24 82 49 24 82 49 24 92 50 25 12 50 24
92 48 24 92 50 24 82 50 25 02 50 24 92 50 25 02
51 25 12 50 24 92 49 25 02 50 25 02 49 25 12 49
25 02 49 25 02 47 25 12 47 25 22 50 24 82 47 24
82 50 24 72 50 24 82 49 24 82 50 24 72 50 24 82
50 24 72 49 24 82 49 25 22 52 24 92 50 24 82 50
24 72 47 25 00 etc.
编辑#3:解决方案
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
IntPtr ptr = bmpData.Scan0;
Marshal.Copy(byteArray, 0, ptr, height * width * 3);
bmp.UnlockBits(bmpData);
pictureBox.Image = bmp;
需要检查4字节对齐,现在加载功能:
TextReader tr = new StreamReader(file);
string File = tr.ReadToEnd();
string[] bits = File.Split('\t');
List<string> image = new List<string>(bits);
height = int.Parse(bits[0]);
width = int.Parse(bits[1]);
int falseBits = 0;
int oldWidth = width;
while (width % 4 != 0)
{
width++;
falseBits++;
}
int size = height * width * 3;
byte[] byteArray = new byte[size];
Parallel.For(0, size - 1, i => byteArray[i] = 255);
int index = 0;
int lineIndex = 0;
image.RemoveRange(0, 2);
image.RemoveAt(image.Count - 1);
foreach (string s in image)
{
byteArray [index] = byte.Parse(s);
byteArray [index + 1] = byteArray [index];
byteArray [index + 2] = byteArray [index];
index +=3;
lineIndex++;
if (lineIndex == oldWidth)
{
lineIndex = 0;
index += 3*falseBits;
}
}
return byteArray ;
答案 0 :(得分:2)
每个Image都需要描述字节数组的内容。此描述称为Header。如果您现在想要交换字节,则需要避免更改标题。
http://en.wikipedia.org/wiki/BMP_file_format
这是我使用这样一个ByteArray时的源代码示例
''' <summary>
''' Copies an Bytearray into an image and return it.
''' </summary>
''' <param name="ArrSrc">Source byte array of image which can be anything</param>
''' <param name="ImageSize">the image size of the image</param>
''' <param name="SourceArrayPixelFormat">Pixel format, like 24Bit or 32Bit</param>
''' <returns>System.Drawing.Image</returns>
''' <remarks>copyright, http://software.goldengel.ch, 2012</remarks>
Public Function ArrayToBitmapData(ByVal ArrSrc() As Byte, ByVal ImageSize As System.Drawing.Size, ByVal SourceArrayPixelFormat As System.Drawing.Imaging.PixelFormat) As System.Drawing.Bitmap
'Kopiert ein ByteArray in ein Bitmap
Dim m As Integer
Dim bmTemp As System.Drawing.Bitmap = Nothing
Dim S As System.Drawing.Size
Dim MemorySize As Integer
Dim ScanLine As Integer
'Bild prüfen
If ArrSrc Is Nothing Then Return bmTemp
'Bildgrösse definieren
'Bei unterschiedlichen Grössen, wird muss die kleinere Grösse verwendet werden
S = ImageSize
'Helfer für die Bildverarbeitung erzeugen
Dim bts As System.Drawing.Imaging.BitmapData
'Bitmap erzeugen um damit zu arbeiten
bmTemp = New System.Drawing.Bitmap(S.Width, S.Height, SourceArrayPixelFormat)
'Farbtiefe berechnen
'24Bit und 32Bit Bilder werden unterstützt
'Kann beliebig erweitert werden
m = BytesInPixelFormat(SourceArrayPixelFormat)
'*** Hauptroutine - Array --> Bitmap ***
'Bilddaten in die Picturebox laden
bts = bmTemp.LockBits(New System.Drawing.Rectangle(0, 0, S.Width, _
S.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, SourceArrayPixelFormat)
'Speicherplatz reservieren
'MemorySize = S.Height * S.Width * m
'Nur zur Kontrolle
ScanLine = GetScanline(S, SourceArrayPixelFormat)
MemorySize = S.Height * bts.Stride
If ArrSrc.Length >= MemorySize Then
'Bilddaten aus dem Array laden
Global.System.Runtime.InteropServices.Marshal.Copy(ArrSrc, 0, bts.Scan0, MemorySize)
End If
bmTemp.UnlockBits(bts)
'Erzeugtes Bitmap zurückgeben
Return bmTemp
End Function
convert Bitmap image into byte array
'Neue Funktion 27.2.2008
'Mit korrekter Dimensionierung mittels bts.Stride und Umrechnung auf das Pixelformat
''' <summary>
''' Get an Array of the data of any image.
''' Bitmap header execluded.
''' </summary>
''' <param name="bmSrc">Source image</param>
''' <param name="NeededDestinationPixelFormat">Pixelformat, like 24Bit or 32Bit</param>
''' <returns>Image content</returns>
''' <remarks>copyright http://software.goldengel.ch, 2012</remarks>
Public Function BitmapDataToArray(ByVal bmSrc As System.Drawing.Bitmap, ByVal NeededDestinationPixelFormat As System.Drawing.Imaging.PixelFormat, ByRef DstStride As Integer) As Byte()
'Kopiert ein Bild in ein Bytearray
Dim m As Integer
Dim A() As Byte = Nothing
Dim S As System.Drawing.Size
Dim MemorySize As Integer
Dim bmTemp As System.Drawing.Bitmap = Nothing
'Bild prüfen
If bmSrc Is Nothing Then Return A
'Bildgrösse definieren
'Bei unterschiedlichen Grössen, wird muss die kleinere Grösse verwendet werden
S = bmSrc.Size
'Helfer für die Bildverarbeitung erzeugen
Dim bts As System.Drawing.Imaging.BitmapData
'Farbtiefe berechnen
'24Bit und 32Bit Bilder werden unterstützt
'Kann beliebig erweitert werden
m = BytesInPixelFormat(NeededDestinationPixelFormat)
'*** Hauptroutine - Bitmap --> Array ***
'Bilddaten aus der Picturebox laden
If NeededDestinationPixelFormat <> bmSrc.PixelFormat Then
'Bitmap erzeugen um damit zu arbeiten
bmTemp = New System.Drawing.Bitmap(S.Width, S.Height, NeededDestinationPixelFormat)
Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmTemp)
gr.DrawImage(bmSrc, 0, 0)
End Using
'ImgSrc.Dispose()'Achtung, würde das Original mit zerstören
bmSrc = bmTemp
End If
bts = bmSrc.LockBits(New System.Drawing.Rectangle(0, 0, S.Width, _
S.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, NeededDestinationPixelFormat)
'Speicherplatz reservieren
MemorySize = S.Height * bts.Stride
ReDim A(MemorySize - 1) '28.2.2010. wichtige Änderung. 1 Byte zuviel wurde reserviert. Das konnte bei Wiederholung von Graphics.Drawing zu einem Fehler kommen
'Bitmapdaten in das Array kopieren
Global.System.Runtime.InteropServices.Marshal.Copy(bts.Scan0, A, 0, A.Length)
bmSrc.UnlockBits(bts)
DstStride = bts.Stride
If bmTemp IsNot Nothing Then bmTemp = Nothing
Return A
End Function
答案 1 :(得分:1)
根据您帖子顶部的原始建议,我对此工作没有任何问题。
pictureBox.Image = GetImage();
public Image GetImage()
{
Image image;
using (FileStream fs = File.OpenRead(@"C:\picture.jpg"))
{
long length = fs.Length;
byte[] bytes = new byte[length];
for (int pos = 0; pos < length; )
pos += fs.Read(bytes, pos, (int)length - pos);
fs.Position = 0;
using (MemoryStream ms = new MemoryStream(bytes))
image = Image.FromStream(ms);
}
return image;
}
现在,无论这是否安全/正确,我都不知道,但似乎有效。