使用C#创建缩略图图像

Ber*_*eer 5 c# jpeg gdi+ razor asp.net-mvc-3

@functions{

    public void GetThumbnailView(string originalImagePath, int height, int width)
    {
        //Consider Image is stored at path like "ProductImage\\Product1.jpg"

        //Now we have created one another folder ProductThumbnail to store thumbnail image of product.
        //So let name of image be same, just change the FolderName while storing image.
        string thumbnailImagePath = originalImagePath;
        originalImagePath = originalImagePath.Replace("thumb_", "");
        //If thumbnail Image is not available, generate it.
        if (!System.IO.File.Exists(Server.MapPath(thumbnailImagePath)))
        {
            System.Drawing.Image imThumbnailImage; 
            System.Drawing.Image OriginalImage = System.Drawing.Image.FromFile(Server.MapPath(originalImagePath));

            double originalWidth = OriginalImage.Width;
            double originalHeight = OriginalImage.Height;

            double ratioX = (double)width / (double)originalWidth;
            double ratioY = (double)height / (double)originalHeight;

            double ratio = ratioX < ratioY ? ratioX : ratioY; // use whichever multiplier is smaller

            // now we can get the new height and width
            int newHeight = Convert.ToInt32(originalHeight * ratio);
            int newWidth = Convert.ToInt32(originalWidth * ratio);

            imThumbnailImage = OriginalImage.GetThumbnailImage(newWidth, newHeight,
                         new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);
            imThumbnailImage.Save(Server.MapPath(thumbnailImagePath), System.Drawing.Imaging.ImageFormat.Jpeg);

            imThumbnailImage.Dispose();
            OriginalImage.Dispose();
        }

    }

    public bool ThumbnailCallback() { return false; }

}
Run Code Online (Sandbox Code Playgroud)

在另一个stackowerflow问题我发现这个代码,并且非常喜欢它,但在使用它时,在创建缩略图图像时出现了问题,如下所示:

'/'应用程序中的服务器错误.

内存不足.描述:执行当前Web请求期间发生未处理的异常.请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息.

异常详细信息:System.OutOfMemoryException:内存不足.

来源错误:

