ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

在C#中的pictureBox中显示一个字节数组

2019-06-30 06:53:23  阅读:287  来源: 互联网

标签:c bitmap picturebox


我读了很多问题和答案,大多数建议:

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’类型的未处理异常

附加信息:参数无效.“

关于流参数.

即使在以下情况下:

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 ;

解决方法:

每个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

标签:c,bitmap,picturebox
来源: https://codeday.me/bug/20190630/1334328.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有