private void TransformPerPixelBase(ImageBuffer target, IList <Point> path, Delegate transformAction, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(path, "path"); Guard.CheckNull(target, "target"); Guard.CheckNull(transformAction, "transformAction"); // updates the palette UpdatePalette(); target.UpdatePalette(); // checks the dimensions if (Width != target.Width || Height != target.Height) { const String message = "Both images have to have the same dimensions."; throw new ArgumentOutOfRangeException(message); } // determines mode Boolean isAdvanced = transformAction is TransformPixelAdvancedFunction; // process the image in a parallel manner Action <LineTask> transformPerPixel = lineTask => { // creates individual pixel structures per task Pixel sourcePixel = new Pixel(this); Pixel targetPixel = new Pixel(target); // enumerates the pixels row by row for (Int32 pathOffset = lineTask.StartOffset; pathOffset < lineTask.EndOffset; pathOffset++) { Point point = path[pathOffset]; Boolean allowWrite; // enumerates the pixel, and returns the control to the outside sourcePixel.Update(point.X, point.Y); targetPixel.Update(point.X, point.Y); // when read is allowed, retrieves current value (in bytes) if (CanRead) { ReadPixel(sourcePixel); } if (target.CanRead) { target.ReadPixel(targetPixel); } // process the pixel by custom user operation if (isAdvanced) { TransformPixelAdvancedFunction transformAdvancedFunction = (TransformPixelAdvancedFunction)transformAction; allowWrite = transformAdvancedFunction(sourcePixel, targetPixel, this, target); } else // use simplified version with pixel parameters only { TransformPixelFunction transformFunction = (TransformPixelFunction)transformAction; allowWrite = transformFunction(sourcePixel, targetPixel); } // when write is allowed, copies the value back to the row buffer if (target.CanWrite && allowWrite) { target.WritePixel(targetPixel); } } }; // transforms image per pixel ProcessInParallel(path, transformPerPixel, parallelTaskCount); }