基于.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.pswp.cn/news/284957.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284957.shtml
英文地址,請注明出處:http://en.pswp.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…