字节到BMP获取RGB的位

时间:2012-03-17 00:24:12

标签: c# .net winforms bitmap rgb

我编写了下面的代码来操纵图像的颜色。我想以某种方式撕开图像的每个像素。因此,对于每个像素,我想要访问5位红色,6位绿色和5位蓝色(根据16位图像)。我如何更改我的代码来执行此操作?我想我必须以某种方式将我设置的字节值转换为位?

任何帮助都会很棒。

        private Bitmap InvertBitmap(Bitmap bmp)
        {

            unsafe
            {
                //create an empty bitmap the same size as original
                Bitmap newBitmap = new Bitmap(bmp.Width, bmp.Height);

            //lock the original bitmap in memory
            System.Drawing.Imaging.BitmapData originalData = bmp.LockBits(
               new Rectangle(0, 0, bmp.Width, bmp.Height),
               System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            //lock the new bitmap in memory
            System.Drawing.Imaging.BitmapData newData = newBitmap.LockBits(
               new Rectangle(0, 0, bmp.Width, bmp.Height),
               System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            //set the number of bytes per pixel
            int pixelSize = 3;

            for (int y = 0; y < bmp.Height; y++)
            {
                //get the data from the original image
                byte* originalImageRow = (byte*)originalData.Scan0 + (y * originalData.Stride);

                //get the data from the new image
                byte* newImageRow = (byte*)newData.Scan0 + (y * newData.Stride);

                for (int x = 0; x < bmp.Width; x++)
                {

                    //set the new image's pixel to the inverted version

                    newImageRow[x * pixelSize] = (byte)(255 - originalImageRow[x * pixelSize + 0]); //B
                    newImageRow[x * pixelSize + 1] = (byte)(255 - originalImageRow[x * pixelSize + 1]); //G
                    newImageRow[x * pixelSize + 2] = (byte)(255 - originalImageRow[x * pixelSize + 2]); //R
                }
            }

            //unlock the bitmaps
            newBitmap.UnlockBits(newData);
            bmp.UnlockBits(originalData);

            return newBitmap;
        }
}

2 个答案:

答案 0 :(得分:2)

如果你有一个16位整数x,你可以先用二进制AND屏蔽这些位,然后移动结果,从而提取其中的位范围。像这样:

int x = 33808;  // 1000010000010000, for testing

int r = (x & 63488) >> 11;    // 63488 = 1111100000000000
int g = (x & 2016) >> 5;      //  2016 = 0000011111100000
int b = (x & 31);             //    31 = 0000000000011111

// r = 10000
// g = 100000
// b = 10000

我希望有所帮助。

答案 1 :(得分:1)

RGB24每个颜色通道为1个字节,因此您无需进行任何操作即可从已有数据中提取它们。 “获取位”并没有真正意义,因为你可以设置它们的值,例如。

newImageRow[x * pixelSize] = (byte)(originalImageRow[x * pixelSize + 0] | 0x80); //B

将新图像蓝色通道设置为原始图像蓝色通道,但会将高位设置为1.

newImageRow[x * pixelSize] = (byte)(originalImageRow[x * pixelSize + 0] ^ 0xFF); //B

会反转频道。

所以你真的需要对你已经拥有的数据使用按位运算符(|&amp;&gt;&gt;&lt;&lt; ^)。