C# 关于图片缩放、合并的算法

         最近想做一个图片缩放的软件,能批量处理一批图片,并且能够在图片添加水印文字和水印logo。从网上参考的核心代码如下:

        1.合并两个图片

           /// <summary>
        /// 合并两张图片,支持不透明度和透明色
        /// </summary>
        /// <param name="b0">图片一</param>
        /// <param name="b1">图片二</param>
        /// <param name="X">起始坐标X</param>
        /// <param name="Y">起始坐标Y</param>
        /// <param name="b1_alpha">图片二的不透明度</param>
        /// <param name="TransColor">被作为透明色处理的颜色</param>
        /// <param name="delta">透明色的容差,类似Ps中的魔棒的容差。</param>
        /// <returns>合并后的图片</returns>
        public static Bitmap KiMerge(Bitmap b0, Bitmap b1, int X, int Y, int b1_alpha,Color TransColor,int delta)
        {
            if (b0.Equals(null) || b1.Equals(null))
            {
                return null;
            }

            int w0 = b0.Width;
            int h0 = b0.Height;

            int w1 = b1.Width;
            int h1 = b1.Height;

            int w, h;

            if (X + w1 > w0)
            {
                w = w0 - X;
            }
            else
            {
                w = w1;
            }

            if (Y + h1 > h0)
            {
                h = h0 - Y;
            }
            else
            {
                h = h1;
            }

            BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            unsafe
            {
                byte* pIn = (byte*)srcData.Scan0.ToPointer();
                byte* pLogo = (byte*)dstData.Scan0.ToPointer();

                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w; x++)
                    {

                        // 判断透明色
                        Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]);
                        if (!ColorIsSimilar(c, TransColor, delta))
                        {                          

                            float bili = (float)b1_alpha / (float)255; // 不是透明色,加权平均
                            float inbili = 1.0f - bili;

                            int r, g, b;

                            b = (int)(pIn[0] * inbili + pLogo[0] * bili);
                            g = (int)(pIn[1] * inbili + pLogo[1] * bili);
                            r = (int)(pIn[2] * inbili + pLogo[2] * bili);

                            pIn[0] = (byte)b;
                            pIn[1] = (byte)g;
                            pIn[2] = (byte)r;
                        }
                        pIn += 3;
                        pLogo += 3;
                    }


                    pIn += srcData.Stride - w * 3;
                    pLogo += dstData.Stride - w * 3;
                }

                b0.UnlockBits(srcData);
                b1.UnlockBits(dstData);
            }

            return b0;
        }

      2.图片缩放(1)

//************************************************************//
  //下面给出三个简单的方法,后面两个方法是扩展,估计有时用得着
  //************************************************************//
   /// <summary>
   /// 缩小图片
   /// </summary>
   /// <param name="strOldPic">源图文件名(包括路径)</param>
   /// <param name="strNewPic">缩小后保存为文件名(包括路径)</param>
   /// <param name="intWidth">缩小至宽度</param>
   /// <param name="intHeight">缩小至高度</param>
   public void SmallPic(string strOldPic, string strNewPic, int intWidth, int intHeight)
   {
   System.Drawing.Bitmap objPic,objNewPic;
   try
   {
   objPic = new System.Drawing.Bitmap(strOldPic);
   objNewPic=new System.Drawing.Bitmap(objPic,intWidth,intHeight);
   objNewPic.Save(strNewPic);
   }
   catch(Exception exp){throw exp;}
   finally
   {
   objPic=null;
   objNewPic=null;
   }
   }
   /// <summary>
   /// 按比例缩小图片,自动计算高度
   /// </summary>
   /// <param name="strOldPic">源图文件名(包括路径)</param>
   /// <param name="strNewPic">缩小后保存为文件名(包括路径)</param>
   /// <param name="intWidth">缩小至宽度</param>
   public void SmallPic(string strOldPic, string strNewPic, int intWidth)
   {
   System.Drawing.Bitmap objPic,objNewPic;
   try
   {
   objPic = new System.Drawing.Bitmap(strOldPic);
   int intHeight=(intWidth / objPic.Width) * objPic.Height;
   objNewPic=new System.Drawing.Bitmap(objPic,intWidth,intHeight);
   objNewPic.Save(strNewPic);
   }
   catch(Exception exp){throw exp;}
   finally
   {
   objPic=null;
   objNewPic=null;
   }
   }
   /// <summary>
   /// 按比例缩小图片,自动计算宽度
   /// </summary>
   /// <param name="strOldPic">源图文件名(包括路径)</param>
   /// <param name="strNewPic">缩小后保存为文件名(包括路径)</param>
   /// <param name="intHeight">缩小至高度</param>
   public void SmallPic(string strOldPic, string strNewPic, int intHeight)
   {
   System.Drawing.Bitmap objPic,objNewPic;
   try
   {
   objPic = new System.Drawing.Bitmap(strOldPic);
   int intWidth=(intHeight / objPic.Height) * objPic.Width;
   objNewPic=new System.Drawing.Bitmap(objPic,intWidth,intHeight);
   objNewPic.Save(strNewPic);
   }
   catch(Exception exp){throw exp;}
   finally
   {
   objPic=null;
   objNewPic=null;
   }
   }
  //************************************************************//

       图片缩放(2)效果最好的。

      图片无损缩放

*     一个图片缩放的类
*  
********************************************************************/
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace ZHT.Utility.Share
{
public class Thumbnail
{
   public Thumbnail()
   {
 
   }  

   /// <SUMMARY>
   /// 图片缩放
   /// </SUMMARY>
   /// <PARAM name="sourceFile">图片源路径</PARAM>
   /// <PARAM name="destFile">缩放后图片输出路径</PARAM>
   /// <PARAM name="destHeight">缩放后图片高度</PARAM>
   /// <PARAM name="destWidth">缩放后图片宽度</PARAM>
   /// <RETURNS></RETURNS>
        public static bool GetThumbnail(string sourceFile, string destFile, int destHeight, int destWidth)
        {
            System.Drawing.Image imgSource = System.Drawing.Image.FromFile(sourceFile);
            System.Drawing.Imaging.ImageFormat thisFormat = imgSource.RawFormat;
    int sW = 0, sH = 0;
            // 按比例缩放
            int sWidth = imgSource.Width;
            int sHeight = imgSource.Height;

    if(sHeight>destHeight || sWidth>destWidth)
    {
     if((sWidth*destHeight)>(sHeight*destWidth))
     {
      sW = destWidth;
      sH = (destWidth*sHeight)/sWidth;
     }
     else
     {
      sH = destHeight;
      sW = (sWidth*destHeight)/sHeight;
     }
    }
    else
    {
     sW = sWidth;
     sH = sHeight;
    }

            Bitmap outBmp = new Bitmap(destWidth, destHeight);
            Graphics g = Graphics.FromImage(outBmp);
    g.Clear(Color.WhiteSmoke);

            // 设置画布的描绘质量
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            g.DrawImage(imgSource, new Rectangle((destWidth-sW)/2,(destHeight-sH)/2, sW, sH),0,0, imgSource.Width, imgSource.Height, GraphicsUnit.Pixel);
            g.Dispose();

            // 以下代码为保存图片时,设置压缩质量
            EncoderParameters encoderParams = new EncoderParameters();
            long[] quality = new long[1];
            quality[0] = 100;

            EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            encoderParams.Param[0] = encoderParam;

            try
            {
                //获得包含有关内置图像编码解码器的信息的ImageCodecInfo 对象。
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICI = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICI = arrayICI[x];//设置JPEG编码
                        break;
                    }
                }

                if (jpegICI != null)
                {
                    outBmp.Save(destFile, jpegICI, encoderParams);
                }
                else
                {
                    outBmp.Save(destFile, thisFormat);
                }

                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                imgSource.Dispose();
                outBmp.Dispose();
            }
        }
}
}

       3.图片的裁剪

       C#图片处理之:图片缩放和剪裁    作者:ki1381   

                   
其实在GDI+中,缩放和剪裁可以看作同一个操作,无非就是原始区域的选择不同罢了。空口无凭,先看具体算法可能更好理解。

        /// <summary>
        /// Resize图片
        /// </summary>
        /// <param name="bmp">原始Bitmap</param>
        /// <param name="newW">新的宽度</param>
        /// <param name="newH">新的高度</param>
        /// <param name="Mode">保留着,暂时未用</param>
        /// <returns>处理以后的图片</returns>
        public static Bitmap KiResizeImage(Bitmap bmp, int newW, int newH, int Mode)
        {
            try
            {
                Bitmap b = new Bitmap(newW, newH);
                Graphics g = Graphics.FromImage(b);

                // 插值算法的质量
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;

                g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
                g.Dispose();

                return b;
            }
            catch
            {
                return null;
            }
        }

// ===============================

         /// <summary>
        /// 剪裁 -- 用GDI+
        /// </summary>
        /// <param name="b">原始Bitmap</param>
        /// <param name="StartX">开始坐标X</param>
        /// <param name="StartY">开始坐标Y</param>
        /// <param name="iWidth">宽度</param>
        /// <param name="iHeight">高度</param>
        /// <returns>剪裁后的Bitmap</returns>
        public static Bitmap KiCut(Bitmap b, int StartX, int StartY, int iWidth, int iHeight)
        {
            if (b == null)
            {
                return null;
            }

            int w = b.Width;
            int h = b.Height;

            if (StartX >= w || StartY >= h)
            {
                return null;
            }

            if (StartX + iWidth > w)
            {
                iWidth = w - StartX;
            }

            if (StartY + iHeight > h)
            {
                iHeight = h - StartY;
            }

            try
            {
                Bitmap bmpOut = new Bitmap(iWidth, iHeight, PixelFormat.Format24bppRgb);

                Graphics g = Graphics.FromImage(bmpOut);
                g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel);
                g.Dispose();

                return bmpOut;
            }
            catch
            {
                return null;
            }
        }

注意到区别了吗?提示,g.DrawImage中第二个new Rectangle。

目标其实都是new Rectangle(0, 0, iWidth, iHeight),缩放算法把整个原始图都往目标区域里塞new Rectangle(0, 0, bmp.Width, bmp.Height),而剪裁只是把原始区域上等宽等高的那个区域new Rectangle(StartX, StartY, iWidth, iHeight)1:1的塞到目标区域里。很容易吧。

       4.浮雕图片

         private void button1_Click(object sender, EventArgs e)
{
    //以浮雕效果显示图像
    try
    {
        int Height = this.pictureBox1.Image.Height;
        int Width = this.pictureBox1.Image.Width;
        Bitmap newBitmap = new Bitmap(Width, Height);
        Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image;
        Color pixel1, pixel2;
        for (int x = 0; x < Width - 1; x++)
        {
            for (int y = 0; y < Height - 1; y++)
            {
                int r = 0, g = 0, b = 0;
                pixel1 = oldBitmap.GetPixel(x, y);
                pixel2 = oldBitmap.GetPixel(x + 1, y + 1);
                r = Math.Abs(pixel1.R - pixel2.R + 128);
                g = Math.Abs(pixel1.G - pixel2.G + 128);
                b = Math.Abs(pixel1.B - pixel2.B + 128);
                if (r > 255)
                    r = 255;
                if (r < 0)
                    r = 0;
                if (g > 255)
                    g = 255;
                if (g < 0)
                    g = 0;
                if (b > 255)
                    b = 255;
                if (b < 0)
                    b = 0;
                newBitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
            }
        }
        this.pictureBox1.Image = newBitmap;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值