Example #1
0
        /// <summary>
        /// Places one image on top of the other. The top image should fit within the bottom
        /// image. The top image completely cover the bottom image.
        /// </summary>
        /// <param name="bmpTop"></param>
        /// <param name="xstart">The x value of the point in the bottom image at which the left
        /// hand top corner of the top image is placed</param>
        /// <param name="ystart">The y value of the point in the bottom image at which the left
        /// hand top corner of the top image is placed</param>
        /// <returns>Returns an interface to the image</returns>
        IImageAdapterUnmanaged IImageAdapterUnmanaged.Overlay(
            IImageAdapterUnmanaged bmpTop,
            int xstart,
            int ystart)
        {
            System.Diagnostics.Debug.WriteLine("Overlay() started");

            Rectangle rBg  = new Rectangle(0, 0, this.Width, this.Height);
            Rectangle rTop = new Rectangle(xstart, ystart, bmpTop.Width, bmpTop.Height);

            System.Diagnostics.Debug.WriteLine("Overlay() \n\nrBg " + rBg.ToString() + "\nrTop " + rTop.ToString());
            if (Rectangle.Intersect(rBg, rTop) != rTop)
            {
                throw new ArgumentOutOfRangeException("Top BMP must be inside Bg one");
            }

            // Copy Color from background image into this (same as cloning bg image into 'this')
            ImageAdapter temp = new ImageAdapter((IImageAdapter)this);

            System.Diagnostics.Debug.WriteLine("Overlay() : 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 colorTop = bmpTop[x - rTop.Left, y - rTop.Top];
                        temp[x, y] = colorTop;
                    }
                }
            }
            return((IImageAdapterUnmanaged)temp);
        }
Example #2
0
        /// <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);
        }
Example #3
0
 /// <summary>
 /// Get the machineInfo associated with this imageAdapter
 /// </summary>
 /// <param name="imageAdapter"></param>
 /// <returns></returns>
 static public string GetMachineInfo(ImageAdapter imageAdapter)
 {
     if (imageAdapter == null)
     {
         throw new ArgumentNullException("imageAdapter", "Cannot pass a null argument");
     }
     if (imageAdapter.Metadata == null)
     {
         return(string.Empty);
     }
     return(GetMachineInfo(imageAdapter.Metadata));
 }
Example #4
0
        /// <summary>
        /// Clips the image at the RECT specified
        /// </summary>
        /// <param name="left">The left side of the RECT</param>
        /// <param name="top">The top side of the RECT</param>
        /// <param name="right">The right side of the RECT</param>
        /// <param name="bottom">The bottom side of the RECT</param>
        /// <returns>Returns an interface to the image</returns>
        IImageAdapterUnmanaged IImageAdapterUnmanaged.Clip(
            int left,
            int top,
            int right,
            int bottom)
        {
            System.Diagnostics.Debug.WriteLine("Clip() started");

            Rectangle rBg  = new Rectangle(0, 0, this.Width, this.Height);
            Rectangle rTop = new Rectangle(left, top, right - left, bottom - top);

            System.Diagnostics.Debug.WriteLine("Clip() rBg " + rBg.ToString() + "\nrTop " + rTop.ToString());
            Rectangle intersection = Rectangle.Intersect(rBg, rTop);

            System.Diagnostics.Debug.WriteLine("\n\rClip() Intersection " + intersection.ToString());
            if (intersection != rTop)
            {
                System.Diagnostics.Debug.WriteLine("Clip area is not perfectly within the image\n");
            }

            if (intersection.Width > 0 && intersection.Height > 0)
            {
                ImageAdapter temp = new ImageAdapter(intersection.Width, intersection.Height, (ColorByte)Color.Black);

                System.Diagnostics.Debug.WriteLine("Clip() : Before the loop");
                for (int x = intersection.Left; x < intersection.Right; x++)
                {
                    for (int y = intersection.Top; y < intersection.Bottom; y++)
                    {
                        IColor colorTop = this[x, y];
                        temp[x - rTop.Left, y - rTop.Top] = colorTop;
                    }
                }
                return((IImageAdapterUnmanaged)temp);
            }
            else
            {
                throw new ArgumentOutOfRangeException("Width or Height of the Image are negetive\n\r");
            }
        }
