/// <summary> /// Move a sliding window and apply the filter by using its BottomUp() method. /// </summary> protected override void bottomUp() { System.Collections.Concurrent.ConcurrentStack <IONode> filterClones = new ConcurrentStack <IONode>(); int stepsWidth = (int)(input.Width / stepSize.X); int stepsHeight = (int)(input.Height / stepSize.Y); int totalIterations = stepsWidth * stepsHeight; for (int i = 0; i < totalIterations; i++) { IONode clone = ObjectCopier.Clone(filter); filterClones.Push(clone); } System.Collections.Concurrent.ConcurrentStack <IONode> filterClonesUsed = new ConcurrentStack <IONode>(); //We pass all components of the input signal Parallel.For(0, stepsWidth, stepX => { int xI = stepX * (int)stepSize.X; Parallel.For(0, stepsHeight, stepY => { int yI = stepY * (int)stepSize.Y; //Clone the filter IONode clone; while (!filterClones.TryPop(out clone)) { ; } //We construct the filter input based on its dimensions for (int xF = 0; xF < clone.input.Width; xF++) { for (int yF = 0; yF < clone.input.Height; yF++) { int x = xI - clone.input.Width / 2 + xF; int y = yI - clone.input.Height / 2 + yF; x = Math.Min(input.Width - 1, Math.Max(x, 0)); y = Math.Min(input.Height - 1, Math.Max(y, 0)); clone.input.reality[xF, yF] = input.reality[x, y]; } } //We apply the clone clone.BottomUp(); //We copy the result of the clone to the output for (int xF = 0; xF < clone.output.Width; xF++) { for (int yF = 0; yF < clone.output.Height; yF++) { output.prediction[(int)(xI / stepSize.X) * clone.output.Width + xF, (int)(yI / stepSize.Y) * clone.output.Height + yF] = clone.output.prediction[xF, yF]; } } filterClonesUsed.Push(clone); }); }); if (filter is IONodeAdaptive) { IEnumerable <IONodeAdaptive> casted = filterClonesUsed.Cast <IONodeAdaptive>(); (filter as IONodeAdaptive).fuse(casted); } }