java实现图片压缩功能

最近的业务里有一个场景:需要通过接口传递图片的base64字符串实现图片的上传功能,但众所周知,即使是post请求,也对报文的大小有所限制,而图片的base64字符串有多长呢,如果不是很清楚的话,可以打印出来看一下。
因此,需要将图片进行压缩,使大小控制在可行的范围内,再转成base64字符串,通过接口进行传输。
具体实现代码如下:

@Slf4j
public class ImageUtilJnb {
    private static int mb = 1048576;// 1MB

    public static void main(String[] args) {
        String fullPath="D:\\123.jpg";
        String newPath="D:\\321322198511205873F.jpg";

        long length = new File(fullPath).length();
        if (length / 1048576 >= JnbConstants.JNB_IMAGE_RATE) {// 如果图片大于等于0.5MB 则按80%缩小
            try {
                ImageUtilJnb.zoom(fullPath, newPath, length, JnbConstants.JNB_IMAGE_RATE);
            } catch (IOException e) {
                log.error("出错啦:" + e);
            }
        }

        String base64Str = Base64Util.getBase64Str(newPath);
        System.out.println("base64Str===" + base64Str);

    }

    // 缩图
    public static void zoom(String oldFile, String zoomFile,long length,double newRate) throws IOException {
        DecimalFormat df = new DecimalFormat("0.00");// 设置保留位数
        double rate=0.8;
        log.info("原始图片大小:" + df.format((float) length / mb) + "MB");
        long newfile = new File(oldFile).length();
        int i = 1;
        // 如果首次压缩还大于2MB则继续处理
        while ((float) newfile / mb >= newRate) {
            log.info("压缩后图片大小:" + newfile);
            rate = rate - 0.05;// 暂定按照0.03频率压缩
            log.info(i + " rate=" + rate);
            BufferedImage srcImage = ImageIO.read(new File(oldFile));
            int WIDTH = (int) (srcImage.getWidth() * rate);
            int HEIGHT = (int) (srcImage.getHeight() * rate);
            BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
            Graphics g = image.getGraphics();
            g.drawImage(srcImage, 0, 0, WIDTH, HEIGHT, null);
            // 缩小
            ImageIO.write(image, "jpg", new File(zoomFile));
            i++;
            newfile = new File(zoomFile).length();
            log.info("压缩次数:" + i);
        }
        // 调整方向
         BufferedImage newImage = ImageIO.read(new File(zoomFile));
         BufferedImage image1 = Rotate(newImage, 90);// 顺时针旋转90度
         ImageIO.write(image1, "jpg", new File(zoomFile));
        log.info("处理后图片路径:" + zoomFile + ";缩小之后大小:"
                + df.format((float) new File(zoomFile).length() / mb) + "MB");
    }

    /**
     * 对图片进行旋转
     *
     * @param src
     *            被旋转图片
     * @param angel
     *            旋转角度
     * @return 旋转后的图片
     */
    public static BufferedImage Rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // 计算旋转后图片的尺寸
        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();
        // 进行转换
        g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

        g2.drawImage(src, null, null);
        return res;
    }

    /**
     * 计算旋转后的图片
     *
     * @param src
     *            被旋转的图片
     * @param angel
     *            旋转角度
     * @return 旋转后的图片
     */
    public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        // 如果旋转的角度大于90度做相应的转换
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,535评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,106评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 171,668评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,863评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,874评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,362评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,748评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,717评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,249评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,280评论 3 345
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,408评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,020评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,727评论 3 337
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,191评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,320评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,946评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,473评论 2 365

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,119评论 1 32
  • 1、截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的数据,分别输出它们 ...
    强子ly阅读 2,963评论 8 46
  • 简书已停更,欢迎转到个人博客查看对应教程:https://www.cnblogs.com/superhin/p/1...
    韩志超阅读 46,955评论 6 214
  • Web 页面的实现 Web 基于 HTTP 协议通信 客户端(Client)的 Web 浏览器从 Web 服务器端...
    毛圈阅读 1,097评论 0 2
  • 参考文献链表翻转的图文讲解(递归与迭代两种实现)
    四喜汤圆阅读 239评论 0 0