package com.izouma.awesomeadmin.util;

import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.*;
import java.util.Iterator;

import sun.misc.BASE64Decoder;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;


public class ImagesUtil {

    //base64字符串转化成图片

    /**
     * <p>base64字符串转化成图片流。</p>
     *
     * @param imgStr
     * @return
     */
    public static InputStream GenerateImage(String imgStr) { //对字节数组字符串进行Base64解码并生成图片

        if (imgStr == null) //图像数据为空
            return null;
        imgStr = imgStr.substring(imgStr.indexOf(',') + 1);

        try {
            //Base64解码
            // byte[] b = Base64.getDecoder().decode(imgStr);
            byte[] b = new BASE64Decoder().decodeBuffer(imgStr);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {//调整异常数据
                    b[i] += 256;
                }
            }
            InputStream sbs = new ByteArrayInputStream(b);
            //生成jpeg图片
            //            out.write();
            //            out.flush();
            //            out.close();
            //            //生成jpeg图片
            //            InputStream in = null;
            return sbs;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 等比例压缩算法：
     * 算法思想：根据压缩基数和压缩比来压缩原图，生产一张图片效果最接近原图的缩略图
     *
     * @param fin       原图
     * @param imageType 图片类型
     * @param comBase   压缩基数
     * @param scale     压缩限制(宽/高)比例  一般用1：
     *                  当scale>=1,缩略图height=comBase,width按原图宽高比例;若scale<1,缩略图width=comBase,height按原图宽高比例
     * @throws Exception
     */
    public static InputStream changeMinPhoto(InputStream fin, String imageType, double comBase,
                                             double scale) {
        try {
            // get image format in a file
            //File file = new File("newimage.jpg");

            // create an image input stream from the specified file
            ImageInputStream iis = ImageIO.createImageInputStream(fin);

            Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
            if (readers == null || !readers.hasNext()) {
                throw new RuntimeException("1 No ImageReaders found");
            }
            ImageReader reader = (ImageReader) readers.next();
            reader.setInput(iis);
            String format = reader.getFormatName();
            BufferedImage image = null;

            if ("JPEG".equalsIgnoreCase(format) || "JPG".equalsIgnoreCase(format)|| "PNG".equalsIgnoreCase(format)) {
                try {
                    // 尝试读取图片 (包括颜色的转换).
                    image = reader.read(0); //RGB
                } catch (IIOException e) {
                    // 读取Raster (没有颜色的转换).
                    Raster raster = reader.readRaster(0, null);//CMYK
                    image = createJPEG4(raster);
                }
            }

            int srcHeight = image.getHeight();
            int srcWidth = image.getWidth(null);
            int deskHeight = 0;// 缩略图高
            int deskWidth = 0;// 缩略图宽
            double srcScale = (double) srcHeight / srcWidth;
            /**缩略图宽高算法*/
            if ((double) srcHeight > comBase || (double) srcWidth > comBase) {
                if (srcScale >= scale || 1 / srcScale > scale) {
                    if (srcScale >= scale) {
                        deskHeight = (int) comBase;
                        deskWidth = srcWidth * deskHeight / srcHeight;
                    } else {
                        deskWidth = (int) comBase;
                        deskHeight = srcHeight * deskWidth / srcWidth;
                    }
                } else {
                    if ((double) srcHeight > comBase) {
                        deskHeight = (int) comBase;
                        deskWidth = srcWidth * deskHeight / srcHeight;
                    } else {
                        deskWidth = (int) comBase;
                        deskHeight = srcHeight * deskWidth / srcWidth;
                    }
                }
            } else {
                deskHeight = srcHeight;
                deskWidth = srcWidth;
            }
            BufferedImage tag = new BufferedImage(deskWidth, deskHeight, BufferedImage.TYPE_3BYTE_BGR);
            tag.getGraphics().drawImage(image, 0, 0, deskWidth, deskHeight, null); //绘制缩小后的图

            //BufferedImage 转 InputStream
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);
            ImageIO.write(tag, imageType, imageOutput);
            InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            return inputStream;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    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);
    }
}
