package cn.hmsoft.helper;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import org.springframework.util.StringUtils;

import cn.hmsoft.frame.exception.BusinessException;
import cn.hmsoft.log.LogHelper;
import net.coobird.thumbnailator.Thumbnails;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/***********************
 * 图片辅助类
 * 
 * @author zxq
 * @create 2019-06-28 22:32:59
 * @version 2.0.0
 * @email: revisit@126.com
 * @Company: www.hmsoft.cn
 */
public class ImageHelper {

	/*******************
	 * 将图片压缩到零
	 * 
	 * @param fromImage
	 *            原图
	 * @param width
	 *            需要压缩的高度
	 * @param height
	 *            需要压缩的宽度
	 */
	public static File zipImage(File fromImage, int width, int height) {
		File tmpFile = FileHelper.createTempFile();
		return zipImage(fromImage, width, height, tmpFile.getPath());
	}

	/*******************
	 * 将图片压缩
	 * 
	 * @param fromImage
	 *            原图
	 * @param width
	 *            需要压缩的高度
	 * @param height
	 *            需要压缩的宽度
	 * @param toFile
	 *            压缩后的图片文件
	 */
	public static File zipImage(File fromImage, int width, int height, String toFile) {
		try {
			Thumbnails.of(fromImage).size(width, height).toFile(toFile);
			if (toFile.length() == 0)
				throw new BusinessException("无法将图片进行压缩，请联系系统管理员");
			return new File(toFile);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BusinessException("无法将图片进行压缩，请联系系统管理员");
		}
	}

