今天在某音熱門視頻中刷到的萨惑,圖片轉(zhuǎn)ASCLL碼的視頻,抱著試試看的態(tài)度我使用Spring Boot做了一個簡易web版的贞滨。修為尚淺入热,請多指教!廢話少說晓铆,上代碼。
環(huán)境
/**
*ubuntu
*JDK 1.8
*Spring Boot 1.5.6
*阿里云OSS
*/
第一步 Maven依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zuoyang</groupId>
<artifactId>image2ascll</artifactId>
<version>0.0.2-SNAPSHOT</version>
<name>image2ascll</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 阿里云OSS-->
<!-- https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
第二步 配置文件
server.port=80
## OSS
#OSS配置
oss.endpoint=你的endPoint(見控制臺)
oss.keyid= 你的keyid
oss.keysecre=你的keysecret
oss.bucketname1=你新建的bucket的名字
oss.filehost=你的目錄我做測試的是file(就是一個根目錄)
第三步 編寫配置文件ConsantConfig.java
package com.zuoyang.image2ascll.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author 左羊
* @date 2019-07-31 11:53:24
*/
@Component("constantConfig")
public class ConstantConfig {
@Value("${oss.endpoint}")
private String LXIMAGE_END_POINT;
@Value("${oss.keyid}")
private String LXIMAGE_ACCESS_KEY_ID;
@Value("${oss.keysecre}")
private String LXIMAGE_ACCESS_KEY_SECRET;
@Value("${oss.filehost}")
private String LXIMAGE_FILE_HOST;
@Value("${oss.bucketname1}")
private String LXIMAGE_BUCKET_NAME1;
public String getLXIMAGE_END_POINT() {
return LXIMAGE_END_POINT;
}
public void setLXIMAGE_END_POINT(String LXIMAGE_END_POINT) {
this.LXIMAGE_END_POINT = LXIMAGE_END_POINT;
}
public String getLXIMAGE_ACCESS_KEY_ID() {
return LXIMAGE_ACCESS_KEY_ID;
}
public void setLXIMAGE_ACCESS_KEY_ID(String LXIMAGE_ACCESS_KEY_ID) {
this.LXIMAGE_ACCESS_KEY_ID = LXIMAGE_ACCESS_KEY_ID;
}
public String getLXIMAGE_ACCESS_KEY_SECRET() {
return LXIMAGE_ACCESS_KEY_SECRET;
}
public void setLXIMAGE_ACCESS_KEY_SECRET(String LXIMAGE_ACCESS_KEY_SECRET) {
this.LXIMAGE_ACCESS_KEY_SECRET = LXIMAGE_ACCESS_KEY_SECRET;
}
public String getLXIMAGE_FILE_HOST() {
return LXIMAGE_FILE_HOST;
}
public void setLXIMAGE_FILE_HOST(String LXIMAGE_FILE_HOST) {
this.LXIMAGE_FILE_HOST = LXIMAGE_FILE_HOST;
}
public String getLXIMAGE_BUCKET_NAME1() {
return LXIMAGE_BUCKET_NAME1;
}
public void setLXIMAGE_BUCKET_NAME1(String LXIMAGE_BUCKET_NAME1) {
this.LXIMAGE_BUCKET_NAME1 = LXIMAGE_BUCKET_NAME1;
}
}
第四步 編寫OSS工具類AliyunOSSUtil.java
package com.zuoyang.image2ascll.util;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.zuoyang.image2ascll.config.ConstantConfig;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
/**
* @author 左羊
* @date 2019-07-31 11:53:24
*/
@SuppressWarnings("AliDeprecation")
@Component("aliyunOSSUtil")
public class AliyunOssUtil {
@Autowired
private ConstantConfig constantConfig;
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AliyunOssUtil.class);
/**
* 上傳文件
*/
@SuppressWarnings("AliDeprecation")
public String upLoad(File file) {
LOGGER.info("------OSS文件上傳開始--------" + file.getName());
String endpoint = constantConfig.getLXIMAGE_END_POINT();
System.out.println("獲取到的Point為:" + endpoint);
String accessKeyId = constantConfig.getLXIMAGE_ACCESS_KEY_ID();
String accessKeySecret = constantConfig.getLXIMAGE_ACCESS_KEY_SECRET();
String bucketName = constantConfig.getLXIMAGE_BUCKET_NAME1();
String fileHost = constantConfig.getLXIMAGE_FILE_HOST();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String dateStr = format.format(new Date());
String fileGetUrl = null;
// 判斷文件
if (file == null) {
return null;
}
OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
try {
// 判斷容器是否存在,不存在就創(chuàng)建
if (!client.doesBucketExist(bucketName)) {
client.createBucket(bucketName);
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
client.createBucket(createBucketRequest);
}
// 設置文件路徑和名稱
String fileUrl = fileHost + "/" + (dateStr + "/" + UUID.randomUUID().toString().replace("-", "") + "-" + file.getName());
System.out.println("A+fileUrl:" + fileUrl);
// 上傳文件
PutObjectResult result = client.putObject(new PutObjectRequest(bucketName, fileUrl, file));
// 設置權限(公開讀)
client.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
if (result != null) {
LOGGER.info("------OSS文件上傳成功------" + fileUrl);
LOGGER.info("文件上傳路徑:" + "https://" + constantConfig.getLXIMAGE_BUCKET_NAME1() + "." + constantConfig.getLXIMAGE_END_POINT() + "/" + fileUrl);
fileGetUrl = "https://" + constantConfig.getLXIMAGE_BUCKET_NAME1() + "." + constantConfig.getLXIMAGE_END_POINT() + "/" + fileUrl;
// fileGetUrl = "https://" + constantConfig.getLXIMAGE_BUCKET_NAME1() + "." + constantConfig.getLXIMAGE_END_POINT() + "/" + fileUrl;
return fileGetUrl;
}
} catch (OSSException oe) {
LOGGER.error(oe.getMessage());
} catch (ClientException ce) {
LOGGER.error(ce.getErrorMessage());
} finally {
if (client != null) {
client.shutdown();
}
}
return null;
}
}
第五步 圖片壓縮工具類
package com.zuoyang.image2ascll.util;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
/**
* @author 左羊
* @date 2019-07-31 11:53:24
* 圖片工具類,完成圖片的截取
* 所有方法返回值均未boolean型
*/
public class ImageHelper {
/**
* 實現(xiàn)圖像的等比縮放
* @param source
* @param targetW
* @param targetH
* @return
*/
private static BufferedImage resize(BufferedImage source, int targetW,
int targetH) {
// targetW黍瞧,targetH分別表示目標長和寬
int type = source.getType();
BufferedImage target = null;
double sx = (double) targetW / source.getWidth();
double sy = (double) targetH / source.getHeight();
// 這里想實現(xiàn)在targetW掏膏,targetH范圍內(nèi)實現(xiàn)等比縮放。如果不需要等比縮放
// 則將下面的if else語句注釋即可
if (sx < sy) {
sx = sy;
targetW = (int) (sx * source.getWidth());
} else {
sy = sx;
targetH = (int) (sy * source.getHeight());
}
if (type == BufferedImage.TYPE_CUSTOM) { // handmade
ColorModel cm = source.getColorModel();
WritableRaster raster = cm.createCompatibleWritableRaster(targetW,
targetH);
boolean alphaPremultiplied = cm.isAlphaPremultiplied();
target = new BufferedImage(cm, raster, alphaPremultiplied, null);
} else
target = new BufferedImage(targetW, targetH, type);
Graphics2D g = target.createGraphics();
// smoother than exlax:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
g.dispose();
return target;
}
/**
* 實現(xiàn)圖像的等比縮放和縮放后的截取, 處理成功返回true, 否則返回false
* @param inFilePath 要截取文件的路徑
* @param outFilePath 截取后輸出的路徑
* @param width 要截取寬度
* @param hight 要截取的高度
* @throws Exception
*/
public static boolean compress(String inFilePath, String outFilePath,
int width, int hight) {
boolean ret = false;
File file = new File(inFilePath);
File saveFile = new File(outFilePath);
InputStream in = null;
try {
in = new FileInputStream(file);
ret = compress(in, saveFile, width, hight);
} catch (FileNotFoundException e) {
e.printStackTrace();
ret = false;
} finally{
if(null != in){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return ret;
}
/**
* 實現(xiàn)圖像的等比縮放和縮放后的截取, 處理成功返回true, 否則返回false
* @param in 要截取文件流
* @param width 要截取寬度
* @param hight 要截取的高度
* @throws Exception
*/
public static boolean compress(InputStream in, File saveFile,
int width, int hight) {
// boolean ret = false;
BufferedImage srcImage = null;
try {
srcImage = ImageIO.read(in);
} catch (IOException e) {
e.printStackTrace();
return false;
}
if (width > 0 || hight > 0) {
// 原圖的大小
int sw = srcImage.getWidth();
int sh = srcImage.getHeight();
// 如果原圖像的大小小于要縮放的圖像大小链蕊,直接將要縮放的圖像復制過去
if (sw > width && sh > hight) {
srcImage = resize(srcImage, width, hight);
} else {
String fileName = saveFile.getName();
String formatName = fileName.substring(fileName
.lastIndexOf('.') + 1);
try {
ImageIO.write(srcImage, formatName, saveFile);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
}
// 縮放后的圖像的寬和高
int w = srcImage.getWidth();
int h = srcImage.getHeight();
// 如果縮放后的圖像和要求的圖像寬度一樣事甜,就對縮放的圖像的高度進行截取
if (w == width) {
// 計算X軸坐標
int x = 0;
int y = h / 2 - hight / 2;
try {
saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
// 否則如果是縮放后的圖像的高度和要求的圖像高度一樣谬泌,就對縮放后的圖像的寬度進行截取
else if (h == hight) {
// 計算X軸坐標
int x = w / 2 - width / 2;
int y = 0;
try {
saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
/**
* 實現(xiàn)圖像的等比縮放和縮放后的截取, 處理成功返回true, 否則返回false
* @param in 圖片輸入流
* @param saveFile 壓縮后的圖片輸出流
* @param proportion 壓縮比
* @throws Exception
*/
public static boolean compress(InputStream in, File saveFile, int proportion) {
if(null == in
||null == saveFile
||proportion < 1){// 檢查參數(shù)有效性
//LoggerUtil.error(ImageHelper.class, "--invalid parameter, do nothing!");
return false;
}
BufferedImage srcImage = null;
try {
srcImage = ImageIO.read(in);
} catch (IOException e) {
e.printStackTrace();
return false;
}
// 原圖的大小
int width = srcImage.getWidth() / proportion;
int hight = srcImage.getHeight() / proportion;
srcImage = resize(srcImage, width, hight);
// 縮放后的圖像的寬和高
int w = srcImage.getWidth();
int h = srcImage.getHeight();
// 如果縮放后的圖像和要求的圖像寬度一樣,就對縮放的圖像的高度進行截取
if (w == width) {
// 計算X軸坐標
int x = 0;
int y = h / 2 - hight / 2;
try {
saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
// 否則如果是縮放后的圖像的高度和要求的圖像高度一樣逻谦,就對縮放后的圖像的寬度進行截取
else if (h == hight) {
// 計算X軸坐標
int x = w / 2 - width / 2;
int y = 0;
try {
saveSubImage(srcImage, new Rectangle(x, y, width, hight), saveFile);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
/**
* 實現(xiàn)縮放后的截圖
* @param image 縮放后的圖像
* @param subImageBounds 要截取的子圖的范圍
* @param subImageFile 要保存的文件
* @throws IOException
*/
private static void saveSubImage(BufferedImage image,
Rectangle subImageBounds, File subImageFile) throws IOException {
if (subImageBounds.x < 0 || subImageBounds.y < 0
|| subImageBounds.width - subImageBounds.x > image.getWidth()
|| subImageBounds.height - subImageBounds.y > image.getHeight()) {
//LoggerUtil.error(ImageHelper.class, "Bad subimage bounds");
return;
}
BufferedImage subImage = image.getSubimage(subImageBounds.x,subImageBounds.y, subImageBounds.width, subImageBounds.height);
String fileName = subImageFile.getName();
String formatName = fileName.substring(fileName.lastIndexOf('.') + 1);
ImageIO.write(subImage, formatName, subImageFile);
}
}
第六步 圖片轉(zhuǎn)ASCLL工具類
package com.zuoyang.image2ascll.util;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author 左羊
* @date 2019-07-31 11:23:01
*
*/
public class ImageToAscll {
/**
* @param path
* 圖片路徑
*/
public static String createAsciiPic(final String path) {
final String base = "#8XOHLTI)i=+;:,. ";// 字符串由復雜到簡單
final String txtPath ="/data/image2ascll/txts/abc.txt";
try {
final BufferedImage image = ImageIO.read(new File(path)); //讀取圖片
//輸出到指定文件中
final BufferedWriter fos = new BufferedWriter(new FileWriter(txtPath,false)); //true表示是否追加
for (int y = 0; y < image.getHeight(); y += 2) {
for (int x = 0; x < image.getWidth(); x++) {
final int pixel = image.getRGB(x, y);
final int r = (pixel & 0xff0000) >> 16, g = (pixel & 0xff00) >> 8, b = pixel & 0xff;
final float gray = 0.299f * r + 0.578f * g + 0.114f * b;
final int index = Math.round(gray * (base.length() + 1) / 255);
String s = index >= base.length() ? " " : String.valueOf(base.charAt(index));
fos.write(s);
}
fos.newLine();
}
fos.close();
} catch (final IOException e) {
e.printStackTrace();
}
return txtPath;
}
}
第七步 Service層
接口類
package com.zuoyang.image2ascll.service;
/**
* @author 左羊
* @date 2019-07-31 11:53:24
*/
public interface ImageToAscllServie {
String imageToAscll(String path);
}
實現(xiàn)類
package com.zuoyang.image2ascll.service.imp;
import com.zuoyang.image2ascll.service.ImageToAscllServie;
import com.zuoyang.image2ascll.util.ImageToAscll;
import com.zuoyang.image2ascll.util.ImageHelper;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author 左羊
* @date 2019-07-31 11:53:24
*/
@Service
public class ImageToAscllServiceImp implements ImageToAscllServie {
@Override
public String imageToAscll(String path) {
InputStream in = null;
//縮放后需要保存的路徑
File saveFile = new File("/data/image2ascll/txts/ABC.jpg");
try {
//原圖片的路徑
in = new FileInputStream(new File("/data/image2ascll/txts/"+path));
if(ImageHelper.compress(in, saveFile, 5)){
System.out.println("圖片壓縮5倍掌实!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return ImageToAscll.createAsciiPic("/data/image2ascll/txts/ABC.jpg");
}
}
第八步 controller層
IndexController.class
package com.zuoyang.image2ascll.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 左羊
* @date 2019-07-31 11:53:24
*/
@Controller
public class IndexController {
@RequestMapping("/")
public String index()
{
return "imageToAscll";
}
}
ImageToAscllController.class
package com.zuoyang.image2ascll.controller;
import com.zuoyang.image2ascll.service.imp.ImageToAscllServiceImp;
import com.zuoyang.image2ascll.util.AliyunOssUtil;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
/**
* @author douxiaofeng
* @date 2019-07-31 11:53:24
*/
@RestController
public class ImageToAscllController {
private final org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ImageToAscllServiceImp imageToAscllServiceImp;
@Autowired
private AliyunOssUtil aliyunOSSUtil;
@RequestMapping(value = "/uploadimg")
@PostMapping
public @ResponseBody
String imgUploa(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
logger.info("文件上傳");
String filename = file.getOriginalFilename();
logger.info("文件路徑 = {}",filename);
String uploadUrl = null;
String uploadTxtUrl = null;
String txtName = null;
try {
if (file != null) {
if (!"".equals(filename.trim())) {
// 圖片
File newFile = new File("/data/image2ascll/txts/"+filename);
FileOutputStream os = new FileOutputStream(newFile);
os.write(file.getBytes());
os.close();
file.transferTo(newFile);
// 圖片上傳到OSS
uploadUrl = file.getOriginalFilename();
logger.info("圖片地址={}",uploadUrl);
// 文字
txtName = imageToAscllServiceImp.imageToAscll(uploadUrl);
File newTxtFile = new File(txtName);
// 上傳到OSS
uploadTxtUrl = aliyunOSSUtil.upLoad(newTxtFile);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return uploadTxtUrl;
}
}
啟動類
package com.zuoyang.image2ascll;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author 左羊
* @date 2019-07-31 11:53:24
*/
@SpringBootApplication
public class Image2ascllApplication {
public static void main(String[] args) {
SpringApplication.run(Image2ascllApplication.class, args);
}
}
頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>imageToAscll</title>
<script type="text/javascript" src="lib/jquery-3.2.1.min.js"></script>
<style>
#cert{
/*opacity:0;*/
/*filter:alpha(opacity=0);*/
/*position: absolute;*/
/*top: 0;*/
/*left: 0;*/
z-index: 9;
display: none;
}
</style>
</head>
<body>
<button type="button" id="insert_image_button">添加圖片
<input id="cert" type="file"/>
</button>
</body>
<script>
$(function () {
$("#download-box").hide();
// 添加圖片
$("#insert_image_button").click(function () {
document.getElementById("cert").click();
});
// 圖片上傳
function upload() {
var type = "file"; //后臺接收時需要的參數(shù)名稱,自定義即可
var id = "cert"; //即input的id跨跨,用來尋找值
var formData = new FormData();
formData.append(type, $("#" + id)[0].files[0]); //生成一對表單屬性
$.ajax({
type: "POST", //因為是傳輸文件潮峦,所以必須是post
url: '/uploadimg', //對應的后臺處理類的地址
data: formData,
processData: false,
contentType: false,
success: function (data) {
window.open(data);
// location.href=data;
}
});
};
//圖片上傳引用
$("#cert").on("change", function () {
if ($("#cert").val() != "") {
upload();
}
});
});
</script>
</html>
測試 生成jar文件
上傳至服務器,啟動jar文件 --》 瀏覽器輸入地址
看下結果
將顯示文字復制到記事本
最后附上博主大餅臉
參考地址:
https://blog.csdn.net/abubu123/article/details/77099950
https://blog.csdn.net/renhd_1987/article/details/52948978