2012-05-23 4 views
4

Я тестирую производительность для управления растровыми пикселями на уровне JNI с использованием OpenCv.NDK Обработка растровых изображений с использованием цвета OpenCv оранжевого цвета?

два варианта:
1. Проход массив целых чисел, манипулировать пикселей и записывать пиксели обратно в Bitmap. [41ms]
2. Пропустите весь растровый рисунок. [35ms]

Я заметил, что это примерно на 5 мс быстрее, чтобы передать битмап, чем передать массив пикселей и назначить массив битмапу.

Проблема в том, что с использованием опции 2 я теряю синий цвет и получаю оранжевый цвет вместо синего, которого я ожидаю. Изображение - ARGB, и похоже, что он изменен на RGBA? В чем может быть проблема?

Метод 1:
Java

Bitmap out = Bitmap.createBitmap(width, height, Config.ARGB_8888); 

int[] rgba = new int[width*height]; 

mSmasher.loadImage(imagePath, rgba, 0); 

out.setPixels(rgba, 0, width, 0, 0, width, height); 

JNI

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

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

       // bgra image manipulations 
    } 

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

Способ 2:

JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_getLayersBitmap 
    (JNIEnv *pEnv, jobject obj, jobject bitmap) 
{ 
    int ret; 
    AndroidBitmapInfo info; 
    void*    pixels = 0; 

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

    if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) 
    { 
     LOGE("Bitmap format is not RGBA_8888!"); 
     return; 
    } 

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

    // init our output image 
    Mat mbgra(info.height, info.width, CV_8UC4, pixels); 

    mLayers[0].copyTo(mbgra); 

    AndroidBitmap_unlockPixels(pEnv, bitmap); 
} 

Решение 05/23:
Проблема заключалась в том, что при использовании массива целых чисел и передачи его в JNI порядок байт изменен с ARGB (Java), чтобы BGRA (родной). Это было прекрасно для работы с пикселями. Однако, передавая фактический объект Bitmap при блокировке пикселей, порядок байтов не изменялся, поэтому ему необходимо было изменить его после изменения данных пикселя.

cvtColor(mbgra, mbgra, COLOR_BGR2RGBA, 4); 
+0

Я заинтересован в ваших тестах скорости. Не могли бы вы обобщить оба метода, я не понимаю, что подразумевается в первом. –

+0

Добавлено несколько деталей ... Надеюсь, что это имеет смысл :) – Jona

ответ

2

Opencv заказ BGR не RGB. Я собираюсь угадать, что A находится в нужном месте (или вы будете видеть полупрозрачное изображение), но синий и красный будут меняться.

+0

Любые идеи, как их поменять? – Jona

+0

Я вспоминаю в clrConvert (sp?), Есть BGR2RGB. Существует также mixchannels (опять же, sp? Far from my opencv2refman.pdf прямо сейчас). –

+1

Ах! Вот решение. cvtColor (mbgra, mbgra, COLOR_BGR2RGBA, 4); – Jona

1

В значении цвета JNI возвращается как ARGB в то время как в JAVA это RGBA попробовать это

alpha = (int) ((color & 0xFF000000) >> 24); 
    blue = (int) ((color & 0xFF0000) >> 16); 
    green = (int)((color & 0x00FF00) >> 8); 
    red = (int) (color & 0x0000FF); 
    blue = blue * alpha/255; 
    green = green * alpha/255; 
    red = red * alpha/255; 

    int tmp = 0; 
    tmp = red; 
    red = blue; 
    blue = tmp; 

    color = ((alpha<< 24) & 0xFF000000) | ((blue<< 16) & 0xFF0000) | 
        ((green << 8) & 0x00FF00) | 
        (red & 0x0000FF); 
Смежные вопросы