2011-05-04 132 views
16

在.NET中生成縮略圖的最快和最可靠的方法是什麼?我需要得到任何圖像,以JPEG格式壓縮並調整大小。在ASP.NET中生成圖像縮略圖?

我見過幾個GDI +的例子,一些非自由組件,我記得WPF有一些關於圖像的好東西。 GDI +很老,WPF的東西可能對服務器環境沒有任何好處。

這必須在完全信任的運行的ASP.NET MVC應用程序中運行,並且如果可能的話同步運行。

你會推薦什麼?

UPDATE:

基於Mantorok's answer我已經制定了這個例子,但它仍然是GDI +,它崩潰,如果我試圖用一個大的圖像:

public void GenerateThumbnail(String filename, Int32? desiredWidth, 
    Int32? desiredHeight, Int64 quality, Stream s) 
{ 
    using (Image image = Image.FromFile(filename)) 
    { 
     Int32 width=0, height=0; 

     if ((!desiredHeight.HasValue && !desiredWidth.HasValue) || 
      (desiredHeight.HasValue && desiredWidth.HasValue)) 
      throw new ArgumentException(
       "You have to specify a desired width OR a desired height"); 

     if (desiredHeight.HasValue) 
     { 
      width = (desiredHeight.Value * image.Width)/image.Height; 
      height = desiredHeight.Value; 
     } 
     else 
     { 
      height = (desiredWidth.Value * image.Height)/image.Width; 
      width = desiredWidth.Value; 
     } 

     using (var newImage = new Bitmap(width, height)) 
     using (var graphics = Graphics.FromImage(newImage)) 
     using (EncoderParameter qualityParam = 
      new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 
       quality)) 
     using (EncoderParameters encoderParams = new EncoderParameters(1)) 
     { 
      graphics.DrawImage(image, 0, 0, width, height); 
      ImageCodecInfo jpegCodec = ImageCodecInfo.GetImageEncoders(). 
       Single(e => e.MimeType.Equals("image/jpeg", 
        StringComparison.Ordinal)); 
      encoderParams.Param[0] = qualityParam; 
      newImage.Save(s, jpegCodec, encoderParams); 
     } 
    } 
} 
+0

什麼是異常被拋出? – Mantorok 2011-05-05 11:38:26

+0

Image.FromFile中的OutOfMemoryException(文件名) – vtortola 2011-05-06 17:01:57

+0

Blimey!文件有多大!? – Mantorok 2011-05-09 10:20:02

回答

5

對於密集的服務器端代碼,我建議您使用除GDI +以外的其他技術,這些技術還沒有設計用於處理圖像(以流式方式)。

您可以使用Windows Imaging Component或WPF執行此任務。這裏是如何做到這一點的快速和一個很好的例子 - 更重要的 - 可擴展的方式在這裏:

The fastest way to resize images from ASP.NET. And it’s (more) supported-ish.

+0

太好了,謝謝! – vtortola 2011-05-11 08:19:31

+0

http://imageresizing.net庫現在提供基於WIC的調整大小。它比Bertrand的示例代碼更快,並且可以正確管理內存。它非常簡單易用。 – 2012-01-09 21:01:07

2

我不能說無論這是最有效的方式,但這裏是我寫的代碼片段,用於從大圖像中產生3個較小的圖像:

private void GenerateImages(byte[] data, string extension, string filename) 
    { 
    // Assuming data is the original filename. 
    var ms = new MemoryStream(data); 
    var image = Image.FromStream(ms); 
    image.Save(filename); 
    ResizeImage(image, 800, 600, "large.jpg"); 
    ResizeImage(image, 480, 320, "medium.jpg"); 
    ResizeImage(image, 192, 144, "small.jpg"); 
    } 

    private void ResizeImage(Image image, int width, int height, string filename) 
    { 
    using (var newImage = new Bitmap(width, height)) 
    { 
     var graphics = Graphics.FromImage(newImage); 
     graphics.DrawImage(image, 0, 0, width, height); 
     newImage.Save(filename, ImageFormat.Jpeg); 
    } 
    } 
