当前位置: 首页 > article >正文

基于Java的不固定长度字符集在指定宽度和自适应模型下图片绘制生成实战

目录

前言

一、需求介绍

1、指定宽度生成

2、指定列自适应生成

二、Java生成实现

1、公共方法

2、指定宽度生成

3、指定列自适应生成

三、总结


前言

        在当今数字化与信息化飞速发展的时代,图像的生成与处理技术正日益成为众多领域关注的焦点。从创意设计到数据可视化,从游戏开发到人工智能辅助创作,高效、精准且具有高度适应性的图像生成方案有着广泛而迫切的需求。Java 作为一种强大、稳定且广泛应用的编程语言,在图像绘制领域也发挥着不可忽视的作用。

        在GIS领域,比如图例的生成就会面对以上的问题。由于在进行字符标注时无法预测文本的长度,因此我们需要能有一种自适应文本长度的生成方法,但是同时,也有可能我们需要指定一种宽度从而对字符文本进行绘制的需要。如下两图所示:

自适应宽度生成示意图

指定宽度生成示意图 

        本实战旨在深入探讨基于 Java 的不固定长度字符集在指定宽度和自适应模型下图片绘制生成的方法与技巧。不固定长度字符集为图片绘制带来了独特的挑战与机遇。一方面,其灵活多变的字符组合方式能够创造出丰富多样、极具个性化的图像效果,为创意表达提供了广阔空间;另一方面,如何在保证图像整体协调性与美观性的前提下,合理安排不同长度字符在指定宽度内的布局,实现自适应模型下的高效绘制,需要深入研究与实践。

        通过本次实战,我们期望为读者提供一套完整、实用且具有创新性的基于 Java 的图片绘制解决方案,帮助读者提升在图像生成领域的技术能力,激发他们在数字创作方面的灵感与潜力,从而在各自的应用场景中创造出更具价值与吸引力的图像作品,为推动图像技术的发展与应用贡献一份力量。

一、需求介绍

        在面向地理空间的图例生成过程,我们通常会遇到以下两种情况:第一种是需要指定宽度,比如要求在宽度为200px的图片中,将指定的文字在图片中生成。第二种就是需要根据指定列,即一行展示几列,然后自适应的生成固定宽度的图片。本节将主要介绍这两个需求。这里我们需要展示的是一些不一定长的字符串集合,模拟展示以下这些地名数据,如下所示:

String[] demoTexts = {" 项目管理", "软件开发", "数据分析","人工智能", "云计算", "网络安全","用户体验", "测试验证", "运维部署", "昆明市","曲靖市","玉溪市","保山市","昭通市","丽江市","普洱市","临沧市","楚雄彝族自治州","红河哈尼族彝族自治州","文山壮族苗族自治州","西双版纳傣族自治州","湘西土家族苗族自治州","深圳市","保亭黎族苗族自治县","阿坝藏族羌族自治州","黔西南布依族苗族自治州","克孜勒苏柯尔克孜自治州","双江拉祜族佤族布朗族傣族自治县","积石山保安族东乡族撒拉族自治县","中国石油集团东方地球物理勘探有限责任公司霸州基地管理处居委会","天津市蓟州区京津州河科技产业园管理委员会虚拟社区","窑街煤电集团民勤县瑞霖生态农林有限责任公司生活区","沈阳市于洪区红旗土地股份合作经营有限公司生活区","大理白族自治州","德宏傣族景颇族自治州","怒江傈僳族自治州","迪庆藏族自治州"
};

1、指定宽度生成

        指定宽度生成,即我们对目标成果的图片宽度是有要求的,比如宽度指定为200px。核心需求如下:

        固定总宽度模式

  • 平均分配列宽:根据总宽度和列数计算每列可用宽度

  • 自动换行:根据列数自动计算行数

  • 文本截断:超长文本添加省略号

2、指定列自适应生成

        自适应列宽模式

  • 动态计算列宽:根据每列中最长的条目确定列宽,遍历所有文本,计算每个条目(矩形+间距+文本)的总宽度,确定最大宽度作为图像宽度。

  • 计算高度:基于行数和字体高度计算总高度

  • 自动换行:根据列数自动计算行数

  • 保持完整显示:不截断文本

二、Java生成实现

        本小节将根据上面的生成需求来具体讲解如何进行详细的生成。java生成的实现分成三个部分,第一部分是介绍两个公共方法,第二部分介绍如何按照指定宽度生成,第三部分介绍如何进行自适应生成,通过代码实例的方法进行讲解。

1、公共方法

        为了方便对对绘制的文字展示得更加美观,这里我们每进行一次绘制就修改画笔的颜色。因此需要一个生成指定颜色的方法,在java中生成Color对象,并且转为十六进制的颜色表示,核心方法如下:

/**
* - 将color转十六进制字符串
* @param color
* @return
*/
public static String Color2String(Color color) {// 获取 RGB 颜色值,格式为 0x00RRGGBBint rgb = color.getRGB();// 将 RGB 转换为十六进制字符串,去掉前两位的透明度部分(如果是纯不透明颜色)String hexColor = "#" + Integer.toHexString(rgb & 0xffffff);return hexColor;
}

        根据不同字符串生成均匀分布的颜色方法如下:

// 生成可区分颜色(HSV色环均匀分布)
private static Color[] generateDistinctColors(int count) {Color[] colors = new Color[count];float goldenRatio = 0.618033988749895f;  // 黄金分割比例float saturation = 0.8f;  // 饱和度float brightness = 0.9f;  // 亮度for (int i = 0; i < count; i++) {float hue = (i * goldenRatio) % 1.0f;colors[i] = Color.getHSBColor(hue, saturation, brightness);}return colors;
}

         以上两个方法在指定宽度生成和自适应生成中均会使用到,因此在此简单列出来。

2、指定宽度生成

按指定宽度生成的核心方法如下:

// 固定总宽度模式
public static BufferedImage createFixedColumnsImage(String[] texts, int columns,int totalWidth, Font font,int padding, int columnSpacing,int rowSpacing) {BufferedImage tempImg = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);Graphics2D tempG = tempImg.createGraphics();tempG.setFont(font);FontMetrics fm = tempG.getFontMetrics();final int RECT_SIZE = 10;final int ENTRY_SPACING = 5;// 生成颜色序列Color[] colors = generateDistinctColors(texts.length);// 计算列宽int availableWidth = totalWidth - padding * 2 - (columns - 1) * columnSpacing;int columnWidth = availableWidth / columns;int textMaxWidth = columnWidth - RECT_SIZE - ENTRY_SPACING;// 处理文本List<String> processedTexts = new ArrayList<>();for (String text : texts) {processedTexts.add(truncateText(text, textMaxWidth, fm));}// 计算总高度int rows = (int) Math.ceil((double)texts.length / columns);int totalHeight = padding * 2 + rows * (fm.getHeight() + rowSpacing) - rowSpacing;// 创建图像BufferedImage image = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_INT_ARGB);Graphics2D g = image.createGraphics();setupGraphics(g, font);// 绘制背景g.setColor(Color.WHITE);g.fillRect(0, 0, totalWidth, totalHeight);// 绘制条目int yBase = padding + fm.getAscent();int[] columnX = new int[columns];for (int i = 0; i < columns; i++) {columnX[i] = padding + i * (columnWidth + columnSpacing);}for (int i = 0; i < processedTexts.size(); i++) {g.setColor(colors[i]);int col = i % columns;int row = i / columns;int y = yBase + row * (fm.getHeight() + rowSpacing);int rectY = y - fm.getAscent() + (fm.getHeight() - RECT_SIZE)/2;// 绘制矩形g.fillRect(columnX[col], rectY, RECT_SIZE, RECT_SIZE);// 绘制文本g.drawString(processedTexts.get(i), columnX[col] + RECT_SIZE + ENTRY_SPACING, y);}g.dispose();tempG.dispose();return image;
}

        由于在指定宽度的生成方式中,绘制的图片宽度是固定的,而文字的字数是不固定的。因此在绘制的过程中,需要对超长的文本进行截取,超长的部分将使用省略号来进行展示。对超长文本字符进行截断处理的方法如下:

