程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> 您能看出這個生成縮略圖的方法有什麼問題嗎?

您能看出這個生成縮略圖的方法有什麼問題嗎?

編輯:.NET實例教程


昨天又使用了某個多年以前寫的,或者說是“收集”而來的方法。這個方法的作用是根據一幅圖片(一般是幅大圖)生成它的縮略圖。這個方法用了許多年了,一直沒有去懷疑過它的正確性,但是昨天忽然發現它一直以來都存在一個問題,雖然可能不是那麼明顯,而且也不會造成太大問題(否則早就發現了)——但是,這的確是個不妥的地方。這個問題在我看來也有一定借鑒意義,因此我打算把它展示出來。那麼,您能否看出它究竟是錯在什麼地方了呢?

  生成縮略圖的規則很簡單,概括地說有三點:

  包含圖片完整內容,以及長寬比不變。

  尺寸盡可能大,但如果圖片本身很小,也不做拉伸。

  不超過指定的width * height的范圍內。

  這個規則其實就是最傳統的縮略圖生成方式,使用如Windows照片浏覽器等軟件打開圖片後,一般來說默認都會如此調整圖片尺寸。而我們如果需要寫一段代碼來實現這一點也並不困難,以下便是我用了許多年的方法:

/// <summary> 
/// Creates a thumbnail from an existing image. Sets the biggest dimension of the 
/// thumbnail to either desiredWidth or Height and scales the other dimension down 
/// to preserve the ASPect ratio 
/// </summary> 
/// <param name="imageStream">stream to create thumbnail for</param> 
/// <param name="desiredWidth">maximum desired width of thumbnail</param> 
/// <param name="desiredHeight">maximum desired height of thumbnail</param> 
/// <returns>Bitmap thumbnail</returns> 
public Bitmap CreateThumbnail(Bitmap originalBmp, int desiredWidth, int desiredHeight) 
{ 
  // If the image is smaller than a thumbnail just return it 
  if (originalBmp.Width <= desiredWidth && originalBmp.Height <= desiredHeight) 
  { 
    return originalBmp; 
  } 
 
  int newWidth, newHeight; 
 
  // scale down the smaller dimension 
  if ((decimal)desiredWidth / originalBmp.Width < (decimal)desiredHeight / originalBmp.Height) 
  { 
    decimal desiredRatio = (decimal)desiredWidth / originalBmp.Width; 
    newWidth = desiredWidth; 
    newHeight = (int)(originalBmp.Height * desiredRatio); 
  } 
  else 
  { 
    decimal desiredRatio = (decimal)desiredHeight / originalBmp.Height; 
    newHeight = desiredHeight; 
    newWidth = (int)(originalBmp.Width * desiredRatio); 
  } 
 
  // This code creates cleaner (though bigger) thumbnails and properly 
  // and handles GIF files better by generating a white background for 
  // transparent images (as opposed to black) 
  // This is preferred to calling Bitmap.GetThumbnailImage() 
  Bitmap bmpOut = new Bitmap(newWidth, newHeight); 
 
  using (Graphics graphics = Graphics.FromImage(bmpOut)) 
  { 
    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
    graphics.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight); 
    graphics.DrawImage(originalBmp, 0, 0, newWidth, newHeight); 
  } 
 
  return bmpOut; 
}

它的具體來源我已經記不得了,不過從英文注釋上來看這應該是個老外寫的代碼,那麼我們現在就來解釋一番。首先,這個方法會先判斷源圖片的大小是否已經可以放入目標區域(desiredWidth * desiredHeight)中了,如果是,則直接返回源圖片。如果不滿足第一個判斷,則說明寬和高之中至少有一個超出了目標尺寸,而我們要對源圖片進行等比例縮放。

  那麼縮放的“比例”又是多少呢?自然是“寬”或“高”中縮放“程度大”的那個。因為如果按照縮放程度小的那條邊的比例來改變圖片尺寸,那麼另一條邊勢必會超出范圍。因此,我們接下來便是比較desiredWidth與originalBmp.Width之比,以及desiredHeight與 originalBmp.Height之比孰大孰小。哪個小,則意味著我們要把它作為縮放依據,因為它對圖片尺寸的限制要比另一條邊來的嚴格。於是乎,再第二個條件判斷的任意一個分支中,我們都可以計
算出縮放的比例(desiredRatio),然後把作為“依據”的那條邊設為 desiredWidth/Height,將另一條邊根據縮放比例進行調整。在計算和比較過程中我們都使用了decimal數據類型,因為它是.Net中精度最高的浮點數類型,我們以此減少計算過程中所帶來的誤差。

  至於得到了newWidth和newHeight之後,我們便只要根據這個尺寸生成目標圖片即可,它便是源圖片的縮略圖,符合我們之前提出的三個要求。

  聽起來很簡單,看上去也沒有什麼問題,不是嗎?不過,其實這個實現中有一個不那麼明顯的問題,您發現了嗎

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved