//Apply SVD on each small piece of the bitmap public Image SVD_Fraction(Bitmap bmp, int newRank, ref double RootMeanSquareError) { int bestRank = (bmp.Height * bmp.Width) / (1 + bmp.Height + bmp.Width); if (newRank > bestRank) return bmp; int FactorRank = (int)Math.Round(BMP_FRAC_SIZE * ((double)newRank / bestRank)); MatrixFromBitmap(ref bmp); int numx = bmp.Width / BMP_FRAC_SIZE; int numy = bmp.Height / BMP_FRAC_SIZE; MMatrix[] C = new MMatrix[numx]; MMatrix tmpMat = new MMatrix(BMP_FRAC_SIZE, BMP_FRAC_SIZE); int FromRow, ToRow; MMatrix Red = new MMatrix(MRed); for (int k = 0; k < numx; ++k) { FromRow = k * BMP_FRAC_SIZE; ToRow = (k + 1) * BMP_FRAC_SIZE; tmpMat.Copy(Red, FromRow, ToRow, 0, BMP_FRAC_SIZE); SVD(ref tmpMat, FactorRank); C[k] = tmpMat; for (int m = 1; m < numy; ++m) { tmpMat.Copy(Red, FromRow, ToRow, m * BMP_FRAC_SIZE, (m + 1) * BMP_FRAC_SIZE); SVD(ref tmpMat, FactorRank); C[k] = MMatrix.Concat_Horizontal(C[k], tmpMat); } } for (int k = 1; k < numx; ++k) C[0] = MMatrix.Concat_Vertical(C[0], C[k]); MRed = FloorToBitmap(C[0].MArray); RootMeanSquareError = MMatrix.RootMeanSquareError(new MMatrix(MRed), C[0]); return BitmapFromMatrix(ref MRed, ref MGreen, ref MBlue); }