1. 程式人生 > >關於c#呼叫usb攝像頭的回撥碼流解碼問題

關於c#呼叫usb攝像頭的回撥碼流解碼問題

最近,想用c#呼叫電腦攝像頭,參考了“赤色火焰”的部落格http://www.cnblogs.com/mgod/archive/2008/06/18/1224351.html,但對碼流解碼方面的介紹沒有,上網搜也沒有找到。於是,開始分析FrameCallBack中的VideoData的碼流結構發現其解析度是640*480,排列方式是YCbYCr,一行的排列是Y0CbY1CrY2CbY3CrY4CbY5Cr...,採用從左到右 從上到下的排列方式。其中YCbYCr表示左右相鄰的兩個畫素,這兩個畫素的Y值不同,共用Cb和Cr,例如:Y0CbY1Cr解碼是應為:Y0CbCr、Y1CbCr。

根據,YCbYCr轉RGB公式:

                               r = 1.164 * (y - 16) + 1.596 * (cr - 128);
                               g = 1.164 * (y - 16) - 0.391 * (cb - 128) - 0.813 * (cr - 128);
                               b = 1.164 * (y - 16) + 2.018 * (cb - 128);

編寫解碼函式,再呼叫解碼函式

	private double[] ycbcrToRGB(byte y, byte cb, byte cr)
        {
            double[] rgb = new double[3];
            rgb[0] = 1.164 * (y - 16) + 1.596 * (cr - 128);
            rgb[1] = 1.164 * (y - 16) - 0.391 * (cb - 128) - 0.813 * (cr - 128);
            rgb[2] = 1.164 * (y - 16) + 2.018 * (cb - 128);
            rgb[0] = Math.Min(Math.Max(0, rgb[0]), 255);
            rgb[1] = Math.Min(Math.Max(0, rgb[1]), 255);
            rgb[2] = Math.Min(Math.Max(0, rgb[2]), 255);
            return rgb;
        }
	protected unsafe void wc_RecievedFrame(byte[] data)
        {
            int w = 320, h = 480;
            Bitmap bi = new Bitmap(w * 2, h);
            BitmapData bData = bi.LockBits(new Rectangle(0, 0, w * 2, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    byte* pRef = (byte*)bData.Scan0 + bData.Stride * j + i * 2 * 3;
                    int index = i * 4 + j * w * 4;

                    byte Y0 = data[index];
                    byte cb = data[index + 1];
                    byte cr = data[index + 3];
                    byte Y1 = data[index + 2];

                    double[] rgb0 = ycbcrToRGB(Y0, cb, cr);
                    double[] rgb1 = ycbcrToRGB(Y1, cb, cr);
                    pRef[0] = (byte)rgb0[2];
                    pRef[1] = (byte)rgb0[1];
                    pRef[2] = (byte)rgb0[0];

                    pRef[3] = (byte)rgb1[2];
                    pRef[4] = (byte)rgb1[1];
                    pRef[5] = (byte)rgb1[0];
                }
            }
            bi.UnlockBits(bData);
            pictureBox1.Image = bi;
        }