求:C# 将bmp转成灰度图(8位,256色),然后再转成单色图(1位,只有黑白两色)的算法

时间:2022-07-02 15:24:59
求:C#中 将bmp格式的图片转成灰度图(8位,256色),然后再转成单色图(1位,只有黑白两色)的算法,不要把网上找来的贴上来,最好是自己编码实现过。

10 个解决方案

#1


该回复于2009-08-18 16:07:36被版主删除

#2


up..

#3


up

#4


没实现过。。。

#5


AForge找这个开源工程,里面你想要都有。

#6


这是我原来写的一个调整位图的类,你试试合不合用
  Bitmap bmp = new Bitmap("test.bmp");
  BmpAdjuster.Monochrome(ref bmp);


    class BmpAdjuster
    {
        public delegate ColorPalette PaletteAdjustEvent(ColorPalette plt);
        public unsafe delegate void ConvertScanLineEvent(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp);

        public static void AdjustColor(ref Bitmap bmp, PixelFormat format, PaletteAdjustEvent PalleteAdjust, ConvertScanLineEvent ConvertScanLine)
        {
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            Bitmap bmpOut = new Bitmap(bmp.Width, bmp.Height, format);

            bmpOut.Palette = PalleteAdjust(bmpOut.Palette);

            PixelFormat srcFmt = bmp.PixelFormat;
            PixelFormat dstFmt = bmpOut.PixelFormat;
            int srcPixBit = GetPixelSize(srcFmt);
            int dstPixBit = GetPixelSize(dstFmt);

            BitmapData srcData = null;
            BitmapData dstData = null;
            try
            {
                srcData = bmp.LockBits(rect, ImageLockMode.ReadOnly, srcFmt);
                dstData = bmpOut.LockBits(rect, ImageLockMode.WriteOnly, dstFmt);
                
                unsafe
                {
                    byte* srcLine = (byte*)srcData.Scan0.ToPointer();
                    byte* dstLine = (byte*)dstData.Scan0.ToPointer();
                    for (int L = 0; L < srcData.Height; L++)
                    {
                        ConvertScanLine((IntPtr)srcLine, (IntPtr)dstLine, srcData.Width, srcPixBit, dstPixBit, bmp, bmpOut);
                        
                        srcLine += srcData.Stride;
                        dstLine += dstData.Stride;
                    }
                }
            }
            finally
            {
                bmp.UnlockBits(srcData);
                bmpOut.UnlockBits(dstData);
            }

            bmp = bmpOut;
        }

        internal static int GetPixelSize(PixelFormat format)
        {
            switch (format)
            {
                case PixelFormat.Format16bppRgb555: return 16;
                case PixelFormat.Format16bppRgb565: return 16;
                case PixelFormat.Format24bppRgb: return 24;
                case PixelFormat.Format32bppRgb: return 32;
                case PixelFormat.Format1bppIndexed: return 1;
                case PixelFormat.Format4bppIndexed: return 4;
                case PixelFormat.Format8bppIndexed: return 8;
                case PixelFormat.Format16bppArgb1555: return 16;
                case PixelFormat.Format32bppPArgb: return 32;
                case PixelFormat.Format16bppGrayScale: return 16;
                case PixelFormat.Format48bppRgb: return 48;
                case PixelFormat.Format64bppPArgb: return 64;
                case PixelFormat.Canonical: return 32;
                case PixelFormat.Format32bppArgb: return 32;
                case PixelFormat.Format64bppArgb: return 64;
            }
            return 0;
        }

        public unsafe static void Monochrome(ref Bitmap bmp)
        {
            AdjustColor(ref bmp, PixelFormat.Format1bppIndexed,
                new PaletteAdjustEvent(SetBlackWhitePallete),
                new ConvertScanLineEvent(ConvertBlackWhiteScanLine));
        }

        static ColorPalette SetBlackWhitePallete(ColorPalette plt)
        {
            plt.Entries[0] = Color.Black;
            plt.Entries[1] = Color.White;
            return plt;
        }

        unsafe static void ConvertBlackWhiteScanLine(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp)
        {
            byte* src = (byte*)srcLine.ToPointer();
            byte* dst = (byte*)dstLine.ToPointer();
            int srcPixByte = srcPixBit / 8;
            int x, v, t = 0;

            for (x = 0; x < width; x++)
            {
                v = 28 * src[0] + 151 * src[1] + 77 * src[2];
                t = (t << 1) | (v > 200*256 ? 1 : 0);
                src += srcPixByte;

                if (x % 8 == 7)
                {
                    *dst = (byte)t;
                    dst++;
                    t = 0;
                }
            }

            if ((x %= 8) != 7)
            {
                t <<= 8-x;
                *dst = (byte)t;
            }
        }

        public static void Gray(ref Bitmap bmp)
        {
            AdjustColor(ref bmp, PixelFormat.Format8bppIndexed,
                new PaletteAdjustEvent(SetGrayPallete),
                new ConvertScanLineEvent(ConvertGaryScanLine));
        }

        static ColorPalette SetGrayPallete(ColorPalette plt)
        {
            for (int i = plt.Entries.Length - 1; i >= 0; i--)
                plt.Entries[i] = Color.FromArgb(i, i, i);
            return plt;
        }

        unsafe static void ConvertGaryScanLine(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp)
        {
            byte* src = (byte*)srcLine.ToPointer();
            byte* dst = (byte*)dstLine.ToPointer();
            int srcPixByte = srcPixBit / 8;

            for (int x = 0; x < width; x++)
            {
                *dst = (byte)((28 * src[0] + 151 * src[1] + 77 * src[2]) >> 8);
                src += srcPixByte;
                dst++;
            }
        }
        
    }

