最近做的关于打印机打印图片的项目,需要将图片转为打印机能打的点阵位图。我参考了很多文章,但是也没有说的很详细的,其中流浪的鱼的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//右边像素处理
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//下方像素处理
gray[width*(i+1)+j]+=3*e/8;
}else if (j//右边像素处理
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开发,博客也是第一次写,平时也主要是看别人的博客在学习。考虑到和我一样的新手,处理这个问题会比较困难,就写了这个。参考的思路主要是鱼神的。我写的,是给新手直接用的。不怎么会,图片不会传。有问题欢迎留言。


更多相关文章

  1. Android开发笔记(一)像素的单位
  2. Android中的dip,dp,sp,px
  3. Android加载Bitmap出现OutofMemoryError的原因(官方译文)
  4. Android中px, ppi, dpi, dp, dip, sp概念解析
  5. android学习笔记之图像像素操作
  6. Android(安卓)Camera生成bmp格式的图片
  7. android多分辨率多密度下界面适配方案
  8. android资源自适应的认识(一)
  9. Nine Patch PNG in Android!

随机推荐

  1. Android(安卓)之 Activity的加载模式
  2. Android-x86 4.2 发布,基于 Android 4.2.2
  3. android log输出控制
  4. Android之获取手机上的图片和视频缩略图t
  5. Android(安卓)shape 矩形边框
  6. Android横竖屏切换生命周期你真的了解么?
  7. 史上最强劲之android模拟器命令详解
  8. Android技术积累汇总(4月28日更新)
  9. Android(安卓)通知栏自定义样式
  10. rk3288 Android(安卓)5.1root方法