• c# 图像转化成灰度图


     /// <summary>
            /// 将源图像灰度化,但是没有转化为8位灰度图像。
            /// http://www.bobpowell.net/grayscale.htm
            /// </summary>
            /// <param name="original"> 源图像。 </param>
            /// <returns> 灰度RGB图像。 </returns>
            public static Bitmap MakeGrayScale(Bitmap original)
            {
                //create a blank bitmap the same size as original
                Bitmap newBitmap = new Bitmap(original.Width, original.Height, PixelFormat.Format24bppRgb);
    
                //get a graphics object from the new image
                Graphics g = Graphics.FromImage(newBitmap);
    
                //create the grayscale ColorMatrix
                ColorMatrix colorMatrix = new ColorMatrix(
                    new float[][] 
            {
                new float[] { .3f, .3f, .3f, 0, 0 },
                new float[] { .59f, .59f, .59f, 0, 0 },
                new float[] { .11f, .11f, .11f, 0, 0 },
                new float[] { 0, 0, 0, 1, 0 },
                new float[] { 0, 0, 0, 0, 1 }
            });
                /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                ┌                          ┐
                │  0.3   0.3   0.3   0   0 │
                │ 0.59  0.59  0.59   0   0 │
                │ 0.11  0.11  0.11   0   0 │
                │    0     0     0   1   0 │
                │    0     0     0   0   1 │
                └                          ┘
                 * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                //create some image attributes
                ImageAttributes attributes = new ImageAttributes();
    
                //set the color matrix attribute
                attributes.SetColorMatrix(colorMatrix);
    
                //draw the original image on the new image
                //using the grayscale color matrix
                g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
                   0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
    
                //dispose the Graphics object
                g.Dispose();
                return newBitmap;
            }
    
    
    
    
    
    
            /// <summary>
    /// 将源图像灰度化,并转化为8位灰度图像。
    /// </summary>
    /// <param name="original"> 源图像。 </param>
    /// <returns> 8位灰度图像。 </returns>
    public static Bitmap RgbToGrayScale(Bitmap original)
    {
         if (original != null)
         {
              // 将源图像内存区域锁定
              Rectangle rect = new Rectangle(0, 0, original.Width, original.Height);
              BitmapData bmpData = original.LockBits(rect, ImageLockMode.ReadOnly,
                   original.PixelFormat);
    
              // 获取图像参数
              int width = bmpData.Width;
              int height = bmpData.Height;
              int stride = bmpData.Stride;  // 扫描线的宽度
              int offset = stride - width * 3;  // 显示宽度与扫描线宽度的间隙
              IntPtr ptr = bmpData.Scan0;   // 获取bmpData的内存起始位置
              int scanBytes = stride * height;  // 用stride宽度,表示这是内存区域的大小
    
              // 分别设置两个位置指针,指向源数组和目标数组
              int posScan = 0, posDst = 0;
              byte[] rgbValues = new byte[scanBytes];  // 为目标数组分配内存
              Marshal.Copy(ptr, rgbValues, 0, scanBytes);  // 将图像数据拷贝到rgbValues中
              // 分配灰度数组
              byte[] grayValues = new byte[width * height]; // 不含未用空间。
              // 计算灰度数组
              for (int i = 0; i < height; i++)
              {
                   for (int j = 0; j < width; j++)
                   {
                        double temp = rgbValues[posScan++] * 0.11 +
                            rgbValues[posScan++] * 0.59 + 
                            rgbValues[posScan++] * 0.3;
                        grayValues[posDst++] = (byte)temp;
                   }
                   // 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixel
                   posScan += offset;
              }
    
              // 内存解锁
              Marshal.Copy(rgbValues, 0, ptr, scanBytes);
              original.UnlockBits(bmpData);  // 解锁内存区域
    
              // 构建8位灰度位图
              Bitmap retBitmap = BuiltGrayBitmap(grayValues, width, height);
              return retBitmap;
         }
         else
         {
              return null;
         }
    }
    
    
    
    
    
    
    
    /// <summary>
    /// 用灰度数组新建一个8位灰度图像。
    /// http://www.cnblogs.com/spadeq/archive/2009/03/17/1414428.html
    /// </summary>
    /// <param name="rawValues"> 灰度数组(length = width * height)。 </param>
    /// <param name="width"> 图像宽度。 </param>
    /// <param name="height"> 图像高度。 </param>
    /// <returns> 新建的8位灰度位图。 </returns>
    private static Bitmap BuiltGrayBitmap(byte[] rawValues, int width, int height)
    {
        // 新建一个8位灰度位图,并锁定内存区域操作
        Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
        BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height),
             ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
    
        // 计算图像参数
        int offset = bmpData.Stride - bmpData.Width;        // 计算每行未用空间字节数
        IntPtr ptr = bmpData.Scan0;                         // 获取首地址
        int scanBytes = bmpData.Stride * bmpData.Height;    // 图像字节数 = 扫描字节数 * 高度
        byte[] grayValues = new byte[scanBytes];            // 为图像数据分配内存
    
        // 为图像数据赋值
        int posSrc = 0, posScan = 0;                        // rawValues和grayValues的索引
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                grayValues[posScan++] = rawValues[posSrc++];
            }
            // 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixel
            posScan += offset;
        }
    
        // 内存解锁
        Marshal.Copy(grayValues, 0, ptr, scanBytes);
    
        bitmap.UnlockBits(bmpData);  // 解锁内存区域
    
        // 修改生成位图的索引表,从伪彩修改为灰度
        ColorPalette palette;
        // 获取一个Format8bppIndexed格式图像的Palette对象
        using (Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
        {
            palette = bmp.Palette;
        }
        for (int i = 0; i < 256; i++)
        {
            palette.Entries[i] = Color.FromArgb(i, i, i);
        }
        // 修改生成位图的索引表
        bitmap.Palette = palette;
    
        return bitmap;
    }
    速度最快
    public static unsafe void ConvertTo8BitBitmap(Bitmap img, string destFile)
            {
                var bit = new Bitmap(img.Width, img.Height, PixelFormat.Format8bppIndexed);
                BitmapData data = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly,
                                               PixelFormat.Format24bppRgb);
                var bp = (byte*)data.Scan0.ToPointer();
                BitmapData data2 = bit.LockBits(new Rectangle(0, 0, bit.Width, bit.Height), ImageLockMode.ReadWrite,
                                                PixelFormat.Format8bppIndexed);
                var bp2 = (byte*)data2.Scan0.ToPointer();
                for (int i = 0; i != data.Height; i++)
                {
                    for (int j = 0; j != data.Width; j++)
                    {
                        //0.3R+0.59G+0.11B
                        float value = 0.11F * bp[i * data.Stride + j * 3] + 0.59F * bp[i * data.Stride + j * 3 + 1] +
                                      0.3F * bp[i * data.Stride + j * 3 + 2];
                        bp2[i * data2.Stride + j] = (byte)value;
                    }
                }
                img.UnlockBits(data);
                bit.UnlockBits(data2);
                ColorPalette palette = bit.Palette;
                for (int i = 0; i != palette.Entries.Length; i++)
                {
                    palette.Entries[i] = Color.FromArgb(i, i, i);
                }
                bit.Palette = palette;
                bit.Save(destFile, ImageFormat.Bmp);
                img.Dispose();
                bit.Dispose();
            }
    bp[i * data.Stride + j * 3]
  • 相关阅读:
    别人直播带货,李彦宏却想直播带“知识”
    什么能毁掉程序员的一生?
    如何清爽的安排日常?
    优秀的程序员真的不写注释吗?
    淘宝内测Bug风波:惹谁别惹程序员
    如果员工都不快乐,还谈什么绩效增长
    前端有架构吗?
    [转]BDC’s and CTR’s
    SAP data migration: Change vendor account group
    [转]abap程序设计方法
  • 原文地址:https://www.cnblogs.com/liuxinls/p/3090859.html
Copyright © 2020-2023  润新知