private static String truncateText(String text, int maxWidth, FontMetrics fm) {if (fm.stringWidth(text) <= maxWidth) return text;int ellipsisWidth = fm.stringWidth("...");int availableWidth = maxWidth - ellipsisWidth;int length = text.length();while (length > 0 && fm.stringWidth(text.substring(0, length)) > availableWidth) {length--;}return length > 0 ? text.substring(0, length) + "..." : "";
}

         生成指定宽度的图片调用方法如下:

// 生成固定宽度图片(400px宽,2列)
BufferedImage fixedImage = createFixedColumnsImage(demoTexts, 2, 400,new Font("宋体", Font.PLAIN, 12),15, 20, 10
);
ImageIO.write(fixedImage, "PNG", new File("D:/fixed_columns_250420.png"));

        生成的成果图片如下:

3、指定列自适应生成

        生成指定列的自适应图片生成的核心方法如下:

// 自适应列宽模式public static BufferedImage createAdaptiveColumnsImage(String[] texts, int columns,Font font, int padding, int columnSpacing, int rowSpacing) {BufferedImage tempImg = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);Graphics2D tempG = tempImg.createGraphics();tempG.setFont(font);FontMetrics fm = tempG.getFontMetrics();final int RECT_SIZE = 10;final int ENTRY_SPACING = 5; // 图标与文字间距// 生成颜色序列Color[] colors = generateDistinctColors(texts.length);int index = 0;for (String text : texts) {texts[index] = Color2String(colors[index]) + " " + text; //processedTexts.add(truncateText(text, textMaxWidth, fm));index ++;}// 计算列宽int[] columnWidths = new int[columns];for (int i = 0; i < texts.length; i++) {int col = i % columns;int width = RECT_SIZE + ENTRY_SPACING + fm.stringWidth(texts[i]);if (width > columnWidths[col]) {columnWidths[col] = width;}}// 计算总尺寸int totalWidth = padding * 2;for (int w : columnWidths) {totalWidth += w + columnSpacing;}totalWidth -= columnSpacing; // 最后一列不加间距int rows = (int) Math.ceil((double)texts.length / columns);int totalHeight = padding * 2 + rows * (fm.getHeight() + rowSpacing) - rowSpacing;// 创建图像BufferedImage image = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_INT_ARGB);Graphics2D g = image.createGraphics();setupGraphics(g, font);// 绘制背景g.setColor(Color.WHITE);g.fillRect(0, 0, totalWidth, totalHeight);// 绘制条目int x = padding;int yBase = padding + fm.getAscent();int[] columnX = new int[columns];for (int i = 0; i < columns; i++) {columnX[i] = x;x += columnWidths[i] + columnSpacing;}g.setColor(Color.RED);for (int i = 0; i < texts.length; i++) {g.setColor(colors[i]);int col = i % columns;int row = i / columns;int y = yBase + row * (fm.getHeight() + rowSpacing);int rectY = y - fm.getAscent() + (fm.getHeight() - RECT_SIZE)/2;// 绘制矩形g.fillRect(columnX[col], rectY, RECT_SIZE, RECT_SIZE);// 绘制文本g.drawString(texts[i], columnX[col] + RECT_SIZE + ENTRY_SPACING, y);}g.dispose();tempG.dispose();return image;}

        在自适应生成的过程中,最需要处理的逻辑就是动态的计算宽度等值。最终生成的结果图片如下:

三、总结

        以上就是本文的主要内容,本实战旨在深入探讨基于 Java 的不固定长度字符集在指定宽度和自适应模型下图片绘制生成的方法与技巧。不固定长度字符集为图片绘制带来了独特的挑战与机遇。一方面,其灵活多变的字符组合方式能够创造出丰富多样、极具个性化的图像效果,为创意表达提供了广阔空间;另一方面,如何在保证图像整体协调性与美观性的前提下,合理安排不同长度字符在指定宽度内的布局,实现自适应模型下的高效绘制,需要深入研究与实践。

        通过本次实战,我们期望为读者提供一套完整、实用且具有创新性的基于 Java 的图片绘制解决方案,帮助读者提升在图像生成领域的技术能力,激发他们在数字创作方面的灵感与潜力,从而在各自的应用场景中创造出更具价值与吸引力的图像作品,为推动图像技术的发展与应用贡献一份力量。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。

        完整的代码链接如下:Java根据字符串集合生成固定宽度和自适应宽度源码。

相关文章:

基于Java的不固定长度字符集在指定宽度和自适应模型下图片绘制生成实战

目录 前言 一、需求介绍 1、指定宽度生成 2、指定列自适应生成 二、Java生成实现 1、公共方法 2、指定宽度生成 3、指定列自适应生成 三、总结 前言 在当今数字化与信息化飞速发展的时代&#xff0c;图像的生成与处理技术正日益成为众多领域关注的焦点。从创意设计到数…...

【版本控制】idea中使用git

大家好&#xff0c;我是jstart千语。接下来继续对git的内容进行讲解。也是在开发中最常使用&#xff0c;最重要的部分&#xff0c;在idea中操作git。目录在右侧哦。 如果需要git命令的详解&#xff1a; 【版本控制】git命令使用大全-CSDN博客 一、配置git 要先关闭项目&#xf…...

QT:Qt5 串口模块 (QSerialPort) 在 VS2015 中正确关闭串口避免被占用

以下是使用 Qt5 串口模块 (QSerialPort) 在 VS2015 中正确关闭串口避免被占用的完整示例代码&#xff1a; #include <QSerialPort> #include <QDebug>// 创建全局或类成员变量&#xff08;推荐使用智能指针&#xff09; QSerialPort *serialPort nullptr; // 打开…...

Linux——入门常用基础指令

文章目录 Linux入门常用基础指令使用工具介绍基础指令clear指令pwd指令ls指令cd指令Linux系统下的文件路径及文件存储结构文件结构家目录绝对路径和相对路径tree工具 stat指令which指令alias指令touch指令mkdir指令cat指令rm指令man指令cp指令通配符 * Linux入门常用基础指令 …...

【技术追踪】Differential Transformer(ICLR-2025)

Differential Transformer&#xff1a;大语言模型新架构&#xff0c; 提出了 differential attention mechanism&#xff0c;Transformer 又多了一个小 trick~ 论文&#xff1a;Differential Transformer 代码&#xff1a;https://github.com/microsoft/unilm/tree/master/Diff…...

overlay 模块加载失败问题分析

问题背景 CentOS 7系统上&#xff0c;内核版本是3.10.0-693.21.1.el7.x86_64&#xff0c;加载overlay模块的时候失败了。错误提示说找不到支持的overlay文件系统&#xff0c;让我确认内核足够新并且已经加载了overlay支持。但是检查发现/lib/modules/3.10.0-693.el7.x86_64/ke…...

【Linux网络】应用层自定义协议与序列化

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12891150.html 目录 应用层 再谈 "协议" 网络版计算器 序列化 和 反序列化 重新理解…...

Vue接口平台学习十——接口用例页面2

效果图及简单说明 左边选择用例&#xff0c;右侧就显示该用例的详细信息。 使用el-collapse折叠组件&#xff0c;将请求到的用例详情数据展示到页面中。 所有数据内容&#xff0c;绑定到caseData中 // 页面绑定的用例编辑数据 const caseData reactive({title: "",…...

目标检测中的损失函数(二) | BIoU RIoU α-IoU

BIoU来自发表在2018年CVPR上的文章&#xff1a;《Improving Object Localization With Fitness NMS and Bounded IoU Loss》 论文针对现有目标检测方法只关注“足够好”的定位&#xff0c;而非“最优”的框&#xff0c;提出了一种考虑定位质量的NMS策略和BIoU loss。 这里不赘…...

SpringAI系列 - MCP篇(一) - 什么是MCP

目录 一、引言二、MCP核心架构三、MCP传输层(stdio / sse)四、MCP能力协商机制(Capability Negotiation)五、MCP Client相关能力(Roots / Sampling)六、MCP Server相关能力(Prompts / Resources / Tools)一、引言 之前我们在接入大模型时,不同的大模型通常都有自己的…...

Linux 入门十一:Linux 网络编程

一、概述 1. 网络编程基础 网络编程是通过网络应用编程接口&#xff08;API&#xff09;编写程序&#xff0c;实现不同主机上进程间的信息交互。它解决的核心问题是&#xff1a;如何让不同主机上的程序进行通信。 2. 网络模型&#xff1a;从 OSI 到 TCP/IP OSI 七层模型&…...

沐渥氮气柜控制板温湿度氧含量氮气流量四显智控系统

氮气柜控制板通常用于实时监控和调节柜内环境参数&#xff0c;确保存储物品如电子元件、精密仪器、化学品等&#xff0c;处于低氧、干燥的稳定状态。以下是沐渥氮气柜控制板核心参数的详细介绍及控制逻辑&#xff1a; 一、控制板核心参数显示模块 1&#xff09;‌温度显示‌&am…...

vue3 主题模式 结合 element-plus的主题

vue3 主题模式 结合 element-plus的主题 npm i element-plus --save-dev在 Vue 3 中&#xff0c;实现主题模式主要有以下几种方式 1.使用 CSS 变量&#xff08;自定义属性&#xff09; CSS 变量是一种在 CSS 中定义可重用值的方式。在主题模式中&#xff0c;可以将颜色、字体…...

Redis 有序集合(Sorted Set)

Redis 有序集合&#xff08;Sorted Set&#xff09; 以下从基础命令、内部编码和使用场景三个维度对 Redis 有序集合进行详细解析&#xff1a; 一、基础命令 命令时间复杂度命令含义zadd key score member [score member …] O ( k l o g ( n ) ) O(klog(n)) O(klog(n))&…...

[c语言日寄]免费文档生成器——Doxygen在c语言程序中的使用

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…...

QtCreator的设计器、预览功能能看到程序图标,编译运行后图标消失

重新更换虚拟机&#xff08;Vmware Kylin&#xff09;&#xff0c;重新编译和配置了很多第三方库后&#xff0c;将代码跑到新的这个虚拟机环境中&#xff0c;但是出现程序图标不可见&#xff0c;占位也消失&#xff0c;后来继续检查ui文件&#xff0c;ui文件图标也异常&#x…...

QT文件和文件夹拷贝操作

1.拷贝文件夹 //(源文件目录路劲&#xff0c;目的文件目录&#xff0c;文件存在是否覆盖) bool copyDirectory(const QString& srcPath, const QString& dstPath, bool coverFileIfExist) { QDir srcDir(srcPath); QDir dstDir(dstPath); if (!dstDir.exi…...

面试常用基础算法

目录 快速排序归并排序堆排序 n n n皇后问题最大和子数组爬楼梯中心扩展法求最长回文子序列分割回文串动态规划求最长回文子序列最长回文子串单调栈双指针算法修改 分割回文串滑动窗口栈 快速排序 #include <iostream> #include <algorithm>using namespace std;…...

Python-24:小R的随机播放顺序

问题描述 小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌&#xff0c;播放后将其从歌单中移除。如果歌单中还有歌曲&#xff0c;则会将当前第一首歌移到最后一首。这个过程会一直重复&#xff0c;直到歌单中没有任何歌曲。 例如&#xff0c;给定歌单 [5, 3, 2, 1,…...

悬空引用和之道、之禅-《分析模式》漫谈57

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的第5章“对象引用”原文&#xff1a; Unless you can catch all such references, there is the risk of a dangling reference, which often has painful con…...

Python accumulate 函数详解

https://docs.python.org/zh-cn/3/library/itertools.html#itertools.accumulate 在 Python 中&#xff0c;accumulate 是一个生成器&#xff08;generator&#xff09;, 是来自 itertools 模块的一个函数。 它的作用是返回一个迭代器&#xff0c;该迭代器生成输入数据的累积结…...

Cursor可视化大屏搭建__0420

主题:用Cursor怎么进行数据洞察,做AI预测化内容。 Python基础语法与AI python生态强大,代码简洁,相对其他语言Python更好上手,浙江高考将Python列为可选科目 科学计算:Sklearn,Numpy,Pandas 人工智能:Tensorflow,Pytorch 网络爬虫:Scrapy…...

【初阶数据结构】树——二叉树(上)

文章目录 目录 前言 一、树 1.树的概念与结构 2.树相关术语 3.树的表示 二、二叉树 1.概念与结构 2.特殊的二叉树 3.二叉树存储结构 总结 前言 本篇带大家学习一种非线性数据结构——树&#xff0c;简单认识树和二叉数以及了解二叉树的存储结构。 一、树 1.树的概念与结构 树…...

ECharts散点图-散点图14,附视频讲解与代码下载

引言&#xff1a; ECharts散点图是一种常见的数据可视化图表类型&#xff0c;它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图&#xff0c;包括图表效果预览、视频讲解及代码下载&#xff0c;让你轻松掌握…...

C++中的算术转换、其他隐式类型转换和显示转换详解

C中的类型转换&#xff08;Type Conversion&#xff09;是指将一个数据类型的值转换为另一个数据类型的过程&#xff0c;主要包括&#xff1a; 一、算术类型转换&#xff08;Arithmetic Conversions&#xff09; 算术类型转换通常发生在算术运算或比较中&#xff0c;称为**“标…...

GAIA-2:用于自动驾驶的可控多视图生成世界模型

25年3月来自英国创业公司 Wayze 的论文“GAIA-2: A Controllable Multi-View Generative World Model for Autonomous Driving”。&#xff08;注&#xff1a;23年9月其发布GAIA-1&#xff09; 生成模型为模拟复杂环境提供一种可扩展且灵活的范例&#xff0c;但目前的方法不足…...

(一)CMake / MsBuild Ninja Make/ MSVC g++ clang++ 等c++编译概念解释

c 几个编译概念 一 概念二 层级关系总结2.1层级表格2.2 关键点说明2.3 示例流程&#xff08;以 Ninja 为例&#xff09;2.4 示例流程&#xff08;Windows 平台&#xff09;​​ 三 总结 一 概念 CMake 通过 CMakeLists.txt 生成不同平台的构建文件&#xff08;如 .sln、build.n…...

创建 Node.js Playwright 项目:从零开始搭建自动化测试环境

一、环境准备 在开始创建 Playwright 项目之前&#xff0c;确保你的电脑上已经安装了以下工具&#xff1a; Node.js&#xff1a;Playwright 依赖于 Node.js 环境&#xff0c;确保你已经安装了最新版本的 Node.js。可以通过以下命令检查是否安装成功&#xff1a; node -v npm -…...

浅谈AI致幻

文章目录 当前形势下存在的AI幻觉&#xff08;AI致幻&#xff09;什么是AI幻觉AI幻觉的类型为什么AI会产生幻觉AI幻觉的危害与影响当前应对AI幻觉的技术与方法行业与学术界的最新进展未来挑战与展望结论 当前形势下存在的AI幻觉&#xff08;AI致幻&#xff09; 什么是AI幻觉 …...

postman乘法计算,变量赋值

postman脚本怎么计算乘法 在Postman中&#xff0c;你可以通过多种方式计算乘法&#xff0c;这取决于你的具体需求。例如&#xff0c;如果你想在发送请求前计算乘法结果&#xff0c;或者在测试标签中计算响应数据的乘法&#xff0c;下面是一些常见的方法。 1. 使用JavaScript代…...