⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grayprocessing.cs

📁 一个C#开发的类似PHOTOSHOP的软件,用到了很多图形算法.
💻 CS
字号:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace PhotoSprite.ImageProcessing
{
  /// <summary>
  /// 灰度处理类
  /// </summary>
  public class GrayProcessing : ImageInfo
  {
    /// <summary>
    /// 灰度方法
    /// </summary>
    public enum GrayMethod
    {
      /// <summary>
      /// 加权平均法
      /// </summary>
      WeightAveraging,

      /// <summary>
      /// 最大值法
      /// </summary>
      Maximum,

      /// <summary>
      /// 平均值法
      /// </summary>
      Average
    }


    /************************************************************
     * 
     * 初始化二维数组、位图转数组、数组转位图
     * 
     ************************************************************/


    /// <summary>
    /// 初始化一个二维数组
    /// </summary>
    /// <param name="width">数组宽</param>
    /// <param name="height">数组高</param>
    /// <param name="init">初始值</param>
    /// <returns></returns>
    public byte[,] InitArray(int width, int height, byte init)
    {
      byte[,] dst = new byte[width, height];

      for (int y = 0; y < height; y++)
      {
        for (int x = 0; x < width; x++)
        {
          dst[x, y] = init;
        } // x
      } // y

      return dst;
    } // end of InitArray


    /// <summary>
    /// 将灰度位图流转换为二维数组
    /// </summary>
    /// <param name="b">灰度位图流</param>
    /// <returns></returns>
    public byte[,] Image2Array(Bitmap b)
    {
      int width = b.Width;
      int height = b.Height;

      // 申请一个二维数组
      byte[,] GrayArray = new byte[width, height];

      BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

      unsafe
      {
        byte* p = (byte*)data.Scan0;
        int offset = data.Stride - width * BPP;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            // 因为已经是灰度色,这里只取蓝色分量作为灰度
            GrayArray[x, y] = p[0];

            p += BPP;
          } //  x

          p += offset;
        } // y
      }

      b.UnlockBits(data);

      return GrayArray;
    } // end of Image2Array


    /// <summary>
    /// 将二维数组转换为灰度位图流
    /// </summary>
    /// <param name="GrayArray">灰度数组</param>
    /// <returns></returns>
    public Bitmap Array2Image(byte[,] GrayArray)
    {
      int width = GrayArray.GetLength(0);
      int height = GrayArray.GetLength(1);

      Bitmap b = new Bitmap(width, height);
      BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

      unsafe
      {
        byte* p = (byte*)data.Scan0;
        int offset = data.Stride - width * BPP;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            p[0] = p[1] = p[2] = GrayArray[x, y];
            p[3] = 255;

            p += BPP;
          } //  x

          p += offset;
        } // y
      }

      b.UnlockBits(data);

      return b;
    } // end of Array2Image


    /************************************************************
     * 
     * 位图转二维数组、二值数组转位图、阈值化、自适应阈值、灰度
     * 
     ************************************************************/


    /// <summary>
    /// 将位图流转换为二值数组
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="threshold">阈值</param>
    /// <returns></returns>
    public byte[,] BinaryArray(Bitmap b, byte threshold)
    {
      int width = b.Width;
      int height = b.Height;

      //先将位图灰度化
      b = Gray(b, GrayMethod.WeightAveraging);

      // 将灰度图转化为灰度数组
      byte[,] GrayArray = Image2Array(b);

      b.Dispose();

      for (int y = 0; y < height; y++)
      {
        for (int x = 0; x < width; x++)
        {
          // 当前像素颜色灰度值与指定阈值相比较
          if (GrayArray[x, y] >= threshold)
            GrayArray[x, y] = 255;
          else
            GrayArray[x, y] = 0;
        } //  x
      } // y

      return GrayArray;
    } // end of BinaryArray


    /// <summary>
    /// 将二值数组转换为双色位图流
    /// </summary>
    /// <param name="GrayArray">二值数组</param>
    /// <param name="bgColor">背景色</param>
    /// <param name="fgColor">前景色</param>
    /// <returns></returns>
    public Bitmap BinaryImage(byte[,] GrayArray, Color bgColor, Color fgColor)
    {
      // 获取二维数组的宽高
      int width = GrayArray.GetLength(0);
      int height = GrayArray.GetLength(1);

      // 背景色
      byte bgAlpha = (byte)bgColor.A;
      byte bgRed = (byte)bgColor.R;
      byte bgGreen = (byte)bgColor.G;
      byte bgBlue = (byte)bgColor.B;

      // 前景色
      byte fgAlpha = (byte)fgColor.A;
      byte fgRed = (byte)fgColor.R;
      byte fgGreen = (byte)fgColor.G;
      byte fgBlue = (byte)fgColor.B;

      Bitmap b = new Bitmap(width, height);
      BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

      unsafe
      {
        byte* p = (byte*)data.Scan0;
        int offset = data.Stride - width * BPP;

        for (int y = 0; y < height; y++)
        {
          for (int x = 0; x < width; x++)
          {
            // 设置图像前景、背景颜色
            if (GrayArray[x, y] <128 )
            {
              p[3] = fgAlpha;
              p[2] = fgRed;
              p[1] = fgGreen;
              p[0] = fgBlue;
            }
            else
            {
              p[3] = bgAlpha;
              p[2] = bgRed;
              p[1] = bgGreen;
              p[0] = bgBlue;
            }

            p += BPP;
          } //  x

          p += offset;
        } // y
      }

      b.UnlockBits(data);

      return b;
    } // end of BinaryImage


    /// <summary>
    /// 阈值化
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="threshold">阈值</param>
    /// <returns></returns>
    public Bitmap Thresholding(Bitmap b, byte threshold)
    {
      byte[,] GrayArray = BinaryArray(b, threshold);
      Bitmap dstImage = BinaryImage(GrayArray, Color.White, Color.Black);

      return dstImage;
    } // end of Thresholding 


    /// <summary>
    /// 自适应阈值
    /// </summary>
    /// <param name="b">位图流</param>
    /// <returns></returns>
    public Bitmap AutoFitThreshold(Bitmap b)
    {
      // 图像灰度化
      GrayProcessing gp = new GrayProcessing();
      b = gp.Gray(b, GrayMethod.WeightAveraging);

      // 建立直方图,并获取灰度统计信息
      Histogram histogram = new Histogram(b);
      int [] GrayLevel = histogram.Red.Value;

      int peak1, peak2, valley;
      int peak1Index, peak2Index, valleyIndex;

      // 取双峰
      peak1 = peak2 = GrayLevel[0];
      peak1Index = peak2Index = 0;
      for (int i = 1; i < 256; i++)
      {
        // 如果产生新的高峰,则将第一峰退居第二峰,新的高峰升为第一峰
        if (GrayLevel[i] > peak1)
        {
          peak2 = peak1;
          peak2Index = peak1Index;

          peak1 = GrayLevel[i];
          peak1Index = i;
        }
      } // i

      // 判断两个峰值索引
      int max = peak1Index;
      int min = peak2Index;
      if (max < min)
      {
        int t = max;
        max = min;
        min = t;
      }

      // 取峰谷
      valley = GrayLevel[min];
      valleyIndex = min;
      for (int i = min; i < max; i++)
      {
        if (GrayLevel[i] < valley)
        {
          valley = GrayLevel[i];
          valleyIndex = i;
        }
      } // i

      // 根据找到的谷值对图像进行二值化
      return Thresholding(b, (byte)valleyIndex);
    } // end of AutoFitThreshold 


    /// <summary>
    /// 图像灰度变换
    /// </summary>
    /// <param name="b">位图流</param>
    /// <param name="grayMethod">灰度方法</param>
    /// <returns></returns>
    public Bitmap Gray(Bitmap b, GrayMethod grayMethod)
    {
      int width = b.Width;
      int height = b.Height;

      BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
        ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

      unsafe
      {
        byte* p = (byte*)data.Scan0;
        int offset = data.Stride - width * BPP;

        byte R, G, B, gray;

        switch (grayMethod)
        {
          case GrayMethod.Maximum:
            for (int y = 0; y < height; y++)
            {
              for (int x = 0; x < width; x++)
              {
                R = p[2];
                G = p[1];
                B = p[0];

                // gray = Max( R, G, B )
                gray = (gray = B >= G ? B : G) >= R ? gray : R;

                p[0] = p[1] = p[2] = gray;

                p += BPP;
              } // x
              p += offset;
            } // y
            break;

          case GrayMethod.Average:
            for (int y = 0; y < height; y++)
            {
              for (int x = 0; x < width; x++)
              {
                R = p[2];
                G = p[1];
                B = p[0];

                // gray = ( R + G + B ) / 3
                gray = (byte)((R + G + B) / 3);

                p[0] = p[1] = p[2] = gray;

                p += BPP;
              } // x
              p += offset;
            } // y
            break;

          case GrayMethod.WeightAveraging:
          default:
            for (int y = 0; y < height; y++)
            {
              for (int x = 0; x < width; x++)
              {
                R = p[2];
                G = p[1];
                B = p[0];

                // gray = 0.3*R + 0.59*G + 0.11*B
                gray = (byte)((19661 * R + 38666 * G + 7209 * B) >> 16);

                p[0] = p[1] = p[2] = gray;

                p += BPP;
              } // x
              p += offset;
            } // y
            break;
        } // switch
      }

      b.UnlockBits(data);

      return b;
    } // end of Gray


  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -