简体   繁体   English

优化网络图像(C#和ASP.NET MVC)

[英]Optimize image for web (C# & ASP.NET MVC)

I am looking for a way to efficiently prepare large amount of images for website in .NET 我正在寻找一种有效地为.NET网站准备大量图像的方法

Images are often largescale, unedited, 2-5MB 4000x8000px monster images from phone camera. 图片通常是来自手机摄像头的大型,未经编辑的2-5MB 4000x8000px怪物图片。

I would like to generate thumbnails quickly, and as efficient as possible. 我想快速且尽可能高效地生成缩略图。 (not to slow down CPU) or performance for user. (不降低CPU速度)或用户的性能。

I also have to consider caching. 我还必须考虑缓存。

Modern CMS systems are using Image pre-processor that you can invoke via front-end. 现代CMS系统使用的图像预处理器可以通过前端调用。 So I want to make something like this also, but my own. 所以我也想做这样的事情,但我自己做。 Cause in my case, I can't use CMS here. 因为就我而言,我不能在这里使用CMS。

Here is my code: I have a static helper method from Helper class. 这是我的代码:我有一个来自Helper类的静态helper方法。 I call it in razor every time I need to render an image. 每当我需要渲染图像时,我都会用剃刀来称呼它。

public static string GetImgThumbnail(string web_path, int _width = 0, int _height = 0)
{
        //Default parameters
        Image image;
        Image thumbnail;
        string thumb_url = "/img/noimg.png";

        try
        {
            // web_path example input "/images/helloworld.jpg"
            //system_path returns system path of Ogirinal image in the system f.e.: "C:\projects\websites\mysite\images\helloworld.jpg"
            string system_path = HttpContext.Current.Server.MapPath(web_path);
            image = Image.FromFile(system_path);

            //Original image dimensions
            int width = image.Width;
            int height = image.Height;

            //Get New image dimensions
            if(_height == 0)
            {
                if(_width == 0)
                {
                    _width = 700;
                }
                _height = (_width * height) / width;
            }

            if (_width == 0)
            {
                if (_height == 0)
                {
                    _height = 700;
                }
                _width = (_height * width) / height;
            }

            //Generate Thumbnail, passing in new dimensions
            thumbnail = image.GetThumbnailImage(_width, _height, null, IntPtr.Zero);

            //Find out how to call newly created thumbnail.
            //Original image example name = "/images/helloworld.jpg" thumbnail would be "/images/helloworld_thumb_700x250.jpg" or analogical with .png or JPEG etc...
            //Suffix should be "_thumb_{width}x{height}"
            string suffix = string.Format("_thumb_{0}x{1}", _width.ToString(),_height.ToString());

            var bigImgFilename = String.Format("{0}{1}",
                     Path.GetFileNameWithoutExtension(system_path), Path.GetExtension(system_path));

            var newImgFilename = String.Format("{0}{1}{2}",
                     Path.GetFileNameWithoutExtension(system_path), suffix, Path.GetExtension(system_path));

            //New system path of new Thumbnail example: "C:\projects\websites\mysite\images\helloworld_thumb_700x250.jpg"
            var newpath = system_path.Replace(bigImgFilename, newImgFilename);

            //Set new web path, expect this to be: "/images/helloworld_thumb_700x250.jpg"
            thumb_url = web_path.Replace(bigImgFilename, newImgFilename);

            //Check if file exists, no need to overrite if file exists.
            if (!File.Exists(newpath)) 
            { 
                thumbnail.Save(newpath);
            }

        }
        catch (Exception exc)
        {
            // If something goes wrong, just return backup image.
            thumb_url = "/img/noimg.png";
        }

        // return thumbnail 
        return thumb_url;
}

Would love to hear some tips/suggestions or whether I am on the right path, or I should do it in different way? 是否希望听到一些提示/建议,或者我是否走在正确的道路上,还是应该以其他方式进行?

So in your code, you calculate the thumbnail first. 因此,在您的代码中,您首先要计算缩略图。 Then you calculate the filename and check if the thumbnail calculation was necessary. 然后,您计算文件名并检查是否需要进行缩略图计算。

I would do in a different order: 我会以不同的顺序执行:

  1. Load the image (since you need that to calculate the new filename) 加载图像(因为您需要用它来计算新文件名)
  2. Calculate the new filename 计算新文件名
  3. Check if the file is already there 检查文件是否已经存在
  4. If the file is already there, use it 如果文件已经存在,请使用它
  5. If not, generate the thumbnail. 如果没有,请生成缩略图。

In code this would roughtly look like the following: 在代码中,它大致如下所示:

public static string GetImgThumbnail(string web_path, int _width = 0, int _height = 0)
{

    [...]
    string system_path = HttpContext.Current.Server.MapPath(web_path);
    image = Image.FromFile(system_path);

    // calculate new width and height
    [...]

    // calculate new filename
    [...]
        //New system path of new Thumbnail example: "C:\projects\websites\mysite\images\helloworld_thumb_700x250.jpg"
        var newpath = system_path.Replace(bigImgFilename, newImgFilename);

        //Set new web path, expect this to be: "/images/helloworld_thumb_700x250.jpg"
        thumb_url = web_path.Replace(bigImgFilename, newImgFilename);

        //Check if file exists, no need to overrite if file exists.
        if (!File.Exists(newpath)) 
        { 
            //Generate Thumbnail, passing in new dimensions
            thumbnail = image.GetThumbnailImage(_width, _height, null, IntPtr.Zero);
            thumbnail.Save(newpath);
        }

My point is: Loading an image and calculating the size dosen't use much resources. 我的观点是:加载图像并计算尺寸不会占用太多资源。 The resizing part is a heavy on the CPU. 调整大小部分是CPU上的沉重负担。 So you will get faster responses, if you only transform the image if necessary. 因此,如果仅在必要时仅变换图像,您将获得更快的响应。


Here are some points you can consider: 您可以考虑以下几点:

I call it in razor every time I need to render an image. 每当我需要渲染图像时,我都会用剃刀来称呼它。

This will generate a thumbnail on every image view. 这将在每个图像视图上生成一个缩略图。 This is very cpu heavy and most likely not what you want. 这是非常重的CPU,很可能不是您想要的。 Consider creating the thumbnail only once, save it to disk and start using the pre-rendered version. 考虑只创建一次缩略图,将其保存到磁盘并开始使用预渲染的版本。

Next issue: 下期:

 //Check if file exists, no need to overrite if file exists. if (!File.Exists(newpath)) { thumbnail.Save(newpath); } 

You first compute the thumbnail and then check if the computation has already be done. 您首先计算缩略图,然后检查计算是否已经完成。 It should be the other way round. 反之亦然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM