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

发布于 2024-11-05 07:26:37 字数 1962 浏览 4 评论 0原文

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

What is the fastest and more reliable way of generating thumbnails in .NET? I need to get any image, compress it in JPEG and resize it.

I've seen several examples with GDI+, some non-free components and I remember WPF has some good stuff about imaging. GDI+ is pretty old and the WPF stuff maybe has no benefits on a server environment though.

This has to work in a ASP.NET MVC application that runs on full trust, and if possible, synchronously.

What would you recommend?

UPDATE:

Based on Mantorok's answer I have worked out this example, but it's still GDI+, and it crashes if I try with a large image:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

青衫负雪 2024-11-12 07:26:37

多年来,这让我受益匪浅:

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

This has done me fine for years:

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;
}
捶死心动 2024-11-12 07:26:37

对于密集的服务器端代码,我建议您使用 GDI+ 以外的其他技术,这些技术未设计用于逐块处理图像(以流方式)。

您可以使用 Windows 成像组件 或 WPF 来执行此任务。这里有一个非常好的示例,说明如何以快速且更重要的是可扩展的方式执行此操作:

从 ASP.NET 调整图像大小的最快方法。而且它是(更多)受支持的。

For intensive server-side code, I suggest you use other techniques than GDI+ that has not been designed to handle images chunk by chunk (in a streaming manner).

You can use Windows Imaging Component or WPF for this task. There is a very good example on how to do this in a fast and - more important - scalable manner here:

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

2024-11-12 07:26:37

我使用 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);
}

I use ImageMagick for photo processing

UPDATED

Model:

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

Controller:

PhotoProcessing resizeImg = new PhotoProcessing();
[HttpPost]
public string Index(params,params,params...)
{
    var GetResize = resizeImg.ResizeImg(
        destinationFolder + "/" + curFolder, fullFileName);
}
南烟 2024-11-12 07:26:37

在这里查看我的答案 创建缩略图

Image 上有一个函数返回像这样的缩略图:

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

See my answer here Create thumbnail image

There is a function on Image which returns a thumbnail like this:

Image image = Image.FromFile(fileName);
Image thumb = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero);
thumb.Save(Path.ChangeExtension(fileName, "thumb"));
呆橘 2024-11-12 07:26:37

我不能说这是否是最有效的方式,但这是我编写的一段代码,用于从大图像生成 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);
     }
  }

I can't say whether this is the most efficient manner, but here is a snippet of code I wrote to produce 3 smaller images from a large image:

  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);
     }
  }
秋意浓 2024-11-12 07:26:37

我正在使用 Aurigma Image Uploader 工具。这是相当不错的控制。但它是付费的,你可以查看 aurigma

I am using Aurigma Image Uploader tool. it's pretty nice control. but it is paid you can check aurigma

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文