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 }); } } }