FastDFS+java九宫格微信群聊头像

利用flex布局实现仿微信群的多头像九宫格自适应布局 利用flex布局实现微信群的多头像自适应布局 微信群聊的头像是多个成员的组合,例如下图。 可以看到根据单个小头像的大小可以分为三类,分别可以看做是整个大头像的98%,47%和31%。所以可以根据单个数组的长度,分别匹配不同的样式。而为了模拟后台返回的多头像接口,需要额外做一个判断,即最多只能显示9张头像。 <div id="app"> <div class="avata... 阅读详情

参考的工具类出自博客:https://www.jianshu.com/p/394f9b0357b3

我仅仅只是改了下:通过getCombinationOfhead方法返回的是 byte[] 字节数组,其它不变。(因为我要将图片上传到 FastDFS,然后通过FastDFS返回 url 链接)

public final class ImageUtil {

    /**
     * 图片的间隙
     */
    private static final int SIDE = 6;
    /**
     * 画板尺寸
     */
    private static final int CANVANS_W = 112;
    private static final int CANVANS_H = 112;

    /**
     * 尺寸1 (小)
     */
    private static final int ONE_IMAGE_SIZE = CANVANS_H - (2 * SIDE);
    /**
     * 尺寸2 (中)
     */
    private static final int TWO_IMAGE_SIZE = (CANVANS_H - (3 * SIDE)) / 2;
    /**
     * 尺寸3 (大)
     */
    private static final int FIVE_IMAGE_SIZE = (CANVANS_H - (4 * SIDE)) / 3;

    private ImageUtil() {
    }

