1. 程式人生 > >C# 指標法24點陣圖轉8位

C# 指標法24點陣圖轉8位

用指標操作,將24位的彩色影象轉換位8位的灰度圖

試了速度是9ms,比之前的那種方法快了很多。

  注意unsafe,勾選允許不安全的程式碼。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Diagnostics;


namespace my24to8Sec
{
    public partial class Form1 : Form
    {
        Bitmap mypic;
        Stopwatch st;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog op = new OpenFileDialog();
            if (op.ShowDialog() == DialogResult.OK)
            {
                mypic = (Bitmap)Bitmap.FromFile(op.FileName);
                pictureBox1.Image = mypic;
            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if(mypic!=null)
            {
                st = new Stopwatch();
                st.Start();
                int w=mypic.Width;
                int h=mypic.Height;
                int gray = 0;
                Bitmap bit = new Bitmap(w, h, PixelFormat.Format8bppIndexed);
                BitmapData dataIn = mypic.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
                BitmapData dataOut = bit.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
                unsafe
                {

                    byte* pIn = (byte*)(dataIn.Scan0.ToPointer());      //指向原始檔首地址

                    byte* pOut = (byte*)(dataOut.Scan0.ToPointer());  //指向目標檔案首地址

                    for (int y = 0; y < dataIn.Height; y++)  //列掃描
                    {

                        for (int x = 0; x < dataIn.Width; x++)   //行掃描
                        {

                         //   gray = (pIn[0] * 19595 + pIn[1] * 38469 + pIn[2] * 7472) >> 16;  //灰度計算公式  這個借鑑別人,這種運算方式能提高部分速度

                            gray = (int)(pIn[0] * 0.299 + pIn[1] * 0.587 + pIn[2] * 0.114);   

                            pOut[0] = (byte)gray;    

                            pIn += 3; pOut += 1;    

                        }

                        pIn += dataIn.Stride - dataIn.Width * 3;

                        pOut += dataOut.Stride - dataOut.Width;

                    }

                }

                ColorPalette tempPalette;
                {
                    using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
                    {
                        tempPalette = tempBmp.Palette;
                    }
                    for (int i = 0; i < 256; i++)
                    {
                        tempPalette.Entries[i] = Color.FromArgb(i, i, i);
                    }
                    bit.Palette = tempPalette;
                }

                bit.UnlockBits(dataOut);

                mypic.UnlockBits(dataIn);

                st.Stop();
                textBox1.Text = st.ElapsedMilliseconds.ToString();
                pictureBox1.Image = bit;
                }

        }
    }
}