我试图从另一个字节中减去一个字节,同时确保不会发生溢出,但会得到意想不到的结果。
我的情况是我有一个字节黑白图像,我想要减去背景。因此,我需要使用字节并防止溢出发生。当从另一个图像中减去背景图像时,我可能会遇到一些困难。 Data2是背景数组,data1是另一个图像。
在下面的代码中,我希望从data1数组中减去data2数组。但是当我确定应该有高值时,我会得到低值。
for (int i = 0; i < data1.length; i++) {
if (data1[i] > data2[i]) {
dest[i] = (byte) (data1[i] - data2[i]);
} else {
dest[i] = 0;
}
}
我想我应该确保data2字节不是负数并且被添加到data1。 所以我来了:
for (int i = 0; i < data1.length; i++) {
if (data1[i] > data2[i]) {
dest[i] = (byte) ((int)data1[i] & 0xff - (int)data2[i] & 0xff - 128);
} else {
dest[i] = 0;
}
}
然而,这也没有给出正确的结果。
我对此的看法目前是:
(byte) ((int)data1[i] & 0xff - (int)data2[i] & 0xff - 128);
(int) cast: make sure bytes are cast to integer.
&0xff: make value unsigned.
- subtraction smaller value from bigger value.
- 128: subtract 128 to make signed again.
(byte): cast back to byte.
我希望我在这里做一些愚蠢的错事,或者我的问题存在于其他地方,我无法弄清楚在哪里。
修改
我似乎已经找到了问题的一部分: data1 [i]&gt;当字节被签名时,data2 [i]处理错误(在我的情况下)。代替:
if ((data1[i] & 0xff) > (data2[i] & 0xff)) {
似乎产生了正确的结果,而不是之前的比较。
答案 0 :(得分:2)
这里的要点是你的字节来自一个使用8位来编码像素光的API,所以它们的范围是=ArrayFormula(IF(A2:A="",,IF(COUNTIF(B2:B,A2:A)=0,"False","True")))
。但是,Java字节为0; 0xFF
,因此-128; 127
之后的任何位模式都将被解释为负数。例如,如果字节是无符号的,则0x7F
中的位为0xF0
;如果解释为带符号的字节,则128
中的位为-16
:
System.out.println(0xFF > 0); // true
System.out.println((byte) 0xFF > 0); // false
因此,在比较您的无符号字节时,您希望使用int
(或Java 7上的Byte.toUnsignedInt(byteVal)
)将像素提升为((int) byteVal) & 0xFF
。
答案 1 :(得分:2)
始终记住Java字节已签名。如果data1[i]
为127
,data2[i]
为-128
,则data1[i] > data2[i]
,data1[i] - data2[i]
不符合签名byte
;结果是255。
如果将字节视为无符号,那很好。或多或少意味着在使用& 0xFF
之后将它们打印出来,等等。那会很好用;它会给出正确的结果如果你将它们视为无符号。
答案 2 :(得分:0)
要确保只从较大的字节中减去非负字节,您应该使用:
for (int i = 0; i < data1.length; i++) {
if (data1[i] > data2[i] && data2[i]>=0 ) {
dest[i] = (byte) (data1[i] - data2[i]);
} else {
dest[i] = 0;
}
}
你的第二段代码不起作用,因为&amp;运算符将值提升为int类型
考虑data1 = 127(0x7F)和data2 = -128(0x80)的情况
data1 & 0xff
的类型为int,其值为127(0x0000007F)
data2 & 0xff
是int类型,值为128(0x00000080)
data1[i] & 0xff - data2[i] & 0xff
是int类型,值为-1(0xFFFFFFFF)
(byte)(data1[i] & 0xff - data2[i] & 0xff)
是字节类型,值为-1(0xFF)
所以你仍然有溢出
答案 3 :(得分:0)
由于某种原因,奇怪地处理比较字节。如果我在比较中将字节转换为无符号整数,则比较正常,我的结果与我预期的一样。
然后我可以减去这些字节,好像它们是无符号的,就像Louis Wasserman指出的那样,这对我来说是新的。
for (int i = 0; i < data1.length; i++) {
if ((data1[i] & 0xff) > (data2[i] & 0xff)) {
dest[i] = (byte)(data1[i] - data2[i]);
} else {
dest[i] = 0;
}
}