    /**
     * 生成群组头像
     *
     * @param paths   图片链接
     * @return
     * @throws IOException
     */
    public static byte[] getCombinationOfhead(List<String> paths)
            throws IOException {
        List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();

        int imageSize = 0;
        if (paths.size() <= 1) {
            //若为一张图片
            imageSize = ONE_IMAGE_SIZE;
        } else if (paths.size() > 1 && paths.size() < 5) {
            //若为2-4张图片

            imageSize = TWO_IMAGE_SIZE;
        } else {
            //若>=5张图片
            imageSize = FIVE_IMAGE_SIZE;
        }

        for (int i = 0; i < paths.size(); i++) {
            BufferedImage resize2 = ImageUtil.resize2(paths.get(i), imageSize, imageSize, true);
            bufferedImages.add(resize2);
        }

        BufferedImage outImage = new BufferedImage(CANVANS_W, CANVANS_H, BufferedImage.TYPE_INT_RGB);

        // 生成画布
        Graphics g = outImage.getGraphics();

        Graphics2D g2d = (Graphics2D) g;

        // 设置背景色
        g2d.setBackground(new Color(231, 231, 231));

        // 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
        g2d.clearRect(0, 0, CANVANS_W, CANVANS_H);

        // 开始拼凑 根据图片的数量判断该生成那种样式的组合头像目前为九种

        for (int i = 1; i <= bufferedImages.size(); i++) {
            Integer size = bufferedImages.size();
            switch (size) {
                case 1:
                    g2d.drawImage(bufferedImages.get(i - 1), SIDE, SIDE, null);
                    break;
                case 2:
                    if (i == 1) {
                        g2d.drawImage(bufferedImages.get(i - 1), SIDE, (CANVANS_W - imageSize) / 2, null);
                    } else {
                        g2d.drawImage(bufferedImages.get(i - 1), 2 * SIDE + imageSize, (CANVANS_W - imageSize) / 2, null);
                    }
                    break;
                case 3:
                    if (i == 1) {
                        g2d.drawImage(bufferedImages.get(i - 1), (CANVANS_W - imageSize) / 2, SIDE, null);
                    } else {
                        g2d.drawImage(bufferedImages.get(i - 1), (i - 1) * SIDE + (i - 2) * imageSize, imageSize + (2 * SIDE), null);

                    }
                    break;
                case 4:

                    if (i <= 2) {
                        g2d.drawImage(bufferedImages.get(i - 1), i * SIDE + (i - 1) * imageSize, SIDE, null);

                    } else {
                        g2d.drawImage(bufferedImages.get(i - 1), (i - 2) * SIDE + (i - 3) * imageSize, imageSize + 2 * SIDE, null);

                    }
                    break;
                case 5:
                    if (i <= 2) {
                        g2d.drawImage(bufferedImages.get(i - 1), (CANVANS_W - 2 * imageSize - SIDE) / 2 + (i - 1) * imageSize + (i - 1) * SIDE, (CANVANS_W - 2 * imageSize - SIDE) / 2, null);

                    } else {
                        g2d.drawImage(bufferedImages.get(i - 1), (i - 2) * SIDE + (i - 3) * imageSize, ((CANVANS_W - 2 * imageSize - SIDE) / 2) + imageSize + SIDE, null);

                    }
//
                    break;
                case 6:
                    if (i <= 3) {
                        g2d.drawImage(bufferedImages.get(i - 1), SIDE * i + imageSize * (i - 1), (CANVANS_W - 2 * imageSize - SIDE) / 2, null);
                    } else {
                        g2d.drawImage(bufferedImages.get(i - 1), ((i - 3) * SIDE) + ((i - 4) * imageSize), ((CANVANS_W - 2 * imageSize - SIDE) / 2) + imageSize + SIDE, null);
                    }
                    break;
                case 7:
                    if (i <= 1) {
                        g2d.drawImage(bufferedImages.get(i - 1), 2 * SIDE + imageSize, SIDE, null);
                    }
                    if (i <= 4 && i > 1) {
                        g2d.drawImage(bufferedImages.get(i - 1), ((i - 1) * SIDE) + ((i - 2) * imageSize), 2 * SIDE + imageSize, null);
                    }
                    if (i <= 7 && i > 4) {
                        g2d.drawImage(bufferedImages.get(i - 1), ((i - 4) * SIDE) + ((i - 5) * imageSize), 3 * SIDE + 2 * imageSize, null);
                    }
                    break;
                case 8:
                    if (i <= 2) {
                        g2d.drawImage(bufferedImages.get(i - 1), (CANVANS_W - 2 * imageSize - SIDE) / 2 + (i - 1) * imageSize + (i - 1) * SIDE, SIDE, null);
                    }
                    if (i <= 5 && i > 2) {
                        g2d.drawImage(bufferedImages.get(i - 1), ((i - 2) * SIDE) + ((i - 3) * imageSize), 2 * SIDE + imageSize, null);
                    }
                    if (i <= 8 && i > 5) {
                        g2d.drawImage(bufferedImages.get(i - 1), ((i - 5) * SIDE) + ((i - 6) * imageSize), 3 * SIDE + 2 * imageSize, null);
                    }
                    break;
                case 9:
                    if (i <= 3) {
                        g2d.drawImage(bufferedImages.get(i - 1), (i * SIDE) + ((i - 1) * imageSize), SIDE, null);
                    }
                    if (i <= 6 && i > 3) {
                        g2d.drawImage(bufferedImages.get(i - 1), ((i - 3) * SIDE) + ((i - 4) * imageSize), 2 * SIDE + imageSize, null);
                    }
                    if (i <= 9 && i > 6) {
                        g2d.drawImage(bufferedImages.get(i - 1), ((i - 6) * SIDE) + ((i - 7) * imageSize), 3 * SIDE + 2 * imageSize, null);
                    }
                    break;
                default:
                    break;
            }
        }

        //将BufferedImage转为byte[]字节数组
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(outImage, "jpg", baos );
        baos.flush();
        byte[] imageInByte = baos.toByteArray();
        baos.close();
        return imageInByte;
    }

