private void ProcessingAction(DelayedLineTask <ErrorDiffusionElement <Color, ColorComponentError>, int[]> delayedLineTask, int index) { // Get reference elements to work with var inputElement = delayedLineTask.Input[index]; var sourceColor = inputElement.Input; var error = inputElement.Error; // Add error component values to source color var errorDiffusedColor = Color.FromArgb( sourceColor.A, GetClampedValue(sourceColor.R + error.RedError, 0, 255), GetClampedValue(sourceColor.G + error.GreenError, 0, 255), GetClampedValue(sourceColor.B + error.BlueError, 0, 255)); // Quantize error diffused source color delayedLineTask.Output[index] = _quantizer.GetPaletteIndex(errorDiffusedColor); // Retrieve new quantized color for this point var targetColor = _quantizer.GetPalette()[delayedLineTask.Output[index]]; // Calculate errors to distribute for this point int redError = errorDiffusedColor.R - targetColor.R; int greenError = errorDiffusedColor.G - targetColor.G; int blueError = errorDiffusedColor.B - targetColor.B; // Retrieve point position var pixelX = index % _width; var pixelY = index / _width; // Process the matrix for (int shiftY = -MatrixSideHeight; shiftY <= MatrixSideHeight; shiftY++) { for (int shiftX = -MatrixSideWidth; shiftX <= MatrixSideWidth; shiftX++) { int targetX = pixelX + shiftX; int targetY = pixelY + shiftY; var coefficient = Matrix[shiftY + MatrixSideHeight, shiftX + MatrixSideWidth]; var errorFactor = ErrorFactorMatrix[shiftY + MatrixSideHeight, shiftX + MatrixSideWidth]; // If substantial error factor and target point in image bounds if (coefficient != 0 && targetX >= 0 && targetX < _width && targetY >= 0 && targetY < _height) { // Add error to target point for later processing var newTarget = delayedLineTask.Input[targetX + targetY * _width]; newTarget.Error.RedError += Convert.ToInt32(errorFactor * redError); newTarget.Error.GreenError += Convert.ToInt32(errorFactor * greenError); newTarget.Error.BlueError += Convert.ToInt32(errorFactor * blueError); } } } }
/// <summary> /// Processes a list in parallel with a given element threshold per line /// </summary> /// <typeparam name="TInput"></typeparam> /// <typeparam name="TOutput"></typeparam> /// <param name="inputList"></param> /// <param name="output"></param> /// <param name="lineLength"></param> /// <param name="threshold"></param> /// <param name="taskCount"></param> /// <param name="taskDelegate"></param> public static void ProcessList <TInput, TOutput>(TInput[] inputList, TOutput output, int lineLength, int threshold, int taskCount, Action <DelayedLineTask <TInput, TOutput>, int> taskDelegate) { if (inputList.Length % lineLength > 0) { throw new InvalidOperationException("Length of input list needs to be a multiple of lineLength."); } // create line tasks var count = inputList.Length / lineLength; var lineTasks = new DelayedLineTask <TInput, TOutput> [count]; DelayedLineTask <TInput, TOutput> preTask = null; for (int i = 0; i < count; i++) { var lineTask = new DelayedLineTask <TInput, TOutput>(inputList, output, i * lineLength, lineLength, threshold, preTask); lineTasks[i] = preTask = lineTask; } ProcessParallel(lineTasks, taskCount, taskDelegate); }