private Bitmap CreateMozaic(int tiles, string imagesDBPath) { int count = 0; int pixels = Img.Width / tiles; int cols = tiles; int rows = Img.Height / pixels; int mozaicWidth = cols * Db.ImagesSize; int mozaicHeight = rows * Db.ImagesSize; byte[,,] mozaic = new byte[mozaicWidth, mozaicHeight, 3]; int numOfThreads = Environment.ProcessorCount - 2; numOfThreads = numOfThreads < 2 ? 2 : numOfThreads; var options = new ParallelOptions() { MaxDegreeOfParallelism = numOfThreads }; Parallel.For(0, rows, options, j => { var rng = new Random(); for (int i = 0; i < cols; i++) { Bitmap fragment; lock (_lockResources) { count++; double dprogress = (count / (double)(cols * rows)) * 100.0; ProgressChanged?.Invoke(this, new ProgressChangedEventHandler((int)dprogress)); fragment = Img.Clone(new Rectangle(i * pixels, j * pixels, pixels, pixels), PixelFormat.Format32bppRgb); } ImageItem bestImage = FindBest(fragment, rng); var bestImagePath = Path.Combine(imagesDBPath, bestImage.Filename); Bitmap bestImageBMP = (Bitmap)Image.FromFile(bestImagePath); bestImageBMP = Processing.ChangePixelFormat(bestImageBMP, PixelFormat.Format32bppRgb); //bestImageBMP = AdjustColor(bestImageBMP, fragment, bestImage); byte[,,] bestImageArr = Processing.BitmapToRGBArray(bestImageBMP); bestImageBMP.Dispose(); fragment.Dispose(); lock (_lockResources2) { Processing.PasteArray(ref mozaic, bestImageArr, i * Db.ImagesSize, j * Db.ImagesSize); } } }); return(Processing.RGBArrayToBitmap(mozaic)); }