    /**
     * 图片缩放
     *
     * @param filePath 图片路径
     * @param height   高度
     * @param width    宽度
     * @param bb       比例不对时是否需要补白
     */
    public static BufferedImage resize2(String filePath, int height, int width,
                                        boolean bb) {
        try {
            double ratio = 0; // 缩放比例
            BufferedImage bi = null;
            if (filePath.indexOf("http://") == 0) {
                bi = ImageIO.read(new URL(filePath));
            } else {
                bi = ImageIO.read(new File(filePath));
            }
            Image itemp = bi.getScaledInstance(width, height,
                    Image.SCALE_SMOOTH);
            // 计算比例
            if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
                if (bi.getHeight() > bi.getWidth()) {
                    ratio = (new Integer(height)).doubleValue() / bi.getHeight();
                } else {
                    ratio = (new Integer(width)).doubleValue() / bi.getWidth();
                }
                AffineTransformOp op = new AffineTransformOp(
                        AffineTransform.getScaleInstance(ratio, ratio), null);
                itemp = op.filter(bi, null);
            }
            if (bb) {
                BufferedImage image = new BufferedImage(width, height,
                        BufferedImage.TYPE_INT_RGB);
                Graphics2D g = image.createGraphics();
                g.setColor(Color.white);
                g.fillRect(0, 0, width, height);
                if (width == itemp.getWidth(null)) {
                    g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
                            itemp.getWidth(null), itemp.getHeight(null),
                            Color.white, null);
                } else {
                    g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
                            itemp.getWidth(null), itemp.getHeight(null),
                            Color.white, null);
                }
                g.dispose();
                itemp = image;
            }
            return (BufferedImage) itemp;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

关于FastDFS与SpringBoot的配置可以看该博文:https://blog.youkuaiyun.com/xyang81/article/details/52850667

使用的FastDFS版本:

<dependency>
	<groupId>com.github.tobato</groupId>
	<artifactId>fastdfs-client</artifactId>
	<version>1.26.2</version>
</dependency>

在FastDFSClientWrapper中 新增了一个方法:(其实只是把入参变成了 byte[])

@Component
public class FastDFSClientWrapper {

    @Autowired
    private FastFileStorageClient storageClient;

    /**
     * 上传byte[]字节数组
     */
    public String uploadFile(byte[] buff, String fileExtension) {
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream,buff.length, fileExtension,null);
        return getResAccessUrl(storePath);
    }

    // 封装图片URL地址
    private String getResAccessUrl(StorePath storePath) {
        return storePath.getFullPath();
    }
}

然后就可以使用了:

@RestController
@RequestMapping("/")
public class GroupsController {
    
    @Autowired
    private FastDFSClientWrapper dfsClient;


