예제 #1
0
        private static void Verify(SimpleMemory memory, SimpleMemory referenceMemory)
        {
            var mismatches = new List <HardwareExecutionResultMismatchException.Mismatch>();

            for (int i = 0; i < memory.CellCount && i < referenceMemory.CellCount; i++)
            {
                if (!memory.Read4Bytes(i).SequenceEqual(referenceMemory.Read4Bytes(i)))
                {
                    mismatches.Add(new HardwareExecutionResultMismatchException.Mismatch(
                                       i, memory.Read4Bytes(i), referenceMemory.Read4Bytes(i)));
                }
            }

            if (mismatches.Count > 0)
            {
                Console.WriteLine("MISMATCH:");
                Console.WriteLine(new HardwareExecutionResultMismatchException(mismatches));
            }
            if (memory.CellCount != referenceMemory.CellCount)
            {
                Console.WriteLine("MISMATCH IN LENGTH:{0}Hardware: {1}{0}Software: {2}",
                                  Environment.NewLine, memory.CellCount, referenceMemory.CellCount);
            }
            else if (mismatches.Count == 0)
            {
                Console.WriteLine("Verification passed!");
            }
        }
        /// <summary>
        /// Creates an image from a <see cref="SimpleMemory"/> instance.
        /// </summary>
        /// <param name="memory">The <see cref="SimpleMemory"/> instance.</param>
        /// <param name="image">The original image.</param>
        /// <returns>Returns the processed image.</returns>
        private Bitmap CreateImage(SimpleMemory memory, Bitmap image)
        {
            var newImage = new Bitmap(image);

            for (int x = 0; x < newImage.Height; x++)
            {
                for (int y = 0; y < newImage.Width; y++)
                {
                    var bytes = memory.Read4Bytes(x * newImage.Width + y + ChangeContrast_ImageStartIndex);
                    newImage.SetPixel(y, x, Color.FromArgb(bytes[0], bytes[1], bytes[2]));
                }
            }

            return(newImage);
        }
        /// <summary>
        /// Changes the contrast of an image.
        /// </summary>
        /// <param name="memory">The <see cref="SimpleMemory"/> object representing the accessible memory space.</param>
        public virtual void ChangeContrast(SimpleMemory memory)
        {
            var imageWidth    = (ushort)memory.ReadUInt32(ChangeContrast_ImageWidthIndex);
            var imageHeight   = (ushort)memory.ReadUInt32(ChangeContrast_ImageHeightIndex);
            int contrastValue = memory.ReadInt32(ChangeContrast_ContrastValueIndex);

            if (contrastValue > 100)
            {
                contrastValue = 100;
            }
            else if (contrastValue < -100)
            {
                contrastValue = -100;
            }

            contrastValue = (100 + contrastValue * Multiplier) / 100;

            var tasks = new Task <PixelProcessingTaskOutput> [MaxDegreeOfParallelism];

            // Since we only need to compute the loop condition's right side once, not on each loop execution, it's an
            // optimization to put it in a separate variable. This way it's indeed computed only once.
            var pixelCount = imageHeight * imageWidth;
            var stepCount  = pixelCount / MaxDegreeOfParallelism;

            if (pixelCount % MaxDegreeOfParallelism != 0)
            {
                // This will take care of the rest of the pixels. This is wasteful as on the last step not all Tasks
                // will work on something but it's a way to keep the number of Tasks constant.
                stepCount += 1;
            }

            for (int i = 0; i < stepCount; i++)
            {
                for (int t = 0; t < MaxDegreeOfParallelism; t++)
                {
                    var pixelBytes = memory.Read4Bytes(i * MaxDegreeOfParallelism + t + ChangeContrast_ImageStartIndex);

                    // Using an input class to also pass contrastValue because it's currently not supported to access
                    // variables from the parent scope from inside Tasks (you need to explicitly pass in all inputs).
                    // Using an output class to pass the pixel values back because returning an array from Tasks is not
                    // supported at the time either.
                    tasks[t] = Task.Factory.StartNew(
                        inputObject =>
                    {
                        var input = (PixelProcessingTaskInput)inputObject;

                        return(new PixelProcessingTaskOutput
                        {
                            R = ChangePixelValue(input.PixelBytes[0], input.ContrastValue),
                            G = ChangePixelValue(input.PixelBytes[1], input.ContrastValue),
                            B = ChangePixelValue(input.PixelBytes[2], input.ContrastValue)
                        });
                    },
                        new PixelProcessingTaskInput {
                        PixelBytes = pixelBytes, ContrastValue = contrastValue
                    });
                }

                Task.WhenAll(tasks).Wait();

                for (int t = 0; t < MaxDegreeOfParallelism; t++)
                {
                    // It's no problem that we write just 3 bytes to a 4-byte slot.
                    memory.Write4Bytes(
                        i * MaxDegreeOfParallelism + t + ChangeContrast_ImageStartIndex,
                        new[] { tasks[t].Result.R, tasks[t].Result.G, tasks[t].Result.B });
                }
            }
        }