日期:2014-05-18  浏览次数:21125 次

C# Bitmap、Image如何能快速的获取:Stream(流)、或是byte[],谁能帮我优化一下这代码段。
C# code
        private void button_AsyncWriteFileTest_Click(object sender, EventArgs e)
        {
            Image image = pictureBox_Image.Image;//54MB左右的大图

            Stopwatch st = new Stopwatch();
            st.Reset();
            st.Start();
            //Bitmap、Image如何能快速的获取:Stream(流)、或是byte[]
            //以下是为了获取Stream流对象
            MemoryStream ms = new MemoryStream();
            image.Save(ms, image.RawFormat);//4467,4秒多,很慢
            st.Stop();

            MessageBox.Show(st.ElapsedMilliseconds.ToString());
            st.Reset();
            st.Start();
            //以下是为了获取byte[]二进制数据
            byte[] bytes = ms.ToArray();//28,0.028秒,很快
            st.Stop();
            MessageBox.Show(st.ElapsedMilliseconds.ToString());

            int stateObjBufferSize = 1024;
            FileStream fs = new FileStream(
                Application.StartupPath + "\\TestAsyncWriteFile.test",
                FileMode.OpenOrCreate, System.Security.AccessControl.FileSystemRights.FullControl,
                FileShare.None, stateObjBufferSize, FileOptions.Asynchronous);

            AsyncWorkStateObj<FileStream> workStateObj = new AsyncWorkStateObj<FileStream>(fs, bytes.Length);
            workStateObj.Buffer = bytes;

            fs.BeginWrite(workStateObj.Buffer, 0, workStateObj.BufferSize, new AsyncCallback(BeginWrite), workStateObj);
        }

        private void BeginWrite(IAsyncResult ia)
        {
            AsyncWorkStateObj<FileStream> awso = ia.AsyncState as AsyncWorkStateObj<FileStream>;
            FileStream fs = awso.Worker;
            fs.EndWrite(ia);
            MessageBox.Show("写文件成功");
            fs.Close();
            fs = null;
        }


就是想优化获取流,或是二进制数据的问题。现在这方法感觉太慢了。

------解决方案--------------------
建议你用Bitmap.LockBits方法,数据在BitmapData.Scan0中,不过你要用unsafe的指针操作来提取数据,

PixelFormat eFormat = PixelFormat.Format24bppRgb;

Rectangle rcTargetLock=new Rectangle(0,0,rTargetBitmap.Width,rTargetBitmap.Height);
BitmapData rTargetBd = rTargetBitmap.LockBits(rcTargetLock, ImageLockMode.WriteOnly, eFormat);

------解决方案--------------------
// バイト配列をImageオブジェクトに変換
 public static Image ByteArrayToImage(byte[] b) {
ImageConverter imgconv = new ImageConverter();
Image img = (Image)imgconv.ConvertFrom(b);
return img;
 }
 
// Imageオブジェクトをバイト配列に変換
 public static byte[] ImageToByteArray(Image img) {
ImageConverter imgconv = new ImageConverter();
byte[] b = (byte[])imgconv.ConvertTo(img, typeof(byte[]));
return b;
 }
 
------解决方案--------------------
BitmapData
lock
scan0 操作
unlock
------解决方案--------------------
C# code

Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");     // Lock the bitmap's bits.  
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 
    System.Drawing.Imaging.BitmapData bmpData = 
        bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, 
        bmp.PixelFormat); 
    // Get the address of the first line. 
   IntPtr ptr = bmpData.Scan0;     // Declare an array to hold the bytes of the bitmap. 
    // This code is specific to a bitmap with 24 bits per pixels. 
    int bytes = bmp.Width * bmp.Height * 3; 
    byte[] rgbValues = new byte[bytes];     // Copy the RGB values into the array. 
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);     // Set every red value to 255.  
    for (int counter = 0; counter < rgbValues.Length; cou