第199行:{

第200行:System.Drawing.Image imThumbnailImage;

第201行:System.Drawing.Image OriginalImage = System.Drawing.Image.FromFile(Server.MapPath(originalImagePath.ToString()));

202行:

第203行:double originalWidth = OriginalImage.Width;

源文件:c:\ Inetpub\wwwroot\Lokal\Views\Stok\SatisRaporu.cshtml
行:201

我对这个问题的好奇心让我进入了异常细节,看到了这个:

    //
    // Summary:
    //     Creates an System.Drawing.Image from the specified file.
    //
    // Parameters:
    //   filename:
    //     A string that contains the name of the file from which to create the System.Drawing.Image.
    //
    // Returns:
    //     The System.Drawing.Image this method creates.
    //
    // Exceptions:
    //   System.OutOfMemoryException:
    //     The file does not have a valid image format.-or- GDI+ does not support the
    //     pixel format of the file.
    //
    //   System.IO.FileNotFoundException:
    //     The specified file does not exist.
    //
    //   System.ArgumentException:
    //     filename is a System.Uri.
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    public static Image FromFile(string filename);
Run Code Online (Sandbox Code Playgroud)

但是我在该文件夹中的所有图片都有".jpg"扩展名,因此对我来说似乎很奇怪.如果我不能从".jpg"创建缩略图我还能做什么?

我真的想知道是否有其他人在".jpg"文件上尝试过此操作并遇到问题?如果没有问题我可能做错了什么?

一点注意事项:我在使用剃刀语法的视图中执行此操作.我对c#语言有一点了解,并且每天都在提高我的知识.

编辑:

我怎么称呼这个功能:

GetThumbnailView("../pics/thumb_" + (("0000000" + stocks.stockcode).Substring(("0000000" + stocks.stockcode).Length - 7, 7)) + ".jpg", 200, 200);
Run Code Online (Sandbox Code Playgroud)

Rom*_*kov 3

我工作的一个网站使用 WPF API 而不是 GDI+ 生成缩略图。您需要向项目添加两个引用才能启用此功能:WindowsBase、PresentationFramework 和PresentationCore。Here\xe2\x80\x99是如何使用代码的基本示例:

\n\n
try\n{\n    using (var input = File.Open(inputFilename, FileMode.Open, FileAccess.Read, FileShare.Read))\n    using (var thumb = File.Open(thumbFilename, FileMode.Create, FileAccess.Write, FileShare.None))\n    {\n        Thumbnail(input, thumb, 200, 100);\n    }\n}\ncatch (MyException)\n{\n    File.Delete(thumbFilename);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这会将缩略图放入 200x100 的矩形中,同时保留纵横比。

\n\n

(真实的网站并没有像上面那样做。我们实际上做的是尝试在文件上传 POST 处理程序中生成最小的缩略图。我们使用内存流来保存生成的缩略图。如果缩略图可以正确生成,我们保存上传和小缩略图,否则我们向客户端返回错误响应。其他缩略图大小是动态生成并缓存的。)

\n\n

Here\xe2\x80\x99s 是代码 - 请注意,我在将其转换为可重用的东西时可能有点混乱,但核心位应该都在那里。请注意,它将所有缩略图保存为 JPEG,但允许多种输入格式,包括 JPEG 和 PNG。这可能适合你,也可能不适合你。

\n\n
private static void Thumbnail(Stream source, Stream destination, int maxWidth, int maxHeight)\n{\n    int width = 0, height = 0;\n    BitmapFrame frame = null;\n    try\n    {\n        frame = BitmapDecoder.Create(source, BitmapCreateOptions.None, BitmapCacheOption.None).Frames[0];\n        width = frame.PixelWidth;\n        height = frame.PixelHeight;\n    }\n    catch\n    {\n        throw new MyException("The image file is not in any of the supported image formats.");\n    }\n\n    if (width > AbsoluteLargestUploadWidth || height > AbsoluteLargestUploadHeight)\n        throw new MyException("This image is too large");\n\n    try\n    {\n        int targetWidth, targetHeight;\n        ResizeWithAspect(width, height, maxWidth, maxHeight, out targetWidth, out targetHeight);\n\n        BitmapFrame targetFrame;\n        if (frame.PixelWidth == targetWidth && frame.PixelHeight == targetHeight)\n            targetFrame = frame;\n        else\n        {\n            var group = new DrawingGroup();\n            RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);\n            group.Children.Add(new ImageDrawing(frame, new Rect(0, 0, targetWidth, targetHeight)));\n            var targetVisual = new DrawingVisual();\n            var targetContext = targetVisual.RenderOpen();\n            targetContext.DrawDrawing(group);\n            var target = new RenderTargetBitmap(targetWidth, targetHeight, 96, 96, PixelFormats.Default);\n            targetContext.Close();\n            target.Render(targetVisual);\n            targetFrame = BitmapFrame.Create(target);\n        }\n\n        var enc = new JpegBitmapEncoder();\n        enc.Frames.Add(targetFrame);\n        enc.QualityLevel = 80;\n        enc.Save(destination);\n    }\n    catch\n    {\n        throw new MyException("The image file appears to be corrupt.");\n    }\n}\n\n/// <summary>Generic helper to compute width/height that fit into specified maxima while preserving aspect ratio.</summary>\npublic static void ResizeWithAspect(int origWidth, int origHeight, int maxWidth, int maxHeight, out int sizedWidth, out int sizedHeight)\n{\n    if (origWidth < maxWidth && origHeight < maxHeight)\n    {\n        sizedWidth = origWidth;\n        sizedHeight = origHeight;\n        return;\n    }\n\n    sizedWidth = maxWidth;\n    sizedHeight = (int) ((double) origHeight / origWidth * sizedWidth + 0.5);\n    if (sizedHeight > maxHeight)\n    {\n        sizedHeight = maxHeight;\n        sizedWidth = (int) ((double) origWidth / origHeight * sizedHeight + 0.5);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n