上周刚做好一个大头贴功能,使用的腾讯AI平台对图片的处理API接口,实现一张照片根据四张模板生成四张处理的特效照片,然后后台处理拼接成一张图片,可以用照片打印机打印出6寸的照片,效果还不错。坑爹的是今天调试发现接口调用不通了,腾讯AI平台不提供该接口了,好几天的工作量白费了。不过还是把最近写的一些代码整理一下,把一些功能放上来,以后用得上。
功能实现的逻辑:由于接口限制图片大小,所以先对上传的图片进行压缩,然后将四张图片拼接成一张图片保存(效果图如下);
图片处理工具类:
package org.plusgroup.modules.admin.service;
import net.coobird.thumbnailator.Thumbnails;
import org.slfj.Logger;
import org.slfj.LoggerFactory;
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.*;
import java.util.UUID;
/**
* @author Administrator
* @desc 图片操作类
* @date/7/12 09:00
*/public class ImageUtils {
private static Logger logger = LoggerFactory.getLogger(org.plusgroup.common.utils.ImageUtils.class);
/**
* 文件转byte []
* @param filePath 文件地址
* @return byte[]
*/ public static byte[] getBytesByFile(String filePath) {
try {
File file=new File(filePath);
//获取输入流
FileInputStream fis = new FileInputStream(file);
//新的 byte 数组输出流,缓冲区容量byte
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//缓存
byte[] b = new byte[];
int n;
while ((n = fis.read(b)) != -) {
bos.write(b,, n);
}
fis.close();
//改变为byte[]
byte[] data = bos.toByteArray();
//
bos.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据指定大小压缩图片
* @param imageBytes 源图片字节数组
* @param desFileSize 指定图片大小,单位kb
* @return 压缩质量后的图片字节数组
*/ public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
if (imageBytes == null || imageBytes.length <= || imageBytes.length < desFileSize * 1024) {
return imageBytes;
}
long srcSize = imageBytes.length;
double accuracy = getAccuracy(srcSize /);
try {
while (imageBytes.length > desFileSize *) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
Thumbnails.of(inputStream).scale(.99).outputQuality(0.99).toOutputStream(outputStream);
imageBytes = outputStream.toByteArray();
}
logger.info(" 图片原大小={}kb | 压缩后大小={}kb", srcSize /, imageBytes.length / 1024);
} catch (Exception e) {
logger.error("【图片压缩】msg=图片压缩失败!", e);
}
return imageBytes;
}
/**
* 自动调节精度(经验数值)
*
* @param size 源图片大小
* @return 图片压缩质量比
*/ private static double getAccuracy(long size) {
double accuracy;
if (size <) {
accuracy =.85;
} else if (size <) {
accuracy =.6;
} else if (size <) {
accuracy =.44;
} else {
accuracy =.4;
}
return accuracy;
}
/**
* 保存图片到本地
* @param path 地址
* @param bfile 文件流
*/ public static void uploadLocal(String path, byte[] bfile) {
String fileName = UUID.randomUUID().toString().trim().replaceAll("-", "") + ".png";
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
File dir = new File(path);
boolean isDir = dir.isDirectory();
if (!isDir) {// 目录不存在则先建目录
try {
dir.mkdirs();
} catch (Exception e) {
e.printStackTrace();
}
}
file = new File(path + File.separator + fileName);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bfile);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 四张同高度宽度的图片合成。
* mergeImage方法不做判断,自己判断。
*
* @param imgByte 第一张图
* @param imgByte 第二张图
* @param imgByte 第三张图
* @param imgByte 第四张图
* @return 返回合并后的BufferedImage对象
*/ public static byte[] mergeFourImage(byte[] imgByte, byte[] imgByte2,byte[] imgByte3,byte[] imgByte4, String imgFormat) throws IOException {
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte1));
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte2));
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte3));
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgByte4));
//获取图片的宽高
int w = img1.getWidth(null);
int h = img1.getHeight(null);
int w = img2.getWidth(null);
int h = img2.getHeight(null);
int w = img3.getWidth(null);
int h = img3.getHeight(null);
int w = img4.getWidth(null);
int h = img4.getHeight(null);
// 从图片中读取RGB
int[] ImageArrayOne = new int[w * h1];
// 逐行扫描图像中各个像素的RGB到数组中
ImageArrayOne = img.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);
int[] ImageArrayTwo = new int[w * h2];
ImageArrayTwo = img.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);
int[] ImageArray = new int[w3 * h3];
ImageArray = img3.getRGB(0, 0, w3, h3, ImageArray3, 0, w3);
int[] ImageArray = new int[w4 * h4];
ImageArray = img4.getRGB(0, 0, w4, h4, ImageArray4, 0, w4);
// 生成新图片
BufferedImage destImg = new BufferedImage(w + w2 + 5, h1 + h2 + 5, BufferedImage.TYPE_INT_RGB);
destImg.setRGB(, 0, w1, h1, ImageArrayOne, 0, w1);
destImg.setRGB(w + 5, 0, w2, h2, ImageArrayTwo, 0, w2);
destImg.setRGB(, h1 + 5, w3, h3, ImageArray3, 0, w3);
destImg.setRGB(w + 5, h1 +5, w4, h4, ImageArray4, 0, w4);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(destImg, imgFormat, out);
return out.toByteArray();
}
/**
* 图片缩放 (压缩不理想可选)宽高选择 560 (优先选择)等比例缩放 720 960
* @param srcImg 原图片
* @param destImg 目标位置
* @param width 期望宽
* @param height 期望高
* @param equalScale 是否等比例缩放
* @return long 返回文件的大小
*/ public static long reSize(File srcImg, File destImg, int width, int height, boolean equalScale) {
String type = getImageType(srcImg);
if (type == null) {
return;
}
if (width < || height < 0) {
return;
}
BufferedImage srcImage = null;
try {
srcImage = ImageIO.read(srcImg);
System.out.println("srcImg size=" + srcImage.getWidth() + "X" + srcImage.getHeight());
} catch (IOException e) {
e.printStackTrace();
return;
}
// targetW,targetH分别表示目标长和宽
BufferedImage target = null;
double sx = (double) width / srcImage.getWidth();
double sy = (double) height / srcImage.getHeight();
// 等比缩放
if (equalScale) {
if (sx > sy) {
sx = sy;
width = (int) (sx * srcImage.getWidth());
} else {
sy = sx;
height = (int) (sy * srcImage.getHeight());
}
}
System.out.println("destImg size=" + width + "X" + height);
ColorModel cm = srcImage.getColorModel();
WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
boolean alphaPremultiplied = cm.isAlphaPremultiplied();
target = new BufferedImage(cm, raster, alphaPremultiplied, null);
GraphicsD g = target.createGraphics();
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.drawRenderedImage(srcImage, AffineTransform.getScaleInstance(sx, sy));
g.dispose();
// 将转换后的图片保存
try {
ByteArrayOutputStream baas = new ByteArrayOutputStream();
ImageIO.write(target, type, baas);
FileOutputStream fos = new FileOutputStream(destImg);
fos.write(baas.toByteArray());
fos.flush();
fos.close();
System.out.println("图片大小:"+destImg.length());
return destImg.length();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
/**
* 获取文件后缀不带.
* @param file 文件后缀名
* @return String
*/ private static String getImageType(File file) {
if (file != null && file.exists() && file.isFile()) {
String fileName = file.getName();
int index = fileName.lastIndexOf(".");
if (index != - && index < fileName.length() - 1) {
return fileName.substring(index +);
}
}
return null;
}
}
测试类:
package org.plusgroup.modules.admin.service;
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.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author Administrator
* @desc 生成大头贴
* @date/7/12 09:41
*/public class ImageTest {
public static void main(String[] args) throws Exception {
//等比例缩小图片
reSizePhoto();
//拼接四张图片
margeFourPhoto();
}
/**
* 压缩图片至指定大小之下
*/ public static void zipPic(){
byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp101.png");
byte[] destImg = ImageUtils.compressPicForScale(imgByte,500);
//图片保存至本地
ImageUtils.uploadLocal("C:/Users/Public/Pictures/Sample Pictures/temp/temp.png",destImg);
}
/**
* 等比例缩小图片
*/ public static void reSizePhoto(){
File srcImg = new File("C:/Users/Public/Pictures/Sample Pictures/temp/temp.png");
File destImg = null;
for(int i=;i<=2;i++){
destImg = new File("C:/Users/Public/Pictures/Sample Pictures/temp/temp"+i+".png");
//宽高选择 560 等比例缩放 720 960
ImageUtils.reSize(srcImg,destImg,,960,true);
}
}
/**
* 拼接四张图片(寸照片)
*/ public static void margeFourPhoto() throws IOException {
byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp101.png");
byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp102.png");
byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp103.png");
byte[] imgByte = ImageUtils.getBytesByFile("C:/Users/Public/Pictures/Sample Pictures/temp/temp104.png");
byte[] destImg = ImageUtils.mergeFourImage(imgByte,imgByte2,imgByte3,imgByte4,"png");
ImageUtils.uploadLocal("C:/Users/Public/Pictures/Sample Pictures/temp/temp.png",destImg);
}
}
等腾讯接口恢复了,在把调用接口生成大头贴的代码发上来!