您的位置:首页 > 编程语言 > C#

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

2014-10-10 14:32 302 查看
转自: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);

         }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: