【问题标题】:Modify a byte of a C# color int or uint修改 C# 颜色 int 或 uint 的一个字节
【发布时间】:2025-12-19 18:10:12
【问题描述】:

我正在使用 C# 中的位图,如您所知,位图通常以 24bpp 或 32bpp 的形式存储在内存中(锁定时)。提取一个像素的int颜色值后,我需要一次读取一个字节来得到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 对象,因为它对于高速图像处理来说太慢了。

【问题讨论】:

  • 没有得到正确的结果..您是否尝试修改位图每个像素的颜色?
  • 为什么不使用 Color.FromArgb()?然后你可以使用 color.R/G/B。
  • @Carra - 你的方法慢得可怜。只需尝试将每个数字颜色值转换为每个像素的 OOP 颜色对象,然后查看图像处理的速度。我需要非常快地处理字节,所以我试图避免使用位移方法。 OOP 是不可能的。
  • @Geotarget。你是对的,它很慢。当我不得不这样做时,我使用了一个名为 FastBitmap 的类,它使用不安全的方法并且速度更快。

标签: c# pointers colors bitmap int


【解决方案1】:

通常我所做的就是按照您所说的创建一个结构:

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);

_bitmapData 是通过LockBits 返回的BitmapData 结构。

编辑:

来自 cmets。这就是你将如何转换它们:

// 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;

未经测试,但应该没问题。

【讨论】:

  • 没有不安全的代码?你正在改变你的要求..你上面已经说过你想要不安全的代码..(在@Hamlet的回答中)。
  • 不,你的代码很好,我的意思是没有像 Scan0 之类的图像指针代码。这让我很困惑,我只需要查看将 int 转换为 Pixel 结构并返回的代码。
  • 已编辑。希望这就是你的意思。
  • 太棒了!非常非常感谢。那么将 int 转换为 Pixel 并返回是免费的吗?我希望它不会像普通的 OOP 对象那样为新的 Pixel 对象分配内存?
  • 您的Pixel 对象将被分配.. 没有办法避免这种情况。虽然它是一个struct,所以它将被分配在堆栈上..
【解决方案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);

您可以根据需要将这个 sn-p 包装在结构中。

这是不安全代码的解决方案,您必须在构建选项中设置允许不安全代码。

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());
        }
    }
}

【讨论】:

  • 为什么不安全?如果您担心性能,我会说按位运算符非常快。为什么要使用不安全的代码?
  • “我说你”按位运算符不如直接字节访问快。只需计算读/写的操作数,然后自己看看。
  • 尝试解决方案并使用按位运算测试性能并告诉我结果。
最近更新 更多