2017-05-26 102 views
2

我有一个小的JNI方法从屏幕上检索一个像素。该方法接收来自Java的ByteBuffer并根据此问题how to write and read from bytebuffer passing from java to jni以C++写入。JNI:直接缓冲读写

虽然这工作,我注意到的第一个字节我写的是不正确的,但其他人:

输入长度为3在启动000000000239F238

颜色为202,97,79

值在Java读:-54,97%,79

这是我的节目的输出。

的C++代码:

JNIEXPORT void JNICALL Java_capturePixel(JNIEnv * env, jobject clz, jobject buffer) 
{ 
    jbyte* bufferStart = static_cast<jbyte*>(env->GetDirectBufferAddress(buffer)); 
    jlong inputLength = env->GetDirectBufferCapacity(buffer); 


    HDC hScreenDC = GetDC(nullptr); 

    std::cout << "Input length is " << inputLength << " at start " << &bufferStart << std::endl; 

    COLORREF pixel = GetPixel(hScreenDC, 100, 20); 

    int r = GetRValue(pixel); 
    int g = GetGValue(pixel); 
    int b = GetBValue(pixel); 

    std::cout << "Color is " << r << ", " << g << ", " << b << std::endl; 

    bufferStart[0] = r; 
    bufferStart[1] = g; 
    bufferStart[2] = b; 
} 

我的Java代码(实际上科特林):

val r = buffer.get() 
val g = buffer.get() 
val b = buffer.get() 
println("values read in java: $r, $g, $b") 

为什么是第一个字节错了吗?我假设它必须处理它的标志?但是,为什么其他人没有错?我不知道为什么会发生这种情况。

+0

2S补202 == -54。 Java正在输出签名值。 –

+0

@RichardCritten你能解释为什么只发生在第一个字节? – Limnic

+1

其他值不会设置它们设置的字节的最高位。值<= 127将输出为正,值> = 128将输出为负值。数组中的值是正确的,它只是它的输出,让你感到困惑。 –

回答

2

正如理查德在提到的评论中所说的那样,它与字节的符号有关。这两个值是正确的,这是巧合,因为它们不会超过127; RGB是无符号的,范围从0-255,而有符号字节的范围是从-128到127.

缓冲区中的字节是正确的,但java buffer.get()读取的是已签名的。

解决此问题的方法是调用Byte.toUnsignedInt(...)(Java API)并读取字节。

或者,你可以创建科特林扩展方法:

fun Byte.toUnsigned(): Int = this.toInt() and 0xff 

然后你就可以用它来呼吁缓冲这样的get():

val r = buffer.get().toUnsigned() 
val g = buffer.get().toUnsigned() 
val b = buffer.get().toUnsigned()