Отображать IplImage как растровое изображение Android - PullRequest
1 голос
/ 22 марта 2012

Я работаю над приложением Facedetect для Android, которое использует библиотеку OpenCV 2.3.1.Я нашел код, который позволяет мне сделать фотографию на моем Samsung GT-P1000 и сохранить ее в галерее.Затем я хочу выбрать изображение из галереи, которая позволяет файлу .cpp использовать функции OpenCV.Это требует преобразования растрового изображения в IplImage (фрагменты кода .java и .cpp добавляются ниже).

Код Java выглядит следующим образом:

Bitmap bitmap = BitmapFactory.decodeFile(mCurrentImagePath);
Log.i(TAG, mCurrentImagePath);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
opencv.setSourceImage(pixels, width, height);
byte[] imageData = opencv.getSourceImage();
bitmap = BitmapFactory.decodeByteArray(imageData, 0,
imageData.length);
mImageView.setImageBitmap(bitmap);

Код C ++ выглядит следующим образом:

IplImage * pImage = NULL;
IplImage * loadpixels(int * pixels, int width, int height);
IplImage * getIplImageFromIntArray
    (JNIEnv* env, jintArray array_data, jint width, jint height);

JNIEXPORT jboolean JNICALL Java_org_opencv_example_pruts_Test1OpenCV_setSourceImage
    (JNIEnv * env, jobject thiz, jintArray photo_data, jint width, jint height)
{
    if(pImage != NULL)
    {
        cvReleaseImage(&pImage);
        pImage = NULL;
    }

    pImage = getIplImageFromIntArray(env, photo_data, width, height);
    if(pImage == 0)
    {
        return 0;
    }

    return 1;
}

Однако мне нужна еще одна функция JNIEXPORT, которая преобразует IplImage в растровые данные.Для этого будут использованы последние 4 строки кода.imageData должен быть заполнен, чтобы BitmapFactory мог его декодировать.Я натолкнулся на множество примеров, и эти фрагменты кода тоже взяты из них.Однако я не могу найти решение для моей проблемы.У кого-нибудь есть предложения?

1 Ответ

4 голосов
/ 22 марта 2012

Кажется, вы собираетесь использовать сжатый формат, и это возможно, но сложно.здесь я даю решение с использованием несжатых данных.Поскольку растровое изображение в Android в основном имеет формат rgba, поэтому вы можете создавать растровые изображения, используя данные IplImage напрямую, за исключением проблемы выравнивания байтов.

JNIEXPORT jintArray JNICALL Java_org_opencv_example_pruts_Test1OpenCV_getSourceImage
    (JNIEnv * env, jobject thiz){    
    if(pImage == 0)
    {
        return NULL;
    }

    int len = pImage->width * pImage->height * 4;
    jintArray rgbaData = env->NewIntArray(len);
    if(pImage->nChannels == 4){
        env->SetIntArrayRegion(rgbaData,0,len,(jint*)pImage->imageData);
    }else if(pImage->nChannels == 3){
        IplImage* t = cvCreateImage(cvGetSize(pImage),8,4);
        for(int h = 0; h< pImage->height; h++){
            char* pt= t->imageData + h * t->widthStep;
            char* pImg = pImage->imageData+ h * pImage->widthStep;
            for(int w =0 ; w < pImage->width; w++){
                memcpy(pt,pImg,3);
                pt[3] = 255;//alpha 
                pt+=4;
                pImg += 3;
            }
        }
        env->SetIntArrayRegion(rgbaData,0,len,(jint*)t->imageData);
        cvReleaseImage(&t);
    }else {
        // if pImage -> nChannels == 1 , handle it in the way you prefer 
        // I donot think your image is gray ,so forget about this situation
    }

    cvReleaseImage(&pImage);
    return rgbaData;
}

И код Java должен быть таким:

int[] imageData = opencv.getSourceImage();
bitmap = Bitmap.createBitmap(imageData, 0, width,width, height, Config.ARGB_8888);
...