C#中使用byte[]数据,生成Bitmap

转自:http://www.bitscn.com/pdb/dotnet/200904/160808.html
    摸索了3天,终于成功实现了使用已知byte[]数据,生成Bitmap(256色灰度 BMP位图)。
    其中遇到了很多问题:
    如何在C#(GDI+)中操作Bitmap,获取位图的各种数据,就像在C++|中一样
    如何修改Bitmap的调色板

如何解决位图显示错位的问题,即位图的4字节对齐问题

如何用数据生成位图

总结一下,希望对需要的朋友有所帮助,少走弯路。


///   <summary>
        
///  使用byte[]数据,生成256色灰度 BMP 位图
        
///   </summary>
        
///   <param name="originalImageData"></param>
        
///   <param name="originalWidth"></param>
        
///   <param name="originalHeight"></param>
        
///   <returns></returns>
         public   static  Bitmap CreateBitmap( byte [] originalImageData,  int  originalWidth,  int  originalHeight)
         {
            
// 指定8位格式,即256色
             Bitmap resultBitmap  =   new  Bitmap(originalWidth, originalHeight, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);

            
// 将该位图存入内存中
             MemoryStream curImageStream  =   new  MemoryStream();
             resultBitmap.Save(curImageStream, System.Drawing.Imaging.ImageFormat.Bmp);
             curImageStream.Flush();

            
// 由于位图数据需要DWORD对齐(4byte倍数),计算需要补位的个数
             int  curPadNum  =  ((originalWidth  *   8   +   31 /   32   *   4 -  originalWidth;

            
// 最终生成的位图数据大小
             int  bitmapDataSize  =  ((originalWidth  *   8   +   31 /   32   *   4 *  originalHeight;

            
// 数据部分相对文件开始偏移,具体可以参考位图文件格式
             int  dataOffset  =  ReadData(curImageStream,  10 4 );


            
// 改变调色板,因为默认的调色板是32位彩色的,需要修改为256色的调色板
             int  paletteStart  =   54 ;
            
int  paletteEnd  =  dataOffset;
            
int  color  =   0 ;

            
for  ( int  i  =  paletteStart; i  <  paletteEnd; i  +=   4 )
             {
                
byte [] tempColor  =   new   byte [ 4 ];
                 tempColor[
0 =  ( byte )color;
                 tempColor[
1 =  ( byte )color;
                 tempColor[
2 =  ( byte )color;
                 tempColor[
3 =  ( byte ) 0 ;
                 color
++ ;

                 curImageStream.Position 
=  i;
                 curImageStream.Write(tempColor, 
0 4 );
             }

            
// 最终生成的位图数据,以及大小,高度没有变,宽度需要调整
             byte [] destImageData  =   new   byte [bitmapDataSize];
            
int  destWidth  =  originalWidth  +  curPadNum;

            
// 生成最终的位图数据,注意的是,位图数据 从左到右,从下到上,所以需要颠倒
             for  ( int  originalRowIndex  =  originalHeight  -   1 ; originalRowIndex  >=   0 ; originalRowIndex -- )
             {
                
int  destRowIndex  =  originalHeight  -  originalRowIndex  -   1 ;

                
for  ( int  dataIndex  =   0 ; dataIndex  <  originalWidth; dataIndex ++ )
                 {
                    
// 同时还要注意,新的位图数据的宽度已经变化destWidth,否则会产生错位
                     destImageData[destRowIndex  *  destWidth  +  dataIndex]  =  originalImageData[originalRowIndex  *  originalWidth  +  dataIndex];
                 }
             }


            
// 将流的Position移到数据段   
             curImageStream.Position  =  dataOffset;

            
// 将新位图数据写入内存中
             curImageStream.Write(destImageData,  0 , bitmapDataSize);

             curImageStream.Flush();

            
// 将内存中的位图写入Bitmap对象
             resultBitmap  =   new  Bitmap(curImageStream);

            
return  resultBitmap;
         }

        
///   <summary>
        
///  从内存流中指定位置,读取数据
        
///   </summary>
        
///   <param name="curStream"></param>
        
///   <param name="startPosition"></param>
        
///   <param name="length"></param>
        
///   <returns></returns>
         public   static   int  ReadData(MemoryStream curStream,  int  startPosition,  int  length)
         {
            
int  result  =   - 1 ;

            
byte [] tempData  =   new   byte [length];
             curStream.Position 
=  startPosition;
             curStream.Read(tempData, 
0 , length);
             result 
=  BitConverter.ToInt32(tempData,  0 );

            
return  result;
         }

        
///   <summary>
        
///  向内存流中指定位置,写入数据
        
///   </summary>
        
///   <param name="curStream"></param>
        
///   <param name="startPosition"></param>
        
///   <param name="length"></param>
        
///   <param name="value"></param>
         public   static   void  WriteData(MemoryStream curStream,  int  startPosition,  int  length,  int  value)
         {
             curStream.Position 
=  startPosition;
             curStream.Write(BitConverter.GetBytes(value), 
0 , length);
         }

你可能感兴趣的:(C#中使用byte[]数据,生成Bitmap)