<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Loading

      基于.NetCore開(kāi)發(fā)博客項(xiàng)目 StarBlog - (15) 生成隨機(jī)尺寸圖片

      系列文章

      前言

      之前我寫(xiě)了一篇 .NetCore實(shí)現(xiàn)圖片縮放與裁剪 - 基于ImageSharp,里面有生成尺寸隨機(jī)圖片的算法,同時(shí)也是StarBlog博客中原有的實(shí)現(xiàn)方式,不過(guò)偶爾刷新頁(yè)面的時(shí)候我注意到有些圖片加載不出來(lái),調(diào)試了一下發(fā)現(xiàn)原來(lái)是報(bào)錯(cuò)了,原本這個(gè)算法有bug。于是利用周末時(shí)間重新實(shí)現(xiàn)了一遍,這下可以說(shuō)是完美了~

      同時(shí)所有項(xiàng)目代碼已經(jīng)上傳GitHub,歡迎各位大佬Star/Fork!

      生成隨機(jī)尺寸圖片的功能目前用在文章卡片上,原本使用的是LoremPicsum提供的服務(wù),但它的服務(wù)器在國(guó)外,上線之后發(fā)現(xiàn)加載太慢了,經(jīng)常加載不出來(lái),于是決定自己實(shí)現(xiàn)一版。功能基礎(chǔ)是上文提到的文章中的ImageSharp。

      image

      思路

      先理一下需求

      • 指定一個(gè)目錄作為圖片庫(kù)位置,把之前搜集的壁紙圖片放進(jìn)去,大概放個(gè)幾百?gòu)埦托辛税?/li>
      • 遍歷獲取到庫(kù)中的圖片列表
      • 隨機(jī)取出一張圖片
      • 根據(jù)指定的尺寸縮放或裁剪圖片

      其他的還有諸如指定隨機(jī)seed、將seed與圖片進(jìn)行靜態(tài)映射等擴(kuò)展功能的實(shí)現(xiàn)。

      關(guān)鍵功能

      關(guān)鍵功能在于「根據(jù)指定的尺寸縮放或裁剪圖片」

      難點(diǎn)在于裁剪和縮放圖片要保證:

      • 不改變圖片原有的比例
      • 盡量保持圖片原有的內(nèi)容元素

      第一版我是將橫屏和豎屏的圖片分開(kāi)處理,(在輸入尺寸不超過(guò)原圖尺寸的情況下)先把比例接近的邊調(diào)整成一樣的大小,再裁剪中間部分,不過(guò)問(wèn)題也很明顯,如果調(diào)整大小之后另一條邊的長(zhǎng)度小于輸入長(zhǎng)度,那就會(huì)拉伸圖片,導(dǎo)致比例改變。

      在參考幾個(gè)類似的MATLAB和Python項(xiàng)目之后,我換了別的思路:

      1. 在輸入尺寸不超過(guò)原圖尺寸的情況下,先按輸入的尺寸比例裁剪、再調(diào)整尺寸
      2. 如果超出原圖尺寸,則先按比例調(diào)整原圖的大小,再重復(fù)第一步

      舉個(gè)例子

      比如原圖是 1080 x 2340 的尺寸,輸入的圖片是 400 x 200 尺寸

      那第一步判斷尺寸不超過(guò)原圖,不需要縮放

      然后是「按輸入的尺寸比例裁剪」,把 400 x 200 化簡(jiǎn)成 2 : 1 的比例

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

      然后再把截取的圖片調(diào)整到 400 x 200,搞定!

      看下效果

      原圖 輸出(400x200) 輸出(200x300)
      image image image

      雖然比一開(kāi)始的方案更費(fèi)一丟丟內(nèi)存,但卻實(shí)實(shí)在在提升了出圖成功率,nice~

      代碼實(shí)現(xiàn)

      直接上代碼好了,根據(jù)上面提到的思路,分兩步走,代碼也比一開(kāi)始的方案更整潔

      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));
                  else
                      image.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);
          }
      

      里面還用到了計(jì)算圖片比例,很簡(jiǎn)單,先算出圖片寬度和高度的最大公約數(shù),然后寬高分別除以這個(gè)最大公約數(shù),就是比例了(也就是化簡(jiǎn)分?jǐn)?shù))

      計(jì)算最大公約數(shù)代碼

      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;
      }
      

      計(jì)算圖片比例代碼

      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);
      }
      

      參考資料

      posted @ 2022-07-08 10:21  程序設(shè)計(jì)實(shí)驗(yàn)室  閱讀(1028)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 精品人妻少妇一区二区三区| 国产精品欧美一区二区三区不卡 | 特黄特色的大片观看免费视频| 日本一码二码三码的区分| 精品不卡一区二区三区| 汝州市| 国产精品一二三区久久狼| 午夜成人无码免费看网站| 黄网站色视频免费观看| 日本韩国日韩少妇熟女少妇| 久女女热精品视频在线观看| 国产精品午夜福利合集| 国产老肥熟一区二区三区| 国产成人8X人网站视频| 西乌| 国产一区二区三区黄色片 | 日韩亚洲精品国产第二页| 亚洲国产片一区二区三区| 国产熟睡乱子伦视频在线播放 | 日韩在线观看 一区二区| 亚洲在线一区二区三区四区| 漠河县| 欧美日韩国产图片区一区| 国产成人8X人网站视频| 日本成本人片免费网站| 日产中文字幕在线精品一区| 国产精品无码a∨麻豆| 日本污视频在线观看| 日韩视频中文字幕精品偷拍| 国内自拍偷拍一区二区三区| 午夜福利国产精品视频| 99国内精品久久久久久久| 国产一区二区三区黄色片| 国产高清亚洲一区亚洲二区| 国产精品亚洲mnbav网站| 天天做天天爱夜夜爽导航| 国内精品久久久久影院日本| 欧美人人妻人人澡人人尤物| 精品少妇人妻av无码久久| 久久精品国产亚洲av麻| 鹤山市|