package com.sifang.modules.customer.utils;


import com.jhlabs.image.PixelUtils;
import com.sifang.modules.esign.cn.tsign.hz.comm.FileTransformation;
import com.sifang.modules.sys.common.utils.IdGen;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Kernel;
import java.io.*;
import java.util.Hashtable;
import java.util.UUID;

/**
 * 给图片添加蒙版方法
 */
public class MyGaussianFilterUtil {

    public static int CLAMP_EDGES = 1;
    public static int WRAP_EDGES = 2;
    protected Kernel kernel;
    protected boolean alpha = false;
    protected boolean premultiplyAlpha = false;

    protected float radius;

    public MyGaussianFilterUtil() {
        this(2.0F);
    }

    public MyGaussianFilterUtil(float radius) {
        this.setRadius(radius);
    }

    public void setRadius(float radius) {
        this.radius = radius;
        this.kernel = makeKernel(radius);
    }

    public float getRadius() {
        return this.radius;
    }

    public BufferedImage filter(BufferedImage src, BufferedImage dst) {
        int width = src.getWidth();
        int height = src.getHeight();
        if (dst == null) {
            dst = this.createCompatibleDestImage(src, (ColorModel)null);
        }

        int[] inPixels = new int[width * height];
        int[] outPixels = new int[width * height];
        src.getRGB(0, 0, width, height, inPixels, 0, width);
        if (this.radius > 0.0F) {
            //这里是对图片进行处理
            convolveAndTranspose(this.kernel, inPixels, outPixels, width, height, this.alpha, this.alpha && this.premultiplyAlpha, false, CLAMP_EDGES, 1);
            convolveAndTranspose(this.kernel, outPixels, inPixels, height, width, this.alpha, false, this.alpha && this.premultiplyAlpha, CLAMP_EDGES, 2);
        }

        dst.setRGB(0, 0, width, height, inPixels, 0, width);
        return dst;
    }

    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
        if (dstCM == null) {
            dstCM = src.getColorModel();
        }

        return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), (Hashtable)null);
    }

    public static Kernel makeKernel(float radius) {
        int r = (int)Math.ceil((double)radius);
        int rows = r * 2 + 1;
        float[] matrix = new float[rows];
        float sigma = radius / 3.0F;
        float sigma22 = 2.0F * sigma * sigma;
        float sigmaPi2 = 6.2831855F * sigma;
        float sqrtSigmaPi2 = (float)Math.sqrt((double)sigmaPi2);
        float radius2 = radius * radius;
        float total = 0.0F;
        int index = 0;

        int i;
        for(i = -r; i <= r; ++i) {
            float distance = (float)(i * i);
            if (distance > radius2) {
                matrix[index] = 0.0F;
            } else {
                matrix[index] = (float)Math.exp((double)(-distance / sigma22)) / sqrtSigmaPi2;
            }

            total += matrix[index];
            ++index;
        }

        for(i = 0; i < rows; ++i) {
            matrix[i] /= total;
        }

        return new Kernel(rows, 1, matrix);
    }

    public static void convolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, boolean alpha, boolean premultiply, boolean unpremultiply, int edgeAction,
                                            int type) {
        float[] matrix = kernel.getKernelData((float[])null);
        int cols = kernel.getWidth();
        int cols2 = cols / 2;

        int y = 0;
        //这里的height相当于要模糊图片的width（x轴），默认从0开始，我们修改这里的开始值，就能定义模糊位置
        if (type == 2) {
            y = height/3;
        }

        for(; y < height; ++y) {
            int index = y;
            int ioffset = y * width;

            for(int x = 0; x < width; ++x) {
                float r = 0.0F;
                float g = 0.0F;
                float b = 0.0F;
                float a = 0.0F;
                int moffset = cols2;

                int ia;
                int ix;
                int rgb;
                for(ia = -cols2; ia <= cols2; ++ia) {
                    float f = matrix[moffset + ia];
                    if (f != 0.0F) {
                        ix = x + ia;
                        if (ix < 0) {
                            if (edgeAction == CLAMP_EDGES) {
                                ix = 0;
                            } else if (edgeAction == WRAP_EDGES) {
                                ix = (x + width) % width;
                            }
                        } else if (ix >= width) {
                            if (edgeAction == CLAMP_EDGES) {
                                ix = width - 1;
                            } else if (edgeAction == WRAP_EDGES) {
                                ix = (x + width) % width;
                            }
                        }

                        rgb = inPixels[ioffset + ix];
                        int pa = rgb >> 24 & 255;
                        int pr = rgb >> 16 & 255;
                        int pg = rgb >> 8 & 255;
                        int pb = rgb & 255;
                        if (premultiply) {
                            float a255 = (float)pa * 0.003921569F;
                            pr = (int)((float)pr * a255);
                            pg = (int)((float)pg * a255);
                            pb = (int)((float)pb * a255);
                        }

                        a += f * (float)pa;
                        r += f * (float)pr;
                        g += f * (float)pg;
                        b += f * (float)pb;
                    }
                }

                if (unpremultiply && a != 0.0F && a != 255.0F) {
                    float f = 255.0F / a;
                    r *= f;
                    g *= f;
                    b *= f;
                }

                ia = alpha ? PixelUtils.clamp((int)((double)a + 0.5D)) : 255;
                int ir = PixelUtils.clamp((int)((double)r + 0.5D));
                ix = PixelUtils.clamp((int)((double)g + 0.5D));
                rgb = PixelUtils.clamp((int)((double)b + 0.5D));
                outPixels[index] = ia << 24 | ir << 16 | ix << 8 | rgb;
                index += height;
            }
        }

    }

    public static void  filter(String path,String savepath){
        try {
            MyGaussianFilterUtil gaussianFilter = new MyGaussianFilterUtil();
            BufferedImage fromImage = ImageIO.read(new File(path));
            BufferedImage toImage = new BufferedImage(fromImage.getWidth(), fromImage.getHeight(),BufferedImage.TYPE_INT_RGB);
            gaussianFilter.setRadius(140);
            gaussianFilter.filter(fromImage, toImage);
            //  ImageIO.write(toImage, "jpg", new File(savepath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归删除目录下的所有文件及子目录下所有文件
     * @param dir 将要删除的文件目录
     * @return boolean Returns "true" if all deletions were successful.
     *                 If a deletion fails, the method stops attempting to
     *                 delete and returns "false".
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空，可以删除
        return dir.delete();
    }

    public static String getImageEncode(String imgPath,String filePath) {// 将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        String imgFile = imgPath;// 待处理的图片
        InputStream in = null;
        byte[] data = null;
        String encode = null; // 返回Base64编码过的字节数组字符串
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        try {
            // 读取图片字节数组
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            encode = encoder.encode(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        deleteDir(new File(filePath));
        return encode;
    }

    public static void getFilterBytes(){
        try {
            String filePath = System.getProperty("user.dir") + File.separator + "tempfile"+ File.separator + UUID.randomUUID().toString()+File.separator;
            File file = new File(filePath);
            if(!file.exists()){
                file.mkdirs();
            }
            // byte[] bytes =FileTransformation.fileToBytes("D:\\20230602165828.jpg");
            //给图片添加蒙版

            long begin = System.currentTimeMillis();
            String savepath =filePath+ IdGen.uuid()+".jpg";
            MyGaussianFilterUtil.filter("D:\\20230523151752.jpg",savepath);
            System.out.println(savepath);
            long end = System.currentTimeMillis();
            System.out.println("下推结束，共耗时：[" + (end-begin) / 1000 + "]秒");
            //合并图片
            //  String bigPath = filePath+ UUID.randomUUID().toString()+".jpg";
            //  MergeImageUtil.mergeImage(bytes,bigPath,savepath,"325","390");
            // return getImageEncode(bigPath,filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {

        try {


            MyGaussianFilterUtil.getFilterBytes();
            //  FileUtil.decoderBase64File(filterBytes,"E:\\workspace\\fline_work\\js\\file\\"+UUID.randomUUID().toString()+".jpg");
//            System.out.println(filterBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}