#7


up





#8


还是使用opencv最方便阿

#9


灰度图象就是单色图象,首先楼主的理解有误, 我想楼主第二步想要的是 黑白二值图(1 位,要么是0,要么是1)

//灰度图

            Color c = new Color();
            Color cc = new Color();

            Bitmap box1 = new Bitmap(pictureBox1.Image);
            Bitmap box2 = new Bitmap(pictureBox1.Image);
            
            int rr,gg,bb;

            for (int i = 0; i < pictureBox1.Image.Width; i++)
            {
                for (int j = 0; j < pictureBox1.Image.Height; j++)
                {
                    c = box1.GetPixel(i, j);

                    rr = c.R;
                    gg = c.G;
                    bb = c.B;

                    cc = Color.FromArgb(rr, rr, rr);
                    box2.SetPixel(i, j, cc);
                }
            }
            pictureBox2.Refresh();
            pictureBox2.Image = box2;


//二值图

            Color c = new Color();
            Color cc = new Color();

            Bitmap box1 = new Bitmap(pictureBox1.Image);
            Bitmap box2 = new Bitmap(pictureBox1.Image);
            
            int rr;

            for (int i = 0; i < pictureBox1.Image.Width; i++)
            {
                for (int j = 0; j < pictureBox1.Image.Height; j++)
                {
                    c = box1.GetPixel(i, j);

                    rr = c.R;
                    if(rr >=128)
                    {
                        rr = 255;
                    }
                    else
                    {
                        rr = 0;
                    }
                    cc = Color.FromArgb(rr, rr, rr);
                    box2.SetPixel(i, j, cc);
                }
            }
            pictureBox2.Refresh();
            pictureBox2.Image = box2;

#10


mark

#1


该回复于2009-08-18 16:07:36被版主删除

#2


up..

#3


up

#4


没实现过。。。

#5


AForge找这个开源工程,里面你想要都有。

#6


