文件放在xhdpi,xxhdpi,xxxhdpi哪个文件夹下更高效?
大家可以看我上篇文章Bitmap全面解析
理论:首先bitmap会开辟一个原图的内存,如果需要缩放会再开辟内存
放到当前主流的手机屏幕,现在主要是xxhdpi。此时native只会开辟一次内存
如果只放一个文件夹,会不会存在适配的问题?
不会,native层源码中有这行代码
scale = (float) targetDensity / density;
targetDensity是手机的dpi,density是文件夹下的dpi,也就是说,它会根据你放的文件夹进行自动适配,比如xxhdpi的文件夹的图标尺寸是144* 144,你放到xhdpi文件夹(图标尺寸96* 96),当手机适配的时候,它会自动将图片转成144*144的
首先定以两个工具类,用来bitmap和mat之间互转
#include <jni.h>
#include <string>
#include <android/bitmap.h>
#include <malloc.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <android/log.h>
using namespace cv;
#define TAG "JNI_TAG"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
/**
* bitmap转成mat
*/
Mat bitmap2Mat(JNIEnv *env, jobject bitmap) {
// 1. 获取图片的宽高,以及格式信息
AndroidBitmapInfo info;
AndroidBitmap_getInfo(env, bitmap, &info);
void *pixels;
AndroidBitmap_lockPixels(env, bitmap, &pixels);
Mat mat;
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("nMatToBitmap: CV_8UC4 -> RGBA_8888");
mat = Mat(info.height, info.width, CV_8UC4, pixels);
} else {
LOGE("nMatToBitmap: CV_8UC2 -> RGBA_565");
mat = Mat(info.height, info.width, CV_8UC2, pixels);
}
AndroidBitmap_unlockPixels(env, bitmap);
return mat;
}
/**
* mat转成bitmap
*/
void mat2bitmap(JNIEnv *env, Mat src, jobject bitmap) {
// 1. 获取图片的宽高,以及格式信息
AndroidBitmapInfo info;
AndroidBitmap_getInfo(env, bitmap, &info);
void *pixels;
AndroidBitmap_lockPixels(env, bitmap, &pixels);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
Mat tmp(info.height, info.width, CV_8UC4, pixels);
if (src.type() == CV_8UC1) {
LOGE("nMatToBitmap: CV_8UC1 -> RGBA_8888");
cvtColor(src, tmp, COLOR_GRAY2RGBA);
} else if (src.type() == CV_8UC3) {
LOGE("nMatToBitmap: CV_8UC3 -> RGBA_8888");
cvtColor(src, tmp, COLOR_RGB2RGBA);
} else if (src.type() == CV_8UC4) {
LOGE("nMatToBitmap: CV_8UC4 -> RGBA_8888");
src.copyTo(tmp);
}
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
Mat tmp(info.height, info.width, CV_8UC2, pixels);
if (src.type() == CV_8UC1) {
LOGE("nMatToBitmap: CV_8UC1 -> RGB_565");
cvtColor(src, tmp, COLOR_GRAY2BGR565);
} else if (src.type() == CV_8UC3) {
LOGE("nMatToBitmap: CV_8UC3 -> RGB_565");
cvtColor(src, tmp, COLOR_RGB2BGR565);
} else if (src.type() == CV_8UC4) {
LOGE("nMatToBitmap: CV_8UC4 -> RGB_565");
cvtColor(src, tmp, COLOR_RGBA2BGR565);
}
}
AndroidBitmap_unlockPixels(env, bitmap);
}
中值滤波:medianBlur
对所有考虑的点进行排序,取中间的值。主要用来去掉噪声图片
如下面这图上面的黑色点,就是噪声
c.jpg
Mat src = bitmap2Mat(env, bitmap);
Mat dest;
medianBlur(src, dest, 7);
//掩膜
Mat final;
Mat kernel;
kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(dest,final,dest.depth(),kernel);
mat2bitmap(env, final, bitmap);
image.png
双边滤波:bilateralFilter
主要用来图片美容,基于高斯模糊,高斯模糊保留轮廓并不强,双边保留轮廓信息会增强,基于高斯再增加像素差
腐蚀与膨胀
都是数学形态学,和卷积操作类似,用的是任意形状,矩形,椭圆形,最大值,最小值,中值等。主要用于处理黑白图片
erode:腐蚀,最小值
dilate:膨胀,最大值
src = bitmap2Mat(env, bitmap);
//创建一个kernel
Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15));
erode(src, dest, kernel);
/*namedWindow("out_image");
//动态控制
createTrackbar("Trackbar", "out_image", &element_size, max_size,trackbarCallback);*/
mat2bitmap(env, dest, bitmap);
网友评论