2011-10-01 68 views
6

我試圖通過本機功能,使用從安卓在行動(第二版;你也可以看到它here)採取一段代碼轉換爲灰度圖像。不幸的是,返回的位圖對象,而不是灰度,最終是空的。本機位圖處理和ALPHA_8

這是我如何加載文件(.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保持空。我想我錯過了一些關鍵的東西。

測試環境:emulator,v2.2。使用此版本時,當從主線程調用本機代碼時,此功能可用。在2.3仿真器上,無論調用C代碼的線程或加載位圖的方式如何,函數都不起作用。 Android NDK:4b & 6b。

更新#1:你會找到完整的源代碼here

UPDATE#2: RGB_565代替ALPHA_8給出了一些結果。它似乎甚至沒有Java中的setPixels()適用於ALPHA_8,並且我有 問題查找有關此配置類型的信息。任何形式的幫助將是 非常讚賞。

+0

你有沒有考慮嘗試使用字節緩衝區作爲輸出?如果這有效,那麼我們可以更確定AndroidBitmap有什麼問題......還有'bitmapIn','bitmapOrig'和'original'是同一個對象嗎? –

+0

我對JNI完全陌生,所以不,我沒有嘗試過。我會試一試,然後回報。我仍然會感激一些提示或方向,可以加快這個過程。並且,是的,bitmapIn = bitmapOrig = original(對於後兩者抱歉;我應該更清楚一點;修復它)。 –

+0

@SamuelAudet:好的,我試過[這一個](http://imrannazar.com/Augmented-Reality-with-the-Android-NDK:-Part-2)。結果是*幾乎*空白位圖(具有黑色僞像的白色表面(隨機黑色點))。其他人是否會善意給這個鏡頭? –

回答

1

我有類似的問題。 首先,我使用android RGBA_8888格式進行信息而不是A_8(原始位圖是使用ARGB_8888格式創建的)。 然後,如果你使用的argb結構爲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; 
    } 
+0

嗯,它確實給出了一些結果,但輸出圖像是藍色的。我希望能夠使用A_8來保存一些內存(我想嘗試一些實時圖像處理)。 –

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; 
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">