1

私は C# でビットマップを扱っていますが、ご存じのとおり、ビットマップは通常 24bpp または 32bpp としてメモリに格納されます (ロックされている場合)。ピクセルの int カラー値を抽出した後、一度に 1 バイトを読み取って R、G、B を取得し、同じバイトを編集して RGB をそれぞれ変更する必要があります。ポインターを使用して、4 バイト 32 ビット int の特定のバイトを変更する方法はありますか? またはstruct、個々のバイトのアクセス/変更を可能にする構造体を作成して int をキャストできますか?

int color = 0xFFAABB

// attempt to read individual bytes of an int
int R = *((*color));
int G = *((*color)+1);
int B = *((*color)+2);

// attempt to modify individual bytes of an int
*((*color)) = R;
*((*color)+1) = G;
*((*color)+2) = B;

個々のバイトを高速に読み書きするための方法が必要です。そのようなポインターを操作する方法があれば、unsafeそれも気にしません。Color高速な画像操作には遅すぎるため、各ピクセルをオブジェクトに変換できません。

4

2 に答える 2

3

一般的に、私がしていることは、あなたが言ったように構造体を作成することです:

public struct Pixel {
    public byte Blue;
    public byte Green;
    public byte Red;
    public byte Alpha;
}

次に、次のようなユーティリティ関数があります。

public void SetPixel(int x, int y, Pixel colour) {
    Pixel* pixel = GetPixelAt(x, y);
    *pixel = colour;
}

public Pixel* GetPixelAt(int x, int y) {
    return (Pixel*)((byte*)_bitmapData.Scan0.ToPointer() + y * _width + x * sizeof(Pixel));
}

次に、次のように呼び出すことができます。

Pixel p;
p.Red = 255;
p.Green = 0;
p.Blue = 0;
p.Alpha = 255;

SetPixel(0, 0, p);

_bitmapDataBitmapData経由で返される構造体LockBitsです。

編集:

コメントより。これは、それらを変換する方法です。

// from pixel to int
Pixel p;
p.Red = 0;
p.Green = 0;
p.Blue = 0;
p.Alpha = 0;

int* i = (int*)&p;

// from int to pixel
Pixel p2;

p2 = *(Pixel*)&i;

未テストですが、問題ないはずです。

于 2013-01-19T08:13:50.520 に答える
2

ポインターを使用するには、アンセーフ コードを使用する必要があります。ただし、シフト演算子とビット演算子を使用して、目的を達成できます。

// attempt to read individual bytes of an int
int r = (color & 0x00FF0000)>>16;
int g = (color & 0x0000FF00)>>8;
int b = (color & 0x000000FF);

Console.WriteLine("R-{0:X}, G-{1:X}, B-{2:X}", r, g, b);
// attempt to modify individual bytes of an int
int r1 = 0x1A;
int g1 = 0x2B;
int b1 = 0x3C;
color = (color & ~0x00FF0000) | r1 << 16;
color = (color & ~0x0000FF00) | g1 << 8;
color = (color & ~0x000000FF) | b1;

Console.WriteLine("Color-{0:X}", color);

必要に応じて、このスニペットを構造でラップできます。

これはアンセーフ コードを使用したソリューションです。ビルド オプションでアンセーフ コードを許可するように設定する必要があります。

using System;

namespace PixelTest
{
    public unsafe struct Pixel
    {
        private int _color;

        public Pixel(int color)
        {
            _color = color;
        }

        public int GetColor()
        {
            return _color;
        }

        public int GetR()
        {
            fixed(int* c = &_color)
            {
                return *((byte*)c + 2);
            }
        }

        public int GetG()
        {
            fixed(int* c = &_color)
            {
                return *((byte*)c + 1);
            }
        }

        public int GetB()
        {
            fixed(int* c = &_color)
            {
                return *(byte*)c;
            }
        }

        public void SetR(byte red)
        {
            fixed (int* c = &_color)
            {
                *((byte*)c + 2) = red;
            }
        }

        public void SetG(byte green)
        {
            fixed (int* c = &_color)
            {
                *((byte*)c + 1) = green;
            }
        }

        public void SetB(byte blue)
        {
            fixed (int* c = &_color)
            {
                *(byte*)c = blue;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Pixel c = new Pixel(0xFFAABB);
            Console.WriteLine("R-{0:X}, G-{1:X}, B-{2:X}", c.GetR(), c.GetG(), c.GetB());
            c.SetR(0x1A);
            c.SetG(0x2B);
            c.SetB(0x3D);
            Console.WriteLine("Color - {0:X}", c.GetColor());
        }
    }
}
于 2013-01-19T09:05:30.520 に答える