    /**
     * @param picUrls FastDFS上的图片链接集合
     * @return 返回图片在FastDFS上的url链接
     */
    private String init9Pic(List<String> picUrls){
        try {
            //生成九宫格群组头像
            byte[] buff = ImageUtil.getCombinationOfhead(picUrls);
            //上传到FastDFS
            String url = dfsClient.uploadFile(buff,"jpg");
            if(!Objects.equals(url, "")){
                return url;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
     
}

搞定:        

Uniapp实现微信群聊头像|九宫格合并图片 【代码】Uniapp实现微信群聊头像|九宫格合并图片。 阅读详情

相关推荐

9宫格 java_java 拼接头像9宫格

java后台拼接9宫格头像和添加水印文字,效果: 参考:https://blog.youkuaiyun.com/shichen88/article/details/1012935411、拼接工具类:package com.bai.blog.utils.files;import javax.imageio.ImageIO;import java.awt.*;import java.awt.geom.A...

weixin_42514627的博客 549

JAVA生成九宫格图片 微信群头像(不限制张数)拿走即可用

废话不多说 先上效果 再上代码 package cn.specil.util.file; import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.Bu...

weixin_41712724的博客 5316

Java 生成微信群头像 九宫格头像

通过获取用户网络路径地址的 头像.生成一张网络路径的九宫格头像. dir是网络服务器路径import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; im

刘弘扬的博客 8461

(显示示图像)请写一个程序,在一个网格面板里面显示 4 个图像,如图 14-43a 所示。JavaFX实现

import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene

Code->Y的博客 1022

Android-仿微信群头像九宫格控件

仿微信群头像九宫格控件 一、简介: 参照Android 仿微信群聊头像文章学习开发的一个仿微信群头像九宫格控件

微信群组九宫图java后台生成

java实现防微信群组头像 参考:http://download.youkuaiyun.com/detail/tiantianshangcha/5891775

java 微信群组头像_仿微信生成群组头像

背景项目中涉及到群组聊天的功能,由于前期项目比较紧张,群组头像并没有按照群成员头像去自动生成,即类似微信群组头像的效果,今天进行一下效果优化,效果如下:仿微信生成群组头像实现步骤获取群组成员头像可以采用开源图片加载库把图片加载至本地即可。说明一下,这里并没有在线去加载头像,而是考虑到在其它地方有单独加载头像的地方,所以头像都是从本地直接读取。生成群组头像先上代码public Bitmap gene...

weixin_33040687的博客 994

微信群聊生成九宫格形式的头像

微信群聊生成九宫格形式的头像 [注意:本资源来自网络,如有侵权,请联系我删除,谢谢。]

Java生成微信群组图标

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34262482的博客 447

4、设备树的处理(1)

其实到第4节才写设备树的问题完全是因为忘记了,之前有一个版本是先关闭了设备树的,习惯性的认为设备树已经处理完了,失误了!!!前文说过,这个系统是依着荣品的开发板和核心板来的,使用的是5.1内核的SDK。它的SDK里是开发板全功能的,所以设备树也是的。

wsen2012的博客 417

2024银行科技岗笔试通关秘籍:从资料准备到实战技巧

本文系统解析了2024年银行科技岗笔试的考察内容与备考策略。文章指出,笔试是一场涵盖通用能力测试、计算机专业基础、金融科技知识和英语性格测试的复合型考试,并重点提供了数据结构与算法、计算机网络、数据库等高频考点的深度解析与实战突破技巧,帮助考生高效准备,顺利通关。

weixin_29243279的博客 122

图像合成 - Java实现仿微信群聊头像

java实现仿微信QQ群聊头像图片合成,根据群聊内的用户头像合成群聊头像,九宫格图。

以夢爲馬的博客 1408

告别效率低谷:用ADS仿真手把手教你设计高回退Doherty功放(附1:2非对称案例)

本文详细解析了如何使用ADS仿真设计高回退Doherty功放,特别针对1:2非对称架构进行深入探讨。通过优化功率分配比、峰值管开启阈值等关键参数,显著提升功放在9dB回退点的效率至75%以上,适用于LTE等高PAPR信号场景。文章还提供了ADS仿真环境搭建、参数优化及工程化设计的实用技巧。

weixin_33743248的博客 457

java模仿微信QQ群聊头像拼接,根据群聊内的用户头像拼接群聊头像,九宫格

java模仿微信QQ群聊头像拼接,根据群聊内的用户头像拼接群聊头像,九宫格 效果图 附带测试 package im.bide.utils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp;...

qq_40618664的博客 2701

集成电路模拟版图入门-版图基础学习笔记(四)

第三部分:版图的准备 2. 设计规则 3) Design Rule 2. 设计规则 4) 规则定义 4.1 NW(N WELL) 2. 设计规则 4) 规则定义 4.1 NW(N WELL) 2. 设计规则 4) 规则定义 4.2 PO(Poly) 2. 设计规则 4) 规则定义 4.3 M1(Metal1) 2. 设计规则 4) 规则定义 4.4 VIA 3. DRC文件 3.1 DRC:Design Rule Check,设计规则检查。 3.2 DRC程序了解有关

weixin_52955333的博客 6737

CASS3D实战:高效三维房屋与地形采集绘制技巧

本文详细介绍了CASS3D在三维房屋与地形采集绘制中的高效技巧,包括智能绘房功能、不规则结构处理、特殊构件快速绘制及地形数据采集策略。通过实战案例和进阶操作指南,帮助用户快速掌握CASS3D的核心功能,提升三维采集与绘制效率。

weixin_29216049的博客 868

java 拼接头像9宫格

