Байт в биты в BMP, получая RGB - PullRequest
2 голосов
/ 17 марта 2012

Я написал код ниже, чтобы манипулировать цветом изображения.Я хочу как-то разорвать каждый пиксель изображения.Поэтому для каждого пикселя я хочу получить доступ к 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 ]

2 голосов
/ 17 марта 2012

Если у вас есть 16-битное целое число x, вы можете извлечь диапазоны битов внутри него, сначала замаскировав эти биты двоичным И, а затем сместив результат.Вот так:

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 голос
/ 17 марта 2012

RGB24 составляет 1 байт на цветовой канал, поэтому вам не нужно ничего менять, чтобы извлечь их из данных, которые у вас уже есть. «получать биты» на самом деле не имеет смысла, так как вы можете установить их значения, например,

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

установит новый канал синего изображения в исходный синий канал изображения, но установит бит старшего разряда в 1.

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

инвертирует канал.

Так что вам действительно нужно использовать побитовые операторы (| & >> << ^) для данных, которые у вас уже есть. </p>

...