Android 打印之将文字转换成 Bitmap 图片,再转换成Bytes 数组 进行打印

一、前言

Android 打印解决文字显示?问好 乱码

最近在处理打印的时候,打印机有些繁体的字无法打印出来,或者其它韩文打印出来显示 ? 问题

解决思路:

将需要打印的 String 文本内容,先转换成 Bitmap 位图 , 然后将图片转换成打印机能打印的byte[]类型

不同印机 最终丢给印机打印的方法不同。

如下图,打印的是一栏地址,原来第三个字呢打印出来是 ? 号的 ,这张图是用以下的转换方法修复后的。

使用印机都是 EPSON,其它也类似。

左边的是 网络打印 (通过 OutputStream 流的方式 将 byte[] 写入 到缓冲区)

右边的是 USB 连接 EPSON 打印 (通过EPSON SDK的方法,addImage() ) 打印出来的很OK

其实还有一个问题就是,通过网络传递的Esc 指令打印之后,打印文字可能打印像素有点不全的问题 ,我感觉是 下面的 genBitmapCode 方法 转换出来的时候,像素精度还是什么问题 ,如果有好的解决方式 请给我留言 谢谢。(文末已找到完美解决方式)

后面发现,如果打印的文字很大的话,或者给文字 设置字体是加粗的话 就 不会打印出来是缺像素的,不过其实这样也不太好。总之目前就是如果是有SDK的,就优先使用专门的打印 Bitmap 的方法, 而网络打印只能发 Esc 指令发送Bytes。

    String familyName ="宋体";Typeface font = Typeface.create(familyName,Typeface.BOLD);textPaint.setTypeface(font);

下面提供了 ,创建Bitmap 图片, 创建 QRCode 二维码图片 ,转换成 Bytes 数组 进行打印

二、将文字转换成Bitmap

    /*** 根据文字创建一个 bitmap  , 打印的位图需要 黑字 白底** @param text* @param height* @param width* @return*/public Bitmap getNewBitMap(String text, int height, int width) {Bitmap newBitmap = createBitmap(width, height, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(newBitmap);canvas.drawColor(Color.WHITE);canvas.drawBitmap(newBitmap, 0, 0, null);TextPaint textPaint = new TextPaint();//       String familyName ="宋体";//  Typeface font = Typeface.create(familyName,Typeface.BOLD);// textPaint.setTypeface(font);textPaint.setAntiAlias(true);textPaint.setTextSize(height * 2 / 3);
//        textPaint.setColor(Color.rgb(0, 0, 0));textPaint.setColor(Color.BLACK);//     "在Android开发中,Canvas.drawText不会换行,即使一个很长的字符串也只会显示一行,超出部分会隐藏在屏幕之外.StaticLayout是android中处理文字的一个工具类,StaticLayout 处理了文字换行的问题";StaticLayout sl = new StaticLayout(text, textPaint, newBitmap.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);textPaint.setStyle(Paint.Style.FILL);canvas.translate(0, height / 10);sl.draw(canvas);return newBitmap;}/*** 生成二维码bitmap 要转换的地址或字符串,可以是中文** @param url* @param width* @param height* @return*/public Bitmap createQRImage(String url, final int width, final int height) {try {// 判断URL合法性if (url == null || "".equals(url) || url.length() < 1) {return null;}Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();hints.put(EncodeHintType.CHARACTER_SET, "utf-8");// 图像数据转换,使用了矩阵转换BitMatrix bitMatrix = new QRCodeWriter().encode(url,BarcodeFormat.QR_CODE, width, height, hints);int[] pixels = new int[width * height];// 下面这里按照二维码的算法,逐个生成二维码的图片,// 两个for循环是图片横列扫描的结果for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {if (bitMatrix.get(x, y)) {pixels[y * width + x] = 0xff000000;} else {pixels[y * width + x] = 0xffffffff;}}}// 生成二维码图片的格式,使用ARGB_8888Bitmap bitmap = createBitmap(width, height,Bitmap.Config.ARGB_8888);bitmap.setPixels(pixels, 0, width, 0, 0, width, height);return bitmap;} catch (WriterException e) {e.printStackTrace();}return null;}

三、把图片转换成POS机能打印的byte[]类型

  /*** 将图片转换成POS机能打印的byte[]类型** @param bm* @param doubleWidth* @param doubleHeight* @return*/private static byte[] genBitmapCode(Bitmap bm, boolean doubleWidth, boolean doubleHeight) {int w = bm.getWidth();int h = bm.getHeight();
//        if(w > MAX_BIT_WIDTH)
//            w = MAX_BIT_WIDTH;int bitw = ((w + 7) / 8) * 8;int bith = h;int pitch = bitw / 8;byte[] cmd = {0x1D, 0x76, 0x30, 0x00, (byte) (pitch & 0xff), (byte) ((pitch >> 8) & 0xff), (byte) (bith & 0xff), (byte) ((bith >> 8) & 0xff)};byte[] bits = new byte[bith * pitch];// 倍宽if (doubleWidth) {cmd[3] |= 0x01;}// 倍高if (doubleHeight) {cmd[3] |= 0x02;}for (int y = 0; y < h; y++) {for (int x = 0; x < w; x++) {int color = bm.getPixel(x, y);if ((color & 0xFF) < 128) {bits[y * pitch + x / 8] |= (0x80 >> (x % 8));}}}ByteBuffer bb = ByteBuffer.allocate(cmd.length + bits.length);bb.put(cmd);bb.put(bits);return bb.array();}

四、调用打印文本方式

      //生成的bitmap 显示 固定是一行 ,如果要生成多行,需要自行通过文本控制Bitmap的宽高Bitmap newBitMap = getNewBitMap(IMAGE, 20, 300);byte[] bytes = genBitmapCode(newBitMap, true, true);//此方式是网络打印 通过 OutputStream 流的方式 将 byte[] 写入 到缓冲区socketOut.write(bytes);

五、EPSON 爱普生 中打印图片的方式

        //创建单行文字 Bitmap newBitMap = getNewBitMap(IMAGE, 40, 600);//打印图片 方式 1  打印出来很漂亮mPrinter.addImage(newBitMap, 0, 0,newBitMap.getWidth(),newBitMap.getHeight(),Printer.COLOR_1,Printer.MODE_MONO,Printer.HALFTONE_DITHER,Printer.PARAM_DEFAULT,Printer.COMPRESS_AUTO);// 方式2 打印出来 有少像素没打全Bitmap newBitMap = getNewBitMap(IMAGE, 20, 300);byte[] bytes = genBitmapCode(newBitMap, true, true);mPrinter.addCommand(bytes)

六、调用打印二维码图片

Bitmap qrImage = createQRImage("qr123456", 170, 170);byte[] bytes = genBitmapCode(qrImage, true, true);socketOut.write(bytes);

以上代码只是作为一个参考思路, 主要是 将 String 转换 为 Bitmap ,再丢给打印机 进行打印。

不同印机应优选考虑不同的调用方式,如果是 USB 连接 EPSON 的话 其实也支持 Esc 指令 进行命令打印的。

网络打印的话,只能传递 Esc 指令集 通过流的方式传输进行打印了。


X、 解决图片像素打印不全问题

经过排查,使用了另外一种创建 Bitmap 的方式,可正常进行完美打印不会像素失真, 另外也可以使用另外一种 将 Bitmap 图片转化为打印机可以打印的字节流的方法

/*** 将文字 生成 文字图片 生成显示编码的Bitmap,目前这个方法是可用的 ,  打印的位图需要 黑字 白底* @param contents* @param context*/public static Bitmap creatCodeBitmap(String contents ,Context context) {float scale=context.getResources().getDisplayMetrics().scaledDensity;TextView tv = new TextView(context);LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);tv.setLayoutParams(layoutParams);tv.setText(contents);tv.setTextSize(scale*12);tv.setGravity(Gravity.CENTER_HORIZONTAL);tv.setDrawingCacheEnabled(true);tv.setTextColor(Color.BLACK);tv.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());tv.setBackgroundColor(Color.WHITE);tv.buildDrawingCache();Bitmap bitmapCode = tv.getDrawingCache();return bitmapCode;}/*** 把一张Bitmap图片转化为打印机可以打印的字节流** @param bmp* @return*/public static byte[] draw2PxPoint(Bitmap bmp) {//用来存储转换后的 bitmap 数据。为什么要再加1000,这是为了应对当图片高度无法//整除24时的情况。比如bitmap 分辨率为 240 * 250,占用 7500 byte,//但是实际上要存储11行数据,每一行需要 24 * 240 / 8 =720byte 的空间。再加上一些指令存储的开销,//所以多申请 1000byte 的空间是稳妥的,不然运行时会抛出数组访问越界的异常。int size = bmp.getWidth() * bmp.getHeight() / 8 + 1000;byte[] data = new byte[size];int k = 0;//设置行距为0的指令data[k++] = 0x1B;data[k++] = 0x33;data[k++] = 0x00;// 逐行打印for (int j = 0; j < bmp.getHeight() / 24f; j++) {//打印图片的指令data[k++] = 0x1B;data[k++] = 0x2A;data[k++] = 33;data[k++] = (byte) (bmp.getWidth() % 256); //nLdata[k++] = (byte) (bmp.getWidth() / 256); //nH//对于每一行,逐列打印for (int i = 0; i < bmp.getWidth(); i++) {//每一列24个像素点,分为3个字节存储for (int m = 0; m < 3; m++) {//每个字节表示8个像素点,0表示白色,1表示黑色for (int n = 0; n < 8; n++) {byte b = px2Byte(i, j * 24 + m * 8 + n, bmp);data[k] += data[k] + b;}k++;}}data[k++] = 10;//换行}return data;}/*** 灰度图片黑白化,黑色是1,白色是0** @param x   横坐标* @param y   纵坐标* @param bit 位图* @return*/public static byte px2Byte(int x, int y, Bitmap bit) {if (x < bit.getWidth() && y < bit.getHeight()) {byte b;int pixel = bit.getPixel(x, y);int red = (pixel & 0x00ff0000) >> 16; // 取高两位int green = (pixel & 0x0000ff00) >> 8; // 取中两位int blue = pixel & 0x000000ff; // 取低两位int gray = RGB2Gray(red, green, blue);if (gray < 128) {b = 1;} else {b = 0;}return b;}return 0;}/*** 图片灰度的转化*/private static int RGB2Gray(int r, int g, int b) {int gray = (int) (0.29900 * r + 0.58700 * g + 0.11400 * b);  //灰度转化公式return gray;}

使用方式

     //生成的bitmap 显示 固定是一行Bitmap bitmap = creatCodeBitmap(IMAGE, App.getInstance());byte[] bytes = draw2PxPoint(bitmap);socketOut.write(bytes);

借鉴

android 字符串 转换成Bitmap 设置文本的字体: 宋体,隶书啥的,获取字体的 行高, 文字生成图片

Android 打印之将文字转换成 Bitmap 图片,再转换成Bytes 数组 进行打印相关推荐

  1. Drawable的Tint变色(让Android也能有iOS那么方便的图片色调转换)

    2019独角兽企业重金招聘Python工程师标准>>> Drawable的Tint变色(让Android也能有iOS那么方便的图片色调转换) 字数590 阅读475 评论0 喜欢1 ...

  2. PDF转换成JPG图片怎么转换?这两招轻松搞定

    PDF转换成JPG图片怎么转换?PDF文件是我们常用的一类文件,在现在的办公环境中,PDF真的用途很广,不仅是日常发送文件,还有学习工作中都会用到,不过有时候我们也需要将PDF文件转换成其他的格式,比 ...

  3. 如何 将 超过int最大值的 long值 转成int , 然后再转换回来

    因为 long值 如果 超过int的最大值, 在转换成int的时候, 会出现丢失位的现象 , 所以通过普通的方法 是转不回来的, 需要进行位运算, 才可以 ```public static void ...

  4. pdf怎么转换成jpg图片?转换方式说明

    将PDF转换为JPG图片是一种常见的文件格式转换操作,通常用于在不同设备上查看和共享PDF文档.但是,大多数情况下,将PDF转换为JPG图片可能并不总是可行或有效的.在本文中,我们将讨论为什么不能将P ...

  5. 如何将照片格式转换jpg?图片格式转换jpg的方法

    网站上传照片很多都只能是JPG格式,平时使用的最多的也都是jpg格式图片.如果想要把其他格式的图片转换为jpg该怎么处理呢?这时候需要使用图片格式转换(https://www.yasuotu.com/ ...

  6. java 图片文件 格式转换_Java的图片文件格式转换和线性缩放

    Java的图片文件格式转换和线性缩放 来源:68design.net 2007年07月13日 08:31 图片文件格式转换最核心的问题就是要解决各种图片格式的编码和解码,推荐用jimi包,可从 htt ...

  7. php doc转swf,centos安装openoffice将doc、ppt、txt、xls等转换成pdf,再转换成swf用‍FlexPaper显示...

    教程 下载:http://www.openoffice.org/download/other.html 下载中文的openoffice和英文的sdk,相关文件已上传到百度网盘中:linux>ce ...

  8. c#如何wmf图片转换成png图片_C#转换图片格式小工具源码(支持icon/jpg/bmp/gif/png/tif/wmf格式)...

    [实例简介] C#转换图片格式实例 [实例截图] [核心代码] using System; using System.Collections.Generic; using System.Compone ...

  9. Android 自定义RadioButton 实现文字上下左右方向的图片大小设置

    好久没有更新博客,写这篇技术时,感觉很多东西生疏了好多.于是心有感慨:我们做技术的,要是长时间不搞技术,那就是被技术搞!所以攻守之间,大家谨慎思量. 冬天已过,放假出去玩耍时,看到两旁嫩嫩的树叶,想起 ...

  10. 将Bitmap byte裸数据转换成Bitmap图片int数据

    转自:http://blog.sina.com.cn/s/blog_025270e901014z3p.html,尊重原创 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何转换为Bitmap呢 ...

最新文章

  1. 这个AI让马斯克头秃,还能帮他设计特斯拉
  2. gevent queue应用2 队列设置了最大数量限制
  3. 网站打开速度变慢可以从哪些方面进行分析呢?
  4. 手机型号大全资料_电子元器件知识资料大全
  5. 在游戏中强制关机,不能对关机提示框进行操作
  6. CF1060D Social Circles
  7. 系统架构师笔记(2)
  8. mysql安装check requirements出错_超详细的MySQL8.0.17版本安装教程
  9. android 安装包 权限,确定Android中已安装应用程序使用的权限列表
  10. python读取txt文件出现UnicodeError
  11. 在html种颜色的代码,html颜色代码生成器
  12. 2017-12-24 手机编程环境初尝试-用AIDE开发Android应用...
  13. 调整DOS窗口大小的方法 2021-03-06
  14. 【HTML CSS JS 蝴蝶飞舞特效 绝美(附完整代码)】
  15. 电脑上怎样安装python,【初学者教程】在电脑上安装Python,写第一个程序
  16. Linux学习笔记之MySql的安装(CentOS)
  17. Rosalind Java|Consensus and Profile
  18. 2、二叉树的后序遍历
  19. Linux中set -x 与 set +x命令的使用
  20. js报错类型(6种错误类型)

热门文章

  1. 绝美中国建筑!为中国摄影师鼓掌!
  2. 【Paper Reading】Improving Availability of Vertical Federated Learning Relaxing Inference on Non-overl
  3. 什么是4G工业智能网关?与DTU有什么区别
  4. 行测中数量关系的练习题集(07-29)【2】
  5. 苹果系统中国日历服务器,ios日历中国节日不见了(2021年苹果日历订阅地址)...
  6. 使用Cisco Packet Tracer 搭建网络
  7. 美国7月ISM制造业PMI录得52.8创两年多新低 新订单连续第二个月萎缩
  8. 宽带运营商为什么限制上行带宽
  9. 机器人与matlab——Robotics Toolbox—02建立机器人模型
  10. word只在第一页插入页眉