package com.mosty.common.util;


import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.net.ssl.*;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Iterator;

/**
 * 图片处理类<br>
 *
 * @author Esacpe
 * @version 2014-8-22
 */

public class ImageUtils {

    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);



    public static byte[] getImage(String imagePath)
    {
        InputStream is = getFile(imagePath);
        try
        {
            return IOUtils.toByteArray(is);
        }
        catch (Exception e)
        {
            log.error("图片加载异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
    }

    public static InputStream getFile(String imagePath)
    {
        try
        {
            byte[] result = readFile(imagePath);
            result = Arrays.copyOf(result, result.length);
            return new ByteArrayInputStream(result);
        }
        catch (Exception e)
        {
            log.error("获取图片异常 {}", e);
        }
        return null;
    }

    /**
     * 读取文件为字节数据
     *
     * @param url 地址
     * @return 字节数据
     */
    public static byte[] readFile(String url)
    {
        InputStream in = null;
        try
        {
            // 网络地址
            URL urlObj = new URL(url);
            URLConnection urlConnection = urlObj.openConnection();
            urlConnection.setConnectTimeout(30 * 1000);
            urlConnection.setReadTimeout(60 * 1000);
            urlConnection.setDoInput(true);
            in = urlConnection.getInputStream();
            return IOUtils.toByteArray(in);
        }
        catch (Exception e)
        {
            log.error("访问文件异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(in);
        }
    }


    /**
     * 将图片缩放处理方法<br>
     *
     * @param source    源图片对象
     * @param targetW   转换后的宽度
     * @param targetH   转换后的高度
     * @param sameScale 是否等比例缩放
     * @return BufferedImage
     */
    public static BufferedImage resize(BufferedImage source, int targetW,
                                       int targetH, boolean sameScale) { // targetW，targetH分别表示目标长和宽
        int type = source.getType();
        BufferedImage target = null;
        double sx = (double) targetW / source.getWidth();
        double sy = (double) targetH / source.getHeight();
        if (sameScale) { // 需要等比例缩放
            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_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();
        return target;
    }

    /**
     * 将图片放大与缩小<br>
     *
     * @param sourceByte 源图片的字节数组
     * @param width      转换后的宽度
     * @param height     转换后的高度
     * @param sameScale  是否等比例缩放
     * @return byte[]
     */
    public static byte[] convertImageSize(byte[] sourceByte, int width,
                                          int height, boolean sameScale) throws Exception {
        byte[] returnValue = null;
        if (sourceByte != null && sourceByte.length > 0) {
            ByteArrayInputStream in = new ByteArrayInputStream(sourceByte);
            // BufferedImage srcImage = getReadImage(in);
            BufferedImage srcImage = null;
            try {
                srcImage = ImageIO.read(in); // RGB
            } catch (Exception e) {
            }
            if (srcImage != null) {
                BufferedImage srcImageTarget = resize(srcImage, width, height,
                        sameScale);
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                boolean flag = ImageIO.write(srcImageTarget, "JPEG", out);
                returnValue = out.toByteArray();
            }
        }
        return returnValue;
    }

    /**
     * 将图片放大与缩小后另存<br>
     *
     * @param fromFileStr   来源文件名
     * @param saveToFileStr 目标文件名
     * @param width         转换后的宽度
     * @param height        转换后的高度
     * @param sameScale     是否等比例缩放
     */
    public static void saveImageAsJpg(String fromFileStr, String saveToFileStr,
                                      int width, int height, boolean sameScale) throws Exception {
        String imgType = "JPEG";
        if (fromFileStr.toLowerCase().endsWith(".png")) {
            imgType = "PNG";
        }
        File saveFile = new File(saveToFileStr);
        File fromFile = new File(fromFileStr);
        BufferedImage srcImage = getReadImage(fromFile);
        if (srcImage != null) {
            if (width > 0 || height > 0) {
                srcImage = resize(srcImage, width, height, sameScale);
            }
            ImageIO.write(srcImage, imgType, saveFile);
        }
    }

    /**
     * 根据文件取得bufferedImage对象（自动识别RGB与CMYK）<br>
     *
     * @param file 来源文件名
     * @return BufferedImage
     */
    private static BufferedImage getReadImage(File file) throws Exception {
        BufferedImage srcImage = null;
        ImageInputStream input = ImageIO.createImageInputStream(file); // 只能接收File或FileInputStream，ByteArrayInputStream无效
        Iterator readers = ImageIO.getImageReaders(input);
        if (readers == null || !readers.hasNext()) {
            throw new RuntimeException("1 No ImageReaders found");
        }
        ImageReader reader = (ImageReader) readers.next();
        reader.setInput(input);
        String format = reader.getFormatName();
        if ("JPEG".equalsIgnoreCase(format) || "JPG".equalsIgnoreCase(format)) {
            try {
                srcImage = ImageIO.read(file); // RGB
            } catch (Exception e) {
                Raster raster = reader.readRaster(0, null);// CMYK
                srcImage = createJPEG4(raster);
            }
            input.close();
        }
        return srcImage;
    }

    /**
     * RGB彩色空间转换为CMYK<br>
     *
     * @param raster
     * @return BufferedImage
     */
    private static BufferedImage createJPEG4(Raster raster) {
        int w = raster.getWidth();
        int h = raster.getHeight();
        byte[] rgb = new byte[w * h * 3]; // 彩色空间转换
        float[] Y = raster.getSamples(0, 0, w, h, 0, (float[]) null);
        float[] Cb = raster.getSamples(0, 0, w, h, 1, (float[]) null);
        float[] Cr = raster.getSamples(0, 0, w, h, 2, (float[]) null);
        float[] K = raster.getSamples(0, 0, w, h, 3, (float[]) null);
        for (int i = 0, imax = Y.length, base = 0; i < imax; i++, base += 3) {
            float k = 220 - K[i], y = 255 - Y[i], cb = 255 - Cb[i], cr = 255 - Cr[i];
            double val = y + 1.402 * (cr - 128) - k;
            val = (val - 128) * .65f + 128;
            rgb[base] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
                    : (byte) (val + 0.5);
            val = y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128) - k;
            val = (val - 128) * .65f + 128;
            rgb[base + 1] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
                    : (byte) (val + 0.5);
            val = y + 1.772 * (cb - 128) - k;
            val = (val - 128) * .65f + 128;
            rgb[base + 2] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
                    : (byte) (val + 0.5);
        }
        raster = Raster.createInterleavedRaster(new DataBufferByte(rgb,
                rgb.length), w, h, w * 3, 3, new int[]{0, 1, 2}, null);
        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        ColorModel cm = new ComponentColorModel(cs, false, true,
                Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
        return new BufferedImage(cm, (WritableRaster) raster, true, null);
    }

    public static byte[] encodeImageTobyte(String url) {
        //打开链接
        try {
            URL urls = new URL(url);
            HttpURLConnection conn = null;

            conn = (HttpURLConnection) urls.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            //得到图片的二进制数据，以二进制封装得到数据，具有通用性
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            //使用一个输入流从buffer里把数据读取出来
            while ((len = inStream.read(buffer)) != -1) {
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }
            //关闭输入流
            inStream.close();
            byte[] data = outStream.toByteArray();
            return data;//返回Base64编码过的字节数组字符串
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 网络图片转成base64 https
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static byte[] encodeImageToByteHttps(String url) {
        byte[] data = null;
        try {
            SSLContext sslcontext = SSLContext.getInstance("SSL", "SunJSSE");
            sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());
            URL urls = new URL(url);
            HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
                public boolean verify(String s, SSLSession sslsession) {
                    System.out.println("WARNING: Hostname is not matched for cert.");
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
            HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
            //之后任何Https协议网站皆能正常访问，同第一种情况
            HttpURLConnection conn = null;

            conn = (HttpURLConnection) urls.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            if (conn.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM) {
                String location = conn.getHeaderField("Location");
                byte[] data1 = encodeImageToByteHttps(location.trim());
                if (null != data && data1.length > 0) {
                    return data1;
                }

            } else {
                //通过输入流获取图片数据
                InputStream inStream = conn.getInputStream();
                //得到图片的二进制数据，以二进制封装得到数据，具有通用性
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                //创建一个Buffer字符串
                byte[] buffer = new byte[1024];
                //每次读取的字符串长度，如果为-1，代表全部读取完毕
                int len = 0;
                //使用一个输入流从buffer里把数据读取出来
                while ((len = inStream.read(buffer)) != -1) {
                    //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                    outStream.write(buffer, 0, len);
                }
                //关闭输入流
                inStream.close();
                data = outStream.toByteArray();

            }
        } catch (Exception e) {
            System.out.println("解析失败！------》" + e.getMessage());
        }
        return data;
    }


    /**
     * 网络图片转成base64 https
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static String encodeImageToBase64Https(String url) {
        String base64 = null;
        try {
            SSLContext sslcontext = SSLContext.getInstance("SSL", "SunJSSE");
            sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());
            URL urls = new URL(url);
            HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
                public boolean verify(String s, SSLSession sslsession) {
                    System.out.println("WARNING: Hostname is not matched for cert.");
                    return true;
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
            HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
            //之后任何Https协议网站皆能正常访问，同第一种情况
            HttpURLConnection conn = null;

            conn = (HttpURLConnection) urls.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            if (conn.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM) {
                String location = conn.getHeaderField("Location");
                String s = encodeImageToBase64Https(location.trim());
                if (StringUtils.isNotBlank(s)) {
                    return s;
                }

            } else {
                //通过输入流获取图片数据
                InputStream inStream = conn.getInputStream();
                //得到图片的二进制数据，以二进制封装得到数据，具有通用性
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                //创建一个Buffer字符串
                byte[] buffer = new byte[1024];
                //每次读取的字符串长度，如果为-1，代表全部读取完毕
                int len = 0;
                //使用一个输入流从buffer里把数据读取出来
                while ((len = inStream.read(buffer)) != -1) {
                    //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                    outStream.write(buffer, 0, len);
                }
                //关闭输入流
                inStream.close();
                byte[] data = outStream.toByteArray();
                //对字节数组Base64编码
                BASE64Encoder encoder = new BASE64Encoder();
                base64 = encoder.encode(data).replaceAll("[\\s*\t\n\r]", "");
            }
        } catch (Exception e) {
            System.out.println("解析失败！------》" + e.getMessage());
        }
        return base64;
    }

    /**
     * 网络图片转成base64
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static String encodeImageToBase64(String url) throws Exception {
        //打开链接
        URL urls = new URL(url);
        HttpURLConnection conn;
        try {
            conn = (HttpURLConnection) urls.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            //得到图片的二进制数据，以二进制封装得到数据，具有通用性
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            //使用一个输入流从buffer里把数据读取出来
            while ((len = inStream.read(buffer)) != -1) {
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }
            //关闭输入流
            inStream.close();
            byte[] data = outStream.toByteArray();
            //对字节数组Base64编码
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(data).replaceAll("[\\s*\t\n\r]", "");
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception("解析失败!");
        }
    }

    public static String ImageToBase64(String imgPath) {
        byte[] data = null;
        try {
            InputStream in = new FileInputStream(imgPath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
//        return StringUtils.replaceBlank(StringUtils.getByteToBase64(data));
        return "";
    }

    /**
     * 网络图片转成base64
     *
     * @param url
     * @return
     * @throws Exception
     */
    public static byte[] encodeImageToByte(String url) throws Exception {
        //打开链接
        URL urls = new URL(url);
        HttpURLConnection conn = null;
        try {
            conn = (HttpURLConnection) urls.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            //得到图片的二进制数据，以二进制封装得到数据，具有通用性
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            //使用一个输入流从buffer里把数据读取出来
            while ((len = inStream.read(buffer)) != -1) {
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }
            //关闭输入流
            inStream.close();
            byte[] data = outStream.toByteArray();
            return data;
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception("解析失败!");
        }
    }




    public static void main(String argv[]) throws Exception{
//            ImageUtils.saveImageAsJpg("C:/test.jpg", "c:/test2.jpg", 179, 220,
//                    true);

            //		String s = ImageUtils.ImageToBase64("C:\\Users\\admin\\Desktop\\ryxp.jpg");
//		System.out.println(s);
//            String str = "normal://repository-builder/20190628/ehlZxEcjZp09UubZQugxug==@11";
//            //编码加密
//            String encodeStr = Base64.getEncoder().encodeToString(str.getBytes("UTF-8"));
//            System.out.println("加密后的字符串为:" + encodeStr);
//            //解码解密
//            String decoderStr = new String(Base64.getDecoder().decode(encodeStr), StandardCharsets.UTF_8); //
//            // 推荐使用StandardCharsets类指定
//            System.out.println("解密后的字符串为" + decoderStr);



            String tp="http://10.64.201.128:7266/xlpcAdminNew/requestservice/czrk/ryxp.jpg?sfzh=510502195403065021";
        String s = ImageUtils.encodeImageToBase64(tp);
        System.out.println(s);
    }
}
