fixing bug #1987(android keeps RGBA in alpha pre-multiplied form, Mat <-> Bitmap should handle this correctly)

This commit is contained in:
Andrey Pavlenko
2012-06-29 15:38:10 +00:00
parent 2b6b6f12e2
commit a72f4474b4
7 changed files with 203 additions and 45 deletions

View File

@@ -21,14 +21,14 @@ extern "C" {
/*
* Class: org_opencv_android_Utils
* Method: void nBitmapToMat(Bitmap b, long m_addr)
* Method: void nBitmapToMat(Bitmap b, long m_addr, boolean unPremultiplyAlpha)
*/
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr);
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha);
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr)
(JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha)
{
AndroidBitmapInfo info;
void* pixels = 0;
@@ -46,7 +46,8 @@ JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
{
LOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4");
Mat tmp(info.height, info.width, CV_8UC4, pixels);
tmp.copyTo(dst);
if(needUnPremultiplyAlpha) cvtColor(tmp, dst, COLOR_mRGBA2RGBA);
else tmp.copyTo(dst);
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
LOGD("nBitmapToMat: RGB_565 -> CV_8UC4");
@@ -73,54 +74,55 @@ JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
/*
* Class: org_opencv_android_Utils
* Method: void nMatToBitmap(long m_addr, Bitmap b)
* Method: void nMatToBitmap(long m_addr, Bitmap b, boolean premultiplyAlpha)
*/
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap);
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha);
JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap)
(JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha)
{
AndroidBitmapInfo info;
void* pixels = 0;
Mat& dst = *((Mat*)m_addr);
Mat& src = *((Mat*)m_addr);
try {
LOGD("nMatToBitmap");
CV_Assert( AndroidBitmap_getInfo(env, bitmap, &info) >= 0 );
CV_Assert( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565 );
CV_Assert( dst.dims == 2 && info.height == (uint32_t)dst.rows && info.width == (uint32_t)dst.cols );
CV_Assert( dst.type() == CV_8UC1 || dst.type() == CV_8UC3 || dst.type() == CV_8UC4 );
CV_Assert( src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols );
CV_Assert( src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4 );
CV_Assert( AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 );
CV_Assert( pixels );
if( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 )
{
Mat tmp(info.height, info.width, CV_8UC4, pixels);
if(dst.type() == CV_8UC1)
if(src.type() == CV_8UC1)
{
LOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888");
cvtColor(dst, tmp, CV_GRAY2RGBA);
} else if(dst.type() == CV_8UC3){
cvtColor(src, tmp, CV_GRAY2RGBA);
} else if(src.type() == CV_8UC3){
LOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888");
cvtColor(dst, tmp, CV_RGB2RGBA);
} else if(dst.type() == CV_8UC4){
cvtColor(src, tmp, CV_RGB2RGBA);
} else if(src.type() == CV_8UC4){
LOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888");
dst.copyTo(tmp);
if(needPremultiplyAlpha) cvtColor(src, tmp, COLOR_RGBA2mRGBA);
else src.copyTo(tmp);
}
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
Mat tmp(info.height, info.width, CV_8UC2, pixels);
if(dst.type() == CV_8UC1)
if(src.type() == CV_8UC1)
{
LOGD("nMatToBitmap: CV_8UC1 -> RGB_565");
cvtColor(dst, tmp, CV_GRAY2BGR565);
} else if(dst.type() == CV_8UC3){
cvtColor(src, tmp, CV_GRAY2BGR565);
} else if(src.type() == CV_8UC3){
LOGD("nMatToBitmap: CV_8UC3 -> RGB_565");
cvtColor(dst, tmp, CV_RGB2BGR565);
} else if(dst.type() == CV_8UC4){
cvtColor(src, tmp, CV_RGB2BGR565);
} else if(src.type() == CV_8UC4){
LOGD("nMatToBitmap: CV_8UC4 -> RGB_565");
cvtColor(dst, tmp, CV_RGBA2BGR565);
cvtColor(src, tmp, CV_RGBA2BGR565);
}
}
AndroidBitmap_unlockPixels(env, bitmap);

View File

@@ -81,19 +81,28 @@ public class Utils {
* <br>The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type,
* it keeps the image in RGBA format.
* <br>The function throws an exception if the conversion fails.
*
* @param b is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
* @param m is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat.
* @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
* @param mat is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat.
* @param unPremultiplyAlpha is a flag if the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one. The flag is ignored for 'RGB_565' bitmaps.
*/
public static void bitmapToMat(Bitmap b, Mat m) {
if (b == null)
throw new java.lang.IllegalArgumentException("Bitmap b == null");
if (m == null)
throw new java.lang.IllegalArgumentException("Mat m == null");
nBitmapToMat(b, m.nativeObj);
public static void bitmapToMat(Bitmap bmp, Mat mat, boolean unPremultiplyAlpha) {
if (bmp == null)
throw new java.lang.IllegalArgumentException("bmp == null");
if (mat == null)
throw new java.lang.IllegalArgumentException("mat == null");
nBitmapToMat(bmp, mat.nativeObj, unPremultiplyAlpha);
}
/**
* Shortened form of the bitmapToMat(bmp, mat, unPremultiplyAlpha=false)
* @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'.
* @param mat is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat.
*/
public static void bitmapToMat(Bitmap bmp, Mat mat) {
bitmapToMat(bmp, mat, false);
}
/**
* Converts OpenCV Mat to Android Bitmap.
* <p>
@@ -102,18 +111,34 @@ public class Utils {
* <br>The output Bitmap object has to be of the same size as the input Mat and of the types 'ARGB_8888' or 'RGB_565'.
* <br>The function throws an exception if the conversion fails.
*
* @param m is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
* @param b is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'.
* @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
* @param bmp is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'.
* @param premultiplyAlpha is a flag if the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps). The flag is ignored for 'RGB_565' bitmaps.
*/
public static void matToBitmap(Mat m, Bitmap b) {
if (m == null)
throw new java.lang.IllegalArgumentException("Mat m == null");
if (b == null)
throw new java.lang.IllegalArgumentException("Bitmap b == null");
nMatToBitmap(m.nativeObj, b);
public static void matToBitmap(Mat mat, Bitmap bmp, boolean premultiplyAlpha) {
if (mat == null)
throw new java.lang.IllegalArgumentException("mat == null");
if (bmp == null)
throw new java.lang.IllegalArgumentException("bmp == null");
nMatToBitmap(mat.nativeObj, bmp, premultiplyAlpha);
}
private static native void nBitmapToMat(Bitmap b, long m_addr);
/**
* Shortened form of the <b>matToBitmap(mat, bmp, premultiplyAlpha=false)</b>
* @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'.
* @param bmp is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'.
*/
public static void matToBitmap(Mat mat, Bitmap bmp) {
matToBitmap(mat, bmp, false);
}
// native stuff
static {
System.loadLibrary("opencv_java");
}
private static native void nMatToBitmap(long m_addr, Bitmap b);
private static native void nBitmapToMat(Bitmap b, long m_addr, boolean unPremultiplyAlpha);
private static native void nMatToBitmap(long m_addr, Bitmap b, boolean premultiplyAlpha);
}