java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解

简介: 这篇文章介绍了如何使用Java的Graphics2D类在图片上合成另一个照片,并将照片切割成圆形头像的方法。

前言

  1. 文字换行算法详解,传送门:java制作海报一:java使用Graphics2D 在图片上写字,文字换行算法详解
  2. 头像切割成圆形方法详解,传送门:java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
  3. 获取微信二维码详情,传送门:java制作海报三:获取微信二维码详情,并改变大小,合成到海报(另一张图片)上
  4. java BufferedImage 转 InputStreampng 图片合成到模板(另一个图片)上时,透明部分变成了黑色,传送门:java制作海报四:java BufferedImage 转 InputStream 上传至OSS。png 图片合成到模板(另一个图片)上时,透明部分变成了黑色
  5. java 整合echarts 画出 折线图,传送门:
  6. Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题,传送门:java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
  7. 项目部署到linux下中文不显示,echarts图上的中文也不显示问题,传送门:java制作海报七:java Graphics2D 合成图片 在 linux下中文不显示,echarts图上的中文也不显示问题
  • 本次博客主要是 稍微说一下头像切割成圆形方法,这里的代码都在 PosterUtil.java

一、核心代码

    /**
     * @return java.awt.image.BufferedImage
     * @Author fengfanli
     * @Description //TODO 将正方形的头像 改为 圆形头像
     * @Date 14:37 2021/3/31
     * @Param [imgUrl, width]
     **/
    public static BufferedImage drawImgToCircle(String imgUrl, int width) throws IOException {
        BufferedImage avatarImage = ImageIO.read(new URL(imgUrl));
        //int width = 120;
        // 透明底的图片
        BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = formatAvatarImage.createGraphics();
        //把图片切成一个圓
        {
            // 抗锯齿
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            //留一个像素的空白区域,这个很重要,画圆的时候把这个覆盖
            int border = 1;
            //图片是一个圆型
            Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
            //需要保留的区域
            graphics.setClip(shape);
            graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
            graphics.dispose();
        }
        return formatAvatarImage;
    }

二、测试代码,可直接生成

package com.feng.controller;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;

/**
 * Created by zengrenyuan on 18/5/29.
 */
/**
 * @Author fengfanli
 * @Description //TODO 将头像画成圆形
 * @Date 18:29 2021/4/7
 * @Param 
 * @return 
 **/
public class Test3_HeadImageToCircle {

    /**
     * @Author fengfanli
     * @Description //TODO 将一个头像 变成圆形
     * @Date 18:11 2021/4/8
     * @Param [args]
     * @return void
     **/
    public static void main(String[] args) throws IOException {
        String url = "https://img-blog.csdn.net/20180529211243786?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3plbmdyZW55dWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/7";
        BufferedImage avatarImage = ImageIO.read(new URL(url));
        int width = 120;
        // 透明底的图片
        BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = formatAvatarImage.createGraphics();
        //把图片切成一个圓
        {
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            //留一个像素的空白区域,这个很重要,画圆的时候把这个覆盖
            int border = 1;
            //图片是一个圆型
            Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
            //需要保留的区域
            graphics.setClip(shape);
            graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
            graphics.dispose();
        }
        try (OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\test2.png")) {
            ImageIO.write(formatAvatarImage, "PNG", os);
        }
        //在圆图外面再画一个圆
        {
            //新创建一个graphics,这样画的圆不会有锯齿
            graphics = formatAvatarImage.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            int border = 3;
            //画笔是4.5个像素,BasicStroke的使用可以查看下面的参考文档
            //使画笔时基本会像外延伸一定像素,具体可以自己使用的时候测试
            Stroke s = new BasicStroke(4.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            graphics.setStroke(s);
            graphics.setColor(Color.WHITE);
            graphics.drawOval(border, border, width - border * 2, width - border * 2);
            graphics.dispose();
        }
        try (OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\test3.png")) {
            ImageIO.write(formatAvatarImage, "PNG", os);
        }
        {
            url = "https://img-blog.csdn.net/20180529213113521";
            BufferedImage srcImg = ImageIO.read(new URL(url));
            //scrImg加载完之后没有任何颜色
            BufferedImage blankImage = new BufferedImage(srcImg.getWidth(), srcImg.getHeight(), BufferedImage.TYPE_INT_RGB);
            graphics = blankImage.createGraphics();
            graphics.drawImage(srcImg, 0, 0, null);

            int x = (blankImage.getWidth() - width) / 2;
            int y = (blankImage.getHeight() - width) / 2;
            graphics.drawImage(formatAvatarImage, x, y, width, width, null);
            try (OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\test4.png")) {
                ImageIO.write(blankImage, "PNG", os);
            }
        }

    }
}

三、生成的图片如下

在这里插入图片描述

相关文章
|
4月前
|
Java
Java语言实现字母大小写转换的方法
Java提供了多种灵活的方法来处理字符串中的字母大小写转换。根据具体需求,可以选择适合的方法来实现。在大多数情况下,使用 String类或 Character类的方法已经足够。但是,在需要更复杂的逻辑或处理非常规字符集时,可以通过字符流或手动遍历字符串来实现更精细的控制。
371 18
|
4月前
|
Java 编译器 Go
【Java】(5)方法的概念、方法的调用、方法重载、构造方法的创建
Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中被创建,在其他地方被引用方法的优点使程序变得更简短而清晰。有利于程序维护。可以提高程序开发的效率。提高了代码的重用性。方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。这种就属于驼峰写法下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。
256 4
|
4月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
354 5
|
5月前
|
算法 安全 Java
除了类,Java中的接口和方法也可以使用泛型吗?
除了类,Java中的接口和方法也可以使用泛型吗?
200 11
|
5月前
|
Java 开发者
Java 函数式编程全解析:静态方法引用、实例方法引用、特定类型方法引用与构造器引用实战教程
本文介绍Java 8函数式编程中的四种方法引用:静态、实例、特定类型及构造器引用,通过简洁示例演示其用法,帮助开发者提升代码可读性与简洁性。
|
6月前
|
算法 Java
Java语言实现链表反转的方法
这种反转方法不需要使用额外的存储空间,因此空间复杂度为,它只需要遍历一次链表,所以时间复杂度为,其中为链表的长度。这使得这种反转链表的方法既高效又实用。
541 0
|
6月前
|
存储 Java 数据处理
Java映射操作:深入Map.getOrDefault与MapUtils方法
结合 `getOrDefault`方法的简洁性及 `MapUtils`的丰富功能,Java的映射操作变得既灵活又高效。合理地使用这些工具能够显著提高数据处理的速度和质量。开发人员可以根据具体的应用场景选择适宜的方法,以求在性能和可读性之间找到最佳平衡。
258 0
|
前端开发 安全 Java
Java实现把图片上传到图片服务器(nginx+vsftp)
在我另一篇笔记中已经记载了如何用nginx + vsftp搭建图片服务器(请参考nginx + vsftp搭建图片服务器),并且用vsftp的客户端工具filezilla测试过已经可用。但是在开发中应该是把用户在前端页面提交的图片保存到图片服务器中,接下来就来实现这个功能。
 Java实现把图片上传到图片服务器(nginx+vsftp)
|
4月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
260 1
|
4月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
269 1