基于.NetCore开发博客项目 StarBlog - (15) 生成随机尺寸图片

系列文章

  • 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?

  • 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目

  • 基于.NetCore开发博客项目 StarBlog - (3) 模型设计

  • 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入

  • 基于.NetCore开发博客项目 StarBlog - (5) 开始搭建Web项目

  • 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表

  • 基于.NetCore开发博客项目 StarBlog - (7) 页面开发之文章详情页面

  • 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示

  • 基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入

  • 基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流

  • 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计

  • 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译

  • 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能

  • 基于.NetCore开发博客项目 StarBlog - (14) 实现主题切换功能

  • 基于.NetCore开发博客项目 StarBlog - (15) 生成随机尺寸图片

  • ...

前言

之前我写了一篇 .NetCore实现图片缩放与裁剪 - 基于ImageSharp,里面有生成尺寸随机图片的算法,同时也是StarBlog博客中原有的实现方式,不过偶尔刷新页面的时候我注意到有些图片加载不出来,调试了一下发现原来是报错了,原本这个算法有bug。于是利用周末时间重新实现了一遍,这下可以说是完美了~

生成随机尺寸图片的功能目前用在文章卡片上,原本使用的是LoremPicsum提供的服务,但它的服务器在国外,上线之后发现加载太慢了,经常加载不出来,于是决定自己实现一版。功能基础是上文提到的文章中的ImageSharp。

611f95e19c2f395706ca12ca4621ae25.png
主页推荐文章

思路

先理一下需求

  • 指定一个目录作为图片库位置,把之前搜集的壁纸图片放进去,大概放个几百张就行了吧

  • 遍历获取到库中的图片列表

  • 随机取出一张图片

  • 根据指定的尺寸缩放或裁剪图片

其他的还有诸如指定随机seed、将seed与图片进行静态映射等扩展功能的实现。

关键功能

关键功能在于「根据指定的尺寸缩放或裁剪图片」

难点在于裁剪和缩放图片要保证:

  • 不改变图片原有的比例

  • 尽量保持图片原有的内容元素

第一版我是将横屏和竖屏的图片分开处理,(在输入尺寸不超过原图尺寸的情况下)先把比例接近的边调整成一样的大小,再裁剪中间部分,不过问题也很明显,如果调整大小之后另一条边的长度小于输入长度,那就会拉伸图片,导致比例改变。

在参考几个类似的MATLAB和Python项目之后,我换了别的思路:

  1. 在输入尺寸不超过原图尺寸的情况下,先按输入的尺寸比例裁剪、再调整尺寸

  2. 如果超出原图尺寸,则先按比例调整原图的大小,再重复第一步

举个例子

比如原图是 1080 x 2340 的尺寸,输入的图片是 400 x 200 尺寸

那第一步判断尺寸不超过原图,不需要缩放

然后是「按输入的尺寸比例裁剪」,把 400 x 200 化简成 2 : 1 的比例

在原图中截取 2 : 1 的大小,即 1080 x 540

然后再把截取的图片调整到 400 x 200,搞定!

看下效果

原图输出(400x200)输出(200x300)
08696f918cf3cb8e9453ad75ec0365ae.jpeg9369b092e71a675f6ffe11af6ad0c720.jpegb0e568a85f9d5053a774dcc27a29064f.jpeg

虽然比一开始的方案更费一丢丢内存,但却实实在在提升了出图成功率,nice~

代码实现

直接上代码好了,根据上面提到的思路,分两步走,代码也比一开始的方案更整洁

