/* 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; } } } }
/* 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; }
/* 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; }
/* 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; }
/* 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; }