在ASP.NET中生成图像缩略图?

17

什么是.NET中生成缩略图最快且最可靠的方法?我需要获取任何图像,将其压缩为JPEG并调整大小。

我看过几个使用GDI+和一些非免费组件的示例,我记得WPF在图像处理方面有一些好东西。尽管GDI+相当古老,但WPF可能在服务器环境下没有好处。

这必须在运行于完全信任的ASP.NET MVC应用程序中工作,并且如果可能,同步进行。

你会推荐什么?

更新:

基于Mantorok的答案,我已经制定了这个示例,但它仍然是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);
        }
    }
}

抛出了什么异常? - Mantorok
在 Image.FromFile(filename) 中发生 OutOfMemoryException。 - vtortola
哎呀!这个文件有多大啊!? - Mantorok
8.75 Mb:http://greatmarta.deviantart.com/art/KovuKiaraCubs-114524760 - vtortola
快速搜索得到了这个结果:https://dev59.com/-3NA5IYBdhLWcg3wC5Xh - Mantorok
7个回答

7
这对我来说已经足够好用了多年:

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

简单而优雅,我一定会借鉴这个! - kite
不过,试试用一张大图,比如 1920 * 60000。这样并不够健壮。 - TEK

5

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

你怎么使用它?我找到了一个 .net 封装器,但是它没有文档,而且你提到的那些类在其中并不存在。 - vtortola
我不使用ImageMagick.NET,而是使用ImageMagickObject dll(因为像你写的那样,.NET版本完全没有文档说明)。等一下,我会在这里放上完整的解决方案。 - Evgeniy Labunskiy
ImageMagickObject是一个COM+对象吗? - vtortola
是的。已经下载并安装在电脑上,然后附加到项目中。 - Evgeniy Labunskiy
抱歉,我忘了提到我正在使用Azure,显然COM+对象不起作用:(。无论如何,这是一个很好的例子,非常感谢。我会在其他项目中使用它。 - vtortola

3

请看我在这里的回答:创建缩略图

Image上有一个返回缩略图的函数,如下所示:

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

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

0

0

我正在使用Aurigma Image Uploader工具。它是一个非常好的控件,但需要付费。你可以查看aurigma


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接