这是我原来写的一个调整位图的类,你试试合不合用
  Bitmap bmp = new Bitmap("test.bmp");
  BmpAdjuster.Monochrome(ref bmp);


    class BmpAdjuster
    {
        public delegate ColorPalette PaletteAdjustEvent(ColorPalette plt);
        public unsafe delegate void ConvertScanLineEvent(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp);

        public static void AdjustColor(ref Bitmap bmp, PixelFormat format, PaletteAdjustEvent PalleteAdjust, ConvertScanLineEvent ConvertScanLine)
        {
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            Bitmap bmpOut = new Bitmap(bmp.Width, bmp.Height, format);

            bmpOut.Palette = PalleteAdjust(bmpOut.Palette);

            PixelFormat srcFmt = bmp.PixelFormat;
            PixelFormat dstFmt = bmpOut.PixelFormat;
            int srcPixBit = GetPixelSize(srcFmt);
            int dstPixBit = GetPixelSize(dstFmt);

            BitmapData srcData = null;
            BitmapData dstData = null;
            try
            {
                srcData = bmp.LockBits(rect, ImageLockMode.ReadOnly, srcFmt);
                dstData = bmpOut.LockBits(rect, ImageLockMode.WriteOnly, dstFmt);
                
                unsafe
                {
                    byte* srcLine = (byte*)srcData.Scan0.ToPointer();
                    byte* dstLine = (byte*)dstData.Scan0.ToPointer();
                    for (int L = 0; L < srcData.Height; L++)
                    {
                        ConvertScanLine((IntPtr)srcLine, (IntPtr)dstLine, srcData.Width, srcPixBit, dstPixBit, bmp, bmpOut);
                        
                        srcLine += srcData.Stride;
                        dstLine += dstData.Stride;
                    }
                }
            }
            finally
            {
                bmp.UnlockBits(srcData);
                bmpOut.UnlockBits(dstData);
            }

            bmp = bmpOut;
        }

        internal static int GetPixelSize(PixelFormat format)
        {
            switch (format)
            {
                case PixelFormat.Format16bppRgb555: return 16;
                case PixelFormat.Format16bppRgb565: return 16;
                case PixelFormat.Format24bppRgb: return 24;
                case PixelFormat.Format32bppRgb: return 32;
                case PixelFormat.Format1bppIndexed: return 1;
                case PixelFormat.Format4bppIndexed: return 4;
                case PixelFormat.Format8bppIndexed: return 8;
                case PixelFormat.Format16bppArgb1555: return 16;
                case PixelFormat.Format32bppPArgb: return 32;
                case PixelFormat.Format16bppGrayScale: return 16;
                case PixelFormat.Format48bppRgb: return 48;
                case PixelFormat.Format64bppPArgb: return 64;
                case PixelFormat.Canonical: return 32;
                case PixelFormat.Format32bppArgb: return 32;
                case PixelFormat.Format64bppArgb: return 64;
            }
            return 0;
        }

        public unsafe static void Monochrome(ref Bitmap bmp)
        {
            AdjustColor(ref bmp, PixelFormat.Format1bppIndexed,
                new PaletteAdjustEvent(SetBlackWhitePallete),
                new ConvertScanLineEvent(ConvertBlackWhiteScanLine));
        }

        static ColorPalette SetBlackWhitePallete(ColorPalette plt)
        {
            plt.Entries[0] = Color.Black;
            plt.Entries[1] = Color.White;
            return plt;
        }

        unsafe static void ConvertBlackWhiteScanLine(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp)
        {
            byte* src = (byte*)srcLine.ToPointer();
            byte* dst = (byte*)dstLine.ToPointer();
            int srcPixByte = srcPixBit / 8;
            int x, v, t = 0;

            for (x = 0; x < width; x++)
            {
                v = 28 * src[0] + 151 * src[1] + 77 * src[2];
                t = (t << 1) | (v > 200*256 ? 1 : 0);
                src += srcPixByte;

                if (x % 8 == 7)
                {
                    *dst = (byte)t;
                    dst++;
                    t = 0;
                }
            }

            if ((x %= 8) != 7)
            {
                t <<= 8-x;
                *dst = (byte)t;
            }
        }

        public static void Gray(ref Bitmap bmp)
        {
            AdjustColor(ref bmp, PixelFormat.Format8bppIndexed,
                new PaletteAdjustEvent(SetGrayPallete),
                new ConvertScanLineEvent(ConvertGaryScanLine));
        }

        static ColorPalette SetGrayPallete(ColorPalette plt)
        {
            for (int i = plt.Entries.Length - 1; i >= 0; i--)
                plt.Entries[i] = Color.FromArgb(i, i, i);
            return plt;
        }

        unsafe static void ConvertGaryScanLine(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp)
        {
            byte* src = (byte*)srcLine.ToPointer();
            byte* dst = (byte*)dstLine.ToPointer();
            int srcPixByte = srcPixBit / 8;

            for (int x = 0; x < width; x++)
            {
                *dst = (byte)((28 * src[0] + 151 * src[1] + 77 * src[2]) >> 8);
                src += srcPixByte;
                dst++;
            }
        }
        
    }

#7


up





#8


还是使用opencv最方便阿

#9


灰度图象就是单色图象,首先楼主的理解有误, 我想楼主第二步想要的是 黑白二值图(1 位,要么是0,要么是1)

//灰度图

            Color c = new Color();
            Color cc = new Color();

            Bitmap box1 = new Bitmap(pictureBox1.Image);
            Bitmap box2 = new Bitmap(pictureBox1.Image);
            
            int rr,gg,bb;

            for (int i = 0; i < pictureBox1.Image.Width; i++)
            {
                for (int j = 0; j < pictureBox1.Image.Height; j++)
                {
                    c = box1.GetPixel(i, j);

                    rr = c.R;
                    gg = c.G;
                    bb = c.B;

                    cc = Color.FromArgb(rr, rr, rr);
                    box2.SetPixel(i, j, cc);
                }
            }
            pictureBox2.Refresh();
            pictureBox2.Image = box2;


//二值图

            Color c = new Color();
            Color cc = new Color();

            Bitmap box1 = new Bitmap(pictureBox1.Image);
            Bitmap box2 = new Bitmap(pictureBox1.Image);
            
            int rr;

            for (int i = 0; i < pictureBox1.Image.Width; i++)
            {
                for (int j = 0; j < pictureBox1.Image.Height; j++)
                {
                    c = box1.GetPixel(i, j);

                    rr = c.R;
                    if(rr >=128)
                    {
                        rr = 255;
                    }
                    else
                    {
                        rr = 0;
                    }
                    cc = Color.FromArgb(rr, rr, rr);
                    box2.SetPixel(i, j, cc);
                }
            }
            pictureBox2.Refresh();
            pictureBox2.Image = box2;

#10


mark