/// <summary> /// Merges two images taking into consideration their alpha values. /// </summary> /// <param name="bmpBg">The background Image</param> /// <param name="bmpTop">The image that goes on top of the background</param> /// <param name="xBg">Left corner position of background</param> /// <param name="yBg">Top corner position of the background</param> /// <param name="xTop">Left corner position of the top image</param> /// <param name="yTop">Top corner position of the top image</param> /// <returns>Returns an interface to the image</returns> IImageAdapterUnmanaged IImageAdapterUnmanaged.Merge(IImageAdapterUnmanaged bmpBg, IImageAdapterUnmanaged bmpTop, int xBg, int yBg, int xTop, int yTop) { System.Diagnostics.Debug.WriteLine("Merge() started"); #if DEBUG ImageUtility.ToImageFile(bmpBg, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Before_Merge_Bg.png")); ImageUtility.ToImageFile(bmpTop, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Before_Merge_Top.png")); #endif // debug #if DEBUG ImageUtility.ToImageFile((IImageAdapter)bmpBg, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Merge_BgImage.bmp")); ImageUtility.ToImageFile((IImageAdapter)bmpTop, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Merge_TopImage.bmp")); #endif // DEBUG Rectangle rBg = new Rectangle(xBg, yBg, bmpBg.Width, bmpBg.Height); Rectangle rTop = new Rectangle(xTop, yTop, bmpTop.Width, bmpTop.Height); System.Diagnostics.Debug.WriteLine("Merge() \n\nrBg " + rBg.ToString() + "\nrTop " + rTop.ToString()); if (Rectangle.Intersect(rBg, rTop) != rTop) { throw new ArgumentOutOfRangeException("Top BMP must be inside Bg one"); } int maxAlpha = 0; float bgAlpha = 0; float topAlpha = 0; // Copy Color from background image into this (same as cloning bg image into 'this') ImageAdapter temp = new ImageAdapter((IImageAdapter)bmpBg); System.Diagnostics.Debug.WriteLine("Merge1() : Before the loop"); for (int x = rBg.Left; x < rBg.Right; x++) { for (int y = rBg.Top; y < rBg.Bottom; y++) { if (rTop.Contains(x, y)) { IColor colorBg = bmpBg[x - rBg.Left, y - rBg.Top]; IColor colorTop = bmpTop[x - rTop.Left, y - rTop.Top]; maxAlpha = Math.Max(colorBg.A, colorTop.A); topAlpha = (float)colorTop.Alpha; bgAlpha = (float)((1f - colorTop.Alpha) * colorBg.Alpha); IColor color = new ColorByte((byte)maxAlpha, (byte)(bgAlpha * colorBg.R + topAlpha * colorTop.R), (byte)(bgAlpha * colorBg.G + topAlpha * colorTop.G), (byte)(bgAlpha * colorBg.B + topAlpha * colorTop.B)); temp[x - rBg.Left, y - rBg.Top] = color; } } } #if DEBUG ImageUtility.ToImageFile(temp, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "After_Merge_This.png")); #endif return((IImageAdapterUnmanaged)temp); }
/// <summary> /// Multiply all the pixels with an alpha value. /// </summary> /// <param name="alpha">Alpha value(between 0 and 1)</param> /// <param name="image">BitmapResources to have Alpha applied on</param> /// <returns>Returns an interface to the image</returns> IImageAdapterUnmanaged IImageAdapterUnmanaged.ApplySingleAlpha( double alpha, IImageAdapterUnmanaged image) { #if DEBUG ImageUtility.ToImageFile(this, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Before_ApplyAlpha_this.png")); ImageUtility.ToImageFile(image, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Before_ApplyAlpha_image.png")); #endif if (alpha > 1.0 || alpha < 0.0) { throw new ArgumentOutOfRangeException("Alpha must be between 0.0 and 1.0 (this is percentage)"); } System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() started"); IColor argb = ColorByte.Empty; if ((ImageAdapter)this != (ImageAdapter)image) { System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() this != image"); System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() Before for-loop"); for (int x = 0; x < image.Width; x++) { for (int y = 0; y < image.Height; y++) { argb = (IColor)image[x, y].Clone(); argb.ExtendedAlpha *= alpha; this[x, y] = argb; } } System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() After for-loop"); } else { System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() this == image"); System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() Before for-loop"); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { this[x, y].ExtendedAlpha = this[x, y].ExtendedAlpha * alpha; } } System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() After for-loop"); } #if DEBUG ImageUtility.ToImageFile(this, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "After_ApplyAlpha_Result.png")); ImageUtility.ToImageFile(image, System.IO.Path.Combine(System.IO.Path.GetTempPath(), "After_ApplyAlpha_Operand.png")); #endif System.Diagnostics.Debug.WriteLine("ApplySingleAlpha() ended \n"); return((IImageAdapterUnmanaged)this); }
/// <summary> /// Serialize an IImageAdapterUnmananged /// </summary> /// <param name="fileName">The filename of the image to be saved</param> void IImageAdapterUnmanaged.Save( string fileName) { ImageUtility.ToImageFile(this, fileName); }
private void DoVscanCompare(object asyncData) { AsyncData data = asyncData as AsyncData; if (data == null) { throw new ArgumentException("Parameter passed in to the Method not of type AsyncData (or null)", "asyncData"); } ImageComparator ic = new ImageComparator(); ic.Curve.CurveTolerance.LoadTolerance(data.ToleranceSettings.XmlNodeTolerance); IImageAdapter masterAdapter = new ImageAdapter(data.MasterImage); IImageAdapter capturedAdapter = new ImageAdapter(data.CapturedImage); // compare Master to the Capture image using the Compare overload that will scale the images size accounting for the DPI data.Result.Succeeded = ic.Compare(masterAdapter, MetadataInfoHelper.GetDpi(masterAdapter), capturedAdapter, MetadataInfoHelper.GetDpi(capturedAdapter), false); if (data.Result.Succeeded == false) { Microsoft.Test.Logging.GlobalLog.LogStatus("Regular comparison failed"); } // On filaure, check if user whats to filter the image ( IgnoreAntiAliasing will do ) IImageAdapter masterFiltered = null; IImageAdapter captureFiltered = null; if (data.Result.Succeeded == false && data.ToleranceSettings.Filter != null) { // first save error diff image string errorDiffName = ".\\ErrorDiff_" + data.Index + IMAGE_EXTENSION; ImageUtility.ToImageFile(ic.GetErrorDifference(ErrorDifferenceType.IgnoreAlpha), errorDiffName); Microsoft.Test.Logging.GlobalLog.LogFile(errorDiffName); // Compare failed, filter the images and retry Microsoft.Test.Logging.GlobalLog.LogStatus("Filtering and recompare"); masterFiltered = data.ToleranceSettings.Filter.Process(masterAdapter); captureFiltered = data.ToleranceSettings.Filter.Process(capturedAdapter); data.Result.Succeeded = ic.Compare(masterFiltered, captureFiltered, false); if (data.Result.Succeeded == false) { Microsoft.Test.Logging.GlobalLog.LogStatus("==> Filtered comparison failed as well"); } } if (data.Result.Succeeded) { Microsoft.Test.Logging.GlobalLog.LogStatus("Comparison SUCCEEDED."); } else { // Save Masters * filtered master for easy analysis string masterName = ".\\Master_" + data.Index + IMAGE_EXTENSION; data.MasterImage.Save(masterName, System.Drawing.Imaging.ImageFormat.Tiff); Microsoft.Test.Logging.GlobalLog.LogFile(masterName); if (masterFiltered != null) { string filteredMasterName = ".\\MasterFiltered_" + data.Index + IMAGE_EXTENSION; using (Bitmap filteredMaster = ImageUtility.ToBitmap(masterFiltered)) { SetMetadataToImage(filteredMaster); filteredMaster.Save(filteredMasterName, System.Drawing.Imaging.ImageFormat.Tiff); } Microsoft.Test.Logging.GlobalLog.LogFile(filteredMasterName); } // Save rendered image (as "Actual_n") for easy analysis string capturedName = ".\\Actual_" + data.Index + IMAGE_EXTENSION; data.CapturedImage.Save(capturedName, System.Drawing.Imaging.ImageFormat.Tiff); Microsoft.Test.Logging.GlobalLog.LogFile(capturedName); // Save actual filtered for easy analysis if (captureFiltered != null) { string filteredRenderedName = ".\\ActualFiltered_" + data.Index + IMAGE_EXTENSION; using (Bitmap filteredRendered = ImageUtility.ToBitmap(captureFiltered)) { SetMetadataToImage(filteredRendered); filteredRendered.Save(filteredRenderedName, System.Drawing.Imaging.ImageFormat.Tiff); } Microsoft.Test.Logging.GlobalLog.LogFile(filteredRenderedName); } // Master might need to be updated, save with correct name and metadata // // In this image, encode full criteria string name = System.IO.Path.GetFileName(data.MasterName); string originalName = name.Replace(IMAGE_EXTENSION, "_FullCtriteria" + IMAGE_EXTENSION); Microsoft.Test.Logging.GlobalLog.LogStatus("Saving master with all criteria (new master) as '" + originalName + "'"); SetMetadataToImage(data.CapturedImage); data.CapturedImage.Save(originalName, System.Drawing.Imaging.ImageFormat.Tiff); Microsoft.Test.Logging.GlobalLog.LogFile(originalName); // // In this image, encode only criteria that match the master string originalNameFull = name.Replace(IMAGE_EXTENSION, "_MatchingCriteria" + IMAGE_EXTENSION); Microsoft.Test.Logging.GlobalLog.LogStatus("Saving master with matching criteria encoded (to replace previous master) as '" + originalNameFull + "'"); MasterMetadata metadata = ImageMetadata.MetadataFromImage(data.MasterImage); // Keep master Criteria but update its Description. IMasterDimension[] keys = new IMasterDimension[metadata.Description.Count]; metadata.Description.Keys.CopyTo(keys, 0); for (int t = 0; t < keys.Length; t++) { metadata.Description[keys[t]] = keys[t].GetCurrentValue(); } ImageMetadata.SetMetadataToImage(metadata, data.CapturedImage); data.CapturedImage.Save(originalNameFull, System.Drawing.Imaging.ImageFormat.Tiff); Microsoft.Test.Logging.GlobalLog.LogFile(originalNameFull); // first save error diff image string errorDiffFilterName = ".\\ErrorDiffFiltered_" + data.Index + IMAGE_EXTENSION; if (data.ToleranceSettings.Filter == null) { // Not filter were applied, change name (so it's not confusing) errorDiffFilterName = ".\\ErrorDiff_" + data.Index + IMAGE_EXTENSION; } ImageUtility.ToImageFile(ic.GetErrorDifference(ErrorDifferenceType.IgnoreAlpha), errorDiffFilterName); Microsoft.Test.Logging.GlobalLog.LogFile(errorDiffFilterName); } data.Result.IsCompleted = true; if (data.SynchronizationObject != null) { data.SynchronizationObject.Set(); } }