async Task<(Image, IImageFormat)> GenerateSizedImageAsync(string imagePath, int width, int height) {await using var fileStream = new FileStream(imagePath, FileMode.Open);var (image, format) = await Image.LoadWithFormatAsync(fileStream);// 输出尺寸超出原图片尺寸,放大if (width > image.Width && height > image.Height) {image.Mutate(a => a.Resize(width, height));}else if (width > image.Width || height > image.Height) {// 改变比例大的边if (width / image.Width < height / image.Height)image.Mutate(a => a.Resize(0, height));elseimage.Mutate(a => a.Resize(width, 0));}// 将输入的尺寸作为裁剪比例var (scaleWidth, scaleHeight) = GetPhotoScale(width, height);var cropWidth = image.Width;var cropHeight = (int) (image.Width / scaleWidth * scaleHeight);if (cropHeight > image.Height) {cropHeight = image.Height;cropWidth = (int) (image.Height / scaleHeight * scaleWidth);}var cropRect = new Rectangle((image.Width - cropWidth) / 2, (image.Height - cropHeight) / 2, cropWidth, cropHeight);image.Mutate(a => a.Crop(cropRect));image.Mutate(a => a.Resize(width, height));return (image, format);}

里面还用到了计算图片比例,很简单,先算出图片宽度和高度的最大公约数,然后宽高分别除以这个最大公约数,就是比例了(也就是化简分数)

计算最大公约数代码

private static int GetGreatestCommonDivisor(int m, int n) {if (m < n) (n, m) = (m, n);while (n != 0) {var r = m % n;m = n;n = r;}return m;
}

计算图片比例代码

private static (double, double) GetPhotoScale(int width, int height) {if (width == height) return (1, 1);var gcd = GetGreatestCommonDivisor(width, height);return ((double)width / gcd, (double)height / gcd);
}

参考资料

  • Python PIL图片按比例裁剪:https://blog.csdn.net/lly1122334/article/details/122365539

  • python 等比例裁剪图片:https://blog.csdn.net/chenping1993/article/details/110088858

  • C#基础练习之求两个数的最大公约数与最小公倍数:https://blog.csdn.net/maybe_ice/article/details/104328202

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

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

相关文章

【初探移动前端开发03】jQuery Mobile(上)

前言到目前为止&#xff0c;我打了几天酱油了&#xff0c;这几天落实了工作&#xff0c;并且看了一部电视连续剧&#xff08;陈道明-手机&#xff09;&#xff0c;我很少看连续剧了&#xff0c;但是手机质量很高啊&#xff0c;各位可以看看。我们今天先学习一下jquery mobile的…

Git Bash的一些命令和配置

查看git版本号&#xff1a; git --version 如果是第一次使用Git&#xff0c;你需要设置署名和邮箱&#xff1a; $ git config --global user.name "用户名" $ git config --global user.email "电子邮箱" 检查你的设置 $ git config --list 或单独检查一项…

/dev/null 文件

/dev/null 文件 如果希望执行某个命令&#xff0c;但又不希望在屏幕上显示输出结果&#xff0c;那么可以将输出重定向到 /dev/null&#xff1a; $ command > /dev/null /dev/null 是一个特殊的文件&#xff0c;写入到它的内容都会被丢弃&#xff1b;如果尝试从该文件读取内容…

C语言试题190之实现函数在第一个参数中进行查找,并返回匹配第二个参数所包含的字符的数目

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款刷算法、笔试、面经、拿大公司offer神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现函…

强大的多列 IN 查询语句,及数据库支持情况。

SQL 中最强大的也是最复杂的就是查询部分。在需要查询多条记录时我们一般会采用 in 关键字来指定要查询的条件&#xff1a;SELECT * FROM t_user WHERE uid IN (1,2,3,4,5,6,7,8,9);但如果对应的数据需要两个或更多字段才能确定&#xff0c;可能会写出以下的 SQL 语句&#xff…

ArcGIS实验教程——实验四十二:ArcGIS密度分析(核密度、点密度、线密度)

文章目录 一、密度分析原理二、点密度分析三、线密度分析四、核密度分析一、密度分析原理 密度分析是指根据输入的要素数据集计算整个区域的数据聚集状况,从而产生一个联系的密度表面。通过密度计算,将每个采样点的值散步到整个研究区域,并获得输出栅格中每个像元的密度值。…

Log4Net的WebApplication使用

一、Log4Net的WebApplication使用 1、首先使用nuget 添加log4Net 到WebApplication项目中 log4j每个符号的具体含义&#xff1a;%d %5p %c{1}:%L - %m%n log4j.properties# %m 输出代码中指定的消息# %p 输出优先级&#xff0c;即DEBUG&#xff0c;INFO&#xff0c;WARN&…

C语言试题191之实现strcat函数功能

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款刷算法、笔试、面经、拿大公司offer神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现st…

eclipse启动tomcat无法访问

症状&#xff1a; tomcat在eclipse里面能正常启动&#xff0c;而在浏览器中访问http://localhost:8080/不能访问&#xff0c;且报404错误。同时其他项目页面也不能访问。 关闭eclipse里面的tomcat&#xff0c;在tomcat安装目录下双击startup.bat手动启动tomcat服务器。访问htt:…

[转]IntelliJ IDEA 2020.1 正式发布,15 项重大特性、官方支持中文了!

头图&作者 | YourBatman&#xff0c;CSDN博客专家 责编 | 唐小引 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 前言 千呼万唤始出来&#xff01;自从官方在 2020-01-20 发布了其 2020 年的 Roadmap 后&#xff0c;我便持续关注着、期待着 JetBrains Intell…

【ArcGIS遇上Python】ArcGIS批量为多个矢量图层添加一个或多个字段(Add Field)案例实现

多个人在利用ArcGIS做数字化之后,需要批量为多个图层添加一个或者多个相同的字段,挨个手动添加字段显然不可取。ArcGIS Python提供了快速高效的批量添加字段的解决方案。本文以土地利用数据(Landuse1和Landuse2)为例,采用简单的Python代码实现了文中两个矢量图层批量添加字…

可下载!Vue3+.NET6实战系列:通用管理后台

.NET Framework停更3年&#xff0c;4月份还又停止了3个版本支持&#xff0c;居然还有人没怎么接触.NET跨平台&#xff01;真的该好好学下.NET6了&#xff0c;已经是不得不学了&#xff01;好好看下这套《Vue3.NET6前后端分离电商实战》免费教程&#xff0c;完整的源码视频课件全…

C语言试题192之实现strchr函数功能

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款刷算法、笔试、面经、拿大公司offer神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现st…

简单团队-爬取豆瓣电影TOP250-需求分析

1.实现登录界面 2.搜集相关电影网址 3..按照一定条件爬取电影&#xff0c;实现相关代码部分 项目步骤&#xff1a; 分析豆瓣电影TOP250的url规则, 编写模块获取相关url分析html中有关"排名,分数,名字,简介,导演,演员,前10条影评信息,链接信息"的标签编写将"搜集…

一个想法:成立草根技术联盟对开发人员进行技术定级解决企业员工招聘难问题!...

背景&#xff1a; 吃饭前&#xff0c;想起了<甄嬛传>中皇弟叹息的一句&#xff1a;千军易得&#xff0c;良将难寻&#xff01; 又逢CTO群里有友人让我帮忙评估其公司的项目及技术&#xff0c;一番review code&#xff0c;估计要写那代码的人要落岗了~ 不由想起&#xff0…

对软件工程这门课的收获与总结

转眼间八周已经过去&#xff0c;《现代软件工程》这门课程也在这周结束了。在宋老师的教导下&#xff0c;以及在个人项目以及团队项目的参与中我确实收获了许多。我觉得我有必要将这八周所获得的经验也好&#xff0c;教训也好都记录下来&#xff0c;相信这也会对未来的自己有所…

[转]C++二进制完成加减乘除

首先介绍计算机的二进制码 二进制常用的有原码&#xff0c;反码和补码&#xff0c;他们都是由最左边的一个符号位和右边的数值位构成。在计算机中为了更低成本的计算&#xff0c;数据都是用补码来存储和运算的。 原码 最高位表示符号位&#xff08;0代表正数&#xff0c;1代…

WGS84(GPS)、火星坐标系(GCJ02)、百度地图(BD09)坐标系转换案例教程(附转换工具下载)

在做基于百度地图、高德地图等电子地图做为地图服务的二次开发时,通常需要将具有WGS84等坐标的矢量数据(如行政区划、地名、河流、道路等GIS地理空间数据)添加到地图上面,然而,在线地图大多使用的是火星坐标系,需要事先将矢量数据转为火星坐标系。本文以案例的形式,讲述…

.NET 6 AssemblyLoadContext DLL 库 热插拔逻辑实现

曾经也实现过.Net Framework 基于AppDomain 的 dll库热插拔&#xff0c;经历了版本的迭代&#xff0c;.Net Core 不支持 AppDomain&#xff0c;之前也搞过.Net Core 3.1 版本的&#xff0c;现在搞一下子.NET 6.0的。热插拔运用的场景主要运用到宿主与插件这个场景或者动态任务的…

C语言试题193之实现strcmp函数功能

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款刷算法、笔试、面经、拿大公司offer神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目: 实现st…