Beispiel #1
0
        private void StretchForDifferentDpi(IntPtr hwnd, int width, int height, Image masterImage)
        {
            Size offset = new Size(masterImage.Width - width, masterImage.Height - height);

            //The original application of this method assumes that a master image was captured on a machine
            //set to 96dpi and scales the window size appropriately.  However, if a master was actually captured on a
            //machine that is set to a dpi other than 96, we want to provide the option not to automatically scale the Window.
            if (_resizeWindowForDpi)
            {
                IMasterDimension currentDpi = MasterMetadata.GetDimension("DpiDimension");
                int standardDpi             = 96;
                if (currentDpi.GetCurrentValue() != standardDpi.ToString())
                {
                    int dpi = int.Parse(currentDpi.GetCurrentValue());

                    float ratio = (float)dpi / standardDpi;
                    offset.Width  = (int)(masterImage.Width * ratio - width + .5);
                    offset.Height = (int)(masterImage.Height * ratio - height + .5);
                }
            }

            if (offset.IsEmpty)
            {
                return;
            }

            ResizeWindow(hwnd, offset.Width, offset.Height, true);
        }
Beispiel #2
0
        private void SetMetadataToImage(Image image)
        {
            MasterMetadata metadata = ImageMetadata.MetadataFromImage(image);

            metadata._criteria.Clear();
            metadata._criteria.AddRange(_masterIndex.GetCurrentCriteriaValue().Keys);
            ImageMetadata.SetMetadataToImage(metadata, image);
        }
Beispiel #3
0
        private AsyncData CommonCompare(IntPtr hwnd, System.Drawing.Rectangle rect, ManualResetEvent resetEvent)
        {
            _counter++;

            Bitmap masterImage = _masterIndex.Resolve();
            string masterName  = string.Empty;

            if (masterImage != null)
            {
                masterName = _masterIndex.ResolvedMasterName;
                Microsoft.Test.Logging.GlobalLog.LogStatus("Picking master '" + masterName + "'");
            }
            else
            {
                Microsoft.Test.Logging.GlobalLog.LogStatus("No Matching master found !");
            }

            if (_stabilizeWindowBeforeCapture)
            {
                StabilizeWindow(hwnd, masterImage);
            }

            Bitmap actualImage;

            if (rect != System.Drawing.Rectangle.Empty)
            {
                actualImage = SnapshotRect(rect);
            }
            else
            {
                actualImage = SnapshotWindow(hwnd);
            }

            if (masterImage == null)
            {
                Microsoft.Test.Logging.GlobalLog.LogStatus("Encoding information in new master");

                MasterMetadata metadata = ImageMetadata.MetadataFromImage(actualImage);
                metadata._criteria.Clear();
                metadata._criteria.AddRange(_masterIndex.GetCurrentCriteriaValue().Keys);
                ImageMetadata.SetMetadataToImage(metadata, actualImage);

                // Save rendered as actual
                string actualName = ".\\Actual_" + _counter + IMAGE_EXTENSION;
                actualImage.Save(actualName, System.Drawing.Imaging.ImageFormat.Tiff);
                Microsoft.Test.Logging.GlobalLog.LogFile(actualName);

                // Save render with new name already set
                actualName = _masterIndex.GetNewMasterName();
                Microsoft.Test.Logging.GlobalLog.LogStatus("Saving master as '" + System.IO.Path.GetFileName(actualName) + "'");
                actualImage.Save(actualName, System.Drawing.Imaging.ImageFormat.Tiff);
                Microsoft.Test.Logging.GlobalLog.LogFile(actualName);
            }

            return(new AsyncData(masterImage, masterName, actualImage, resetEvent, _toleranceSettings, _counter));
        }
Beispiel #4
0
        /// <summary>
        /// Set the metadata OSinfo into an image
        /// </summary>
        /// <param name="metadata"></param>
        /// <param name="image"></param>
        public static void SetMetadataToImage(MasterMetadata metadata, Image image)
        {
            // Serialize Description and Criteria into an Xml node and put into image metadata
            using (System.IO.MemoryStream metadataStream = new System.IO.MemoryStream())
            {
                XmlWriterSettings writerSettings = new XmlWriterSettings();
                writerSettings.Encoding = System.Text.ASCIIEncoding.UTF8;
                using (XmlWriter writer = XmlWriter.Create(metadataStream, writerSettings))
                {
                    writer.WriteStartElement("MasterMetadata");
                    foreach (KeyValuePair <IMasterDimension, string> keyValue in metadata.Description)
                    {
                        writer.WriteStartElement("Description");
                        writer.WriteStartElement("Dim");
                        writer.WriteAttributeString("name", keyValue.Key.GetType().Name);
                        writer.WriteAttributeString("value", keyValue.Value);
                        writer.WriteEndElement(); // </Dim>
                        writer.WriteEndElement(); // </Description>
                    }
                    foreach (KeyValuePair <IMasterDimension, string> keyValue in metadata.Criteria)
                    {
                        writer.WriteStartElement("Criteria");
                        writer.WriteStartElement("Index");
                        writer.WriteAttributeString("name", keyValue.Key.GetType().Name);
                        writer.WriteEndElement(); // </Index>
                        writer.WriteEndElement(); // </Criteria>
                    }
                    writer.WriteEndElement();     // </MasterMetadata>;
                }

                // Workaround Win7 Bug 687567: GDI+ : 1.1 expects NULL terminated string when
                //  the PropertyItem type is PropertyTagTypeASCII in SetPropertyItem, while 1.0 always append NULL terminator
                UTF8Encoding utf8Encoding   = new UTF8Encoding();
                byte[]       nullTerminator = utf8Encoding.GetBytes(new char[] { '\0' });
                metadataStream.WriteByte(nullTerminator[0]);

                metadataStream.Position = 0;

                // Build PropertyItem and save serialized info into it.
                PropertyItem pi = CreatePropertyItem();
                pi.Id    = EXIF_IMAGEINFO;
                pi.Value = metadataStream.GetBuffer();
                pi.Len   = pi.Value.Length;
                pi.Type  = 2;
                image.SetPropertyItem(pi);
            }

            // Encode XP Keyword & description into image
            image.SetPropertyItem(BuildUserFriendlyTag(EXIF_XP_KEYWORD, metadata.Criteria));
            image.SetPropertyItem(BuildUserFriendlyTag(EXIF_XP_DESCRIPTION, metadata.Description));

            // Add Vista Comments and Tag (Description and Keyword counterpart to XP)
            image.SetPropertyItem(AddVistaInfo(metadata));
        }
Beispiel #5
0
        /// <summary>
        /// Retrieve the OSinfo stored in the image
        /// </summary>
        /// <param name="image">The image to parse</param>
        /// <returns>returne a MasterMetadata object containing the description and criteria</returns>
        public static MasterMetadata MetadataFromImage(Image image)
        {
            MasterMetadata retVal = new MasterMetadata();

            // Check if the image contains criteria & description
            List <int> idList = new List <int>();

            idList.AddRange(image.PropertyIdList);
            if (idList.Contains(EXIF_IMAGEINFO))
            {
                // Deserialize Description and Criteria from the image metadata (saved as xmlNode)

                PropertyItem pi = image.GetPropertyItem(EXIF_IMAGEINFO);

                // Remove trailing '\0' since it messes up deserialization
                string serializedInfo = System.Text.UTF8Encoding.UTF8.GetString(pi.Value);
                System.IO.MemoryStream memoryStream   = new System.IO.MemoryStream(System.Text.UTF8Encoding.UTF8.GetBytes(serializedInfo.Trim('\0')));
                XmlReaderSettings      readerSettings = new XmlReaderSettings();
                memoryStream.Position = 0;
                XmlReader reader = XmlReader.Create(memoryStream, readerSettings);
                while (reader.Read())
                {
                    string dim   = string.Empty;
                    string val   = string.Empty;
                    string index = string.Empty;

                    if (reader.Name == "Dim")
                    {
                        dim = reader["name"];
                        val = reader["value"];
                        retVal.Description[MasterMetadata.GetDimension(dim)] = val;
                    }
                    if (reader.Name == "Index")
                    {
                        index = reader["name"];
                        retVal._criteria.Add(MasterMetadata.GetDimension(index));
                    }
                }
            }

            return(retVal);
        }
Beispiel #6
0
        private static PropertyItem AddVistaInfo(MasterMetadata metadata)
        {
            PropertyItem retVal = CreatePropertyItem();

            retVal.Id   = EXIF_VISTA_INFO;
            retVal.Type = 1;

            List <string> keywords = new List <string>();

            if (metadata.Criteria != null)
            {
                foreach (KeyValuePair <IMasterDimension, string> criteriaKeyPair in metadata.Criteria)
                {
                    string keywordTag = KEYWORD_TAG.Replace(KEYWORD, criteriaKeyPair.Key.GetType().Name + "=" + criteriaKeyPair.Value);
                    keywords.Add(keywordTag);
                }
            }

            string descriptions = string.Empty;

            if (metadata.Description != null)
            {
                foreach (KeyValuePair <IMasterDimension, string> descKeyPair in metadata.Description)
                {
                    descriptions += descKeyPair.Key.GetType().Name + "=" + descKeyPair.Value + " / ";
                }
            }

            string xmpString = XMP_STRING;

            xmpString    = xmpString.Replace(KEYWORD_TAGS, string.Join("", keywords.ToArray()));
            xmpString    = xmpString.Replace(DESCRIPTIONS, descriptions);
            retVal.Value = System.Text.UTF8Encoding.UTF8.GetBytes(xmpString);
            retVal.Len   = retVal.Value.Length;
            return(retVal);
        }
Beispiel #7
0
        internal Bitmap Resolve()
        {
            _resolvedMasterName = string.Empty;
            if (System.IO.Directory.Exists(_path) == false)
            {
                return(null);
            }

            // Get the current Dimensions (and its the values) for what the user cares about
            Dictionary <IMasterDimension, string> expectedDimensions = GetCurrentCriteriaValue();


            // Get all masters with for this testcase
            string[] files = System.IO.Directory.GetFiles(_path, FileName);

            // Loop thru all potential masters
            int[] matchingScores = new int[files.Length];
            for (int fileIndex = 0; fileIndex < files.Length; fileIndex++)
            {
                matchingScores[fileIndex] = 0;

                MasterMetadata masterMetadata = null;
                using (Image img = new Bitmap(files[fileIndex]))
                {
                    // Retrieve Image metadata (Description and Criteria) for each master
                    masterMetadata = ImageMetadata.MetadataFromImage(img);
                }

                // Check that every master dimensions are required by the user
                foreach (KeyValuePair <IMasterDimension, string> masterDim in masterMetadata.Criteria)
                {
                    if (expectedDimensions.ContainsKey(masterDim.Key) == false)
                    {
                        // User did not specfy this Dimension
                        matchingScores[fileIndex] = -1;
                        break;
                    }
                    if (expectedDimensions[masterDim.Key].ToLowerInvariant() != masterDim.Value.ToLowerInvariant())
                    {
                        // Dimension specified by user but this machine is not the right value.
                        matchingScores[fileIndex] = -1;
                        break;
                    }
                    matchingScores[fileIndex] += _weightedCriteria[masterDim.Key];
                }
            }

            // Find the best master
            int bestMatchIndex = -1;
            int bestScore      = -1;

            for (int t = 0; t < matchingScores.Length; t++)
            {
                if (matchingScores[t] > bestScore)
                {
                    bestScore      = matchingScores[t];
                    bestMatchIndex = t;
                }
            }

            if (bestMatchIndex == -1)
            {
                return(null);
            }

            _resolvedMasterName = files[bestMatchIndex];
            return(new Bitmap(files[bestMatchIndex]));
        }
Beispiel #8
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();
            }
        }