Example #5
0
        /// <summary>
        /// Equalize the image on all channels
        /// </summary>
        /// <param name="imageAdapter">The image to equalize</param>
        /// <returns>The Equalized image</returns>
        internal static IImageAdapter EqualizeImage(IImageAdapter imageAdapter)
        {
            // Check params
            if (imageAdapter == null)
            {
                throw new ArgumentNullException("imageAdapter", "Argument cannot be null");
            }

            IImageAdapter retVal = new ImageAdapter(imageAdapter.Width, imageAdapter.Height);

            int[]     sum       = new int[] { 0, 0, 0, 0 };
            Hashtable dico      = BuildHistogram(imageAdapter);
            Hashtable equalized = new Hashtable();

            for (int channel = 1; channel < intColor.Length; channel++)  // Ignore Alpha Channel
            {
                ArrayList[] list = new ArrayList[256];
                for (int index = 0; index < 256; index++)
                {
                    list[index] = new ArrayList();
                }

                equalized.Add(intColor[channel], list);
            }
            equalized[ALPHA] = ((ArrayList[])dico[ALPHA]).Clone();  // Clone Alpha channel from original Histogram

            // compute the sum per channel
            for (int channel = 0; channel < intColor.Length; channel++)
            {
                ArrayList[] array = (ArrayList[])dico[intColor[channel]];
                for (int index = 0; index < 256; index++)
                {
                    sum[channel] += array[index].Count;
                }
            }

            // Stretch and Normalize the histogram
            // Transformation used :
            //    (min <= i <= max)
            //    Normalize :   0.5 + ( Sum(0,i-1) + ( Sum(i-1,i) / 2 ) ) * 255 / Sum(0,255)
            for (int channel = 1; channel < intColor.Length; channel++) // Ignore Alpha channel
            {
                ArrayList[] channelOriginal  = (ArrayList[])dico[intColor[channel]];
                ArrayList[] channelEqualized = (ArrayList[])equalized[intColor[channel]];
                float       equalizeConstant = 255.0f / ((sum[channel] != 0) ? sum[channel] : 1);
                int         currentSum       = 0;
                float       equalize         = 0f;
                for (int index = 0; index < 256; index++)
                {
                    equalize    = 0.5f + (currentSum + channelOriginal[index].Count / 2) * equalizeConstant;
                    currentSum += channelOriginal[index].Count;
                    channelEqualized[(int)equalize].AddRange(channelOriginal[index]);
                }
            }


            retVal = HistogramToIImageAdapter(equalized, imageAdapter);

            equalized.Clear();
            dico.Clear();

            return(retVal);
        }
Example #6
0
        /// <summary>
        /// Contrast an image by Streching the Histogram associated with this image
        /// </summary>
        /// <param name="imageAdapter">the image to contrast</param>
        /// <returns>The contrasted image</returns>
        internal static IImageAdapter ContrastStretch(IImageAdapter imageAdapter)
        {
            // Check Params
            if (imageAdapter == null)
            {
                throw new ArgumentNullException("imageAdapter", "Argument cannot be null");
            }
            IImageAdapter retVal = new ImageAdapter(imageAdapter.Width, imageAdapter.Height);
            IColor        color  = imageAdapter[0, 0];

            int[]     min       = new int[] { (int)color.MinChannelValue, (int)color.MinChannelValue, (int)color.MinChannelValue, (int)color.MinChannelValue };
            int[]     max       = new int[] { (int)color.MaxChannelValue, (int)color.MaxChannelValue, (int)color.MaxChannelValue, (int)color.MaxChannelValue };
            Hashtable dico      = BuildHistogram(imageAdapter);
            Hashtable stretched = new Hashtable();

            for (int channel = 1; channel < intColor.Length; channel++)  // channel = 1 to Ignore Alpha Channel
            {
                ArrayList[] list = new ArrayList[256];
                for (int index = 0; index < 256; index++)
                {
                    list[index] = new ArrayList();
                }
                stretched.Add(intColor[channel], list);
            }
            stretched[ALPHA] = ((ArrayList[])dico[ALPHA]).Clone();      // Clone Alpha channel from original Histogram


            // Find the min and max value of the histogram
            for (int channel = 1; channel < intColor.Length; channel++) // ignore the alpha channel
            {
                bool        minFound = false;
                ArrayList[] array    = (ArrayList[])dico[intColor[channel]];

                for (int index = 0; index < 256; index++)
                {
                    if (array[index].Count != 0)
                    {
//                      sum[channel] += array[index].Count;
                        max[channel] = index;
                        minFound     = true;
                    }
                    else
                    {
                        if (!minFound)
                        {
                            min[channel] = index;
                        }
                    }
                }
            }

            // Stretch the histogram
            // Transformation used :
            //    (min <= i <= max)
            //    Stretch   :   (i - min) * 255 / ( max - min) + 0.5
            for (int channel = 1; channel < intColor.Length; channel++) // Ignore the Alpha Channel
            {
                ArrayList[] channelOriginal  = (ArrayList[])dico[intColor[channel]];
                ArrayList[] channelStretched = (ArrayList[])stretched[intColor[channel]];
                int         minChannel       = min[channel];
                int         maxChannel       = max[channel];
                float       stretchConstant  = 255.0f / (float)(maxChannel - minChannel);
                float       stretch          = 0f;

                for (int index = minChannel; index <= maxChannel; index++)
                {
                    stretch = (index - minChannel) * stretchConstant + 0.5f;
                    channelStretched[(int)stretch].AddRange(channelOriginal[index]);
                }
            }

            retVal = HistogramToIImageAdapter(stretched, imageAdapter);

            dico.Clear();
            stretched.Clear();

            return(retVal);
        }
Example #7
0
        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();
            }
        }