【图片、字符画互转】字符画实现(JAVA)
一、实现方法
字符画实际上是将图片的每一个像素点,按一定的标准(如灰度值等)替换为字符(如图所示,图示为黑色背景,白色字体)。
二、图片转字符画 实现过程
①读取图片(这里使用java.jwt自带的BufferedImage对象读取)
/** 获取最原生的BufferedImage对象 */public static BufferedImage getBufferedImage(final String src) throws FileNotFoundException, IOException {return ImageIO.read(new FileInputStream(new File(src.trim())));}
②对图片进行处理(如压缩、灰度化、二值化等),一般来说,先二值/灰度化后再压缩,效果比较好,当然具体情况具体分析
下面贴上代码
/*** 按设置的宽度高度比例压缩图片文件,如果width和height都大于0,则以此为基准进行压缩(可能造成图片变型)* * @param oldFile* 要进行压缩的文件全路径* @param newFile* 新文件* @param width* 宽度* @param height* 高度* @return 返回压缩后的文件的全路径*/
public static BufferedImage zipImageFileWithRate(BufferedImage image, int width, int height) {if (image == null) {return null;}if(width<=0&&height<=0){return image;}/* 对服务器上的临时文件进行处理 *//* 按比例压缩 */int w = image.getWidth(null);int h = image.getHeight(null);double bili;if (width > 0&&height<=0) {bili = width / (double) w;height = (int) (h * bili);} else if (height > 0&&width<=0) {bili = height / (double) h;width = (int) (w * bili);}BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D graphics = buffImg.createGraphics();graphics.getFontRenderContext();graphics.setBackground(new Color(255, 255, 255));graphics.setColor(new Color(255, 255, 255));graphics.fillRect(0, 0, width, height);graphics.drawImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);StringOutputter.print("压缩图片 (宽:?,高:?)==>成功", width,height);return buffImg;
}/*** 根据路径获取灰度化后的图片*/
public static BufferedImage getGrayBufferedImage(final BufferedImage image)throws FileNotFoundException, IOException {int width = image.getWidth();int height = image.getHeight();BufferedImage grayImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);for (int i = 0; i < width; i++) {for (int j = 0; j < height; j++) {int rgb = image.getRGB(i, j);grayImage.setRGB(i, j, rgb);}}return grayImage;
}
/*** 获取二值化图片*/
public static BufferedImage getBinaryBufferedImage(final BufferedImage image) {if (image == null) {return null;}int width = image.getWidth();int height = image.getHeight();BufferedImage binaryImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);for (int i = 0; i < width; i++) {for (int j = 0; j < height; j++) {int rgb = image.getRGB(i, j);binaryImage.setRGB(i, j, rgb);}}return binaryImage;
}
③遍历图片,根据灰度值,从已知的字符字典里获取字符,并写入txt文件
/*** 获取图片在x,y轴的rgb值*/public static RgbPixel getScreenPixel(BufferedImage image, int x, int y) {if (isLegal(image, x, y)) {RgbPixel rgb = new RgbPixel();int pix = image.getRGB(x, y);rgb.setRed((pix & 0xff0000) >> 16);// 最高8位为Redrgb.setGreen((pix & 0x00ff00) >> 8);// 中间8位为Greenrgb.setBlue((pix & 0x0000ff));// 最低8位为Bluereturn rgb;}return null;}/* 主要实现函数,遍历整张图片 */public static void write(BufferedImage image,FileOutputStream fop) throws IOException{/* 遍历整个图像,xy像素点填充字符 */for (int j = image.getMinY(); j < image.getHeight(); j++) {for (int i = image.getMinX(); i < image.getWidth(); i++) {RgbPixel pixel = PictureReader.getScreenPixel(image, i, j);int index = RgbNumberWritter.getChar(pixel);fop.write(DICTORY.charAt(index));// 插入字符fop.write(32);// 加个空格,防止图片会看起来扁了一半}/* 填充换行符 */fop.write(10);}}
这里为了方便,自己写了一个RgbPixel类(getter和setter没有贴出)
public class RgbPixel {private int red;private int green;private int blue;public double getGray(){/** 灰度值公式:Gray=R×0.299+G×0.587+B×0.114*/double gray=red*0.299+green*0.587+blue*0.114;return gray;}
从字符字典中获取对应字符(根据灰度值):DICTORY是字典,下标越大,代表其灰度值越大
private final static String DICTORY=" .,·-'`:!1+*abcdefghijklmnopqrstuvwxyz<>()\\/{}[]?23456789AJKLICFDBEGHMNPQRSTUVWXYZ%&#$0O@";private final static int DICTORY_LEN=DICTORY.length();/** 获取该灰度值对应下标 */public static int getChar(RgbPixel rgb){double key =DICTORY_LEN- Math.round(rgb.getGray()/STEP);if(key>=1){key-=1;}return (int)key;}
通过上面几个步骤,可以很快的生成对应的txt文本:
三、字符画(txt)转图片
(一)、方法
字符画转图片,只需要读取txt文本里的文本信息,然后直接画在图片上即可,
Graphics提供了drawString方法,可以很方便的生成,需要注意的是,为了生成的图片能尽可能的还原图片,所以建议使用等宽字体,并且调整好图片的大小(字体的单位是pt,像素单位是px,具体请参考:https://blog.csdn.net/gogl/article/details/48584191 、 https://blog.csdn.net/flyeek/article/details/43934945 )
为什么还要多此一举把txt生成图片呢?因为我电脑上的文本阅读器功能比较少,不能将文字缩放成特别小的尺寸,所以生成的字符画看不到全局,而图片可以。
这里挖个坑,剩下的以后写,部分代码如下
(二)、代码
public static boolean writePictureFromFile(File file,String output,int IMAGE_WIDTH , int IMAGE_HEIGHT,final int fontSize,boolean whiteBackGround){boolean flag=false;if(file!=null&&file.exists()&&!file.isDirectory()){BufferedReader reader = null;try {reader = new BufferedReader(new FileReader(file));//像素点和字体大小转化
// IMAGE_WIDTH*=ptToPx(fontSize);
// IMAGE_HEIGHT*=(ptToPx(fontSize)+2);IMAGE_WIDTH*=((fontSize&1)==0? fontSize:fontSize+1); IMAGE_HEIGHT*=(fontSize+2);
// StringOutputter .print("produce a image with Width:? ,Height:?",IMAGE_WIDTH,IMAGE_HEIGHT);BufferedImage bimage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT,BufferedImage.TYPE_INT_RGB);//获取图像上下文Graphics g = createGraphics(bimage,IMAGE_WIDTH,IMAGE_HEIGHT,fontSize,whiteBackGround);String line;//图片中文本行高FontMetrics metrics = g.getFontMetrics();
// final int Y_LINEHEIGHT = (ptToPx(fontSize)+2);//一般是像素大小+2final int Y_LINEHEIGHT = metrics.getHeight(); //相当于fontsize+2;
// StringOutputter.print("@ :height:? ,Y_LINEHEIGHT: ?", height,Y_LINEHEIGHT);int lineNum = 1;try {while((line = reader.readLine()) != null){
// StringOutputter.print("Get Line[?]:?",lineNum,line);g.drawString(line, 0, lineNum * Y_LINEHEIGHT);
// StringOutputter.print("lineNum * Y_LINEHEIGHT: ? ,width:?", lineNum * Y_LINEHEIGHT,metrics.stringWidth(line));lineNum++;}g.dispose();//保存为jpg图片FileOutputStream out = new FileOutputStream(output);ImageIO.write(bimage, "JPEG", out);out.close();StringOutputter.print("写文本图片(像素:(?,?))==>成功 (输出路径:?)",IMAGE_WIDTH,IMAGE_HEIGHT, output);} catch (IOException e) {e.printStackTrace();return false;}return true;} catch (FileNotFoundException e) {e.printStackTrace();return false;}finally{if(reader!=null){try {reader.close();} catch (IOException e) {e.printStackTrace();}}}}return flag;}
/*** 获取图片的上下文,设置样式* @param image 处理的图片对象* @param IMAGE_WIDTH 宽* @param IMAGE_HEIGHT 高* @param fontSize 字体大小* @param whiteBackGround 是否为白底黑字* @return*/
private static Graphics createGraphics(final BufferedImage image,final int IMAGE_WIDTH,final int IMAGE_HEIGHT,final int fontSize,final boolean whiteBackGround){if(IMAGE_WIDTH>0&&IMAGE_HEIGHT>0){//创建图片Graphics g = image.createGraphics();//设置背景色if(whiteBackGround){g.setColor(null); }else{g.setColor(Color.BLACK);}g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);//绘制背景//设置前景色if(whiteBackGround){g.setColor(Color.BLACK); }else{g.setColor(Color.WHITE); }g.setFont(new Font(FONT_NAME, Font.PLAIN, fontSize)); //设置字体return g;}return null;
}
四、代码共享
挖个坑以后填…
【图片、字符画互转】字符画实现(JAVA)相关推荐
- python图像转字符画_python图像处理-字符画风格图片
前言 字符画图片,顾名思义就是由一个个字符组成的图片,下面这张图片很容易帮助你理解,如果我们可以将字符排列好,让他看上去像一个物体的形状,那么最后再将它输出保存为一张图片就可以实现了. 下面的这些形状 ...
- python学习之手把手教你将图片变成黑白或彩色字符画(骚操作)
文章目录 前言 一.字符画的实现原理 二.黑白字符画实现代码 三.彩色字符画生成 代码实现: 总结 前言 字符画这个话题,似乎早在贴吧时代就已经被玩烂了.在百度图片随便一搜索,就能够看到非常多.然后在 ...
- vue-quill-editor上传内容由于图片是base64的导致字符太长的问题解决
vue-quill-editor上传内容由于图片是base64的导致字符太长的问题解决 参考文章: (1)vue-quill-editor上传内容由于图片是base64的导致字符太长的问题解决 (2) ...
- 仿抖音--将图片转化成对应的字符图片
起初看到抖音上的那个将图片转化成对应的字符图片的视频,心动不已,哇!这哥们也太有心了吧,虽说莉哥好看,但你做这图要花多长时间呀!值不值啊! 后来我才知道,java实现的话简直一秒钟的事. 第一开始只能 ...
- 仅仅有人物没背景的图片怎么弄_纯干货//只会画人物不会画背景?这3种方法教你快速画背景!...
很多同学只会画人物不会画背景,于是就想到了一些骚操作-- 1.万年"留白"党:不会画干脆就不画,一片白板走天下!喂喂喂,你就这么随便留一大片空白的背景,对得起可爱的纱雾妹妹吗! 2 ...
- 【python】将图片绘制成像素风的画,Tiler
这个项目超级火! 将图片转化成像素风的画. 不要问,问就是Tiler! 项目地址: git clone https://github.com/nuno-faria/tiler.git 安装依赖包: p ...
- 使用Python完成曾火爆全网的图片转符号图片、GIF图像转字符GIF动画操作
前言 这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题 于是乎,我自己开发了一款面试宝典,希 ...
- excel 画散点图 怎么设置图片的分辨率_Slynyrd像素画教程:像素画基础教程
Slynyrd像素画教程:像素画基础教程 作者:Slynyrd[1] 翻译:三二 (转载请注明出处) 关注公众号:教你画像素画 微信号:pixelfish 微博:教你画像素画2014 在合适的条件下, ...
- 仅仅有人物没背景的图片怎么弄_只会画人物不会画背景?这3种方法教你快速画背景!...
原标题:只会画人物不会画背景?这3种方法教你快速画背景! 很多同学只会画人物不会画背景,于是就想到了一些骚操作-- 1.万年"留白"党:不会画干脆就不画,一片白板走天下! 喂喂喂, ...
- python画正方形-用python画正方形
广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我正在学习python学习教程,我无法打开屏幕进行绘图. 我没有发现错误,它只是 ...
最新文章
- 控制器属性传值的一些小问题
- linux不保存退出命令_面试提问说出16个linux命令,能凑齐不!高频22个Linux命令在这里...
- linux修改容器内的mysql端口映射_修改docker容器端口映射的方法
- 打开pix4d无有效许可_我市两家企业通过危险废物综合经营许可证专家核查
- 实现EventHandler的监测
- simply scheme 第一章 练习+ 看书计划
- Linux与Windows中的UTC时间
- 获取 子文件夹 后缀_后期制作老司机教你一键批量生成项目文件夹
- oracle 10g的进程主要分为,Oracle10g 后台进程列表
- LSTM背后的数学原理
- hadoop无法停止
- Xeam Visual Installer白金版,Xeam Visual Installer完整用户体验
- uniapp 获取android设备 GPS 信号强弱
- 花花的森林(倍增,LCA
- 流浪地球的终点正是三体人要逃离的地方
- 日志易之配置日志内容黑名单
- 数加使用自定义调度资源进行数据同步
- 记一次spark两个大表join数据倾斜调优
- 所有手机都支持物联卡吗,物联卡为什么手机不能用
- 条形码、二维码的生成与扫描、解析本地二维码
热门文章
- python 爬取链家二手房信息
- c语言程序设计课程表,c语言怎样编写课程表,请问程序怎样写?
- lan pci 联想开机_联想笔记本bios怎么设置 联想笔记本进入bios方法【详解】
- g729编解码的总结
- 华为给出的测试账号里面的题
- Java为什么要面向接口编程
- 使用typescript开发集成阿里云短信接口
- php mktime 2037,phpmktime计算两时间之差_PHP教程
- POI 4.1.2 word转html(保留样式及图片)
- 启动马达接线实物图_常见电机控制实物接线图,简单原理分析,学习入门,值得收藏...