go使用letteravatar生成圆形透明头像图标

news2024/9/25 13:26:24

官网地址:GitHub - disintegration/letteravatar: Letter avatar generation for Go

我对其中函数改了一下,支持多个字符,效果如下:

func TestCreateAvatar(t *testing.T) {
	GenerateAvatar("Bird Fish", 0, "Bird.png")
	GenerateAvatar("飞鸟真人", 1, "飞鸟.png")
	GenerateAvatar("Жозефина", 1, "1.png")
	GenerateAvatar("Ярослав", 1, "2.png")
	GenerateAvatar("ちびまる子ちゃん", 1, "日语.png")

}

其中把源码放到自己目录下,改其中的函数,将rune类型参数改为string,

然后自己加个蒙版:

package utils

import (
	"birdtalk/server/utils/myavatar"
	"fmt"
	"github.com/fogleman/gg"
	"github.com/golang/freetype/truetype"
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"os"
	"unicode/utf8"
)

func GenerateAvatar(name string, gender int, saveFilePath string) error {

	onceShort.Do(func() {
		initFont()
	})

	// 生成圆形图标
	avatar, err := generateAvatar(name, 100, gender)
	if err != nil {
		return err
	}

	// 创建相同尺寸的圆形蒙版
	mask := createCircularMask(avatar.Bounds())

	// 创建一个新的透明背景图像
	bgImg := image.NewRGBA(avatar.Bounds())

	// 使用圆形蒙版将文字图标覆盖到透明背景图像上
	draw.DrawMask(bgImg, bgImg.Bounds(), avatar, image.Point{}, mask, image.Point{}, draw.Over)

	// 保存图像到文件
	file, err := os.Create(saveFilePath)
	if err != nil {
		return err
	}
	defer file.Close()

	err = png.Encode(file, bgImg)
	if err != nil {
		return err
	}

	//fmt.Println("Avatar saved as avatar.png")
	return nil
}

// LoadFontToMemory 加载字体文件到内存中,返回一个粗体
func loadFontToMemory(fontPath string) (*truetype.Font, error) {
	// Read the font file into memory
	fontBytes, err := os.ReadFile(fontPath)
	if err != nil {
		return nil, err
	}

	// Parse the font file
	font, err := truetype.Parse(fontBytes)
	if err != nil {
		return nil, err
	}

	return font, nil
}

var defaultFont *truetype.Font = nil

func initFont() {
	strFilePath := "D:\\GBuild\\\utils\\SourceHanSans-VF.ttf"
	//strFilePath = "C:\\Windows\\Fonts\\simfang.ttf"
	font, err := loadFontToMemory(strFilePath)
	if err != nil {
		return
	}
	defaultFont = font
}

// createCircularMask 创建一个圆形蒙版,与指定的边界大小相同
func createCircularMask(bounds image.Rectangle) *image.Alpha {
	dc := gg.NewContext(bounds.Dx(), bounds.Dy())
	dc.DrawCircle(float64(bounds.Dx())/2, float64(bounds.Dy())/2, float64(bounds.Dx())/2)
	dc.Fill()

	mask := image.NewAlpha(bounds)
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			_, _, _, a := dc.Image().At(x, y).RGBA()
			mask.Set(x, y, color.Alpha{A: uint8(a >> 8)})
		}
	}
	return mask
}

func generateAvatar(name string, sz int, gender int) (image.Image, error) {

	if defaultFont == nil {
		// 汉语会出错
	}
	myColor := color.RGBA{0x7f, 0xd3, 0xfa, 0xff} // 蓝色
	if gender == 0 {
		myColor = color.RGBA{0xf6, 0xa1, 0xbe, 0xff} // 粉色
	}
	options := &myavatar.Options{
		Font: defaultFont,
		Palette: []color.Color{
			myColor,
		},
	}

	first6Letter := TakeFirstCharacters(name)
	fmt.Println("返回:", first6Letter)
	avatar, err := myavatar.Draw(sz, first6Letter, options)

	if err != nil {
		return nil, err
	}

	return avatar, nil
}

