Java中字节之间的减法/差异

时间:2015-08-31 21:04:05

标签: java byte

我试图从另一个字节中减去一个字节,同时确保不会发生溢出,但会得到意想不到的结果。

我的情况是我有一个字节黑白图像,我想要减去背景。因此,我需要使用字节并防止溢出发生。当从另一个图像中减去背景图像时,我可能会遇到一些困难。 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)) {

似乎产生了正确的结果,而不是之前的比较。

4 个答案:

答案 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]127data2[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;
        }
    }