android - 在 JNI 中使用像素数据创建新的位图?

标签 android c++ c android-ndk java-native-interface

我使用以下代码在 JNI 中使用“ARGB_8888”配置创建位图(只是一个黑色/灰色图像)。但是,当我将 Bitmap 的内容转储到 Java 代码中时,我只能看到配置,而看不到 Bitmap 中的像素数据。

JNI代码

// Image Details
int imgWidth = 128;
int imgHeight = 128;
int numPix = imgWidth * imgHeight;

// Creaing Bitmap Config Class
jclass bmpCfgCls = env->FindClass("android/graphics/Bitmap$Config");
jmethodID bmpClsValueOfMid = env->GetStaticMethodID(bmpCfgCls, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
jobject jBmpCfg = env->CallStaticObjectMethod(bmpCfgCls, bmpClsValueOfMid, env->NewStringUTF("ARGB_8888"));

// Creating a Bitmap Class
jclass bmpCls = env->FindClass("android/graphics/Bitmap");
jmethodID createBitmapMid = env->GetStaticMethodID(bmpCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jBmpObj = env->CallStaticObjectMethod(bmpCls, createBitmapMid, imgWidth, imgHeight, jBmpCfg);

// Creating Pixel Data
int triplicateLen = numPix * 4;
char *tripPixData = (char*)malloc(triplicateLen);
for (int lc = 0; lc < triplicateLen; lc++)
{ 
    // Gray / Black Image
    if (0 == (lc%4))
        tripPixData[lc] = 0x7F; // Alpha
    else
        tripPixData[lc] = 0x00; // RGB
}

// Setting Pixels in Bitmap
jByteArr = env->NewByteArray(triplicateLen);
env->SetByteArrayRegion(jByteArr, 0, triplicateLen, (jbyte*)tripPixData);
jmethodID setPixelsMid = env->GetMethodID(bmpCls, "setPixels", "([IIIIIII)V");
env->CallVoidMethod(jBmpObj, setPixelsMid, (jintArray)jByteArr, 0, imgWidth, 0, 0, imgWidth, imgHeight);

free(tripPixData);

// Return BitMap Object
return jBmpObj;

在 JAVA 中(输出)

// Checking the Configuration / Image Details
jBmpObj.getWidth() - 128
jBmpObj.getHeight() - 128
jBmpObj.getRowBytes() - 512
jBmpObj.getConfig() - ARGB 8888

// Getting Pixel Data
imgPixs = new int[jBmpObj.getWidth() * jBmpObj.getHeight()];
jBmpObj.getPixels(imgPixs, 0, jBmpObj.getWidth(), 0, 0, jBmpObj.getWidth(), jBmpObj.getHeight());

// Running a Loop on the imgPixs
imgPixs[<0 - imgPixs.lenght>] - 0 (Every Pixel Data)

我使用相同的概念在 Java 代码中创建了一个位图,它工作正常(即使我能够看到图像)。但我希望逻辑在 JNI 部分而不是在 Java 代码中。所以我尝试了上面的逻辑,但未能设置像素数据。

解决此问题的任何输入都将非常有帮助,..

最佳答案

完整的工作示例:

jclass bitmapConfig = jniEnv->FindClass("android/graphics/Bitmap$Config");
    jfieldID rgba8888FieldID = jniEnv->GetStaticFieldID(bitmapConfig, "ARGB_8888", "Landroid/graphics/Bitmap$Config;");
    jobject rgba8888Obj = jniEnv->GetStaticObjectField(bitmapConfig, rgba8888FieldID);

    jclass bitmapClass = jniEnv->FindClass("android/graphics/Bitmap");
    jmethodID createBitmapMethodID = jniEnv->GetStaticMethodID(bitmapClass,"createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
    jobject bitmapObj = jniEnv->CallStaticObjectMethod(bitmapClass, createBitmapMethodID, _width, _height, rgba8888Obj);

    jintArray pixels = jniEnv->NewIntArray(_width * _height);
    for (int i = 0; i < _width * _height; i++)
    {
        unsigned char red = bitmap[i*4];
        unsigned char green = bitmap[i*4 + 1];
        unsigned char blue = bitmap[i*4 + 2];
        unsigned char alpha = bitmap[i*4 + 3];
        int currentPixel = (alpha << 24) | (red << 16) | (green << 8) | (blue);
        jniEnv->SetIntArrayRegion(pixels, i, 1, &currentPixel);
    }

    jmethodID setPixelsMid = jniEnv->GetMethodID(bitmapClass, "setPixels", "([IIIIIII)V");
    jniEnv->CallVoidMethod(bitmapObj, setPixelsMid, pixels, 0, _width, 0, 0, _width, _height);

其中 bitmap 是 unsigned char*。

关于android - 在 JNI 中使用像素数据创建新的位图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14010508/

相关文章:

c++ - 如何在 C++ (Linux) 中获得 CPU 时钟速度?

安卓绘图

python - 用 Boost Python 包装 C++ 函数——numpy 数组类型

android - 为 arm64 Android 手机构建应用程序包时,在 ApplicationInfo.nativeLibraryDir 中找不到 native 库

c++ - 如何在返回语句中对 "implicit"右值进行类型转换

c++ - VS 2008 中 C++/MFC 编译器的奇怪结果

c - SIP用户代理与SIP服务器连接的信息(Opensip)

c - 嵌入 python/cython numpy 数组 : Passing numpy array to c pointer

java - Android Studio Gradle 预构建步骤

android - webview loadurl 无法从本地主机 Web 应用程序加载网页?