// TakeFirstNRunes 返回字符串的前N个字符,确保总字节数不超过4个字节
// TakeFirstCharacters 根据字符类型取字符串的前N个字符
func TakeFirstCharacters(str string) string {

	result := ""
	count := 0
	for len(str) > 0 {
		r, size := utf8.DecodeRuneInString(str)
		//fmt.Printf("字符: %c, 字节数: %d\n", r, size)
		if (count + size) > 6 {
			break
		} else {
			result += string(r)
			count += size
		}

		str = str[size:] // 将已解码的字符从字符串中去除
	}

	return result
}

func TakeFirstNRunes(str string, n int) string {
	var result string
	var bytesCount int
	for _, runeValue := range str {
		runeSize := utf8.RuneLen(runeValue)
		if bytesCount+runeSize > 4 {
			break
		}
		bytesCount += runeSize
		result += string(runeValue)
		if bytesCount == 4 {
			break
		}
	}
	return result
}

其中字体是从如下地址找的开源字体:Releases · adobe-fonts/source-han-sans · GitHub

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1705947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【包邮送书】你好!C语言

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

56. UE5 RPG 给敌人添加AI实现跟随玩家

在这一篇里&#xff0c;我们要实现一下敌人的AI&#xff0c;敌人也需要一系列的行为&#xff0c;比如朝向英雄攻击&#xff0c;移动&#xff0c;在满足条件时施放技能。这些敌人的行为可以通过使用UE的内置的AI系统去实现。 在UE里&#xff0c;只要是基于Character类创建的蓝图…

【从零开始学习RabbitMQ | 第一篇】如何确保生产者的可靠性

目录 前言&#xff1a; 生产者重连机制&#xff1a; 生产者确认机制&#xff1a; Publisher Confirm&#xff08;生产者者确认&#xff09; Publish Return&#xff08;发布返回&#xff09; 总结&#xff1a; 前言&#xff1a; 在现代的分布式系统中&#xff0c;消息队…

5个将文本转语音的工具,高考复习的绝佳助手

高考倒计时10天&#xff01; 在这最后的冲刺阶段&#xff0c;同学们都在拼命刷题&#xff0c;但面对已经整理好的知识点&#xff0c;时间紧迫&#xff0c;如何高效复习呢&#xff1f; 别急&#xff0c;今天我要和大家分享一个绝佳的复习方法——文字转语音。这个方法可以让你…

鸿蒙4.2小版本推出,鸿蒙5.0已经不远了

上个月&#xff0c;市场上迎来了华为鸿蒙系统4字开头的小升级&#xff0c;版本来到了4.2版本。 我们先来看看4.2版本都给用户带来哪些特色&#xff1a; 界面切换更流畅&#xff1a;无论是响应速度还是操作手感&#xff0c;用户都将感受到更加迅速和顺滑的体验 搜星速度的显著…

人类和小鼠转录组上游分析

基础软件 conda install cutadapt, trimmomatic, samtools, hisat2, subread, deeptools -y人类转录组上游分析 # 样本名称 sample_namesample# 线程 threads4# 双端测序原始fastq1和fastq2路径 fastq1_path/path/${sample_name}_1.fq.gz fastq2_path/path/${sample_name}_2.…

【LeetCode】【9】回文数(1047字)

文章目录 [toc]题目描述样例输入输出与解释样例1样例2样例3 提示进阶Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;LeetCode 刷题指南&#xff1a;LeetCode刷题指南 题目描述 给一个整数x&#xff0c;如果x是一个回文整数&#xff0c;返回true&#xff1b;否…

CATIA二次开发VBA入门(2)——认识CATIA内置的VBA开发界面

目录 引出VBA界面介绍工具条介绍view下拉菜单insert下拉format下拉debug下拉tool下拉help下拉【重要】补充窗口窗体的模态【重要】 总结认识CATIA二次开发刘瑞欣 vb程序设计教程Excel中的vba开发catia中的vba开发 宏的录制、回放和编辑宏代码精简画圆柱阵列宏Macro文件的3种类型…

mysql内存和磁盘的关系

mysql内存和磁盘的关系 1.MySQL的内存和磁盘之间的关系是密切的。MySQL的数据存储在磁盘上&#xff0c;但为了高效地执行查询操作&#xff0c;它也会将数据页&#xff08;每个页通常为16KB&#xff09;读入内存。MySQL的缓冲池&#xff08;buffer pool&#xff09;是在内存中的…

数据通信基本概念汇总

