Windows图像处理工具包(2)C#:ImageUtils.dll

同系列文章

工程下载

FileUtils.zip

ImageUtils.cs

/* ----------------------------------------------------------
 * 文件名称:ImageUtils.cs
 * 作者:秦建辉
 * 
 * 微信:splashcn
 * 
 * 博客:http://www.firstsolver.com/wordpress/
 * 
 * 开发环境:
 *      Visual Studio V2017
 *      .NET Framework 4 Client Profile
 *      
 * 版本历史:
 *      V1.1    2018年12月7日
 *              完善接口
 *      
 *      V1.0    2018年04月25日
 *              Image类图像处理工具
------------------------------------------------------------ */
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Com.FirstSolver.Splash
{
    public static class ImageUtils
    {
        /// <summary>
        /// 将Bitmap转换成Bgra线性数组
        /// </summary>
        /// <param name="bmp">要转换的Bitmap</param>
        /// <returns>Bgra线性数组</returns>
        /// <remarks>返回结果后面需要调用Marshal.FreeHGlobal释放资源</remarks>
        public static IntPtr ToBgraPtr(this Bitmap bmp)
        {
            int PixelWidth = bmp.Width;   // 图像宽度
            int PixelHeight = bmp.Height; // 图像高度

            int Size = (PixelHeight * PixelWidth) << 2;
            IntPtr Bgra = Marshal.AllocHGlobal(Size);

            // 锁定位图到系统内存
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            CopyMemory(Bgra, bmpData.Scan0, Size);
            bmp.UnlockBits(bmpData);    // 从系统内存解锁位图

            return Bgra;
        }

        /// <summary>
        /// 将Bitmap转换成灰度线性数组
        /// </summary>
        /// <param name="bmp">要转换的Bitmap</param>
        /// <returns>灰度线性数组</returns>
        /// <remarks>返回结果后面需要调用Marshal.FreeHGlobal释放资源</remarks>
        public static IntPtr ToGrayPtr(this Bitmap bmp)
        {
            int PixelWidth = bmp.Width;   // 图像宽度
            int PixelHeight = bmp.Height; // 图像高度

            int Size = PixelHeight * PixelWidth;
            IntPtr Gray = Marshal.AllocHGlobal(Size);

            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BgraToGray(bmpData.Scan0, Gray, Size);
            bmp.UnlockBits(bmpData);    // 从系统内存解锁位图

            return Gray;
        }

        /// <summary>
        /// 将Bitmap转换成Bgr线性数组
        /// </summary>
        /// <param name="bmp">要转换的Bitmap</param>
        /// <returns>Bgr线性数组</returns>
        /// <remarks>返回结果后面需要调用Marshal.FreeHGlobal释放资源</remarks>
        public static IntPtr ToBgrPtr(this Bitmap bmp)
        {
            int PixelWidth = bmp.Width;   // 图像宽度
            int PixelHeight = bmp.Height; // 图像高度

            int Size = PixelHeight * PixelWidth;
            IntPtr Bgr = Marshal.AllocHGlobal(Size * 3);

            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BgraToBgr(bmpData.Scan0, Bgr, Size);
            bmp.UnlockBits(bmpData);    // 从系统内存解锁位图

            return Bgr;
        }

        /// <summary>
        /// 将位图转换为一维Bgra彩色数组
        /// </summary>
        /// <param name="bmp">原始位图</param>
        /// <returns>一维Bgra彩色数组</returns>
        public static byte[] ToBgra(this Bitmap bmp)
        {
            int PixelWidth = bmp.Width;   // 图像宽度
            int PixelHeight = bmp.Height; // 图像高度

            int Size = (PixelHeight * PixelWidth) << 2;
            byte[] Bgra = new byte[Size];

            // 锁定位图到系统内存
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            Marshal.Copy(bmpData.Scan0, Bgra, 0, Size);  // 从非托管内存拷贝数据到托管内存
            bmp.UnlockBits(bmpData);    // 从系统内存解锁位图

            return Bgra;
        }

        /// <summary>
        /// 将位图转换为线性灰度数组(256级灰度)
        /// </summary>
        /// <param name="bmp">原始位图</param>
        /// <returns>线性灰度数组</returns>
        public static byte[] ToGray(this Bitmap bmp)
        {
            int PixelWidth = bmp.Width;   // 图像宽度
            int PixelHeight = bmp.Height; // 图像高度

            int Size = PixelHeight * PixelWidth;
            byte[] Gray = new byte[Size];

            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BgraToGray(bmpData.Scan0, Gray, Size);
            bmp.UnlockBits(bmpData);    // 从系统内存解锁位图

            return Gray;
        }

        /// <summary>
        /// 将Bitmap转换成Bgr数组
        /// </summary>
        /// <param name="bmp">要转换的Bitmap</param>
        /// <returns>Bgr数组</returns>
        public static byte[] ToBgr(this Bitmap bmp)
        {
            int PixelWidth = bmp.Width;   // 图像宽度
            int PixelHeight = bmp.Height; // 图像高度

            int Size = PixelHeight * PixelWidth;
            byte[] Bgr = new byte[Size * 3];

            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BgraToBgr(bmpData.Scan0, Bgr, Size);
            bmp.UnlockBits(bmpData);    // 从系统内存解锁位图

            return Bgr;
        }

        /// <summary>
        /// 将Image转换为Jpeg图像字节数组
        /// </summary>
        /// <param name="image">要转换的图像</param>
        /// <returns>Jpeg图像字节数组</returns>
        public static byte[] ToJpegByteArray(this Image image)
        {
            ImageCodecInfo codec = GetImageEncoder(ImageFormat.Jpeg);
            if (codec == null) return null;

            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                using (EncoderParameters eps = new EncoderParameters(1))
                {
                    using (EncoderParameter ep = new EncoderParameter(Encoder.Quality, 100L))
                    {
                        eps.Param[0] = ep;
                        image.Save(ms, codec, eps);
                        return ms.ToArray();
                    }
                }
            }
        }

        /// <summary>
        /// 将Image转换为Bmp图像字节数组
        /// </summary>
        /// <param name="image">要转换的图像</param>
        /// <returns>Bmp图像字节数组</returns>
        public static byte[] ToBmpByteArray(this Image image)
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                image.Save(ms, ImageFormat.Bmp);
                return ms.ToArray();
            }
        }

        /// <summary>
        /// 获取指定图像格式的编码器
        /// </summary>
        /// <param name="format">图像格式</param>
        /// <returns>图像编码器</returns>
        public static ImageCodecInfo GetImageEncoder(this ImageFormat format)
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.FormatID.Equals(format.Guid)) return codec;
            }
            return null;
        }

        /// <summary>
        /// 将字节数组转换为位图图像
        /// </summary>
        /// <param name="buffer">字节数组</param>
        /// <returns>位图图像</returns>
        public static Bitmap ToBitmap(this byte[] buffer)
        {
            return new Bitmap(new System.IO.MemoryStream(buffer));
        }

        /// <summary>
        /// 生成Bgra32位图图像
        /// </summary>
        /// <param name="bgra">Bgra数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>Bgra32位图图像</returns>
        public static Bitmap ToBgra32Bitmap(byte[] bgra, int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            Marshal.Copy(bgra, 0, data.Scan0, bgra.Length);
            bmp.UnlockBits(data);
            return bmp;
        }

        /// <summary>
        /// 生成Bgra32位图图像
        /// </summary>
        /// <param name="bgra">Bgra数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>Bgra32位图图像</returns>
        public static Bitmap ToBgra32Bitmap(IntPtr bgra, int width, int height)
        {
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            CopyMemory(data.Scan0, bgra, (width * height) << 2);
            bmp.UnlockBits(data);
            return bmp;
        }

        /// <summary>
        /// 将灰度数组转换为灰度图像(256级灰度)
        /// </summary>
        /// <param name="gray">灰度数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>灰度图像</returns>
        public static Bitmap ToGrayBitmap(byte[] gray, int width, int height)
        {   // 创建灰度图像
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);

            // 设置调色板
            ColorPalette cp = bmp.Palette;
            for (int i = 0; i < 256; i++) cp.Entries[i] = Color.FromArgb(i, i, i);
            bmp.Palette = cp;

            // 设置位图图像特性
            int Stride = ((width + 3) >> 2) << 2;    // 跨距宽度
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
            for (int i = 0; i < height; i++)
            {
                Marshal.Copy(gray, i * width, data.Scan0 + i * Stride, width);
            }
            bmp.UnlockBits(data);
            return bmp;
        }

        /// <summary>
        /// 将灰度数组转换为灰度图像(256级灰度)
        /// </summary>
        /// <param name="gray">灰度数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>灰度图像</returns>
        public static Bitmap ToGrayBitmap(IntPtr gray, int width, int height)
        {   // 创建灰度图像
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);

            // 设置调色板
            ColorPalette cp = bmp.Palette;
            for (int i = 0; i < 256; i++) cp.Entries[i] = Color.FromArgb(i, i, i);
            bmp.Palette = cp;

            // 设置位图图像特性
            int Stride = ((width + 3) >> 2) << 2;    // 跨距宽度
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
            for (int i = 0; i < height; i++)
            {
                CopyMemory(data.Scan0 + i * Stride, gray + i * width, width);
            }
            bmp.UnlockBits(data);
            return bmp;
        }

        /// <summary>
        /// 将二值化数组转换为二值化图像
        /// </summary>
        /// <param name="binary">二值化数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>二值化图像</returns>
        public static Bitmap ToBinaryBitmap(byte[] binary, int width, int height)
        {   // 将二值化数组转换为二值化数据
            int Stride = ((width + 31) >> 5) << 2;
            byte[] Pixels = new byte[height * Stride];
            int Index = 0;
            for (int i = 0; i < height; i++)
            {
                int Base = i * Stride;
                for (int j = 0; j < width; j++)
                {
                    if (binary[Index++] != 0) Pixels[Base + (j >> 3)] |= Convert.ToByte(0x80 >> (j & 0x7));
                }
            }

            // 创建黑白图像
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format1bppIndexed);

            // 设置调色板
            ColorPalette cp = bmp.Palette;
            cp.Entries[0] = Color.Black;    // 黑色
            cp.Entries[1] = Color.White;    // 白色
            bmp.Palette = cp;

            // 设置位图图像特性            
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
            Marshal.Copy(Pixels, 0, data.Scan0, Pixels.Length);
            bmp.UnlockBits(data);
            return bmp;
        }

        /// <summary>
        /// 位图灰度化
        /// </summary>
        /// <param name="bmp">原始位图</param>
        /// <returns>灰度位图</returns>
        public static Bitmap ToGrayBitmap(this Bitmap bmp)
        {
            int PixelHeight = bmp.Height; // 图像高度
            int PixelWidth = bmp.Width;   // 图像宽度
            int Size = (PixelHeight * PixelWidth) << 2;
            byte[] Bgra = new byte[Size];

            // 锁定位图到系统内存
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            Marshal.Copy(bmpData.Scan0, Bgra, 0, Size);  // 从非托管内存拷贝数据到托管内存
            bmp.UnlockBits(bmpData);    // 从系统内存解锁位图

            // 将像素数据转换为灰度数据
            int GrayStride = ((PixelWidth + 3) >> 2) << 2;
            byte[] Gray = new byte[PixelHeight * GrayStride];
            int Index = 0;
            for (int i = 0; i < PixelHeight; i++)
            {
                int Base = i * GrayStride;
                for (int j = 0; j < PixelWidth; j++)
                {
                    Gray[Base++] = Convert.ToByte((Bgra[Index + 2] * 19595 + Bgra[Index + 1] * 38469 + Bgra[Index] * 7471 + 32768) >> 16);
                    Index += 4;
                }
            }

            // 创建灰度图像
            Bitmap GrayBmp = new Bitmap(PixelWidth, PixelHeight, PixelFormat.Format8bppIndexed);

            // 设置调色表
            ColorPalette cp = GrayBmp.Palette;
            for (int i = 0; i < 256; i++) cp.Entries[i] = Color.FromArgb(i, i, i);
            GrayBmp.Palette = cp;

            // 设置位图图像特性
            BitmapData GrayBmpData = GrayBmp.LockBits(new Rectangle(0, 0, PixelWidth, PixelHeight), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
            Marshal.Copy(Gray, 0, GrayBmpData.Scan0, Gray.Length);
            GrayBmp.UnlockBits(GrayBmpData);

            return GrayBmp;
        }

        #region DLLIMPORT
        [DllImport("FileUtils.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool Prepare();

        /// <summary>
        /// 释放存储空间
        /// </summary>
        /// <param name="buffer">存储空间</param>
        [DllImport("FileUtils.dll", EntryPoint = "FreeByteArray")]
        public static extern void Free(ref IntPtr buffer);

        /// <summary>
        /// 读取文件内容到存储空间
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <param name="buffer">存储空间,后续必须调用Free释放存储空间</param>
        /// <param name="size">存储空间大小</param>
        /// <returns>错误代码</returns>
        [DllImport("FileUtils.dll", CharSet = CharSet.Unicode, EntryPoint = "ReadFromFile")]
        public static extern int ReadFile(string filename, out IntPtr buffer, out int size);

        /// <summary>
        /// 存储空间写入文件
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <param name="buffer">存储空间</param>
        /// <param name="size">存储空间大小</param>
        /// <returns>错误代码</returns>
        [DllImport("FileUtils.dll", CharSet = CharSet.Unicode, EntryPoint = "WriteToFile")]
        public static extern int WriteFile(string filename, IntPtr buffer, int size);

        /// <summary>
        /// 将图像Bgra数组转换为图像灰度数组
        /// </summary>
        /// <param name="bgra">图像Bgra数组</param>
        /// <param name="gray">图像灰度数组</param>
        /// <param name="size">需要转换的像素数</param>
        [DllImport("FileUtils.dll")]
        public static extern void BgraToGray(IntPtr bgra, IntPtr gray, int size);

        [DllImport("FileUtils.dll")]
        private static extern void BgraToGray(IntPtr bgra, byte[] gray, int size);

        [DllImport("FileUtils.dll")]
        public static extern void BgraToGray(byte[] bgra, byte[] gray, int size);

        /// <summary>
        /// 将Bgra数组转换为Bgr数组
        /// </summary>
        /// <param name="bgra">要转换的Bgra数组</param>
        /// <param name="bgr">Bgr数组</param>
        /// <param name="size">需要转换的像素数</param>
        [DllImport("FileUtils.dll")]
        public static extern void BgraToBgr(IntPtr bgra, IntPtr bgr, int size);

        [DllImport("FileUtils.dll")]
        private static extern void BgraToBgr(IntPtr bgra, byte[] bgr, int size);

        [DllImport("FileUtils.dll")]
        public static extern void BgraToBgr(byte[] bgra, byte[] bgr, int size);

        [DllImport("FileUtils.dll")]
        public static extern int ToBgra(IntPtr hBmp, out IntPtr bgra, out int width, out int height);

        [DllImport("FileUtils.dll")]
        public static extern int ToGray(IntPtr hBmp, out IntPtr gray, out int width, out int height);

        [DllImport("FileUtils.dll", EntryPoint = "ToHBitmapFromFile")]
        public static extern IntPtr ToHBitmap(string filename);

        [DllImport("FileUtils.dll", EntryPoint = "ToBgraFromFile")]
        public static extern int ToBgra(string filename, out IntPtr bgra, out int width, out int height);

        [DllImport("FileUtils.dll", EntryPoint = "ToGrayFromFile")]
        public static extern int ToGray(string filename, out IntPtr gray, out int width, out int height);

        [DllImport("FileUtils.dll")]
        public static extern int StartupGdiplus();

        [DllImport("FileUtils.dll")]
        public static extern void ShutdownGdiplus();

        [DllImport("FileUtils.dll", EntryPoint = "ToHBitmapFromBuffer")]
        public static extern IntPtr ToHBitmap(IntPtr buffer, int size);

        [DllImport("FileUtils.dll", EntryPoint = "ToHBitmapFromBuffer")]
        public static extern IntPtr ToHBitmap(byte[] buffer, int size);

        [DllImport("FileUtils.dll", EntryPoint = "ToBgraFromBuffer")]
        public static extern int ToBgra(IntPtr buffer, int size, out IntPtr bgra, out int width, out int height);

        [DllImport("FileUtils.dll", EntryPoint = "ToBgraFromBuffer")]
        public static extern int ToBgra(byte[] buffer, int size, out IntPtr bgra, out int width, out int height);

        [DllImport("FileUtils.dll", EntryPoint = "ToGrayFromBuffer")]
        public static extern int ToGray(IntPtr buffer, int size, out IntPtr gray, out int width, out int height);

        [DllImport("FileUtils.dll", EntryPoint = "ToGrayFromBuffer")]
        public static extern int ToGray(byte[] buffer, int size, out IntPtr gray, out int width, out int height);

        [DllImport("Gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DeleteObject(IntPtr hObject);

        /// <summary>
        /// 内存拷贝
        /// </summary>
        /// <param name="dest">目标地址</param>
        /// <param name="src">源地址</param>
        /// <param name="count">要拷贝的字节数</param>
        [DllImport("Kernel32.dll")]
        public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
        #endregion
    }
}

ImageSourceUtils.cs

/* ----------------------------------------------------------
 * 文件名称:ImageSourceUtils.cs
 *
 * 作者:秦建辉
 *
 * 微信:splashcn
 *
 * 博客:http://www.firstsolver.com/wordpress/
 *
 * 开发环境:
 *      Visual Studio V2017
 *      .NET Framework 4 Client Profile
 *
 * 版本历史:
 *      V1.1    2018年12月09日
 *              完善接口
 *              
 *      V1.0    2018年01月03日
 *              ImageSource类图像处理工具
 * ------------------------------------------------------------ */
using System;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Com.FirstSolver.Splash
{
    public static class ImageSourceUtils
    {
        /// <summary>
        /// 生成Bgra数组
        /// </summary>
        /// <param name="bs">位图像素集</param>
        /// <returns>Bgra数组</returns>
        /// <remarks>返回结果后面需要调用Marshal.FreeHGlobal释放资源</remarks>
        public static IntPtr ToBgraPtr(this BitmapSource bs)
        {
            int PixelHeight = bs.PixelHeight;   // 图像高度
            int PixelWidth = bs.PixelWidth;     // 图像宽度
            int Stride = PixelWidth << 2;       // 跨距宽度
            IntPtr Bgra = Marshal.AllocHGlobal(PixelHeight * Stride);

            if (bs.Format == PixelFormats.Bgr32 || bs.Format == PixelFormats.Bgra32)
            {
                bs.CopyPixels(System.Windows.Int32Rect.Empty, Bgra, Stride, 0);
            }
            else
            {
                new FormatConvertedBitmap(bs, PixelFormats.Bgra32, null, 0).CopyPixels(System.Windows.Int32Rect.Empty, Bgra, Stride, 0);
            }
            return Bgra;
        }

        /// <summary>
        /// 生成灰度数组
        /// </summary>
        /// <param name="bs">位图像素集</param>
        /// <returns>灰度数组</returns>
        /// <remarks>返回结果后面需要调用Marshal.FreeHGlobal释放资源</remarks>
        public static IntPtr ToGrayPtr(this BitmapSource bs)
        {
            int Size = bs.PixelHeight * bs.PixelWidth;
            IntPtr Gray = Marshal.AllocHGlobal(Size);

            IntPtr Bgra = bs.ToBgraPtr();
            ImageUtils.BgraToGray(Bgra, Gray, Size);
            Marshal.FreeHGlobal(Bgra);
            return Gray;
        }

        /// <summary>
        /// 生成Bgr数组
        /// </summary>
        /// <param name="bs">位图像素集</param>
        /// <returns>Bgr数组</returns>
        /// <remarks>返回结果后面需要调用Marshal.FreeHGlobal释放资源</remarks>
        public static IntPtr ToBgrPtr(this BitmapSource bs)
        {
            int Size = bs.PixelHeight * bs.PixelWidth;
            IntPtr Bgr = Marshal.AllocHGlobal(Size * 3);

            IntPtr Bgra = bs.ToBgraPtr();
            ImageUtils.BgraToBgr(Bgra, Bgr, Size);
            Marshal.FreeHGlobal(Bgra);
            return Bgr;
        }

        /// <summary>
        /// 生成Bgra数组
        /// </summary>
        /// <param name="bs">位图像素集</param>
        /// <returns>Bgra数组</returns>
        public static byte[] ToBgra(this BitmapSource bs)
        {
            int PixelHeight = bs.PixelHeight;   // 图像高度
            int PixelWidth = bs.PixelWidth;     // 图像宽度
            int Stride = PixelWidth << 2;       // 跨距宽度
            byte[] Bgra = new byte[PixelHeight * Stride];
            if (bs.Format == PixelFormats.Bgr32 || bs.Format == PixelFormats.Bgra32)
            {
                bs.CopyPixels(Bgra, Stride, 0);
            }
            else
            {
                new FormatConvertedBitmap(bs, PixelFormats.Bgra32, null, 0).CopyPixels(Bgra, Stride, 0);
            }
            return Bgra;
        }

        /// <summary>
        /// 生成灰度数组
        /// </summary>
        /// <param name="bs">位图像素集</param>
        /// <returns>灰度数组</returns>
        public static byte[] ToGray(this BitmapSource bs)
        {
            int Size = bs.PixelHeight * bs.PixelWidth;
            byte[] Gray = new byte[Size];
            ImageUtils.BgraToGray(bs.ToBgra(), Gray, Size);
            return Gray;
        }

        /// <summary>
        /// 生成Bgr数组
        /// </summary>
        /// <param name="bs">位图像素集</param>
        /// <returns>Bgr数组</returns>
        public static byte[] ToBgr(this BitmapSource bs)
        {
            int Size = bs.PixelHeight * bs.PixelWidth;
            byte[] Bgr = new byte[Size * 3];
            ImageUtils.BgraToBgr(bs.ToBgra(), Bgr, Size);
            return Bgr;
        }

        /// <summary>
        /// 将 BitmapSource 转化为 Jpeg 字节数组
        /// </summary>
        /// <param name="bs">要转换的 BitmapSource</param>
        /// <returns>Jpeg字节数组</returns>
        public static byte[] ToJpegByteArray(this BitmapSource bs)
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                BitmapEncoder encoder = new JpegBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bs));
                encoder.Save(ms);
                return ms.ToArray();
            }
        }

        /// <summary>
        /// 将 BitmapSource 转化为 Bmp 字节数组
        /// </summary>
        /// <param name="bs">要转换的 BitmapSource</param>
        /// <returns>Bmp字节数组</returns>
        public static byte[] ToBmpByteArray(this BitmapSource bs)
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                BitmapEncoder encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bs));
                encoder.Save(ms);
                return ms.ToArray();
            }
        }

        /// <summary>
        /// 将字节数组转换为 BitmapImage
        /// </summary>
        /// <param name="buffer">要转换的字节数组</param>
        /// <returns>转换后的 BitmapImage</returns>
        public static BitmapImage ToBitmapImage(this byte[] buffer)
        {
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.StreamSource = new System.IO.MemoryStream(buffer);
            bi.EndInit();
            return bi;
        }

        /// <summary>
        /// 生成Bgra32位图图像集
        /// </summary>
        /// <param name="bgra">Bgra数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>Bgra32位图图像集</returns>
        public static BitmapSource ToBgra32BitmapSource(byte[] bgra, int width, int height)
        {
            return BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, bgra, width << 2);
        }

        /// <summary>
        /// 生成Bgra32位图图像集
        /// </summary>
        /// <param name="bgra">Bgra数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>Bgra32位图图像集</returns>
        public static BitmapSource ToBgra32BitmapSource(IntPtr bgra, int width, int height)
        {
            int Stride = width << 2;
            return BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgra32, null, bgra, height * Stride, Stride);
        }

        /// <summary>
        /// 生成灰度位图图像集
        /// </summary>
        /// <param name="gray">灰度数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>灰度位图图像集</returns>
        public static BitmapSource ToGrayBitmapSource(byte[] gray, int width, int height)
        {
            int Stride = ((width + 3) >> 2) << 2;
            byte[] Buffer = new byte[height * Stride];
            for (int i = 0; i < height; i++) Array.Copy(gray, i * width, Buffer, i * Stride, width);
            return BitmapSource.Create(width, height, 96, 96, PixelFormats.Indexed8, BitmapPalettes.Gray256, Buffer, Stride);
        }

        /// <summary>
        /// 生成灰度位图图像集
        /// </summary>
        /// <param name="gray">灰度数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>灰度位图图像集</returns>
        public static BitmapSource ToGrayBitmapSource(IntPtr gray, int width, int height)
        {
            int Stride = ((width + 3) >> 2) << 2;
            byte[] Buffer = new byte[height * Stride];
            for (int i = 0; i < height; i++) Marshal.Copy(gray + i * width, Buffer, i * Stride, width);
            return BitmapSource.Create(width, height, 96, 96, PixelFormats.Indexed8, BitmapPalettes.Gray256, Buffer, Stride);
        }

        /// <summary>
        /// 创建黑白图像
        /// </summary>
        /// <param name="binary">二值化数组</param>
        /// <param name="width">图像宽度</param>
        /// <param name="height">图像高度</param>
        /// <returns>黑白图像</returns>
        public static BitmapSource ToBinaryBitmapSource(byte[] binary, int width, int height)
        {
            int Stride = ((width + 31) >> 5) << 2;
            byte[] Buffer = new byte[height * Stride];
            int Index = 0;
            for (int i = 0; i < height; i++)
            {
                int Base = i * Stride;
                for (int j = 0; j < width; j++)
                {
                    if (binary[Index++] != 0) Buffer[Base + (j >> 3)] |= Convert.ToByte(0x80 >> (j & 0x7));
                }
            }

            // 创建黑白图像
            return BitmapSource.Create(width, height, 96, 96, PixelFormats.Indexed1, BitmapPalettes.BlackAndWhite, Buffer, Stride);
        }

        /// <summary>
        /// 转换成灰度位图图像集
        /// </summary>
        /// <param name="bs">原始位图图像集</param>
        /// <returns>灰度位图图像集</returns>
        public static BitmapSource ToGrayBitmapSource(this BitmapSource bs)
        {
            int PixelHeight = bs.PixelHeight;   // 图像高度
            int PixelWidth = bs.PixelWidth;     // 图像宽度
            int Stride = PixelWidth << 2;       // 跨距宽度
            byte[] Bgra = new Byte[PixelHeight * Stride];
            if (bs.Format == PixelFormats.Bgr32 || bs.Format == PixelFormats.Bgra32)
            {   // 拷贝像素数据
                bs.CopyPixels(Bgra, Stride, 0);
            }
            else
            {   // 先进行像素格式转换,再拷贝像素数据
                new FormatConvertedBitmap(bs, PixelFormats.Bgra32, null, 0).CopyPixels(Bgra, Stride, 0);
            }

            // 将像素数据转换为灰度数据
            int GrayStride = ((PixelWidth + 3) >> 2) << 2;
            byte[] Gray = new byte[PixelHeight * GrayStride];
            int Index = 0;
            for (int i = 0; i < PixelHeight; i++)
            {
                int Base = i * GrayStride;
                for (int j = 0; j < PixelWidth; j++)
                {
                    Gray[Base++] = Convert.ToByte((Bgra[Index + 2] * 19595 + Bgra[Index + 1] * 38469 + Bgra[Index] * 7471 + 32768) >> 16);
                    Index += 4;
                }
            }

            // 从灰度数据中创建灰度图像
            return BitmapSource.Create(PixelWidth, PixelHeight, 96, 96, PixelFormats.Indexed8, BitmapPalettes.Gray256, Gray, GrayStride);
        }

        /// <summary>
        /// 将 Bitmap 转化为 BitmapSource
        /// </summary>
        /// <param name="bmp"/>要转换的 Bitmap
        /// <returns>转换后的 BitmapSource</returns>
        public static BitmapSource ToBitmapSource(this System.Drawing.Bitmap bmp)
        {
            System.IntPtr hBmp = bmp.GetHbitmap();
            try
            {
                return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBmp, System.IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            }
            finally
            {
                DeleteObject(hBmp);
            }
        }

        /// <summary>
        /// 将 Bitmap 转化为 BitmapSource
        /// </summary>
        /// <param name="bmp"/>要转换的 Bitmap
        /// <returns>转换后的 BitmapImage</returns>
        public static BitmapImage ToBitmapImage(this System.Drawing.Bitmap bmp)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            bmp.Save(ms, ImageFormat.Bmp);

            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.StreamSource = ms;
            bi.EndInit();
            return bi;
        }

        /// <summary>
        /// 将 BitmapSource 转化为 Bitmap
        /// </summary>
        /// <param name="bs">要转换的 BitmapSource</param>
        /// <returns>转换后的位图图像</returns>
        public static System.Drawing.Bitmap ToBitmap(this BitmapSource bs)
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                BitmapEncoder encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bs));
                encoder.Save(ms);
                return new System.Drawing.Bitmap(ms);
            }
        }

        [DllImport("Gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool DeleteObject(IntPtr hObject);
    }
}

Comments are closed.