Android Studio自带lldb,安装过程不再赘述。lldb官网https://lldb.llvm.org/use/map.html。
需求
需要获取图片中每一个像素的RGBA值。
代码
Java端代码:
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stringFromJNI(convertImageToBitmap(path));
}
});
public Bitmap convertImageToBitmap(String imagePath) {
BitmapFactory.Options options = new BitmapFactory.Options();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
}
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
return bitmap;
}
native测的代码, 从c++层拿到Java层传递过来的Bitmap。
Java_com_example_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */, jobject bmpObj) {
AndroidBitmapInfo info;
int ret;
if ((ret = AndroidBitmap_getInfo(env, bmpObj, &info)) < 0)
{
return NULL;
}
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
{
return NULL;
}
unsigned char* bitmapPixels;
unsigned char* newBitmapPixels;
//对bitmapPixels的所有操作可直接作用在BitMap上面
if ((ret = AndroidBitmap_lockPixels(env, bmpObj, (void**)&bitmapPixels)) < 0)
{
return NULL;
}
getRGBA(bitmapPixels, info.width, info.height);
AndroidBitmap_unlockPixels(env, bmpObj);
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
bitmapPixels数组的长度是所有像素点个数 * 4。为什么是乘以4,是因为rgba是四个值,这个数组从0开始每隔4个就是一个像素点的r/g/b/a值。所以数组的第0,1,2,3个值分别代表第一个像素点的r,g,b,a的值。从左到右,从上到下。
int getRGBA(unsigned char* ucImageData, int nWidth, int nHeight){
if (ucImageData == NULL || file == NULL) {
return 1;
}
int nChannel = 4;
int nStep = nWidth * nChannel;
for (int y = 0; y < nHeight; y++){
for (int x = 0; x < nWidth; x++)
{
float r = (ucImageData[y * nStep + x * nChannel + 0]);
float g = (ucImageData[y * nStep + x * nChannel + 1]);
float b = (ucImageData[y * nStep + x * nChannel + 2]);
float a = (ucImageData[y * nStep + x * nChannel + 3]);
}
}
return 0;
}
另一种常见的写法:
int getRGBA(unsigned char* ucImageData, int nWidth, int nHeight){
if (ucImageData == NULL || file == NULL) {
return 1;
}
int nChannel = 4;
int nStep = nWidth * nChannel;
for (int y = 0; y < nHeight; y++){
for (int x = 0; x < nWidth; x++)
{
float r = (ucImageData[(y * width + x) * 4 + 0]);
float g = (ucImageData[(y * width + x) * 4 + 1]);
float b = (ucImageData[(y * width + x) * 4 + 2]);
float a = (ucImageData[(y * width + x) * 4 + 3]);
}
}
return 0;
}
lldb命令
查看Disassemble
(lldb) disassemble --name main
(lldb) di -n main
查看寄存器
register read rax rsp rbp
查看局部变量
(lldb) frame variable
(lldb) fr v
查看调用堆栈
(lldb) thread backtrace all
(lldb) bt all
查看内存
(lldb) memory read --size 4 --format x --count 4 0xbffff3c0
(lldb) me r -s4 -fx -c4 0xbffff3c0
(lldb) x -s4 -fx -c4 0xbffff3c0
还有许多其他操作,比如修改值,单步调试等,这个都可以通过Android Studio进行手动操作,不再赘述。
Android Studio的 Evaluate Expression功能
参考
canvas - 使用getImageData()方法获取canvas的每一个像素点的rgba值。以及如何提取该像素点的rgba值。
公众号
更多内容,欢迎关注我的微信公众号:半夏之夜的无情剑客。