java后台拼接9宫格头像和添加水印文字,效果: 参考:https://blog.youkuaiyun.com/shichen88/article/details/101293541 1、拼接工具类: package com.bai.blog.utils.files; import javax.imageio.ImageIO; import java.awt.*; import jav...

漠天的博客 937

概率的接力:拆解大模型“预测下一个词“的底层逻辑

大模型的智能不在于它拥有了意识,而在于它用纯数学的架构,将人类语言的复杂结构压缩为可计算的向量轨迹与概率接力。当我们不再将其拟人化为"思考者",而是视作高维条件概率引擎时,才能真正驾驭它。预测下一个词,从来不是终点,而是起点。未来的核心竞争力,属于那些能洞察其统计本质、善用其模式生成能力,并以人类理性与事实为锚点的协作者。词元的轨迹终会止步于上下文窗口,但对技术底层的清醒认知,才是跨越幻觉、走向真实智能的基石。

AI浩 331

微信群聊生成九宫格形式的头像 css (小程序,vue需改动wxml少量代码)

<view class="item-img"> <image class="item-img-img{{item.voucher_image.length}}" wx:for="{{item.voucher_image}}" wx:for-item="it" wx:for-index="idx" wx:key="idx" src="{{it}}"></image> </view> .item .item-img { width: 580rpx;.

qq_36545095的博客 2682

【ARM Coresight | AMBA BUS | Cache 与 MMU/MPU | CoreLink | GCC | CSH 专栏导读】

1. ARM Coresight(SoC-400/SoC-600) 专栏 2. ARMv8/v9 CPU/Cache 专栏 3. Linux ARM AMBA 总线 专栏 4. Trace32/DS-5 专栏。。。

CodingCos的博客 8241

数字电视中的AD(Audio Description)音频描述技术详解

AD(Audio Description)音频描述是一种辅助技术,旨在帮助视障人士更好地理解视觉内容。通过在节目或视频的自然停顿处插入额外的语音叙述来解释屏幕上的视觉信息,如人物动作、场景变化、文字说明等,从而让视力受损的人士也能获得完整的观影体验。AD服务不仅限于电视广播,也广泛应用于电影、剧院表演、在线视频平台等领域。PID:用于标识和区分不同的音频流。PMT表:提供每个音频流的详细信息,包括PID、编解码器类型和语言代码。时间戳:PTS和DTS用于同步音频与视频内容。解复用。

以实战经验介绍行业知识 741

Android自定义控件---仿微信群聊(九宫格)头像

高仿微信群聊(九宫格)头像

生命欣欣向荣,唯奋斗不息! 7642

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

仿微信的群组九宫格头像

仿微信的群组九宫格头像 github地址:WeChatGroupAvatar 优点: 使用Bitmap合成的方式,而非九宫格里面具有九张图片。这样子的好处是对于图片加载不会出现一张张图片依次出现,刷新的时候不会有掉帧的感觉。 提供了异步和同步获取的方法 外部自定义组合Bitmap的那些Url地址的方式,比如你是使用Glide还是使用HttpUrlConnection都可以。 使用 依赖: im...

weixin_34290352的博客 1855

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

类似微信群聊九宫格头像的算法实现

在工作中遇到了一个开发的需求是将多选的图片聚合起来,类似于微信群聊那种九宫格的头像的那种。当然遇到这个需求首先肯定会从网上查找一些资料,发现大部分的实现类似于通过定义九宫格的ImageView控件来实现,这样一来,实际上图片没有被压缩,而且还生成了一大堆的控件,对内存性能效果是很大的。 既然网上没有合适好的算法方案,那不如自己来实现一个吧,通过分析头像的的形成的原理主要有如下的几个规律:1、当图...

weixin_33887443的博客 1290

java实现微博九宫格图片切分

通过java图片处理,实现微博的九宫格效果,使用简单,毕竟只是个偏移量,不一定高效

dpsp 2507
上一篇: IDEA 2017.2.3 找回Run Dashboard
下一篇: 融云Java服务端(好友、群组)
why_su
博客等级 码龄10年 86粉丝 38原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值