在 Android 上,我使用 JNI 将字符串从 C++ 发送到 Java,然后将其绘制为位图,然后将字节数组返回给 C++ 以将其绘制到 OpenGL,我得到一个黑色矩形。
首先,我通过这种方式在 Java 中创建位图:
public static byte[] DrawString(String text) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.rgb(110, 110, 110));
float scale = ActivityGame.getCurrentActivity().getResources().getDisplayMetrics().density;
paint.setTextSize((int) (24 * scale));
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
Bitmap bitmap = Bitmap.createBitmap((int) (bounds.width() * scale), (int) (bounds.height() * scale), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
int x = (bitmap.getWidth() - bounds.width()) / 6;
int y = (bitmap.getHeight() + bounds.height()) / 5;
canvas.drawText(text, x * scale, y * scale, paint);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
bitmap.recycle();
return byteArray;
}
然后在 C++ 中,我通过这种方式通过 JNI 调用前面的函数:
static unsigned char* DrawString(std::string text,int* length){
JNIEnv *env= nullptr;
JNIUtils::JVM->AttachCurrentThread(&env, NULL);
jclass jniUtilsCls = env->FindClass("com/moussa/mightypolygons/JNIUtils");
jmethodID drawStringMethodId = env->GetStaticMethodID(jniUtilsCls, "DrawString", "(Ljava/lang/String;)[B");
jstring _text=env->NewStringUTF(text.c_str());
jbyteArray bmpArr=(jbyteArray)env->CallStaticObjectMethod(jniUtilsCls,drawStringMethodId,_text);
jsize num_bytes = env->GetArrayLength( bmpArr);
jbyte* elements = env->GetByteArrayElements(bmpArr, NULL);
unsigned char* bmp=new unsigned char[num_bytes];
if (elements) {
for(int i = 0; i < num_bytes; i++) {
bmp[i] = elements[i];
}
*length=(int)num_bytes;
return bmp;
}
return NULL;
}
最后我得到了 char 数组和长度,现在我在 OpenGL 中创建了一个纹理:
Texture::Texture(unsigned char *bmp,int len, TextureTypes type) {
image = stbi_load_from_memory(bmp,len, &width, &height, &nrComponents, 4);
glGenTextures(1, &textureObj);
if (image) {
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
else
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureObj);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
format == GL_RGBA ? GL_CLAMP_TO_EDGE : GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(image);
} else {
stbi_image_free(image);
}
}
我得到一个与位图宽度和高度相同的黑色矩形。
编辑:
我从 Java 端将位图保存为 PNG,然后从 C++ 重新加载它,它使用相同的代码完美呈现,所以问题出在字节数组或 GL 参数或其他方面?
编辑2:
我注意到在 Java 中ByteArray
包含带负值的带符号字节,当它unsigned char*
在 C++ 中被强制转换时,它的值发生了变化,例如,Java 中字节数组中的第一个字节是 -119 如果强制转换为无符号字符则变为 137