【问题标题】:What is the "best" way to create a thumbnail using ASP.NET? [closed]使用 ASP.NET 创建缩略图的“最佳”方法是什么? [关闭]
【发布时间】:2010-09-06 21:00:05
【问题描述】:

故事:用户上传将添加到照片库的图像。作为上传过程的一部分,我们需要 A) 将图像存储在网络服务器的硬盘上,并且 B) 将图像的缩略图存储在网络服务器的硬盘上。

这里的“最佳”定义为

  • 相对容易实施、理解和维护
  • 生成质量合理的缩略图

性能和高质量的缩略图是次要的。

【问题讨论】:

    标签: asp.net image thumbnails


    【解决方案1】:

    我想您最好的解决方案是使用 .NET Image 类中的 GetThumbnailImage

    // Example in C#, should be quite alike in ASP.NET
    // Assuming filename as the uploaded file
    using ( Image bigImage = new Bitmap( filename ) )
    {
       // Algorithm simplified for purpose of example.
       int height = bigImage.Height / 10;
       int width = bigImage.Width / 10;
    
       // Now create a thumbnail
       using ( Image smallImage = image.GetThumbnailImage( width, 
                                                           height,
                                                           new Image.GetThumbnailImageAbort(Abort), IntPtr.Zero) )
       {
          smallImage.Save("thumbnail.jpg", ImageFormat.Jpeg);
       }
    }
    

    【讨论】:

    • GetThumbnailImage 仅适用于 60x60 或更小的缩略图 - 它使用相机生成的缩略图。还有29 other edge cases you need to handle,请确保您了解它们....顺便说一句,imageresizing.net 项目现在是免费的、开源的和受支持的...并且正确处理了 29 个陷阱。
    【解决方案2】:

    这是 VB.NET 中 Image 类的扩展方法

    Imports System.Runtime.CompilerServices
    
    Namespace Extensions
       ''' <summary>
       ''' Extensions for the Image class.
       ''' </summary>
       ''' <remarks>Several usefull extensions for the image class.</remarks>
       Public Module ImageExtensions
    
          ''' <summary>
          ''' Extends the image class so that it is easier to get a thumbnail from an image
          ''' </summary>
          ''' <param name="Input">Th image that is inputted, not really a parameter</param>
          ''' <param name="MaximumSize">The maximumsize the thumbnail must be if keepaspectratio is set to true then the highest number of width or height is used and the other is calculated accordingly. </param>
          ''' <param name="KeepAspectRatio">If set false width and height will be the same else the highest number of width or height is used and the other is calculated accordingly.</param>
          ''' <returns>A thumbnail as image.</returns>
          ''' <remarks>
          ''' <example>Can be used as such. 
          ''' <code>
          ''' Dim _NewImage as Image 
          ''' Dim _Graphics As Graphics
          ''' _Image = New Bitmap(100, 100)
          ''' _Graphics = Graphics.FromImage(_Image)
          ''' _Graphics.FillRectangle(Brushes.Blue, New Rectangle(0, 0, 100, 100))
          ''' _Graphics.DrawLine(Pens.Black, 10, 0, 10, 100)
          ''' Assert.IsNotNull(_Image)
          ''' _NewImage = _Image.ToThumbnail(10)
          ''' </code>
          ''' </example>
          ''' </remarks>
          <Extension()> _
          Public Function ToThumbnail(ByVal Input As Image, ByVal MaximumSize As Integer, Optional ByVal KeepAspectRatio As Boolean = True) As Image
             Dim ReturnImage As Image
             Dim _Callback As Image.GetThumbnailImageAbort = Nothing
             Dim _OriginalHeight As Double
             Dim _OriginalWidth As Double
             Dim _NewHeight As Double
             Dim _NewWidth As Double
             Dim _NormalImage As Image
             Dim _Graphics As Graphics
    
             _NormalImage = New Bitmap(Input.Width, Input.Height)
             _Graphics = Graphics.FromImage(_NormalImage)
             _Graphics.DrawImage(Input, 0, 0, Input.Width, Input.Height)
             _OriginalHeight = _NormalImage.Height
             _OriginalWidth = _NormalImage.Width
             If KeepAspectRatio = True Then
                If _OriginalHeight > _OriginalWidth Then
                   If _OriginalHeight > MaximumSize Then
                      _NewHeight = MaximumSize
                      _NewWidth = _OriginalWidth / _OriginalHeight * MaximumSize
                   Else
                      _NewHeight = _OriginalHeight
                      _NewWidth = _OriginalWidth
                   End If
                Else
                   If _OriginalWidth > MaximumSize Then
                      _NewWidth = MaximumSize
                      _NewHeight = _OriginalHeight / _OriginalWidth * MaximumSize
                   Else
                      _NewHeight = _OriginalHeight
                      _NewWidth = _OriginalWidth
                   End If
                End If
             Else
                _NewHeight = MaximumSize
                _NewWidth = MaximumSize
             End If
             ReturnImage = _
                _NormalImage.GetThumbnailImage(Convert.ToInt32(_NewWidth), Convert.ToInt32(_NewHeight), _Callback, _
                                        IntPtr.Zero)
             _NormalImage.Dispose()
             _NormalImage = Nothing
             _Graphics.Dispose()
             _Graphics = Nothing
             _Callback = Nothing
             Return ReturnImage
          End Function
       End Module
    End Namespace
    

    对不起,代码标签不喜欢 vb.net 代码。

    【讨论】:

    • "对不起,代码标签不喜欢 vb.net 代码。" => 我不怪它:P
    【解决方案3】:

    您可以使用 Image.GetThumbnailImage 函数为您完成。

    http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx (.NET 3.5)

    http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage(VS.80).aspx (.NET 2.0)

    public bool ThumbnailCallback()
    {
      return false;
    }
    
    public void Example_GetThumb(PaintEventArgs e)
    {
      Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);
      Bitmap myBitmap = new Bitmap("Climber.jpg");
      Image myThumbnail = myBitmap.GetThumbnailImage(40, 40, myCallback, IntPtr.Zero);
      e.Graphics.DrawImage(myThumbnail, 150, 75);
    }
    

    【讨论】:

      【解决方案4】:

      GetThumbnailImage 可以,但如果您想要更好的质量,您可以为 BitMap 类指定图像选项并将加载的图像保存到那里。下面是一些示例代码:

      Image photo; // your uploaded image
      
      Bitmap bmp = new Bitmap(resizeToWidth, resizeToHeight);
      graphic = Graphics.FromImage(bmp);
      graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
      graphic.SmoothingMode = SmoothingMode.HighQuality;
      graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
      graphic.CompositingQuality = CompositingQuality.HighQuality;
      graphic.DrawImage(photo, 0, 0, resizeToWidth, resizeToHeight);
      imageToSave = bmp;
      

      这提供了比 GetImageThumbnail 开箱即用的更好的质量

      【讨论】:

        【解决方案5】:

        避免使用 GetThumbnailImage - 它会提供非常不可预测的结果,因为它会尝试使用嵌入的 JPEG 缩略图(如果可用) - 即使嵌入的缩略图大小完全错误。 DrawImage() 是一个更好的解决方案。

        将您的位图包装在 using{} 子句中 - 您不希望泄露的句柄在周围浮动...

        此外,您还需要将 Jpeg 编码质量设置为 90,这是 GDI+ 看起来最好的地方:

        System.Drawing.Imaging.ImageCodecInfo[] info = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
        System.Drawing.Imaging.EncoderParameters encoderParameters;
        encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
        encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L);
        
        thumb.Save(ms, info[1], encoderParameters);
        

        【讨论】:

          【解决方案6】:

          使用上面的示例和其他几个地方的示例,这是一个简单的函数(感谢 Nathanael Jones 和此处的其他人)。

          using System.Drawing;
          using System.Drawing.Drawing2D;
          using System.IO;
          
          public static void ResizeImage(string FileNameInput, string FileNameOutput, double ResizeHeight, double ResizeWidth, ImageFormat OutputFormat)
          {
              using (System.Drawing.Image photo = new Bitmap(FileNameInput))
              {
                  double aspectRatio = (double)photo.Width / photo.Height;
                  double boxRatio = ResizeWidth / ResizeHeight;
                  double scaleFactor = 0;
          
                  if (photo.Width < ResizeWidth && photo.Height < ResizeHeight)
                  {
                      // keep the image the same size since it is already smaller than our max width/height
                      scaleFactor = 1.0;
                  }
                  else
                  {
                      if (boxRatio > aspectRatio)
                          scaleFactor = ResizeHeight / photo.Height;
                      else
                          scaleFactor = ResizeWidth / photo.Width;
                  }
          
                  int newWidth = (int)(photo.Width * scaleFactor);
                  int newHeight = (int)(photo.Height * scaleFactor);
          
                  using (Bitmap bmp = new Bitmap(newWidth, newHeight))
                  {
                      using (Graphics g = Graphics.FromImage(bmp))
                      {
                          g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                          g.SmoothingMode = SmoothingMode.HighQuality;
                          g.CompositingQuality = CompositingQuality.HighQuality;
                          g.PixelOffsetMode = PixelOffsetMode.HighQuality;
          
                          g.DrawImage(photo, 0, 0, newWidth, newHeight);
          
                          if (ImageFormat.Png.Equals(OutputFormat))
                          {
                              bmp.Save(FileNameOutput, OutputFormat);
                          }
                          else if (ImageFormat.Jpeg.Equals(OutputFormat))
                          {
                              ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
                              EncoderParameters encoderParameters;
                              using (encoderParameters = new System.Drawing.Imaging.EncoderParameters(1))
                              {
                                  // use jpeg info[1] and set quality to 90
                                  encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90L);
                                  bmp.Save(FileNameOutput, info[1], encoderParameters);
                              }
                          }
                      }
                  }
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2010-09-09
            • 2019-11-17
            • 1970-01-01
            • 1970-01-01
            • 2014-01-22
            • 1970-01-01
            • 2010-10-19
            • 2018-06-07
            • 2012-01-28
            相关资源
            最近更新 更多