3

我使用ImageMagick的進行照片處理

修訂

型號:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.IO; 
using ImageMagickObject; 

namespace photostorage.Models 
{ 
    public class PhotoProcessing 
    { 
     public MagickImage ResizeImg(string filepath, string filename) 
     { 
      Object[] rotate = new Object[] { filepath + "/" + filename, 
       "-auto-orient", filepath + "/" + filename }; 
      Object[] big = new Object[] { filepath + "/" + filename, 
       "-resize", "800", filepath + "/" + "big_" + filename }; 
      Object[] middle = new Object[] { filepath + "/big_" + filename, 
       "-resize", "400", filepath + "/" + "mid_" + filename }; 
      Object[] small = new Object[] { filepath + "/mid_" + filename, 
       "-resize", "200", filepath + "/" + "small_" + filename }; 
      Object[] crop = new Object[] { filepath + "/small_" + filename, 
       "-resize", "50", filepath + "/" + "crop_" + filename }; 
      ImageMagickObject.MagickImage img = 
       new ImageMagickObject.MagickImage(); 
      img.Convert(rotate); 
      img.Convert(big); 
      img.Convert(middle); 
      img.Convert(small); 
      img.Convert(crop); 
      return img; 
     } 
    } 
} 

控制器:

PhotoProcessing resizeImg = new PhotoProcessing(); 
[HttpPost] 
public string Index(params,params,params...) 
{ 
    var GetResize = resizeImg.ResizeImg(
     destinationFolder + "/" + curFolder, fullFileName); 
} 
+0

你如何使用它?我找到了一個.net包裝器,但它沒有記錄,並且你提到的類不存在。 – vtortola 2011-05-04 14:30:37

+0

我不使用ImageMagick.NET - 我使用ImageMagickObject dll(原因,就像你寫的,.net vertion完全沒有記錄)。等一下,我會在這裏提供完整的解決方案 – 2011-05-04 14:32:37

+0

檢查更新 – 2011-05-04 14:38:25

0

我使用Aurigma圖片上傳工具。這是非常好的控制。但支付你可以檢查aurigma

3

看到這裏Create thumbnail image

我的回答有關於圖像的功能,它返回一個像這樣的縮略圖:

Image image = Image.FromFile(fileName); 
Image thumb = image.GetThumbnailImage(120, 120,()=>false, IntPtr.Zero); 
thumb.Save(Path.ChangeExtension(fileName, "thumb")); 
6

這已經爲我做了罰款歲:

public static void CreateThumbnail(string filename, int desiredWidth, int desiredHeight, string outFilename) 
{ 
    using (System.Drawing.Image img = System.Drawing.Image.FromFile(filename)) 
    { 
     float widthRatio = (float)img.Width/(float)desiredWidth; 
     float heightRatio = (float)img.Height/(float)desiredHeight; 
     // Resize to the greatest ratio 
     float ratio = heightRatio > widthRatio ? heightRatio : widthRatio; 
     int newWidth = Convert.ToInt32(Math.Floor((float)img.Width/ratio)); 
     int newHeight = Convert.ToInt32(Math.Floor((float)img.Height/ratio)); 
     using (System.Drawing.Image thumb = img.GetThumbnailImage(newWidth, newHeight, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailImageAbortCallback), IntPtr.Zero)) 
     { 
      thumb.Save(outFilename, System.Drawing.Imaging.ImageFormat.Jpeg); 
     } 
    } 
} 

public static bool ThumbnailImageAbortCallback() 
{ 
    return true; 
} 
+0

古樸典雅;我偷這個肯定:) – kite 2013-05-01 13:36:50

+0

儘管如此,與大圖像。例如1920 * 60000。不夠健壯。 – TEK 2016-02-20 12:11:07