Android 各种图片转黑白图和抖动算法的黑白图

来源:互联网 发布:桃花源记元神效果数据 编辑:程序博客网 时间:2024/04/30 00:14

最近做的关于打印机打印图片的项目,需要将图片转为打印机能打的点阵位图。我参考了很多文章,但是也没有说的很详细的,其中流浪的鱼的csdn博客写的比较详细,但是,半路出家的Android菜鸟,表示没看太懂,而且那个BufferImage,Android里也没有,又下了个GpuImage处理库,发现效果都不是我想要的,于是,自己看了抖动算法原理,自己写了个。首先,打印机只能通过你传输的数据0或1,来执行打还是不打,打,只能打黑点。所以,传过去的图像像素需要进行判断,到底是打黑点还是不打。

处理方法,先将图片转为灰度图,这个就不说了,方法一大把,你可以自己套用灰度图的算法公式;得到图像的像素数组

int width = img.getWidth();         //获取位图的宽  
int height = img.getHeight();       //获取位图的高  


int[] pixels = new int[width * height]; //通过位图的大小创建像素点数组  


img.getPixels(pixels, 0, width, 0, 0, width, height); 

再套公式:int gray = (int)(0.299 * (double)tr + 0.587 * (double)tg + 0.114 * (double)tb);

Pixels[index] = (ta << 24) | (gray << 16) | (gray << 8) | gray;

当然,Android里有转灰度图的方法,直接调用,就可以得到了;



/***
* 图片去色,返回灰度图片
* @param bmpOriginal 传入的图片
* @return 去色后的图片
*/
public static Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();    


Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}

不用写复杂的算法是不是很爽?!


开始,我用的是二值法来处理,就是用127做临界值,来判断灰度图的灰度是否比他大,大就打白,小就打黑;结果,效果不太理想,如果是文本类的Logo,和颜色分布不密集的,可以选择这样打,但是相片,风景图之类的,我只能说,我要吐了。颜色密集的,就是一片黑,或者一片白。过段不行。

好,用平均值,取所有像素的灰度和,再除以像素个数,得到这个临界值,发现,然并卵。和二值法没有太大区别。

恩嗯,没的选了,只能Floyd-Steinberg算法了。首先,介绍下Floyd-Steinberg算法的原理。它是利用误差的扩散算法的Floyd-Steinberg抖动算法来对图像进行二值化处理。

例如,灰度如的灰度值为g,误差值为e。遍历每个像素值,灰度如果大于m(127,或者像素灰度平均值,看你喜欢),那么pixels【i】=#ffffffff,打白,e=g-255;否则,打黑,pixels【i】=#ff000000,e=g;然后,这个像素点的右边,下边,和右下方的像素点,对应的加上3e/8,3e/8,e/4。最后你的到的像素数组在转成bitmap,就是抖动的单色图了。

public Bitmap convertGreyImgByFloyd(Bitmap img) { 


int width = img.getWidth();         //获取位图的宽  
int height = img.getHeight();       //获取位图的高  


int[] pixels = new int[width * height]; //通过位图的大小创建像素点数组  


img.getPixels(pixels, 0, width, 0, 0, width, height); 
int[] gray=new int[height*width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int grey = pixels[width * i + j]; 
int red = ((grey  & 0x00FF0000 ) >> 16); 
gray[width*i+j]=red;
}
}


int e=0;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int g=gray[width*i+j];
if (g>=128) {
pixels[width*i+j]=0xffffffff;
e=g-255;


}else {
pixels[width*i+j]=0xff000000;
e=g-0;
}
if (j<width-1&&i<height-1) {
//右边像素处理
gray[width*i+j+1]+=3*e/8;
//下
gray[width*(i+1)+j]+=3*e/8;
//右下
gray[width*(i+1)+j+1]+=e/4;
}else if (j==width-1&&i<height-1) {//靠右或靠下边的像素的情况
//下方像素处理
gray[width*(i+1)+j]+=3*e/8;
}else if (j<width-1&&i==height-1) {
//右边像素处理
gray[width*(i)+j+1]+=e/4;
}
}


}


Bitmap mBitmap=Bitmap.createBitmap(width, height, Config.RGB_565);
mBitmap.setPixels(pixels, 0, width, 0, 0, width, height);






return mBitmap; 
}

这个方法,你只需要传入得到的灰度图bitmap对象,就可以返回一个抖动处理过的黑白图。因为自己也才开始做Android开发,博客也是第一次写,平时也主要是看别人的博客在学习。考虑到和我一样的新手,处理这个问题会比较困难,就写了这个。参考的思路主要是鱼神的。我写的,是给新手直接用的。不怎么会,图片不会传。有问题欢迎留言。


3 0
原创粉丝点击