android jni bitmap,在jni函数中使用传入的bitmap

本文详细介绍了如何在Android中将Bitmap转换为OpenCV的Mat类型以进行图像处理。首先,需要获取Bitmap的信息,包括宽度、高度、格式等,然后通过AndroidBitmap_lockPixels函数锁定像素内存地址。一旦获取到像素地址,可以创建Mat对象,操作Mat上的像素会直接影响到原始Bitmap。最后别忘了使用AndroidBitmap_unlockPixels释放锁定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在AS中,有时会要传递bitmap给c++函数,使用opencv等工具进行处理。这时会将bitmap传递给jni函数。bitmap在jni的函数参数中,是jobject类型。下面介绍如何将传入的bitmap转化成opencv常用的mat类型,从而进行处理

首先要包含bitmap的头文件。这个头文件中定义了一些重要信息。了解这些信息非常必要

AndroidBitmapInfo 一个包含bitmap常用信息的结构体

/** Bitmap info, see AndroidBitmap_getInfo(). */typedef struct{

/** The bitmap width in pixels. */uint32_t width;

/** The bitmap height in pixels. */uint32_t height;

/** The number of byte per row. */uint32_t stride;

/** The bitmap pixel format. See {@link AndroidBitmapFormat} */int32_t format;

/** Unused. */uint32_t flags; // 0 for now} AndroidBitmapInfo;

AndroidBitmapFormat 图片格式的枚举类型。格式为图片的像素位数。最常见的是ANDROID_BITMAP_FORMAT_RGBA_8888

/** Bitmap pixel format. */enumAndroidBitmapFormat {

/** No format. */ANDROID_BITMAP_FORMAT_NONE = 0,

/** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/ANDROID_BITMAP_FORMAT_RGBA_8888 = 1,

/** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/ANDROID_BITMAP_FORMAT_RGB_565 = 4,

/** Deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead. **/ANDROID_BITMAP_FORMAT_RGBA_4444 = 7,

/** Alpha: 8 bits. */ANDROID_BITMAP_FORMAT_A_8 = 8,

};

AndroidBitmap_getInfo 获取bitmap信息的函数。返回值为后面的枚举类型。成功读取的返回值为0

/*** Given a java bitmap object, fill out the AndroidBitmapInfo struct for it.* If the call fails, the info parameter will be ignored.*/intAndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,

AndroidBitmapInfo* info);

/** AndroidBitmap functions result code. */enum{

/** Operation was successful. */ANDROID_BITMAP_RESULT_SUCCESS = 0,

/** Bad parameter. */ANDROID_BITMAP_RESULT_BAD_PARAMETER = -1,

/** JNI exception occured. */ANDROID_BITMAP_RESULT_JNI_EXCEPTION = -2,

/** Allocation failed. */ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3,

};

AndroidBitmap_lockPixels 非常关键的一个函数。将bitmap的像素在内存中的地址进行锁定,确保这一块内存不会被移动。传入的addrPtr是一个二级指针,*addPtr是指向bitmap像素地址的指针。该函数正确调用后,一定要在该像素地址指针不再使用后,使用AndroidBitmap_unlockPixels进行释放。

/*** Given a java bitmap object, attempt to lock the pixel address.* Locking will ensure that the memory for the pixels will not move* until the unlockPixels call, and ensure that, if the pixels had been* previously purged, they will have been restored.** If this call succeeds, it must be balanced by a call to* AndroidBitmap_unlockPixels, after which time the address of the pixels should* no longer be used.** If this succeeds, *addrPtr will be set to the pixel address. If the call* fails, addrPtr will be ignored.*/intAndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);

AndroidBitmap_unlockPixels

/*** Call this to balance a successful call to AndroidBitmap_lockPixels.*/intAndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);

了解以上信息之后,就可以探索如何将传入的bitmap转为需要的mat了。通用的做法是先获取bitmap的信息

AndroidBitmapInfo img_info;

CV_Assert(AndroidBitmap_getInfo(env, img, &img_info) >= 0);

CV_Assert(img_info.format == ANDROID_BITMAP_FORMAT_RGBA_8888);

使用CV_Assert确保获取信息成功

然后初始化一个指针,并将该指针的地址传递给AndroidBitmap_lockPixels,若成功则该指针即指向bitmap的像素在内存中的地址

void*ori_img_pxl = NULL;

CV_Assert(AndroidBitmap_lockPixels(env, img, &ori_img_pxl) >= 0);

CV_Assert(ori_img_pxl);

然后就可以将该指针传递给mat的构造函数,创建出我们需要的mat了。

Mat ori_img_mat(img_info.height, img_info.width, CV_8UC4, ori_img_pxl);

需要注意得到的mat的数据指针是指向bitmap的像素内存的,因此mat中对像素的操作会直接反映在bitmap中

AndroidBitmap_unlockPixels(env, img);

最后要记得释放锁定!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值