新一版的需求中,加入了图片二值化的处理,踩过坑,受过累,做一个标记,积累积累。。。
一、Android实现
/**
* 该函数实现对图像进行二值化处理
*/
public static Bitmap gray2Binary(Bitmap graymap) {
//得到图形的宽度和长度
int width = graymap.getWidth();
int height = graymap.getHeight();
//创建二值化图像
Bitmap binarymap = null;
binarymap = graymap.copy(Config.ARGB_8888, true);
//依次循环,对图像的像素进行处理
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//得到当前像素的值
int col = binarymap.getPixel(i, j);
//得到alpha通道的值
int alpha = col & 0xFF000000;
//得到图像的像素RGB的值
int red = (col & 0x00FF0000) >> 16;
int green = (col & 0x0000FF00) >> 8;
int blue = (col & 0x000000FF);
// 用公式X = 0.3×R+0.59×G+0.11×B计算出X代替原来的RGB
int gray = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
//对图像进行二值化处理
if (gray <= 95) {//固定阈值
gray = 0;
} else {
gray = 255;
}
// 新的ARGB
int newColor = alpha | (gray << 16) | (gray << 8) | gray;
//设置新图像的当前像素值
binarymap.setPixel(i, j, newColor);
}
}
return binarymap;
}
以Bitmap形式传入数据,能够实现二值化,输出黑白图片。
当前处理方式,设置固定阈值,会存在数据丢失情形。且使用Android自己的内存运算,运算速度较慢。
二、C实现【编译so库】
1,C代码实现二值化
在C中比较好处理,且内存运算占用较低,使用指针的方式。还可以将图片的归一化,旋转等一些基础的处理都添加到代码中。
2,c代码打包so库
嗯嗯,这是C打包so库源码。
以下描述以下曾遇见的坑:
(1)不能编译出来so库
不能编译出来so库问题主要在两个方面,一是c代码存在bug或者内存泄漏,或者使用数据类型,Android编译平台不支持。
(2)编译出来的so库不能适配全平台
编译不能适配全平台,主要在与配置环境参数的设置。
CmakeList设置C11
cppFlags "-std=c++11" //, "-fuse-ld=bfd"
因为C代码中使用libpng版本比较老,在文章使用中,不能设置C11版本。
cFlags '-std=c99', '-DPNG_ARM_NEON_OPT=0'
三、细节实现注意点
1,adapter细节优化
Log.e("getView", "getView gridview position=" + position + "parent child count=" + parent.getChildCount());
if (parent.getChildCount() == position || mViewItem0 == null) {
if (mViewItem0 != null && position == 0) {
return mViewItem0;
}
//原始代码实现方式实现
if (position == 0) {
mViewItem0 = convertView;
}
} else {
convertView = mViewItem0;
}
2,设置笔形方法优化
public static HashMap<String, Typeface> mTypeface = new HashMap<>();//避免多次读取ttf加载,Typeface占空间很小
if (ttfURL != null && !("".equalsIgnoreCase(ttfURL))) {
if (mTypeface.get(ttfURL) == null) {
File file = new File(ttfURL);
if (file.exists() && file.length() > 0) {
mTypeface.put(ttfURL, Typeface.createFromFile(ttfURL));//文件存在是否需要判断
} else {
mTypeface.put("default", Typeface.createFromAsset(context.getAssets(), "FZKTJW.TTF"));
}
}
setTypeface(mTypeface.get(ttfURL));
} else {
if (mTypeface.get("default") == null) {
mTypeface.put("default", Typeface.createFromAsset(context.getAssets(), "FZKTJW.TTF"));
}
setTypeface(mTypeface.get("default"));
}
3,onpageSelected(),设置adapter
(1)在ViewPager的onPageSelected()中不需要setCurrentItem(),当前已经是选中了,且不用notify。会消耗性能,导致运行缓慢。
(2)adapter默认会加载前后两页数据,设置前后深度切换效果后,也需要将前后两页数据加载出来。
singlePagePreVP.setPageTransformer(true, new DepthPageTransformer());
在新设置数据后,需要已缓存的三页数据刷新时,使用notify()是不成功的。
直接设置adapter就可以,setAdapter(adapter);
这是二值化的效果。