本机位图处理和ALPHA_8

时间:2011-10-01 22:30:37

标签: android android-ndk

我正在尝试通过本机功能将图像转换为灰度,使用从 Android in Action 中获取的代码(第2版;您也可以看到它here )。不幸的是,返回的位图对象(而不是灰度)最终为空。

这是我加载(.png)图片的方式:

Bitmap original = BitmapFactory.decodeResource(this.getResources(), R.drawable.sample, options);

位图通过了许多安全条件(请在下面查看)。这是Java中的本机函数定义:

public native void convertToGray(Bitmap bitmapIn,Bitmap bitmapOut);

和电话:

// Grayscale bitmap (initially empty)     
Bitmap gray = Bitmap.createBitmap(original.getWidth(),original.getHeight(),Config.ALPHA_8);
// Native function call
convertToGray(original,gray);

这是功能:

JNIEXPORT void JNICALL Java_com_example_Preprocessor_convertToGray(JNIEnv * env, jobject  obj, jobject bitmapcolor,jobject bitmapgray)
{
    AndroidBitmapInfo infocolor;
    AndroidBitmapInfo infogray; 
    void* pixelscolor;
    void* pixelsgray;
    int ret;
    int y;
    int x;    

    LOGI("convertToGray");
    if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }    

    if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infogray)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    LOGI("color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infocolor.width,infocolor.height,infocolor.stride,infocolor.format,infocolor.flags);
    if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("Bitmap format is not RGBA_8888 !");
        return;
    }  

    LOGI("gray image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infogray.width,infogray.height,infogray.stride,infogray.format,infogray.flags);
    if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
        LOGE("Bitmap format is not A_8 !");
        return;
    }   

    if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, &pixelscolor)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsgray)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    // modify pixels with image processing algorithm
    for (y=0;y<infocolor.height;y++) {
        argb * line = (argb *) pixelscolor;
        uint8_t * grayline = (uint8_t *) pixelsgray;
        for (x=0;x<infocolor.width;x++) {
            grayline[x] = 0.3 * line[x].red + 0.59 * line[x].green + 0.11*line[x].blue;
        }

        pixelscolor = (char *)pixelscolor + infocolor.stride;
        pixelsgray = (char *) pixelsgray + infogray.stride;
    }

    LOGI("Done! Unlocking pixels...");
    AndroidBitmap_unlockPixels(env, bitmapcolor);
    AndroidBitmap_unlockPixels(env, bitmapgray);
}

颜色位图正确传递,代码的处理部分似乎工作正常,但 bitmapgray 保持为空。我想我错过了一些至关重要的东西。

测试环境:模拟器,v2.2。使用此版本,该功能在从主线程调用本机代码时有效。在2.3仿真器上,无论调用C代码的线程,还是加载位图的方式,该函数都不起作用。 Android NDK:4b&amp;图6b。

  

更新#1:您会找到完整的源代码here

     

UPDATE#2: RGB_565而不是ALPHA_8会产生一些结果。似乎Java中的setPixels()不适用于ALPHA_8,而我正在使用它   在此配置类型上查找信息的问题。任何形式的帮助都会   非常感谢。

3 个答案:

答案 0 :(得分:1)

我有类似的问题。 首先,我使用android RGBA_8888格式代替A_8(原始位图是使用ARGB_8888格式创建的)。 然后,如果你使用argb struct for grayline而不是uint_8,你可以像这样填充像素:

for (y = 0; y < infocolor.height; ++y) {
       argb* line = (argb*) pixelscolor;
       argb* grayline = (argb*) pixelsgray;
       for (x = 0; x < infocolor.width; ++x) {         
          grayline[x].red = grayline[x].green = grayline[x].blue = 0.3 * line[x].red + 0.59 * line[x].green + 0.11 * line[x].blue;
       }
       pixelscolor = (char*)pixelscolor + infocolor.stride;
       pixelsgray = (char*)pixelsgray + infogray.stride;
   }

答案 1 :(得分:1)

我有同样的问题。 我没有尝试使ALPHA_8工作,但使用ARGB_8888解决了这个问题。

是的,回复@ white_pawn的评论(对不起,我无法回复评论)

IBM's示例中的argb结构的顺序错误。在我的模拟器或手机中, 将其转换为RGBA可以解决问题(这可能是您的图像看起来是蓝色的原因,因为您使用alpa作为蓝色)。虽然我不确定这个顺序是否依赖于硬件。

typedef struct
{
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
} argb;

答案 2 :(得分:0)

我有同样的问题,发现出了什么问题!当您使用APHA_8时,您需要将背景更改为 #ffffffff

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff">