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);
                    }
                }
            }
        }
Пример #2
0
        /// <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);
        }