	/**
	 * 本地图片转换成base64字符串
	 */
	public static String ImageToBase64ByLocal(InputStream in) {
		// 将图片文件转化为字节数组字符串，并对其进行Base64编码处理

		byte[] data = null;
		// 读取图片字节数组
		try {
			data = new byte[in.available()];
			in.read(data);
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 对字节数组Base64编码
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encode(data);// 返回Base64编码过的字节数组字符串
	}

	/**
	 * 本地图片转换成base64字符串
	 */
	public static String ImageToBase64ByLocal(String imgFile) {
		// 将图片文件转化为字节数组字符串，并对其进行Base64编码处理

		InputStream in = null;
		byte[] data = null;

		// 读取图片字节数组
		try {
			in = new FileInputStream(imgFile);
			data = new byte[in.available()];
			in.read(data);
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 对字节数组Base64编码
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encode(data);// 返回Base64编码过的字节数组字符串
	}

	/**
	 * base64字符串转换成图片
	 */
	public static boolean Base64ToImage(String imgStr, String imgFilePath) {
		// 对字节数组字符串进行Base64解码并生成图片

		if (StringUtils.isEmpty(imgStr)) // 图像数据为空
			return false;
		BASE64Decoder decoder = new BASE64Decoder();
		try {
			// Base64解码
			byte[] b = decoder.decodeBuffer(imgStr);
			for (int i = 0; i < b.length; ++i) {
				if (b[i] < 0) {// 调整异常数据
					b[i] += 256;
				}
			}
			OutputStream out = new FileOutputStream(imgFilePath);
			out.write(b);
			out.flush();
			out.close();
			return true;
		} catch (Exception e) {
			return false;
		}

	}

	/************************
	 * 返回base64的文件头
	 * 
	 * @param file
	 * @return
	 */
	public static String getImageType(File file) {
		String v = FileHelper.getFileSuffix(file);
		if (v == null)
			throw new BusinessException("不支持该格式的图片");
		if (v.equals("png") || v.equals("jpeg") || v.equals("jpg") || v.equals("bmp"))
			return v;
		throw new BusinessException("不支持该格式的图片");
	}

	/**
	 * 给图片添加文字水印
	 * 
	 * @param srcImgPath
	 *            原图片位置
	 * @param tarImgPath
	 *            加水印后图片输出位置
	 * @param waterMarkContent
	 *            文字水印内容
	 */
	public static void setTextWaterMarkForImage(String srcImgPath, String tarImgPath, String waterMarkContent) {
		try {
			File srcImgFile = new File(srcImgPath);
			java.awt.Image srcImg = ImageIO.read(srcImgFile);
			int srcImgWidth = srcImg.getWidth(null);
			int srcImgHeight = srcImg.getHeight(null);
			// 加水印
			BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = bufImg.createGraphics();
			g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
			g.setColor(Color.RED);
			g.setFont(new Font("宋体", Font.PLAIN, 30));
			g.rotate(Math.toRadians(15)); // 水印旋转
			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3f)); // 设置水印透明度

			// 设置水印的坐标
			int textWidth = g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0,
					waterMarkContent.length());
			int textHight = g.getFontMetrics(g.getFont()).getHeight();

			int x = (srcImgWidth - textWidth / 2) / 2;
			int y = (srcImgHeight - textHight * 4) / 2;
			g.drawString(waterMarkContent, x, y);

			g.dispose();
			// 输出图片
			FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
			ImageIO.write(bufImg, "jpg", outImgStream);
			outImgStream.flush();
			outImgStream.close();
		} catch (javax.imageio.IIOException ex) {

			throw new BusinessException("不支持该格式的图片，请使用jpg、jepg、png格式图片！");
		} catch (Exception ex) {
			LogHelper.error(ex);
			throw new BusinessException("添加水印出现错误！");
		}
	}

	/**
	 * 旋转角度
	 * 
	 * @param src
	 *            源图片
	 * @param angel
	 *            角度
	 * @return 目标图片
	 */
	public static void rotate(File srcFile, String toFile, int angel) {
		try {
			Image src = ImageIO.read(srcFile);
			int src_width = src.getWidth(null);
			int src_height = src.getHeight(null);
			// calculate the new image size
			Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);

			BufferedImage res = null;
			res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g2 = res.createGraphics();
			// transform(这里先平移、再旋转比较方便处理；绘图时会采用这些变化，绘图默认从画布的左上顶点开始绘画，源图片的左上顶点与画布左上顶点对齐，然后开始绘画，修改坐标原点后，绘画对应的画布起始点改变，起到平移的效果；然后旋转图片即可)

			// 平移（原理修改坐标系原点，绘图起点变了，起到了平移的效果，如果作用于旋转，则为旋转中心点）
			g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);

			// 旋转（原理transalte(dx,dy)->rotate(radians)->transalte(-dx,-dy);修改坐标系原点后，旋转90度，然后再还原坐标系原点为(0,0),但是整个坐标系已经旋转了相应的度数
			// ）
			g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

			// //先旋转（以目标区域中心点为旋转中心点，源图片左上顶点对准目标区域中心点，然后旋转）
			// g2.translate(rect_des.width/2,rect_des.height/ 2);
			// g2.rotate(Math.toRadians(angel));
			// //再平移（原点恢复到源图的左上顶点处（现在的右上顶点处），否则只能画出1/4）
			// g2.translate(-src_width/2,-src_height/2);

			g2.drawImage(src, null, null);
			// 输出图片
			FileOutputStream outImgStream = new FileOutputStream(toFile);
			ImageIO.write(res, "jpg", outImgStream);
			outImgStream.flush();
			outImgStream.close();
		} catch (

		Exception e) {

		}
	}

	/**
	 * 计算转换后目标矩形的宽高
	 * 
	 * @param src
	 *            源矩形
	 * @param angel
	 *            角度
	 * @return 目标矩形
	 */
	private static Rectangle CalcRotatedSize(Rectangle src, int angel) {
		double cos = Math.abs(Math.cos(Math.toRadians(angel)));
		double sin = Math.abs(Math.sin(Math.toRadians(angel)));
		int des_width = (int) (src.width * cos) + (int) (src.height * sin);
		int des_height = (int) (src.height * cos) + (int) (src.width * sin);
		return new java.awt.Rectangle(new Dimension(des_width, des_height));
	}

}
