C# byte数组转成Bitmap对象
方法一:
/// <summary> /// 将数组转换成彩色图片 /// </summary> /// <param name="rawValues">图像的byte数组</param> /// <param name="width">图像的宽</param> /// <param name="height">图像的高</param> /// <returns>Bitmap对象</returns> public Bitmap ToColorBitmap(byte[] rawValues, int width, int height) { //// 申请目标位图的变量,并将其内存区域锁定 try { if (width != oldPicWidth || height != oldPicHeight)//如果图像尺寸发生变化,则需要重新new一下Bitmap对象 { if (m_currBitmap != null) m_currBitmap = null; m_currBitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb); m_rect = new Rectangle(0, 0, width, height); m_bitmapData = m_currBitmap.LockBits(m_rect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); } IntPtr iptr = m_bitmapData.Scan0; // 获取bmpData的内存起始位置 //// 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中 System.Runtime.InteropServices.Marshal.Copy(rawValues, 0, iptr, width * height * 3); if (width != oldPicWidth || height != oldPicHeight) { m_currBitmap.UnlockBits(m_bitmapData); oldPicWidth = width; oldPicHeight = height; } //// 算法到此结束,返回结果 return m_currBitmap; } catch (System.Exception ex) {
return null; } }
上述方法有个问题,如果是从在线视频流中取数据,如果在短时间内,多次调用此方法,则会抛GDI+异常,或者提示Bitmap对象被占用。为了解决这个问题,后来想到了用Bitmap数组来解决。
方法如下
方法二:
private Bitmap[] m_pBitmaps = new Bitmap[15]; private int m_nCurrBitmapIdx = -1; public Bitmap ToColorBitmap2(byte[] rawValues, int width, int height) { // 申请目标位图的变量,并将其内存区域锁定 //初始化Bitmap数组 if (m_bFrmSizeChange || m_nCurrBitmapIdx < 0) { for (int i = 0; i < 15; i++) { m_pBitmaps[i] = new Bitmap(width, height, PixelFormat.Format24bppRgb); } m_nCurrBitmapIdx = 0; m_bFrmSizeChange = false; } Bitmap bmp = m_pBitmaps[m_nCurrBitmapIdx]; m_nCurrBitmapIdx++; if (m_nCurrBitmapIdx >= 15) m_nCurrBitmapIdx = 0; try { //Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); //// 获取图像参数 //int stride = bmpData.Stride; // 扫描线的宽度 IntPtr iptr = bmpData.Scan0; // 获取bmpData的内存起始位置 //int scanBytes = stride * height;// 用stride宽度,表示这是内存区域的大小 //// 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中 System.Runtime.InteropServices.Marshal.Copy(rawValues, 0, iptr, width * height * 3); bmp.UnlockBits(bmpData); // 解锁内存区域 //// 算法到此结束,返回结果 return bmp; } catch (System.Exception e) { //Tools.m_CreateLogTxt("ToColorBitmap2", e.ToString(), Index); return null; } }