using System; using System.Collections.Generic; using System.Linq; using System.Drawing; using System.Drawing.Imaging; using System.IO; using Microsoft.Concurrency.TestTools.UnitTesting; namespace FaceReplace { // NOTE: Since this data structure is 32-bits long, we don't need to worry about padding a scan line. /// /// Extension methods for the FastBitmap class. /// public class FastBitmapExamples { public const string TestFaceImagePath = @"M:\School\UofU\PPCP\SVN\hwk\TermProject\JamImplementation\images\faces\Bill Clinton.jpg"; public const string TestFaceImageRegion = "93, 82, 166, 228"; public const string TestFacesImagePath = @"M:\School\UofU\PPCP\SVN\hwk\TermProject\JamImplementation\images\targets\Supreme Court US 2009 - big.jpg"; public const string TestFacesImageRegion1 = "840, 584, 129, 159"; public const string TestFacesImageRegion2 = "2380, 565, 124, 175"; [UnitTestMethod] [TestArgs(TestFaceImagePath, TestFaceImageRegion)] public void AlpagaBug_ParamWithNoConverterFound(string filePath, Rectangle region) { // This test causes an exception in Alpaca because it can't find a type converter. } [UnitTestMethod] [TestArgs(TestFaceImagePath, TestFaceImageRegion)] public void Example_CreateAndAutoDisposeFastBitmap(string filePath, string sregion) { Rectangle region = (Rectangle)System.ComponentModel.TypeDescriptor.GetConverter(typeof(Rectangle)).ConvertFromString(sregion); using (var fastBitmap = new FastBitmap(filePath, region)) { // TODO: Use the fast bitmap } // The compiler will handle the fastBitmap.Dispose here because of the using block } [UnitTestMethod] [TestArgs(TestFaceImagePath, TestFaceImageRegion)] public void Example_CreateAndManualDisposeFastBitmap(string filePath, string sregion) { Rectangle region = (Rectangle)System.ComponentModel.TypeDescriptor.GetConverter(typeof(Rectangle)).ConvertFromString(sregion); var fastBitmap = new FastBitmap(filePath, region); // This try/finally is the same semantics of the using statement in C# try { // TODO: Use the fast bitmap } finally { // Be sure to always dispose of the FastBitmap resource. fastBitmap.Dispose(); } } [UnitTestMethod] [TestArgs(TestFaceImagePath, TestFaceImageRegion)] public void Example_IterateThruEachPixelInActiveRegion(string filePath, string sregion) { Rectangle region = (Rectangle)System.ComponentModel.TypeDescriptor.GetConverter(typeof(Rectangle)).ConvertFromString(sregion); using (var fastBitmap = new FastBitmap(filePath, region)) { Color avgColor = ComputeAverageColor(fastBitmap); Console.WriteLine("Average Color: {0}", avgColor); } } private static Color ComputeAverageColor(FastBitmap fastBitmap) { int regionWidth = fastBitmap.ActiveImageRegion.Width; long sumR = 0; long sumG = 0; long sumB = 0; unsafe { for (int y = fastBitmap.ActiveImageRegion.Y; y < fastBitmap.ActiveImageRegion.Bottom; y++) { // Need to get a fresh pointer for each row, in case PixelData // isn't a 4byte structure. This has to deal with how locking bits // on a bitmap works and how the scan lines are structured. PixelData* pxPtr = fastBitmap.GetInitialPixelForRow(y); // NOTE: I'm also incrementing the row ptr in the for loop for (int i = 0; i < regionWidth; i++, pxPtr++) { // TODO: Do work with the pixel data // This will make a copy, be sure you want the overhead. //PixelData px = *pxPtr; // This will just use the data, w/o the overhead of the copy. sumR += (int)pxPtr->R; sumG += (int)pxPtr->G; sumB += (int)pxPtr->B; } } } int pxCnt = fastBitmap.ActiveImageRegion.Width * fastBitmap.ActiveImageRegion.Height; return Color.FromArgb( (int)(sumR / pxCnt), (int)(sumG / pxCnt), (int)(sumB / pxCnt) ); } [UnitTestMethod] [TestArgs(TestFacesImagePath, TestFacesImageRegion1, TestFacesImageRegion2)] public void Example_ChangeActiveRegion(string filePath, string sregion1, string sregion2) { Rectangle region1 = (Rectangle)System.ComponentModel.TypeDescriptor.GetConverter(typeof(Rectangle)).ConvertFromString(sregion1); Rectangle region2 = (Rectangle)System.ComponentModel.TypeDescriptor.GetConverter(typeof(Rectangle)).ConvertFromString(sregion2); // Lets initialize the fastBitmap to the full image using (var fastBitmap = new FastBitmap(filePath, region1)) { Console.WriteLine("Region1: {0}", region1); Color avgColor = ComputeAverageColor(fastBitmap); Console.WriteLine(" Average Color: {0}", avgColor); // Change the active region to our region fastBitmap.ChangeActiveImageRegion(region2); Console.WriteLine("Region2: {0}", region2); avgColor = ComputeAverageColor(fastBitmap); Console.WriteLine(" Average Color: {0}", avgColor); } } } }