2

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:

ByteArrayJava では、値が変更された C++ にキャストされたときに負の値を持つ符号付きバイトが含まれていることに気付きましたunsigned char*。たとえば、Java のバイト配列の最初のバイトは -119 であり、unsigned char にキャストすると 137 になります。

4

1 に答える 1

0

別の方法を使用して、Bitmap オブジェクトを Java からそのまま送信し、次を使用してそのピクセルを読み取りました。android/bitmap.h

AndroidBitmapInfo androidBitmapInfo ;
void* pixels;
AndroidBitmap_getInfo(env, bitmap, &androidBitmapInfo);
AndroidBitmap_lockPixels(env, bitmap, &pixels);
unsigned char* pixelsChar = (unsigned char*) pixels;
AndroidBitmap_unlockPixels(env, bitmap);

今はうまくいきます。

于 2019-09-19T03:54:39.797 に答える