4

ユーザーが画像を描画して保存し、後でリロードして描画を続行できるようにする描画アプリケーションを作成しました。基本的に、描画をビットマップとして JNI レイヤーに渡して保存し、同じように前の描画をロードします。

私はOpenCvを使ってpngファイルに読み書きしています。

画像の透明度の点で奇妙なことに気付きました。OpenCvの黒色に対して透明度が計算されているように見えますか? 添付の画像を見てください。透明な線が含まれています。

int 配列をネイティブ コードに渡すことで透明度を修正します。色変換は必要ありません。 ここに画像の説明を入力

Bitmap オブジェクトをネイティブ コードに渡すことで透明度を暗くしました。色変換が必要です。 ここに画像の説明を入力

何が起こっている可能性がありますか?

ネイティブの Bitmap get pixel メソッドを使用して画像を保存します。

if ((error = AndroidBitmap_getInfo(pEnv, jbitmap, &info)) < 0) {
    LOGE("AndroidBitmap_getInfo() failed! error:%d",error);
}

if (0 == error)
{
    if ((error = AndroidBitmap_lockPixels(pEnv, jbitmap, &pixels)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", error);
    }
}

if (0 == error)
{
    if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888)
    {
        LOGI("ANDROID_BITMAP_FORMAT_RGBA_8888");
    }
    else
    {
        LOGI("ANDROID_BITMAP_FORMAT %d",info.format);
    }

    Mat bgra(info.height, info.width, CV_8UC4, pixels);
    Mat image;

    //bgra.copyTo(image);

    // fix pixel order RGBA -> BGRA
    cvtColor(bgra, image, COLOR_RGBA2BGRA);

    vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(3);

    // save image
    if (!imwrite(filePath, image, compression_params))
    {
        LOGE("saveImage() -> Error saving image!");
        error = -7;
    }

    // release locked pixels
    AndroidBitmap_unlockPixels(pEnv, jbitmap);
}

ネイティブの int ピクセル配列メソッドを使用して画像を保存します。

JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_saveImageRaw
    (JNIEnv *pEnv, jobject obj, jstring jFilePath, jintArray jbgra, jint options, jint compression)
{
    jint*  _bgra = pEnv->GetIntArrayElements(jbgra, 0);
    const char *filePath = pEnv->GetStringUTFChars(jFilePath, 0);

    if (NULL != filePath)
    {
        Mat image;
        Mat bgra(outputHeight, outputWidth, CV_8UC4, (unsigned char *)_bgra);

        bgra.copyTo(image);

        if (0 == options)
        {
            // replace existing cache value
            mpCache->insert(filePath, image);
        }

        vector<int> compression_params;
        compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
        compression_params.push_back(compression);

        // save image
        if (!imwrite(filePath, image))
        {
            LOGE("saveImage() -> Error saving image!");
        }
    }

    pEnv->ReleaseIntArrayElements(jbgra, _bgra, 0);
    pEnv->ReleaseStringUTFChars(jFilePath, filePath);
}

2012 年 5 月 25 日更新:
もう少し調査した結果、ビットマップからピクセルの int 配列を取得し、それを JNI に直接渡すと、現在行っていることとは対照的に、この問題は発生しないことがわかりました。ビットマップ全体を JNI レイヤーに渡し、ピクセルを取得して、ピクセルをcvtColor適切に変換するために使用します。正しいピクセル変換を使用していますか?

4

2 に答える 2

4

RGBA ピクセルでアルファを表現する方法は 2 つあります。前乗算では、R、G、および B の値にアルファのパーセンテージが乗算されます: color = (color * alpha) / 255. これにより、多くのブレンド計算が簡素化され、イメージング ライブラリで内部的に使用されることがよくあります。PNG などの事前に乗算されたアルファを使用しない形式に保存する前に、色の値は「乗算されていない」必要があります: color = (255 * color) / alpha。そうでない場合、色が暗すぎます。透明度が高いほど、色は暗くなります。それはあなたがここで見ている効果のように見えます。

于 2012-05-25T15:30:41.950 に答える
-1

opencvには透過画像と呼ばれるものはありません。フォアグラウンド イメージとバックグラウンド イメージは適切に混合され、透明感を与えます。これをチェックして、その方法を確認してください。

于 2012-05-25T03:04:59.733 に答える