public override byte[][] Transform(Hashtable input) { //reseed it if(input == null) return null; rnd = new Random(Guid.NewGuid().ToString().GetHashCode()); byte[][] b = (byte[][])input["image"]; int width = (int)input["width"]; int height = (int)input["height"]; allowSawtooth = (bool)input["sawtooth"]; allowVariance = (bool)input["variance"]; allowGauss = (bool)input["gauss"]; ScaleInfo si = new ScaleInfo(b.Length, b[0].Length, width, height); if(si.IsZooming) { //compute k across the entire image int nWidth = si.ResultWidth; int nHeight = si.ResultHeight; //apply the original image values to the given points float w = si.WidthScalingFactor; float h = si.HeightScalingFactor; float?[][] newImage = new float?[nWidth][]; float[][] displacementTable = new float[nWidth][]; float[][] imageF = ToFloatTable(b); byte[][] resultant = new byte[si.ResultWidth][]; for(int i = 0; i < nWidth; i++) { newImage[i] = new float?[nHeight]; displacementTable[i] = new float[nHeight]; resultant[i] = new byte[nHeight]; } for(int i = 0; i < nWidth - 1; i++) { int x0 = (int)((float)i / w); int x1 = (int)((float)(i + 1) / w); float p0 = (float)Math.Pow(x0 - x1, 2.0f); float[] line0 = imageF[x0]; float[] line1 = imageF[x1]; for(int j = 0; j < nHeight - 1; j++) { int y0 = (int)((float)j / h); int y1 = (int)((float)(j + 1) / h); //order has been messed up for sometime //should go (x0,y0), (x0,y1), (x1,y1), (x1,y0) float f0 = line0[y0]; float f1 = line0[y1]; float f2 = line1[y1]; float f3 = line1[y0]; k = ComputeK(2,i,j,b); displacementTable[i][j] = k; //save the base value //if(k < 1.0f) //{ float gauss = !allowGauss ? (float)rnd.NextDouble() : 1.0f; float var = !allowVariance ? Variance(f0,f1,f2,f3) : 1.0f; float tmp = (float)Math.Sqrt(1.0f - (float)Math.Pow(2.0f, 2.0f * k - 2f)) * DeltaX(p0,y0,y1) * gauss * var; k = tmp; //} DivideGrid(resultant, newImage, i, j, w, h, f0, f1, f2, f3); } } if(allowSawtooth) { List<float> temp = new List<float>(); for(int x = 0; x < si.ResultWidth; x++) { int outCount = 0; int pX = x - 1; bool pXValid = (pX >=0); if(pXValid) outCount++; int fX = x + 1; bool fXValid = (fX < si.ResultWidth); if(fXValid) outCount++; for(int y = 0; y < si.ResultHeight; y++) { if(newImage[x][y] == null || newImage[x][y] > 1.0f) { temp.Clear(); int pY = y - 1; int fY = y + 1; int count = outCount; float v0 = 0f, v1 = 0f, v2 = 0f, v3 = 0f; //f-type computation if(pXValid) { v0 = ((float)newImage[pX][y]); temp.Add(v0); } if(pY >= 0) { v1 = ((float)newImage[x][pY]); temp.Add(v1); count++; } if(fXValid) { v2 = ((float)newImage[fX][y]); temp.Add(v2); } if(fY < si.ResultHeight) { v3 = ((float)newImage[x][fY]); temp.Add(v3); count++; } //if count == 0 then we have bigger problems float total = (1.0f / (float)count); float p0 = total * (v0 + v1 + v2 + v3); float gauss = !allowGauss ? (float)rnd.NextDouble() : 1.0f; //get the k value float dX = DeltaX(pX,fX,pY,fY); float cK = displacementTable[x][y]; float var = !allowVariance ? Variance(temp.ToArray()) : 1.0f; float p1 = (float)Math.Pow(2.0f, -(cK / 2.0f)); float p2 = (float)Math.Sqrt(1.0f - (float)Math.Pow(2.0, 2.0f * cK - 2.0f)); float result = 255.0f * Normalize(p0 + p1 * p2 * dX * gauss * var); resultant[x][y] = (byte)result; } } } temp = null; } newImage = null; displacementTable = null; si = null; rnd = null; imageF = null; return resultant; } else { ByteImage image = new ByteImage(b); if(si.IsShrinking) { var _i = image.ReplicationScale(si.ResultWidth, si.ResultHeight); byte[][] target = new byte[_i.Width][]; for(int i = 0; i < _i.Width; i++) { byte[] q = new byte[_i.Height]; for(int j = 0; j < _i.Height; j++) target[i][j] = _i[i,j]; target[i] = q; } image = null; return target; } else return b; } //we create the new }
public override byte[][] Transform(Hashtable input) { //DateTime start = DateTime.Now; //reseed it if(input == null) return null; byte[][] b = (byte[][])input["image"]; int width = (int)input["width"]; int height = (int)input["height"]; //allowSawtooth = (bool)input["sawtooth"]; bool allowVariance = (bool)input["variance"]; bool allowGauss = (bool)input["gauss"]; ScaleInfo si = new ScaleInfo(b.Length, b[0].Length, width, height); if(si.IsZooming) { //compute k across the entire image int nWidth = si.ResultWidth; int nHeight = si.ResultHeight; //apply the original image values to the given points float w = si.WidthScalingFactor; float h = si.HeightScalingFactor; int w0 = (int)Math.Ceiling(w); int h0 = (int)Math.Ceiling(h); // int w0 = 1; // int h0 = 1; float?[][] newImage = new float?[nWidth][]; float[][] imageF = ToFloatTable(b); byte[][] resultant = new byte[si.ResultWidth][]; float[][] preComputedTable = new float[nWidth][]; int[] scaleX = new int[nWidth]; int[] scaleY = new int[nHeight]; float[] xDiv = new float[nWidth - 1]; Thread t = new Thread(() => UpdateDisplacementTable(b, imageF, preComputedTable, nWidth, nHeight, 4, allowGauss, allowVariance, w, h, scaleX, scaleY, xDiv)); for(int i = 0; i < nWidth; i++) { newImage[i] = new float?[nHeight]; resultant[i] = new byte[nHeight]; preComputedTable[i] = new float[nHeight]; scaleX[i] = (int)((float)i / w); } for(int i = 0; i < nWidth - 1; i++) xDiv[i] = (float)Math.Pow(scaleX[i] - scaleX[i + 1], 2.0f); for(int i = 0; i < nHeight; i++) scaleY[i] = (int)((float)i / h); t.Start(); for(int i = 0; i < nWidth - 3; i+=w0) { int x0 = scaleX[i]; int x1 = scaleX[i + 1]; float[] fx0 = imageF[x0]; float[] fx1 = imageF[x1]; float[] pctX = preComputedTable[i]; for(int j = 0; j < nHeight - 3; j+=h0) { int y0 = scaleY[j]; int y1 = scaleY[j + 1]; //order has been messed up for sometime //should go (x0,y0), (x0,y1), (x1,y1), (x1,y0) float f0 = fx0[y0]; float f1 = fx1[y0]; float f2 = fx1[y1]; float f3 = fx0[y1]; float k = pctX[j]; DivideGrid(resultant, newImage, i, j, w, h, f0, f1, f2, f3, k); } } newImage = null; si = null; imageF = null; //Console.WriteLine("Took {0} seconds", DateTime.Now - start); return resultant; } else { ByteImage image = new ByteImage(b); if(si.IsShrinking) { var _i = image.ReplicationScale(si.ResultWidth, si.ResultHeight); byte[][] target = new byte[_i.Width][]; for(int i = 0; i < _i.Width; i++) { byte[] q = new byte[_i.Height]; for(int j = 0; j < _i.Height; j++) target[i][j] = _i[i,j]; target[i] = q; } image = null; return target; } else return b; } }