Android|Android图片的二值化(黑白处理)

Android图片的二值化(黑白处理)
换了一家新公司,做的是自己的产品,也终于从外包转战到了产品行列。
入职后的第一天做的是一个图片处理的项目,主要是把彩色图片转换成黑白图片,同时读取图片的byte,里面只有-1,0,以方便在LED上边显示.
具体的效果如下图
Android|Android图片的二值化(黑白处理)
文章图片

上边是原图,下边是二值化后的图片
上边的滑动条可以调节二值化的程度,同时上下两个图片都是可以拖动和任意缩放的
二值化的代码

/** * 转为二值图像 * * @param bmp *原图bitmap * @param w *转换后的宽 * @param h *转换后的高 * @return */ public static Bitmap convertToBMW(Bitmap bmp, int w, int h,int tmp) { int width = bmp.getWidth(); // 获取位图的宽 int height = bmp.getHeight(); // 获取位图的高 int[] pixels = new int[width * height]; // 通过位图的大小创建像素点数组 // 设定二值化的域值,默认值为100 //tmp = 180; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int alpha = 0xFF << 24; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int grey = pixels[width * i + j]; // 分离三原色 alpha = ((grey & 0xFF000000) >> 24); int red = ((grey & 0x00FF0000) >> 16); int green = ((grey & 0x0000FF00) >> 8); int blue = (grey & 0x000000FF); if (red > tmp) { red = 255; } else { red = 0; } if (blue > tmp) { blue = 255; } else { blue = 0; } if (green > tmp) { green = 255; } else { green = 0; } pixels[width * i + j] = alpha << 24 | red << 16 | green << 8 | blue; if (pixels[width * i + j] == -1) { pixels[width * i + j] = -1; } else { pixels[width * i + j] = -16777216; } } } // 新建图片 Bitmap newBmp = Bitmap.createBitmap(width, height, Config.ARGB_8888); // 设置图片数据 newBmp.setPixels(pixels, 0, width, 0, 0, width, height); Bitmap resizeBmp = ThumbnailUtils.extractThumbnail(newBmp, w, h); return resizeBmp; }

其中tmp就是二值化的阀值,可以根据拖动进行改变
private OnSeekBarChangeListener seekBarListener=new OnSeekBarChangeListener(){@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub if(bitmap==null){}else{ tmp=(int)(progress*2.55); Bitmap bitmapTmp=bitmap; bitmapTmp = convertToBMW(bitmapTmp, dm.widthPixels, (int)(dm.heightPixels/2.3),tmp); // 显得到bitmap图片 imgShow.setImageBitmap(bitmapTmp); LinearLayout.LayoutParams mParams = new LinearLayout.LayoutParams(dm.widthPixels, (int)(dm.heightPixels/2.3)); mParams.topMargin=10; imgShow.setLayoutParams(mParams); }}@Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub}@Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub}};

其中拖动和缩放效果是copy的,但是已经忘记作者了,还请原作者原谅
import android.content.Context; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.FloatMath; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; public class MyImageView extends ImageView{ Matrix matrix = new Matrix(); Matrix savedMatrix = new Matrix(); /**位图对象*/ private Bitmap bitmap = null; /** 屏幕的分辨率*/ private DisplayMetrics dm; /** 最小缩放比例*/ float minScaleR = 1.0f; /** 最大缩放比例*/ static final float MAX_SCALE = 15f; /** 初始状态*/ static final int NONE = 0; /** 拖动*/ static final int DRAG = 1; /** 缩放*/ static final int ZOOM = 2; /** 当前模式*/ int mode = NONE; /** 存储float类型的x,y值,就是你点下的坐标的X和Y*/ PointF prev = new PointF(); PointF mid = new PointF(); float dist = 1f; public MyImageView(Context context) { super(context); setupView(); }public MyImageView(Context context, AttributeSet attrs) { super(context, attrs); setupView(); }public void setupView(){ Context context = getContext(); //获取屏幕分辨率,需要根据分辨率来使用图片居中 dm = context.getResources().getDisplayMetrics(); //根据MyImageView来获取bitmap对象 BitmapDrawable bd = (BitmapDrawable)this.getDrawable(); if(bd != null){ bitmap = bd.getBitmap(); }//设置ScaleType为ScaleType.MATRIX,这一步很重要 this.setScaleType(ScaleType.MATRIX); this.setImageBitmap(bitmap); //bitmap为空就不调用center函数 if(bitmap != null){ center(true, true); } this.setImageMatrix(matrix); this.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { // 主点按下 case MotionEvent.ACTION_DOWN: savedMatrix.set(matrix); prev.set(event.getX(), event.getY()); mode = DRAG; break; // 副点按下 case MotionEvent.ACTION_POINTER_DOWN: dist = spacing(event); // 如果连续两点距离大于10,则判定为多点模式 if (spacing(event) > 10f) { savedMatrix.set(matrix); midPoint(mid, event); mode = ZOOM; } break; case MotionEvent.ACTION_UP:{ break; } case MotionEvent.ACTION_POINTER_UP: mode = NONE; savedMatrix.set(matrix); break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { matrix.set(savedMatrix); matrix.postTranslate(event.getX() - prev.x, event.getY()- prev.y); } else if (mode == ZOOM) { float newDist = spacing(event); if (newDist > 10f) { matrix.set(savedMatrix); float tScale = newDist / dist; matrix.postScale(tScale, tScale, mid.x, mid.y); } } break; } MyImageView.this.setImageMatrix(matrix); //CheckView(); return true; } }); }/** * 横向、纵向居中 */ protected void center(boolean horizontal, boolean vertical) { Matrix m = new Matrix(); m.set(matrix); RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); m.mapRect(rect); float height = rect.height(); float width = rect.width(); float deltaX = 0, deltaY = 0; if (vertical) { // 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移 int screenHeight = dm.heightPixels; if (height < screenHeight) { deltaY = (screenHeight - height) / 2 - rect.top; } else if (rect.top > 0) { deltaY = -rect.top; } else if (rect.bottom < screenHeight) { deltaY = this.getHeight() - rect.bottom; } }if (horizontal) { int screenWidth = dm.widthPixels; if (width < screenWidth) { deltaX = (screenWidth - width) / 2 - rect.left; } else if (rect.left > 0) { deltaX = -rect.left; } else if (rect.right < screenWidth) { deltaX = screenWidth - rect.right; } } matrix.postTranslate(deltaX, deltaY); }/** * 限制最大最小缩放比例,自动居中 */ private void CheckView() { float p[] = new float[9]; matrix.getValues(p); if (mode == ZOOM) { if (p[0] < minScaleR) { //Log.d("", "当前缩放级别:"+p[0]+",最小缩放级别:"+minScaleR); matrix.setScale(minScaleR, minScaleR); } if (p[0] > MAX_SCALE) { //Log.d("", "当前缩放级别:"+p[0]+",最大缩放级别:"+MAX_SCALE); matrix.set(savedMatrix); } } center(true, true); }/** * 两点的距离 */ private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return FloatMath.sqrt(x * x + y * y); }/** * 两点的中点 */ private void midPoint(PointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); point.set(x / 2, y / 2); } }

这个用法很简单,直接在xml文件中调用就好了

【Android|Android图片的二值化(黑白处理)】最后给出源码好了
下载地址demo
明天将给出文字转图片并且二值化的分析

    推荐阅读