图片二值化

新一版的需求中,加入了图片二值化的处理,踩过坑,受过累,做一个标记,积累积累。。。



一、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库

CmakeList打包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'


其他的配置,就按照 CmakeList设置实现就可以。

三、细节实现注意点

1,adapter细节优化

 Log.e("getView", "getView    gridview  position=" + position + "parent child count=" + parent.getChildCount());


通过日志的方式,可以确定第一个view重复了很多次。使用以下优化方案。

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);


这是二值化的效果。






只要你能健康的成长,正直的做人,独立的思考,幸福的生活,这是父辈对你的最高期望。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

壹叁零壹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值