附Java/C/C++/机器学习/算法与数据结构/前端/安卓/Python/程序员必读书籍书单大全:
书单导航页(点击右侧 极客侠栈 即可打开个人博客):极客侠栈
①【Java】学习之路吐血整理技术书从入门到进阶最全50+本(珍藏版)
②【算法数据结构+acm】从入门到进阶吐血整理书单50+本(珍藏版)
③【数据库】从入门到进阶必读18本技术书籍网盘吐血整理网盘(珍藏版)
④【Web前端】从HTML到JS到AJAX到HTTP从框架到全栈帮你走更少弯路(珍藏版)
⑤【python】书最全已整理好(从入门到进阶)(珍藏版)
⑥【机器学习】+python整理技术书(从入门到进阶已经整理好)(珍藏版)
⑦【C语言】推荐书籍从入门到进阶带你走上大牛之路(珍藏版)
⑧【安卓】入门到进阶推荐书籍整理pdf书单整理(珍藏版)
⑨【架构师】之路史诗级必读书单吐血整理四个维度系列80+本书(珍藏版)
⑩【C++】吐血整理推荐书单从入门到进阶成神之路100+本(珍藏)
⑪【ios】IOS书单从入门到进阶吐血整理(珍藏版)
--------------------------------------------------------------------------------------------------------------------
最近抖音上挺火的一个小把戏,在记事本打开,一整篇的乱码字符,然后进过调整之后,出现一张由各种字符组成的黑白照片。先看一个效果图
微信小程序体验
直接体验请微信扫码
选择图片转字符图片
接下来我们就用Java来实现吧。
需要用到的工具类代码
https://gitee.com/xshuai/ai/blob/master/AIDemo/src/main/java/com/xs/util/image/LZWEncoder.java
https://gitee.com/xshuai/ai/blob/master/AIDemo/src/main/java/com/xs/util/image/NeuQuant.java
单独的项目地址
https://gitee.com/xshuai/imagetool
本项目使用的公式为: Gray = R*0.299 + G*0.587 + B*0.114
更多RGB色转灰度可以访问:https://blog.csdn.net/xdrt81y/article/details/8289963
非闪图图片转字符画到记事本
package com.xs.util.image;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import javax.imageio.ImageIO;
import com.xs.util.image.other.ImageHelper;
/**
* Image2ASCII
* @author 小帅丶
* 2018年8月14日
*/
public class Image2ASCII{
static String ascii = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\\\"^`'.";
static String base = "@#&$%*o!;.";//小帅丶使用这个字符
//main方法调用
public static void main(String[] args) throws Exception {
load("G:/phone.jpg", "F:/gif/woman.txt");//静态图片转字符保存为txt文件
}
/**
* 图片转字符
* @param imagePath 图片路径
* @param txtPath 文本存放路径
* @throws IOException
*/
public static void load(String imagePath, String txtPath)
throws IOException {
BufferedImage image = ImageHelper.resize(ImageIO.read(new File(imagePath)),150,150);
load(image, txtPath);
}
/**
* 图片转字符
* @param bi BufferedImage图片
* @param txtPath 文本存放路径
* @throws IOException
*/
public static void load(BufferedImage bi, String txtPath)
throws IOException {
try {
int width = bi.getWidth();
int height = bi.getHeight();
boolean flag = false;
String result = "";
for (int i = 0; i < height; i += 2) {
for (int j = 0; j < width; j++) {
int pixel = bi.getRGB(j, i); // 下面三行代码将一个数字转换为RGB数字
int red = (pixel & 0xff0000) >> 16;
int green = (pixel & 0xff00) >> 8;
int blue = (pixel & 0xff);
float gray = 0.299f * red + 0.578f * green + 0.114f * blue;
int index = Math.round(gray * (base.length() + 1) / 255);
result += index >= base.length() ? " " : String.valueOf(base.charAt(index));
}
result += "\r\n";
}
flag = writeTxtFile(result,txtPath);//保存字符到文本文件
System.out.println(flag?"图片转字符保存成功":"图片转字符保存失败");
} catch (Exception e) {
System.out.println("图片转字符异常"+e.getMessage());
}
}
/**
* 字符保存到txt文件中
* @param imageStr 字符
* @param txtPath txt文件
* @return boolean
* @throws Exception
*/
private static boolean writeTxtFile(String imageStr, String txtPath) throws Exception{
// 先读取原有文件内容,然后进行写入操作
boolean flag = false;
String filein = imageStr;
String temp = "";
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
FileOutputStream fos = null;
PrintWriter pw = null;
try {
// 文件路径
File file = new File(txtPath);
if (!file.exists()) {
file.createNewFile();
}
// 将文件读入输入流
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);
StringBuffer buf = new StringBuffer();
// 保存该文件原有的内容
for (int j = 1; (temp = br.readLine()) != null; j++) {
buf = buf.append(temp);
}
buf.append(filein);
fos = new FileOutputStream(file);
pw = new PrintWriter(fos);
pw.write(buf.toString().toCharArray());
pw.flush();
flag = true;
} catch (IOException e) {
System.out.println("文件保存失败"+e.getMessage());
} finally {
if (pw != null) {
pw.close();
}
if (fos != null) {
fos.close();
}
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
if (fis != null) {
fis.close();
}
}
return flag;
}
}
非闪图图片转字符画返回BASE64
直接保存为图片也可以。
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import sun.misc.BASE64Encoder;
/**
* Image2ASCII
* @author 小帅丶
* 2018年8月14日
*/
public class Image2ASCII{
static String ascii = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\\\"^`'.";
static String base = "@#&$%*o!;.";//小帅丶使用这个字符
/** 图片类型 */
private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_RGB;
/**
* 图片转字符再保存为图片 只返回图片的base64
* @param bi 原图
* @param outPutPath
* @return String
*/
public static String txtToImageByBase64(BufferedImage bi) {
System.out.println("进来的时间"+System.currentTimeMillis());
int width = bi.getWidth();
int height = bi.getHeight();
int minx = bi.getMinX();
int miny = bi.getMinY();
int speed = 7;
BufferedImage bufferedImage = new BufferedImage(width,height,IMAGE_TYPE);
// 获取图像上下文
Graphics g = createGraphics(bufferedImage, width, height, speed);
// 图片中文本行高
final int Y_LINEHEIGHT = speed;
int lineNum = 1;
for (int i = miny; i < height; i += speed) {
for (int j = minx; j < width; j += speed) {
int pixel = bi.getRGB(j, i); // 下面三行代码将一个数字转换为RGB数字
int red = (pixel & 0xff0000) >> 16;
int green = (pixel & 0xff00) >> 8;
int blue = (pixel & 0xff);
float gray = 0.299f * red + 0.578f * green + 0.114f * blue;
int index = Math.round(gray * (base.length() + 1) / 255);
String c = index >= base.length() ? " " : String.valueOf(base.charAt(index));
g.drawString(String.valueOf(c), j, i);
}
lineNum++;
}
g.dispose();
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ImageIO.write(bufferedImage,"jpg",out);
BASE64Encoder base64Encoder = new BASE64Encoder();
String base64 =base64Encoder.encode(out.toByteArray());
return base64;
} catch (IOException e) {
System.out.println("ImageIO.write异常" + e.getMessage());
}finally{
if(null!=out){
try {
out.close();
} catch (IOException e) {
System.out.println("out.close()异常" + e.getMessage());
}
}
}
return null;
}
/**
* 画板默认一些参数设置
* @param image 图片
* @param width 图片宽
* @param height 图片高
* @param size 字体大小
* @return
*/
private static Graphics createGraphics(BufferedImage image, int width,
int height, int size) {
Graphics g = image.createGraphics();
g.setColor(null); // 设置背景色
g.fillRect(0, 0, width, height);// 绘制背景
g.setColor(Color.BLACK); // 设置前景色
g.setFont(new Font("微软雅黑", Font.PLAIN, size)); // 设置字体
return g;
}
}
效果图
方法返回的为图片的base64数据。格式为jpg。加头信息即可在img标签的src中显示图片哦。
在线转base64为图片 需要加头信息 data:image/jpg;base64,
http://imgbase64.duoshitong.com/
闪图图片转字符画返回图片
package com.xs.util.image;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.FileImageInputStream;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.imageio.plugins.gif.GIFImageReader;
import com.sun.imageio.plugins.gif.GIFImageReaderSpi;
import sun.misc.BASE64Encoder;
/**
* Image2ASCII
* @author 小帅丶
* 2018年8月14日
*/
public class Image2ASCII{
static String ascii = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\\\"^`'.";
static String base = "@#&$%*o!;.";//小帅丶使用这个字符
/** 图片类型 */
private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_RGB;
/**
* gif图片转gif字符图
* @param imagePath 原图路径
* @param outPath 输出图片的文件夹路径
* @throws IOException
*/
public static void loadGif(String imagePath, String outPath)
throws IOException {
File imageFile = new File(imagePath);
FileImageInputStream in = new FileImageInputStream(imageFile);
ImageReaderSpi readerSpi = new GIFImageReaderSpi();
GIFImageReader gifImageReader = new GIFImageReader(readerSpi);
gifImageReader.setInput(in);
int num = gifImageReader.getNumImages(true);
System.out.println(num);
BufferedImage[] bufferedImages = new BufferedImage[num];
for (int i = 0; i < num; i++) {
BufferedImage bi = gifImageReader.read(i);
bufferedImages[i] = txtToImage(bi, outPath + "out" + i + ".jpeg"); //每一帧都保存为图片
}
jpgToGif(bufferedImages,outPath + imagePath.substring(imagePath.length() - 6)+ "outGif.gif", 200);
}
/**
* 图片转字符再保存为图片
* @param bi 原图
* @param outPutPath
* @return BufferedImage
*/
public static BufferedImage txtToImage(BufferedImage bi, String outPutPath) {
File imageFile = new File(outPutPath);
if (!imageFile.exists()) {
try {
imageFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
int width = bi.getWidth();
int height = bi.getHeight();
int minx = bi.getMinX();
int miny = bi.getMinY();
System.out.println(width + " " + height);
int speed = 7;
BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
// 获取图像上下文
Graphics g = createGraphics(bufferedImage, width, height, speed);
// 图片中文本行高
final int Y_LINEHEIGHT = speed;
int lineNum = 1;
for (int i = miny; i < height; i += speed) {
for (int j = minx; j < width; j += speed) {
int pixel = bi.getRGB(j, i); // 下面三行代码将一个数字转换为RGB数字
int red = (pixel & 0xff0000) >> 16;
int green = (pixel & 0xff00) >> 8;
int blue = (pixel & 0xff);
float gray = 0.299f * red + 0.578f * green + 0.114f * blue;
int index = Math.round(gray * (base.length() + 1) / 255);
// char c = ascii.charAt((int) (gray / 255 * ascii.length()));
// char c = toChar((int) gray);
// char c = toChar(index);
String c = index >= base.length() ? " " : String.valueOf(base.charAt(index));
g.drawString(String.valueOf(c), j, i);
}
lineNum++;
}
g.dispose();
// 保存为jpg图片
FileOutputStream fos;
try {
fos = new FileOutputStream(imageFile);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
OutputStream out = encoder.getOutputStream();
BASE64Encoder base64Encoder = new BASE64Encoder();
encoder.encode(bufferedImage);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ImageFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bufferedImage;
}
/**
* 画板默认一些参数设置
* @param image 图片
* @param width 图片宽
* @param height 图片高
* @param size 字体大小
* @return
*/
private static Graphics createGraphics(BufferedImage image, int width,
int height, int size) {
Graphics g = image.createGraphics();
g.setColor(null); // 设置背景色
g.fillRect(0, 0, width, height);// 绘制背景
g.setColor(Color.BLACK); // 设置前景色
g.setFont(new Font("微软雅黑", Font.PLAIN, size)); // 设置字体
return g;
}
/**
* n张jpg转gif方法
* @param bufferedImages
* @param newPic
* @param playTime
*/
private static void jpgToGif(BufferedImage[] bufferedImages, String newPic,
int playTime) {
try {
AnimatedGifEncoder e = new AnimatedGifEncoder();
e.setRepeat(0);
e.start(newPic);
for (int i = 0; i < bufferedImages.length; i++) {
e.setDelay(playTime); // 设置播放的延迟时间
e.addFrame(bufferedImages[i]); // 添加到帧中
}
e.finish();
} catch (Exception e) {
System.out.println("jpgToGif Failed:");
}
}
}
调用代码
public static void main(String[] args) throws Exception {
loadGif("C:/Users/Administrator/Desktop/页面录屏显示.gif", "F:/gif/");//动图转为动态的字符图片
}
返回的图片效果原图为小程序演示闪图