//this is a simple function to copy each motion vector into a structured array //simplifies indexing when reconstructing the pixels private void copyMVs(MVPair[,] MVArray) { for (int i = 0; i < MVArray.GetLength(0); i++) { for (int j = 0; j < MVArray.GetLength(1); j++) { int mvX = byteArray[index++]; int mvY = byteArray[index++]; if (mvX > 127) { mvX -= 256; } if (mvY > 127) { mvY -= 256; } //Debug.Write("(" + mvX + ", " + mvY + ") " + Environment.NewLine); MVArray[i, j] = new MVPair(mvX, mvY); } } }
//this is the entire decompression routine function. public void daDecomp() { //open the file! byteArray = File.ReadAllBytes("thefile.cam"); //read width and height width = BitConverter.ToInt32(byteArray, 0); height = BitConverter.ToInt32(byteArray, 4); int width2 = (int)Math.Ceiling(width / 2.0); int height2 = (int)Math.Ceiling(height / 2.0); //read the first frame channels int yCount = BitConverter.ToInt32(byteArray, 8); int CbCount = BitConverter.ToInt32(byteArray, 12); int CrCount = BitConverter.ToInt32(byteArray, 16); //read the 2nd frame channels int diffYCount = BitConverter.ToInt32(byteArray, 20); int diffCbCount = BitConverter.ToInt32(byteArray, 24); int diffCrCount = BitConverter.ToInt32(byteArray, 28); //intialize the Y Cb Cr for class! Y = new double[width, height]; Cb = new double[width, height]; Cr = new double[width, height]; //rewrite array w/o counts, makes indexing SIMPLE! Array.Copy(byteArray, 32, byteArray, 0, byteArray.Length - 32); //decode the Y Cb Cr lists into their channel arrays DecodeChannel(Y, 0, yCount, width, height, luminance); DecodeChannel(Cb, yCount, yCount + CbCount, width2, height2, chrominance); DecodeChannel(Cr, yCount + CbCount, yCount + CbCount + CrCount, width2, height2, chrominance); //initialize the difference Y Cb Cr! double[,] diffY = new double[width, height]; double[,] diffCb = new double[width, height]; double[,] diffCr = new double[width, height]; //decode the Y Cb Cr difference lists into their channel arrays int iFrameCount = yCount + CbCount + CrCount; DecodeChannel(diffY, iFrameCount, iFrameCount + diffYCount, width, height, luminance); DecodeChannel(diffCb, iFrameCount + diffYCount, iFrameCount + diffYCount + diffCbCount, width2, height2, chrominance); DecodeChannel(diffCr, iFrameCount + diffYCount + diffCbCount, iFrameCount + diffYCount + diffCbCount + diffCrCount, width2, height2, chrominance); //INITIALIZE the motion vector structured arrays! MVPair[,] YMV = new MVPair[(int)Math.Ceiling(width / 8.0), (int)Math.Ceiling(height / 8.0)]; MVPair[,] CbMV = new MVPair[(int)Math.Ceiling(width2 / 8.0), (int)Math.Ceiling(height2 / 8.0)]; MVPair[,] CrMV = new MVPair[(int)Math.Ceiling(width2 / 8.0), (int)Math.Ceiling(height2 / 8.0)]; //rewrite the MVs at the start of the array int countsAndChannels = iFrameCount + diffYCount + diffCbCount + diffCrCount; Array.Copy(byteArray, countsAndChannels, byteArray, 0, byteArray.Length - countsAndChannels); //read the bytes as ints and get the 2's complements back as initial values copyMVs(YMV); copyMVs(CbMV); copyMVs(CrMV); //build p frame y cb cr channels from differences and motion vectors implementMotionVectors(YMV, diffY, diffY.GetLength(0), diffY.GetLength(1), Y); implementMotionVectors(CbMV, diffCb, diffCb.GetLength(0) / 2, diffCb.GetLength(1) / 2, Cb); implementMotionVectors(CrMV, diffCr, diffCr.GetLength(0) / 2, diffCr.GetLength(1) / 2, Cr); //supersample iframe cb cr and switch back to rgb and write to the iframe bmp bmp = new Bitmap(width, height); supersample(); convertYCbCr2RGB(); //supersample pframe cb cr and switch back to rgb and write to the pframe bmp bmp2 = new Bitmap(width, height); double[,] superCb = new double[width, height]; double[,] superCr = new double[width, height]; int sx = 0, sy = 0; for (int x = 0; x < width; x = x + 2) { for (int y = 0; y < height; y = y + 2) { superCb[x, y] = diffCb[sx, sy]; if (x < width - 1) { superCb[x + 1, y] = diffCb[sx, sy]; } if (y < height - 1) { superCb[x, y + 1] = diffCb[sx, sy]; } if (x < width - 1 && y < height - 1) { superCb[x + 1, y + 1] = diffCb[sx, sy]; } superCr[x, y] = diffCr[sx, sy]; if (x < width - 1) { superCr[x + 1, y] = diffCr[sx, sy]; } if (y < height - 1) { superCr[x, y + 1] = diffCr[sx, sy]; } if (x < width - 1 && y < height - 1) { superCr[x + 1, y + 1] = diffCr[sx, sy]; } sy++; } sx++; sy = 0; } diffCb = superCb; diffCr = superCr; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { double thisY = diffY[x, y]; double ThisCb = diffCb[x, y]; double thisCr = diffCr[x, y]; int r = (int)(1.164 * (thisY - 16) + 1.596 * (thisCr - 128)); int g = (int)(1.164 * (thisY - 16) - 0.813 * (thisCr - 128) - 0.392 * (ThisCb - 128)); int b = (int)(1.164 * (thisY - 16) + 2.017 * (ThisCb - 128)); r = Math.Max(0, Math.Min(255, r)); g = Math.Max(0, Math.Min(255, g)); b = Math.Max(0, Math.Min(255, b)); bmp2.SetPixel(x, y, Color.FromArgb(r, g, b)); } } }