在我的应用中,我将Bitmap
数据存储在二维整数数组(int[,]
)中。要访问R,G和B值,我使用以下内容:
// read:
int i = _data[x, y];
byte B = (byte)(i >> 0);
byte G = (byte)(i >> 8);
byte R = (byte)(i >> 16);
// write:
_data[x, y] = BitConverter.ToInt32(new byte[] { B, G, R, 0 }, 0);
我使用整数数组而不是实际的System.Drawing.Bitmap
,因为我的应用程序在Windows Mobile设备上运行,其中可用于创建位图的内存受到严重限制。
public struct RGB
{
public byte R;
public byte G;
public byte B;
}
...然后使用RGB
数组而不是int
数组。这样我就可以轻松读取和写入单独的R,G和B值,而无需进行位移和BitConverter。我依旧记得以前几天关于byte
变量在32位系统上被块对齐的事情,所以byte
实际占用4个字节的内存而不是1个(但也许这只是一个Visual Basic的东西)。
使用结构数组(如上面的RGB
示例)会比使用整数数组更快,并且它会使用3/4内存还是内存的3倍?
答案 0 :(得分:2)
为什么不在Color
中使用System.Drawing
结构?它更容易处理和引用。当然,它有4个字节(另一个值代表Alpha),但是你的第一个实现也是如此,如果我没记错的话,任何3个字节都会与4个字节的块对齐。看一下示例here。
答案 1 :(得分:2)
单独一个字节可能会被块对齐,但结构中的多个字节可以被打包。根据Marshal.SizeOf,你的RGB结构确实只占用了三个字节的内存。 (从技术上讲,这是编组到非托管内存时的大小,CLR可以选择以不同方式进行布局;但实际上我认为这是正确的。)
但是,CLR仍然可以在RGB和其他结构之间插入填充,这种行为可能取决于处理器,CLR版本等。在x86系统上,分配3亿RGB的数组导致任务管理器报告大约900 MB承诺,而分配3亿个整数的阵列导致1200 MB承诺。所以看起来x86上的2.0 CLR可以节省25%的成本。 (我不得不承认这让我感到惊讶;就像Traveling Tech Guy一样,我希望3字节结构与4字节边界对齐。所以我可能会遗漏一些东西。)但CF可能会有所不同:你真的会只有通过在目标平台上测试才能知道。
答案 2 :(得分:2)
如果您正在使用速度,那么技术上我希望int[]
版本更快,因为有一个特定的IL指令来获取来自数组的int
(请参阅OpCodes.Ldelem_I4
)。要做一个自定义结构,它必须获取地址(OpCodes.Ldelema
),然后复制结构(OpCodes.Ldobj
) - 处理这两个步骤的类型元数据。
简而言之 - int
方法应该有更好的优化。但这是微优化 - 在 general 中更喜欢使代码更具可读性的版本。你可能考虑的是用int
中的自定义静态隐式转换运算符编写结构到你的结构 - 然后你可以拥有int[]
并仍然执行:
MyColor col = intArr[12];
(当然,它会在中间进行静态调用)
您也可以考虑使用 union ,这样您就不需要进行大量的转换:
重要我没有理智地检查这个字节顺序;只需更改R / G / B的偏移即可更改它。
class Program
{
static void Main()
{
int[] i = { -1 };
RGB rgb = i[0];
}
}
[StructLayout( LayoutKind.Explicit)]
public struct RGB
{
public RGB(int value) {
this.R = this.G = this.B = 0; this.Value = value;
}
[FieldOffset(0)]
public int Value;
[FieldOffset(2)]
public byte R;
[FieldOffset(1)]
public byte G;
[FieldOffset(0)]
public byte B;
public static implicit operator RGB(int value) {
return new RGB(value);
}
public static implicit operator int(RGB value) {
return value.Value;
}
}
答案 3 :(得分:1)
我认为id取决于你想要达到的目标。 它当然更适用于struct的Readabl,你可以安全地使用它与
unsafe { }
这将真正加快位图访问速度。 (如果你知道该怎么做 - 没有检查边界条件和类似的东西) 并且肯定如果你想为位图乘法,屏蔽,灰度,过滤通常的图形东西制作运算符,那么INT在速度方面是你的朋友,但不幸的是不是在可读性的情况下。 矩阵滤波器只能将所述整数(它可以这样写)而不是RGB值独立地相乘,但是Marks结构不应该是问题。 希望它有所帮助