我有一个小的 JNI 方法来从屏幕上检索像素。该方法从Java接收一个ByteBuffer,并根据这个问题用C++写入how to write and read from bytebuffer passing from java to jni .
虽然这确实有效,但我注意到我写入的第一个字节不正确,但其他字节是:
Input length is 3 at start 000000000239F238
Color is 202, 97, 79
values read in 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 代码(实际上是 Kotlin):
val r = buffer.get()
val g = buffer.get()
val b = buffer.get()
println("values read in java: $r, $g, $b")
为什么第一个字节错误?我认为这与其标志有关?但话又说回来,为什么其他人就没有错呢?我不确定为什么会发生这种情况。
最佳答案
正如理查德在评论中提到的,它与字节的符号有关。巧合的是,其他两个值都是正确的,因为它们没有超过 127; RGB 是无符号的,范围是 0-255,而有符号字节的范围是 -128 到 127。
缓冲区中的字节是正确的,但 java buffer.get()
读取它时已签名。
解决这个问题的方法是调用 Byte.toUnsignedInt(...) (Java API)与字节读取。
或者,您可以在 Kotlin 中创建扩展方法:
fun Byte.toUnsigned(): Int = this.toInt() and 0xff
然后您可以使用它来调用缓冲区上的 get(),如下所示:
val r = buffer.get().toUnsigned()
val g = buffer.get().toUnsigned()
val b = buffer.get().toUnsigned()
关于java - JNI : Direct buffer reading & writing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44197468/