1. 数据通信基础 网关: 提供协议转换&#xff0c;路由选择&#xff0c;数据交换的网络设备 报文: 网络中所传递的一个数据单元。 数据载荷: 最终要传递的信息 封装: 给数据载荷添加头部和尾部的过程(形成新的报文) 解封装: 给数据载荷去掉头部和尾部的过程(获取数据载荷) 终端设…

JAVA语言开发的一套云HIS医院管理系统源码 HIS源码 医院管理系统源码 HIS系统是否可以与LIS和RIS进行集成

系统概述 云HIS系统是一种基于云计算的医疗卫生信息系统&#xff0c;它运用云计算、大数据、物联网等新兴信息技术&#xff0c;按照现代医疗卫生管理要求&#xff0c;在一定区域范围内以数字化形式提供医疗卫生行业数据收集、存储、传递、处理的业务和技术平台。云HIS的主要功…

最简单的方式解决android studio 模拟器无法联网的问题

最简单的方式解决android studio 模拟器无法联网的问题 看了网上很多解决android studio内置模拟器无法联网的问题&#xff0c;基本上都是在模拟器手机上配置dns&#xff0c;个人试了多种办法也连不上网&#xff0c;现在给出一种&#xff0c;仅需要在命令行操作的解决安卓模拟…

在线预定酒店预约订房小程序源码系统 可轻松预定房间+随时取消预约 前后端分离 带网站的安装代码包以及搭建教程

系统概述 旅游业的快速发展和人们生活水平的不断提高&#xff0c;越来越多的人选择出行旅游。而在旅行过程中&#xff0c;酒店预订是一个必不可少的环节。传统的酒店预订方式往往需要用户通过电话、网站等渠道进行预订&#xff0c;流程繁琐&#xff0c;效率低下。为了解决这些…

Android15 Beta更新速览

Android15 Beta更新速览 前台服务变更 前台服务使应用保持活动状态&#xff0c;以便它们可以执行关键且对用户可见的操作&#xff0c;通常以牺牲电池寿命为代价。在 Android 15 Beta 2 中&#xff0c;dataSync 和 mediaProcessing 前台服务类型现在具有约 6 小时的超时时间&a…

【机器学习】探究DQN通过训练来解决AI序列决策问题

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

Linux一键安装Docker、kkfileviewer

Linux一键安装Docker、kkfileviewer 一、安装docker 安装docker脚本 vi initDocker.sh脚本内容 #安装前先更新yum&#xff0c;防止连接镜像失败 yum -y update#卸载系统之前的docker&#xff08;可选择&#xff0c;我这里直接注释了&#xff09; #yum remove docker docker…

Geotools--生成等值线

好久没用geotools去写东西了&#xff0c;因为近几年一直在接触所谓数字孪生和可视化相关项目&#xff0c;个人的重心也往前端可视化去倾斜&#xff0c;在后端的开发上到变得停滞下来。 这次用的是geotools 28.4版本&#xff0c;生成等值线的方法在 <dependency><group…

html+CSS部分基础运用7

项目1 设计简易灯箱画廊 1.实验所需素材 在trees文件夹中提供一个MP3文件和18个JPG文件&#xff0c;设计页面时可以使用。 2.编程实现简易灯箱画廊&#xff0c;鼠标单击任一个图像超链接&#xff0c;在底部浮动框架中显示大图像&#xff0c;效果如图4-1所示的页面。 图4-1 简…

中创算力与中国移动初步达成战略合作意向,共同构建智能生态圈!

2024年5月14日&#xff0c;为进一步深化合作&#xff0c;促进业务共同发展&#xff0c;实现双方优势互补。中国移动云能力中心高级专家、郑州移动总经理助理邵根波、管城分公司政企部经理张文孟、航海东路分局张旭红莅临中创算力。中创董事长许伟威、副总经理杨光、技术总监刘朝…

Spring+SpringBoot面试总结(近两万字)

SpringSpringBoot面试总结 一、Spring Bean1.1、bean的生命周期&#xff08;对象的创建使用销毁&#xff09;1.1.1、准备工作1.1.2、创建Bean对象1.1.3、注册销毁 1.2、 bean的作用域1.2.1、配置方式 1.3、 spring 自动装配 bean 有哪些方式&#xff08;存疑存疑&#xff09;1.…