/* Find a vector from a block to the most similar portion of an image */ public Point getVector(double[,] image, Block comparison, int xPos, int yPos, int range) { xPos = xPos + 4; yPos = yPos + 4; double minError = 99999; int minXPos=0; int minYPos=0; double currentError; for (int y= yPos - range; y<yPos+ range; y++) { for (int x = xPos - range; x < xPos + range; x++) { currentError = getErrorForPosition(image, comparison, x, y, 1); if (currentError < minError) { minError = currentError; minXPos = x; minYPos = y; } } } //Debug.WriteLine(minError); Point vector = new Point(minXPos-xPos, minYPos-yPos); return vector; }
/* Returns the amount of error compared to a given block at the current position */ public double getErrorForPosition(double[,] image, Block comparison, int xPos, int yPos, int channel) { xPos -= 4; yPos -= 4; double error = 0; double pixelValue; double currentError; Color color = new Color(); switch (channel) { case 1: YerrorBlock = new Block(); break; case 2: CberrorBlock = new Block(); break; case 3: CrerrorBlock = new Block(); break; } for (int y=yPos; y<yPos+8; y++) { for (int x=xPos; x<xPos+8; x++) { //if out of bounds, treat as a value of zero if (y >= image.GetLength(1) || x >= image.GetLength(0)||x<0||y<0) { switch (channel) { case 1: YerrorBlock.set(x - xPos, y - yPos, Math.Round(0 - comparison.get(x - xPos, y - yPos))); break; case 2: CberrorBlock.set(x - xPos, y - yPos, Math.Round((0 - comparison.get(x - xPos, y - yPos)))); break; case 3: CrerrorBlock.set(x - xPos, y - yPos, Math.Round((0 - comparison.get(x - xPos, y - yPos)))); break; } error += Math.Abs(0 - comparison.get(x - xPos, y - yPos)); continue; } currentError = image[x,y]-comparison.get(x-xPos, y-yPos); error += Math.Abs(currentError); switch (channel) { case 1: YerrorBlock.set(x - xPos, y - yPos, Math.Round(currentError)); break; case 2: CberrorBlock.set(x - xPos, y - yPos, Math.Round(currentError)); break; case 3: CrerrorBlock.set(x - xPos, y - yPos, Math.Round(currentError)); break; } } } if (xPos == 3 && yPos == 0) { //Debug.WriteLine("----------------------------ErrorBlock-----------------------------------"); for (int q = 0; q < 8; q++) { for (int w = 0; w < 8; w++) { //Debug.Write(errorBlock.get(q, w) + ","); //Debug.Write(comparison.get(q, w) + ","); } // Debug.WriteLine(""); } // Debug.WriteLine("----------------------------------------------------------------------------------------------"); } error /= 64; // Debug.WriteLine("Total error = "+error); return error; }
/* Returns the amount of error compared to a given block at the current position */ public void getOriginalFromError(double[,] image, Block errorBlock, int xPos, int yPos, int channel) { xPos -= 4; yPos -= 4; double error = 0; double pixelValue; double currentError; Color color = new Color(); switch (channel) { case 1: YpostBlock = new Block(); break; case 2: CbpostBlock = new Block(); break; case 3: CrpostBlock = new Block(); break; } for (int y = yPos; y < yPos + 8; y++) { for (int x = xPos; x < xPos + 8; x++) { //if out of bounds, treat as a value of zero if (y >= image.GetLength(1) || x >= image.GetLength(0) || x < 0 || y < 0) { switch (channel) { case 1: YpostBlock.set(x - xPos, y - yPos, Math.Round(Math.Abs(0 + errorBlock.get(x - xPos, y - yPos)))); break; case 2: CbpostBlock.set(x - xPos, y - yPos, Math.Round(Math.Abs(0 + errorBlock.get(x - xPos, y - yPos)))); break; case 3: CrpostBlock.set(x - xPos, y - yPos, Math.Round(Math.Abs(0 + errorBlock.get(x - xPos, y - yPos)))); break; } continue; } currentError = Math.Abs(image[x, y] + errorBlock.get(x - xPos, y - yPos)); switch (channel) { case 1: YerrorBlock.set(x - xPos, y - yPos, Math.Round(currentError)); break; case 2: CbpostBlock.set(x - xPos, y - yPos, Math.Round(currentError)); break; case 3: CrpostBlock.set(x - xPos, y - yPos, Math.Round(currentError)); break; } } } }
/* Undo each of the compression steps */ public void decompress(List<List<int>> YencodedList, List<List<int>> CbencodedList, List<List<int>> CrencodedList, int width, int height) { int horizontalBlocks = (int)Math.Ceiling((double)width / 8);//amount of full 8x8 blocks will fit horizontally int verticalBlocks = (int)Math.Ceiling((double)height / 8);//amount of full 8x8 blocks will fit vertically Block[,] YpostBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] CbpostBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] CrpostBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] YdctBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] CbdctBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] CrdctBlocks = new Block[horizontalBlocks, verticalBlocks]; int[] Yencoded,Cbencoded,Crencoded; for (int y = 0; y < verticalBlocks; y++) { for (int x = 0; x < horizontalBlocks; x++) { YpostBlocks[x, y] = new Block(); CbpostBlocks[x, y] = new Block(); CrpostBlocks[x, y] = new Block(); } } int[] Yzig,Cbzig,Crzig; for (int y = 0; y < verticalBlocks; y++) { for (int x = 0; x < horizontalBlocks; x++) { Yencoded = convert2dListToArray(YencodedList, verticalBlocks * y + x); Cbencoded = convert2dListToArray(CbencodedList, verticalBlocks * y + x); Crencoded = convert2dListToArray(CrencodedList, verticalBlocks * y + x); Yzig = undoRunlengthEncoding(Yencoded); Cbzig = undoRunlengthEncoding(Cbencoded); Crzig = undoRunlengthEncoding(Crencoded); if (x == 0 && y == 0) { for (int i = 0; i < Yzig.GetLength(0); i++) { Debug.Write((Yzig[i]) + ","); //Debug.Write((Cbzig[i]) + ","); } Debug.WriteLine(""); Debug.WriteLine("-------------------------------------"); } YdctBlocks[x, y] = undoZigZag(Yzig); CbdctBlocks[x, y] = undoZigZag(Cbzig); CrdctBlocks[x, y] = undoZigZag(Crzig); if (x == 0 && y == 0) { for (int q = 0; q < 8; q++) { for (int w = 0; w < 8; w++) { Debug.Write(YdctBlocks[x, y].get(q, w) + ","); //Debug.Write(CbdctBlocks[x, y].get(q, w) + ","); } Debug.WriteLine(""); } } } } for (int y = 0; y < verticalBlocks; y++) { for (int x = 0; x < horizontalBlocks; x++) { YdctBlocks[x, y] = RemoveQuantization(YdctBlocks[x, y], luminance); CbdctBlocks[x, y] = RemoveQuantization(CbdctBlocks[x, y], chrominance); CrdctBlocks[x, y] = RemoveQuantization(CrdctBlocks[x, y], chrominance); for (int v = 0; v < 8; v++) { for (int u = 0; u < 8; u++) { YpostBlocks[x, y].set(u, v, applyIDCTFormula(YdctBlocks[x, y], u, v)); //if (x % 2 == 0 && y % 2 == 0) //{ CbpostBlocks[x , y ].set(u, v, applyIDCTFormula(CbdctBlocks[x, y], u, v)); CrpostBlocks[x , y ].set(u, v, applyIDCTFormula(CrdctBlocks[x , y], u, v)); //} } } } } this.Yblocks = YpostBlocks; this.Cbblocks = CbpostBlocks; this.Crblocks = CrpostBlocks; YImage = makeDoubleArrayFromBlocks(YpostBlocks, width, height); CbImage = makeDoubleArrayFromBlocks(CbpostBlocks, width, height); CrImage = makeDoubleArrayFromBlocks(CrpostBlocks, width, height); }
/* compresses a pframe */ public void compressPframe(Block[,] Yblocks, Block[,] Cbblocks, Block[,] Crblocks, Point[,] vectors, int width, int height) { int horizontalBlocks = Yblocks.GetLength(0); int verticalBlocks = Yblocks.GetLength(1); Block[,] YdctBlocks = new Block[horizontalBlocks,verticalBlocks]; Block[,] CbdctBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] CrdctBlocks = new Block[horizontalBlocks, verticalBlocks]; List<int> YSaveBuffer = new List<int>(); List<int> CbSaveBuffer = new List<int>(); List<int> CrSaveBuffer = new List<int>(); for (int y = 0; y < verticalBlocks; y++) { for (int x = 0; x < horizontalBlocks; x++) { //Debug.WriteLine("-----------Starting------------"); YdctBlocks[x, y] = new Block(); CbdctBlocks[x, y] = new Block(); CrdctBlocks[x, y] = new Block(); for (int v = 0; v < 8; v++) { for (int u = 0; u < 8; u++) { YdctBlocks[x, y].set(u, v, applyDCTFormula(Yblocks[x, y], u, v)); CbdctBlocks[x, y].set(u, v, applyDCTFormula(Cbblocks[x, y], u, v)); CrdctBlocks[x, y].set(u, v, applyDCTFormula(Crblocks[x, y], u, v)); } //Debug.WriteLine(""); } YdctBlocks[x, y] = applyQuantization(YdctBlocks[x, y], luminance); CbdctBlocks[x, y] = applyQuantization(CbdctBlocks[x, y], chrominance); CrdctBlocks[x, y] = applyQuantization(CrdctBlocks[x, y], chrominance); if (x == 0 && y == 0) { for (int q = 0; q < 8; q++) { for (int w = 0; w < 8; w++) { Debug.Write(YdctBlocks[x, y].get(q, w) + ","); //Debug.Write(CbdctBlocks[x, y].get(q, w) + ","); } Debug.WriteLine(""); } Debug.WriteLine("-------------------------------------"); } int[] Yzig = applyZigZag(YdctBlocks[x, y]); int[] Yencoded = runLengthEncode(Yzig); YSaveBuffer.Add(Yencoded.Length); for (int i = 0; i < Yencoded.Length; i++) { YSaveBuffer.Add(Yencoded[i]); } int[] Cbzig = new int[128]; int[] Crzig = new int[128]; int[] Cbencoded = new int[128]; int[] Crencoded = new int[128]; Cbzig = applyZigZag(CbdctBlocks[x, y]); Crzig = applyZigZag(CrdctBlocks[x, y]); Cbencoded = runLengthEncode(Cbzig); Crencoded = runLengthEncode(Crzig); //first save the length of the run length, so we know how far to read later CbSaveBuffer.Add(Cbencoded.Length); for (int i = 0; i < Cbencoded.Length; i++) { CbSaveBuffer.Add(Cbencoded[i]); } CrSaveBuffer.Add(Crencoded.Length); for (int i = 0; i < Crencoded.Length; i++) { CrSaveBuffer.Add(Crencoded[i]); } if (x == 0 && y == 0) { for (int i = 0; i < Yzig.GetLength(0); i++) //for (int i = 0; i < Cbzig.GetLength(0); i++) { Debug.Write((Yzig[i]) + ","); //Debug.Write((Cbzig[i]) + ","); } Debug.WriteLine(""); Debug.WriteLine("-------------------------------------"); for (int i = 0; i < Yencoded.GetLength(0); i++) //for (int i = 0; i < Cbencoded.GetLength(0); i++) { Debug.Write((Yencoded[i]) + ","); //Debug.Write((Cbencoded[i]) + ","); } Debug.WriteLine(""); Debug.WriteLine("-------------------------------------"); } //saveFile(); //--------------------------------------UNDO COMPRESSION--------------------------------------------------------------------- }//x }//y int position = 0; int totalCount = YSaveBuffer.Count + CbSaveBuffer.Count + CrSaveBuffer.Count; int[] toSave = new int[totalCount + 2]; for (int i = 0; i < YSaveBuffer.Count; i++) { toSave[position++] = YSaveBuffer[i]; } toSave[position++] = 127; for (int i = 0; i < CbSaveBuffer.Count; i++) { toSave[position++] = CbSaveBuffer[i]; } toSave[position++] = 127; for (int i = 0; i < CrSaveBuffer.Count; i++) { toSave[position++] = CrSaveBuffer[i]; } FileFunctions.saveCompressed(toSave, width, height); decodeSavePFrameArray(toSave, width, height); //decompress(Yencoded, Cbencoded, Crencoded, width, height); }
public void runDCT() { int horizontalBlocks = (int)Math.Ceiling((double)Y.GetLength(0) / 8);//amount of full 8x8 blocks will fit horizontally int verticalBlocks = (int)Math.Ceiling((double)Y.GetLength(1) / 8);//amount of full 8x8 blocks will fit vertically Block[,] Yblocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] YdctBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] Cbblocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] CbdctBlocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] Crblocks = new Block[horizontalBlocks, verticalBlocks]; Block[,] CrdctBlocks = new Block[horizontalBlocks, verticalBlocks]; List<int> YSaveBuffer = new List<int>(); List<int> CbSaveBuffer = new List<int>(); List<int> CrSaveBuffer = new List<int>(); int toSaveBufferPos = 0; for (int y=0; y<verticalBlocks; y++) { for (int x = 0; x < horizontalBlocks; x++) { Yblocks[x, y] = generateBlock(Y, x * 8, y * 8);//which block, multiplied by block offset (8) YdctBlocks[x, y] = new Block(); Cbblocks[x, y] = generateBlock(Cb, x * 8, y * 8);//which block, multiplied by block offset (8) CbdctBlocks[x,y] = new Block(); Crblocks[x, y] = generateBlock(Cr, x * 8, y * 8);//which block, multiplied by block offset (8) CrdctBlocks[x, y] = new Block(); } } for (int y = 0; y < verticalBlocks; y++) { for (int x = 0; x < horizontalBlocks; x++) { //Debug.WriteLine("-----------Starting------------"); for (int v = 0; v < 8; v++) { for (int u = 0; u < 8; u++) { YdctBlocks[x, y].set(u, v, applyDCTFormula(Yblocks[x, y], u, v)); CbdctBlocks[x, y].set(u, v, applyDCTFormula(Cbblocks[x, y], u, v)); CrdctBlocks[x, y].set(u, v, applyDCTFormula(Crblocks[x, y], u, v)); } //Debug.WriteLine(""); } YdctBlocks[x, y] = applyQuantization(YdctBlocks[x, y], luminance); CbdctBlocks[x, y] = applyQuantization(CbdctBlocks[x, y], chrominance); CrdctBlocks[x, y] = applyQuantization(CrdctBlocks[x, y], chrominance); if (x == 0 && y == 0) { for (int q = 0; q < 8; q++) { for (int w = 0; w < 8; w++) { Debug.Write(YdctBlocks[x, y].get(q, w) + ","); //Debug.Write(CbdctBlocks[x, y].get(q, w) + ","); } Debug.WriteLine(""); } Debug.WriteLine("-------------------------------------"); } int[] Yzig = applyZigZag(YdctBlocks[x, y]); int[] Yencoded = runLengthEncode(Yzig); YSaveBuffer.Add(Yencoded.Length); for (int i = 0; i < Yencoded.Length; i++) { YSaveBuffer.Add(Yencoded[i]); } int[] Cbzig = new int[128]; int[] Crzig = new int[128]; int[] Cbencoded = new int[128]; int[] Crencoded = new int[128]; Cbzig = applyZigZag(CbdctBlocks[x, y]); Crzig = applyZigZag(CrdctBlocks[x, y]); Cbencoded = runLengthEncode(Cbzig); Crencoded = runLengthEncode(Crzig); //first save the length of the run length, so we know how far to read later CbSaveBuffer.Add(Cbencoded.Length); for (int i = 0; i < Cbencoded.Length; i++) { CbSaveBuffer.Add(Cbencoded[i]); } CrSaveBuffer.Add(Crencoded.Length); for (int i = 0; i < Crencoded.Length; i++) { CrSaveBuffer.Add(Crencoded[i]); } if (x == 0 && y == 0) { for (int i = 0; i < Yzig.GetLength(0); i++) //for (int i = 0; i < Cbzig.GetLength(0); i++) { Debug.Write((Yzig[i]) + ","); //Debug.Write((Cbzig[i]) + ","); } Debug.WriteLine(""); Debug.WriteLine("-------------------------------------"); for (int i = 0; i < Yencoded.GetLength(0); i++) //for (int i = 0; i < Cbencoded.GetLength(0); i++) { Debug.Write((Yencoded[i]) + ","); //Debug.Write((Cbencoded[i]) + ","); } Debug.WriteLine(""); Debug.WriteLine("-------------------------------------"); } //saveFile(); //--------------------------------------UNDO COMPRESSION--------------------------------------------------------------------- }//x }//y Debug.WriteLine("File length = "+toSaveBufferPos); int position = 0; int totalCount = YSaveBuffer.Count + CbSaveBuffer.Count + CrSaveBuffer.Count; int[] toSave = new int[totalCount+2]; for(int i=0; i< YSaveBuffer.Count; i++){ toSave[position++] = YSaveBuffer[i]; } toSave[position++] = 127; for (int i = 0; i < CbSaveBuffer.Count; i++) { toSave[position++] = CbSaveBuffer[i]; } toSave[position++] = 127; for (int i = 0; i < CrSaveBuffer.Count; i++) { toSave[position++] = CrSaveBuffer[i]; } FileFunctions.saveCompressed(toSave, Y.GetLength(0), Y.GetLength(1)); byte[] savedData = FileFunctions.openCompressed("TestFile.cmpr"); decodeSaveArray(savedData); }
/* undoes zig zag on an int array, and outputs the original 8x8 block */ public Block undoZigZag(int[] array) { Block block = new Block(); int arrayPos = 0; int yMove = -1; int xMove = 1; int x = 0; int y = 0; block.set(x, y, array[arrayPos++]); for (int level = 0; level < 8; level++) { for (int depth = 0; depth < level; depth++) { x += xMove; y += yMove; block.set(x, y, array[arrayPos++]); } if (level == 7) break; if (xMove < 0) y++; else x++; block.set(x, y, array[arrayPos++]); yMove *= -1; xMove *= -1; } yMove *= -1; xMove *= -1; if (xMove < 0) y++; else x++; block.set(x, y, array[arrayPos++]); for (int level = 6; level > 0; level--) { for (int depth = level; depth > 0; depth--) { x += xMove; y += yMove; block.set(x, y, array[arrayPos++]); } if (xMove < 0) x++; else y++; block.set(x, y, array[arrayPos++]); yMove *= -1; xMove *= -1; } return block; }
/* Multiplies the values of a quantized block by a quantization table to undo quantization. returns the outcome */ public Block RemoveQuantization(Block block, int[,] table) { Block quantizedBlock = new Block(); for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { quantizedBlock.set(x, y, block.get(x, y) * table[x, y]); } } return quantizedBlock; }
/* converts a block into a 1 dimensional array */ public int[] applyZigZag(Block block) { int[] zigzag = new int[64]; int arrayPos =0; int yMove = -1; int xMove = 1; int x = 0; int y = 0; zigzag[arrayPos++] = (int)block.get(x, y); for (int level = 0; level < 8; level++) { for (int depth = 0; depth < level; depth++) { x += xMove; y += yMove; zigzag[arrayPos++] = (int)block.get(x,y); } if (level == 7) break; if (xMove < 0) y++; else x++; zigzag[arrayPos++] = (int)block.get(x, y); yMove *= -1; xMove *= -1; } yMove *= -1; xMove *= -1; if (xMove < 0) y++; else x++; zigzag[arrayPos++] = (int)block.get(x, y); for (int level = 6; level > 0; level--) { for (int depth = level; depth > 0; depth--) { x += xMove; y += yMove; zigzag[arrayPos++] = (int)block.get(x, y); } if (xMove < 0) x++; else y++; zigzag[arrayPos++] = (int)block.get(x, y); yMove *= -1; xMove *= -1; } return zigzag; }
/* Creates a bitmap from an array of 8*8 blocks. */ public Bitmap createBitmapFromBlocks(Block[,] blocks, int imageWidth, int imageHeight) { Bitmap image = new Bitmap(imageWidth, imageHeight); int blocksVertical = blocks.GetLength(0); int blocksHorizontal = blocks.GetLength(1); for (int y=0; y<blocksHorizontal; y++) { for (int x=0; x<blocksVertical; x++) { for (int blockY=0; blockY<8; blockY++) { for (int blockX=0; blockX<8; blockX++) { if ( y * 8 + blockY >= imageHeight) continue; if (x * 8 + blockX >= imageWidth) continue; image.SetPixel(x*8+blockX, y*8+blockY, Color.FromArgb((int)blocks[x,y].get(blockX,blockY), (int)blocks[x, y].get(blockX, blockY), (int)blocks[x, y].get(blockX, blockY))); } } } } return image; }
/* Divides the values of the block by a passed quantization table, and returns the outcome */ public Block applyQuantization(Block block, int[,] table) { Block quantizedBlock = new Block(); for (int y=0; y<8; y++) { for (int x=0; x<8; x++) { quantizedBlock.set(x,y,Math.Round((double)block.get(x, y) / table[x, y])); } } return quantizedBlock; }
/* Applies inverse DCT formula and returns the image pixel */ public double applyIDCTFormula(Block input, double i, double j) { double sum = 0, firstCos, secondCos; for (double u=0; u<8; u++) { for (double v=0; v<8; v++) { firstCos = Math.Cos((2*i+1)*u*Math.PI/16); secondCos = Math.Cos((2*j+1)*v*Math.PI/16); sum += c(u) * c(v) /4 * firstCos * secondCos*input.get((int)u,(int)v); } } return sum; }
/* Applies DCT formula to a block, and returns the post DCT pixel */ public double applyDCTFormula(Block input, double u, double v) { double sum=0, firstCos, secondCos; for (double i=0; i<8; i++) { for (double j=0; j<8; j++) { firstCos = Math.Cos((2*i+1)*u*Math.PI/16); secondCos = Math.Cos((2 * j + 1) * v * Math.PI / 16); sum += (firstCos * secondCos * input.get((int)i, (int)j)); //if (i < 4 && j < 4) sum += firstCos * secondCos * input.get((int)i, (int)j); } } sum *= c(u) * c(v) / 4; return sum; }
/* Puts an array of blocks back together as a single double array, ready for conversion to image */ public double[,] makeDoubleArrayFromBlocks(Block[,] blocks, int width, int height) { double[,] image = new double[width, height]; for (int y=0; y< height; y++) { for (int x=0; x< width; x++) { int XblockPosition = x / 8; int YblockPosition = y / 8; int XinsidePosition = x-(XblockPosition * 8); int YinsidePosition = y - (YblockPosition * 8); image[x, y] = blocks[XblockPosition, YblockPosition].get(XinsidePosition, YinsidePosition); } } return image; }
/* Generates an 8x8 block from a position */ public Block generateBlock(double[,] fullSize, int xPosition, int yPosition) { Block block = new Block(); for (int y=yPosition; y<yPosition+8; y++) { for (int x=xPosition; x<xPosition+8; x++) { if (x < fullSize.GetLength(0) && y < fullSize.GetLength(1)) { block.set(x-xPosition,y-yPosition,fullSize[x,y]); } else { block.set(x - xPosition, y - yPosition, 0.0); } } } return block; }
/*Generate motion vectors between the two frames*/ private void generateMotionVectorsToolStripMenuItem_Click(object sender, EventArgs e) { int width = uncompressedSecondFrame.Width; int height = uncompressedSecondFrame.Height; double[,] Y = new double[width, height]; double[,] Cb = new double[width / 2, height / 2]; double[,] Cr = new double[width / 2, height / 2]; //generate the Y, Cb, Cr values from the second frame generateYcbcrBitmap(uncompressedSecondFrame, ref Y, ref Cb, ref Cr); double[,] Y2 = new double[width, height]; double[,] Cb2 = new double[width / 2, height / 2]; double[,] Cr2 = new double[width / 2, height / 2]; generateYcbcrBitmap(uncompressedBitmap, ref Y2, ref Cb2, ref Cr2); DCT dct = new DCT(); Point[,] vectors = new Point[(int)Math.Ceiling((double)width/8), (int)Math.Ceiling((double)height / 8)]; Block[,] YerrorBlocks = new Block[(int)Math.Ceiling((double)width / 8), (int)Math.Ceiling((double)height / 8)]; Block[,] CberrorBlocks = new Block[(int)Math.Ceiling((double)width / 8), (int)Math.Ceiling((double)height / 8)]; Block[,] CrerrorBlocks = new Block[(int)Math.Ceiling((double)width / 8), (int)Math.Ceiling((double)height / 8)]; VideoCompression vidcom = new VideoCompression(); for (int y=0; y<height; y+=8) { for (int x = 0; x < width; x += 8) { Block Yblock = dct.generateBlock(Y, x, y); Block Cbblock = dct.generateBlock(Cb, x, y); Block Crblock = dct.generateBlock(Cr, x, y); vectors[x/8,y/8] = vidcom.getVector(Y2, Yblock, x, y, 15); vidcom.getErrorForPosition(Cb2, Cbblock, vectors[x / 8, y / 8].X, vectors[x / 8, y / 8].Y, 2); vidcom.getErrorForPosition(Cr2, Crblock, vectors[x / 8, y / 8].X, vectors[x / 8, y / 8].Y, 3); YerrorBlocks[x/8,y/8] = vidcom.getCurrentYErrorBlock(); CberrorBlocks[x / 8, y / 8] = vidcom.getCurrentCbErrorBlock(); CrerrorBlocks[x / 8, y / 8] = vidcom.getCurrentCrErrorBlock(); Debug.Write("(" + vectors[x/8,y/8].X + "," + vectors[x/8,y/8].Y+"),"); } Debug.WriteLine(""); } dct.compressPframe(YerrorBlocks, CberrorBlocks, CrerrorBlocks, vectors, width, height); Block[,] finalY = new Block[dct.Yblocks.GetLength(0), dct.Yblocks.GetLength(1)]; Block[,] finalCb = new Block[dct.Yblocks.GetLength(0), dct.Yblocks.GetLength(1)]; Block[,] finalCr = new Block[dct.Yblocks.GetLength(0), dct.Yblocks.GetLength(1)]; for (int y=0; y<dct.Yblocks.GetLength(0); y++) { for (int x=0; x<dct.Yblocks.GetLength(1); x++) { vidcom.getOriginalFromError(Y2, dct.Yblocks[x,y], x*8+vectors[x,y].X, y * 8 + vectors[x,y].Y, 1); finalY[x, y] = vidcom.YpostBlock; vidcom.getOriginalFromError(Cb2, dct.Cbblocks[x, y], x * 8 + vectors[x, y].X, y * 8 + vectors[x, y].Y, 2); finalCb[x, y] = vidcom.CbpostBlock; vidcom.getOriginalFromError(Cr2, dct.Crblocks[x, y], x * 8 + vectors[x, y].X, y * 8 + vectors[x, y].Y, 3); finalCr[x, y] = vidcom.CrpostBlock; } } double[,] finalYimage = dct.makeDoubleArrayFromBlocks(finalY, width, height); double[,] finalCbimage = dct.makeDoubleArrayFromBlocks(finalCb, width, height); double[,] finalCrimage = dct.makeDoubleArrayFromBlocks(finalCr, width, height); Bitmap pframe = generateRgbBitmapFromYCbCr(finalYimage, finalCbimage, finalCrimage); pictureBox2.Image = pframe; pictureBox2.SizeMode = PictureBoxSizeMode.Zoom; }