我是从一个单色位图阅读位。 我在每16位存储short
按相反的顺序。 如果位图中的位是黑色的,存储1。如果白色,存储0。
例如:位图:BBBW BBBW BBBW WWWW
我的短是:0000 0111 0111 0111
首届办法,我试图做到这一点是:
short m;
// ...
Color c = bmp.GetPixel(j, i);
if (c.R == Color.Black)
m |= short.MinValue;
m >>= 1;
// ...
一个分配和转移后,我得到了预期-32768(1000 0000 0000 0000)。
第2次后,我得到了-16384(1100 0000 0000 0000)。
我改变代码以使用ushort
并改变了if
线s |= (ushort)Math.Pow(2, 15);
现在它的工作原理。
我的问题是:为什么会标志位不.NET转型呢? 有没有办法转移符号位?
在C#,移是算术移位(与逻辑移位)。 在算术右移,符号位移动在左侧,所以数字的符号被保留。 右移位等效于除以2:
如果你想有一个逻辑移位(无符号扩展), 使用无符号数 :
http://msdn.microsoft.com/en-us/library/k2ay192e.aspx
“>>运算符右侧由expression2中指定的比特数移位表达式1的比特。表达式的符号位被用于填充从左边的数字。位数移向右边被丢弃。表达式的数据类型决定数据类型由该操作返回。”
在C#中,右移符号整数填充符号位左侧位。 有效地,权由单个比特移位带符号的整数的结果等效于除以2。
你可以找到这种权利在其他地方移过。 例如,x86的组件提供两个不同的指令, sar
(其填充有符号位左位)和shr
(填充左比特与零)。
如果你不想在C#这种行为,你必须转移时要使用无符号类型。
每http://www.blackwasp.co.uk/CSharpShiftOperators.aspx
...符号整数使用最高位,以确定是否一个变量的值是正还是负,并且剩余位使用二进制补码负值的最高位通常被视为溢出位的左移位操作。 考虑到这一点,C#了解到,此位不应该为签名的数据类型进行调整和负数应相应转变。 从而转移为负值,以及积极的作品。
int value = -240;
int halved = value >> 1; // Result = -120
简短的回答你的问题,因为你发现是使用无符号整数,以避免带来的符号位,而这一切的罚款。 但是也请考虑以下
优化提示
假设你必须做很多这样的转换的(典型地有以位图许多像素),则应该考虑使用的256个字节的阵列,其将直接提供的位模式的反转版本(或任何的转化可定)为一个完整的字节。 然后通过直接索引这个数组,无论是16位字的喜或低字节的值,你会得到所有8位的结果。 在某些情况下,时间/性能处于溢价(和可用空间......),你甚至可以同时使用64K的数组的大小,处理一个完整的单词。
鉴于您的示例中指定的转换,你必须预先计算出的值数组是这样的:
byte[] mirror = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x78, 0xF8,
// etc..
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};