2020-01-09

转自https://blog.csdn.net/chensong_5260/article/details/51044220?utm_source=app

最近做的关于打印机打印图片的项目,需要将图片转为打印机能打的点阵位图。我参考了很多文章,但是也没有说的很详细的,其中流浪的鱼的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[heightwidth];
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[widthi+j];
if (g>=128) {
pixels[width
i+j]=0xffffffff;
e=g-255;

}else {
pixels[widthi+j]=0xff000000;
e=g-0;
}
if (j<width-1&&i<height-1) {
//右边像素处理
gray[width
i+j+1]+=3e/8;
//下
gray[width
(i+1)+j]+=3e/8;
//右下
gray[width
(i+1)+j+1]+=e/4;
}else if (jwidth-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开发,博客也是第一次写,平时也主要是看别人的博客在学习。考虑到和我一样的新手,处理这个问题会比较困难,就写了这个。参考的思路主要是鱼神的。我写的,是给新手直接用的。不怎么会,图片不会传。有问题欢迎留言。

文章最后发布于: 2016-04-02

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值