重提:上传图片生成略缩图“最佳解决”

本文提供了一种生成高质量缩略图的方法,并附带失真解决及图片保存功能。通过自定义函数,可以灵活地调整缩略图尺寸、对齐方式及图片品质。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从用 .Net Web 开发到现在所看到的略缩生成代码都不尽人意,要不太局限,要不失真厉害。

为此写了一个相对完善的函数供大家学习。

其中的 SaveIamge 函数提供了失真解决方法,对于处理过的图片(如加水印……)要求保持高品质可以直接调用。

using  System;
using  System.IO;
using  System.Drawing;
using  System.Drawing.Drawing2D;
using  System.Drawing.Imaging;
using  System.Drawing.Text;
using  System.Text.RegularExpressions;

///   <summary>
//  图片处理。
//   http://www.hulaka.com/
//  (c) 2008 Dao
///   </summary>
public   class  Image
{
    
///   <summary>
    
///  缩略模式。
    
///   </summary>
     public   enum  ThumbMode :  byte
    {
        
///   <summary>
        
///  完整模式
        
///   </summary>
        Full  =   1 ,
        
///   <summary>
        
///  最大尺寸
        
///   </summary>
        Max
    }

    
///   <summary>
    
///  缩略图。
    
///   </summary>
    
///   <param name="image"> 要缩略的图片 </param>
    
///   <param name="size"> 要缩放的尺寸 </param>
    
///   <param name="mode"> 缩略模式 </param>
    
///   <param name="contentAlignment"> 对齐方式 </param>
    
///   <returns> 返回已经缩放的图片。 </returns>
     public   static  Bitmap Thumbnail(Bitmap image, Size size, ThumbMode mode, ContentAlignment contentAlignment)
    {
        
if  ( ! size.IsEmpty  &&   ! image.Size.IsEmpty  &&   ! size.Equals(image.Size))
        {
            
// 先取一个宽比例。
             double  scale  =  ( double )image.Width  /  ( double )size.Width;
            
// 缩略模式
             switch  (mode)
            {
                
case  ThumbMode.Full:
                    
if  (image.Height  >  image.Width)
                        scale 
=  ( double )image.Height  /  ( double )size.Height;
                    
break ;
                
case  ThumbMode.Max:
                    
if  (image.Height  /  scale  <  size.Height)
                        scale 
=  ( double )image.Height  /  ( double )size.Height;
                    
break ;
            }
            SizeF newSzie 
=   new  SizeF(( float )(image.Width  /  scale), ( float )(image.Height  /  scale));
            Bitmap result 
=   new  Bitmap(size.Width, size.Height);
            
using  (Graphics g  =  Graphics.FromImage(result))
            {
                g.FillRectangle(Brushes.White, 
new  Rectangle( new  Point( 0 0 ), size));
                g.InterpolationMode 
=  InterpolationMode.HighQualityBicubic;
                g.SmoothingMode 
=  SmoothingMode.HighQuality;
                g.PixelOffsetMode 
=  PixelOffsetMode.HighQuality;
                g.CompositingMode 
=  CompositingMode.SourceOver;
                g.CompositingQuality 
=  CompositingQuality.HighQuality;
                g.TextRenderingHint 
=  TextRenderingHint.AntiAliasGridFit;
                
// 对齐方式
                RectangleF destRect;
                
switch  (contentAlignment)
                {
                    
case  ContentAlignment.TopCenter:
                        destRect 
=   new  RectangleF( new  PointF( - ( float )((newSzie.Width  -  size.Width)  *   0.5 ),  0 ), newSzie);
                        
break ;
                    
case  ContentAlignment.TopRight:
                        destRect 
=   new  RectangleF( new  PointF( - ( float )(newSzie.Width  -  size.Width),  0 ), newSzie);
                        
break ;
                    
case  ContentAlignment.MiddleLeft:
                        destRect 
=   new  RectangleF( new  PointF( 0 - ( float )((newSzie.Height  -  size.Height)  *   0.5 )), newSzie);
                        
break ;
                    
case  ContentAlignment.MiddleCenter:
                        destRect 
=   new  RectangleF( new  PointF( - ( float )((newSzie.Width  -  size.Width)  *   0.5 ),  - ( float )((newSzie.Height  -  size.Height)  *   0.5 )), newSzie);
                        
break ;
                    
case  ContentAlignment.MiddleRight:
                        destRect 
=   new  RectangleF( new  PointF( - ( float )(newSzie.Width  -  size.Width),  - ( float )((newSzie.Height  -  size.Height)  *   0.5 )), newSzie);
                        
break ;
                    
case  ContentAlignment.BottomLeft:
                        destRect 
=   new  RectangleF( new  PointF( 0 - ( float )(newSzie.Height  -  size.Height)), newSzie);
                        
break ;
                    
case  ContentAlignment.BottomCenter:
                        destRect 
=   new  RectangleF( new  PointF( - ( float )((newSzie.Width  -  size.Width)  *   0.5 ),  - ( float )(newSzie.Height  -  size.Height)), newSzie);
                        
break ;
                    
case  ContentAlignment.BottomRight:
                        destRect 
=   new  RectangleF( new  PointF( - ( float )(newSzie.Width  -  size.Width),  - ( float )(newSzie.Height  -  size.Height)), newSzie);
                        
break ;
                    
default :
                        destRect 
=   new  RectangleF( new  PointF( 0 0 ), newSzie);
                        
break ;
                }
                g.DrawImage(image, destRect, 
new  RectangleF( new  PointF(0F, 0F), image.Size), GraphicsUnit.Pixel);
                image.Dispose();
            }
            
return  result;
        }
        
else
            
return  image;
    }

    
///   <summary>
    
///  保存图片。
    
///   </summary>
    
///   <param name="image"> 要保存的图片 </param>
    
///   <param name="quality"> 品质(1L~100L之间,数值越大品质越好) </param>
    
///   <param name="filename"> 保存路径 </param>
     public   static   void  SaveIamge(Bitmap image,  long  quality,  string  filename)
    {
        
using  (EncoderParameters encoderParams  =   new  EncoderParameters( 1 ))
        {
            
using  (EncoderParameter parameter  =  (encoderParams.Param[ 0 =   new  EncoderParameter(Encoder.Quality, quality)))
            {
                ImageCodecInfo encoder 
=   null ;
                
// 取得扩展名
                 string  ext  =  Path.GetExtension(filename);
                
if  ( string .IsNullOrEmpty(ext))
                    ext 
=   " .jpg " ;
                
// 根据扩展名得到解码、编码器
                 foreach  (ImageCodecInfo codecInfo  in  ImageCodecInfo.GetImageEncoders())
                {
                    
if  (Regex.IsMatch(codecInfo.FilenameExtension,  string .Format( @" (;|^)\*\{0}(;|$) " , ext), RegexOptions.IgnoreCase))
                    {
                        encoder 
=  codecInfo;
                        
break ;
                    }
                }
                Directory.CreateDirectory(Path.GetDirectoryName(filename));
                image.Save(filename, encoder, encoderParams);
            }
        }
    }

    
///   <summary>
    
///  保存图片。
    
///   </summary>
    
///   <param name="stream"> 要保存的流 </param>
    
///   <param name="quality"> 品质(1L~100L之间,数值越大品质越好) </param>
    
///   <param name="filename"> 保存路径 </param>
     public   static   void  SaveIamge(Stream stream,  long  quality,  string  filename)
    {
        
using  (Bitmap bmpTemp  =   new  Bitmap(stream))
        {
            SaveIamge(bmpTemp, quality, filename);
        }
    }
}

调用方法如下:
using  (Bitmap bmpAvatar  =  Image.Thumbnail( new  Bitmap( /* <流,FileUpload 控件的 PostedFile.InputStream 属性> */ ),  new  Size( 48 48 ), Image.ThumbMode.Full, ContentAlignment.MiddleCenter))
{
    Image.SaveIamge(bmpAvatar, 
95L , Server.MapPath( " ~/upfiles/Avatar.jpg " ));
}


演示程序:



下载演示程序

转载于:https://www.cnblogs.com/dao/archive/2008/02/24/1079571.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值