package com.qs.mp.common.image;

import com.qs.mp.common.utils.LogUtil;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 压缩工具类
 *
 * @author zhongcp
 * @Date 2022/4/16
 */
public class CompressUtil {

  protected static final Logger logger = LoggerFactory.getLogger(CompressUtil.class);

  private static final Integer ZERO = 0;
  private static final Integer ONE_ZERO_TWO_FOUR = 1024;
  private static final Integer NINE_ZERO_ZERO = 400;
  private static final Integer THREE_TWO_SEVEN_FIVE = 2047;
  private static final Integer TWO_ZERO_FOUR_SEVEN = 900;
  private static final Double ZERO_EIGHT_FIVE = 0.85;
  private static final Double ZERO_SIX = 0.6;
  private static final Double ZERO_FOUR_FOUR = 0.44;
  private static final Double ZERO_FOUR = 0.4;

  /**
   * 根据指定大小压缩图片
   *
   * @param imageBytes  源图片字节数组
   * @param desFileSize 指定图片大小，单位kb
   * @return 压缩质量后的图片字节数组
   */
  public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
    if (imageBytes == null || imageBytes.length <= ZERO
        || imageBytes.length < desFileSize * ONE_ZERO_TWO_FOUR) {
      return imageBytes;
    }
    long srcSize = imageBytes.length;
    double accuracy = getAccuracy(srcSize / ONE_ZERO_TWO_FOUR);
    try {

      ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
      while (imageBytes.length > desFileSize * ONE_ZERO_TWO_FOUR) {
        ByteArrayInputStream inputStream = null;
        try {
          inputStream = new ByteArrayInputStream(imageBytes);
          Thumbnails.of(inputStream)
              .scale(accuracy)
              .outputQuality(accuracy)
              .toOutputStream(outputStream);
          imageBytes = outputStream.toByteArray();
        } finally {
          if (null != inputStream) {
            inputStream.close();
          }
        }
      }
      LogUtil.info(logger, "图片原大小={}kb | 压缩后大小={}kb",
          srcSize / ONE_ZERO_TWO_FOUR, imageBytes.length / ONE_ZERO_TWO_FOUR);
    } catch (Exception e) {
      LogUtil.error(logger, "【图片压缩】msg=图片压缩失败!", e);
    }
    return imageBytes;
  }

  /**
   * 自动调节精度(经验数值)
   *
   * @param size 源图片大小
   * @return 图片压缩质量比
   */
  public static double getAccuracy(long size) {
    double accuracy;
    if (size < NINE_ZERO_ZERO) {
      accuracy = ZERO_EIGHT_FIVE;
    } else if (size < TWO_ZERO_FOUR_SEVEN) {
      accuracy = ZERO_SIX;
    } else if (size < THREE_TWO_SEVEN_FIVE) {
      accuracy = ZERO_FOUR_FOUR;
    } else {
      accuracy = ZERO_FOUR;
    }
    return accuracy;
  }
}
