Пример #1
0
        internal string GetFullWindowDom(IPositionProvider positionProvider)
        {
            logger_.Verbose("enter");
            PositionMemento originalPosition = positionProvider.GetState();

            positionProvider.SetPosition(Point.Empty);
            Stopwatch stopwatch = Stopwatch.StartNew();
            string    domJson   = GetDom_();

            logger_.Verbose(nameof(GetDom_) + " took {0} ms", stopwatch.Elapsed.TotalMilliseconds);
            positionProvider.RestoreState(originalPosition);
            logger_.Verbose("exit");
            return(domJson);
        }
Пример #2
0
        private void MaximizeTargetFrameInCurrentFrame_(IWebElement frameElement, IWebElement userDefinedSRE)
        {
            IWebElement currentFrameSRE = EyesSeleniumUtils.GetCurrentFrameScrollRootElement(driver_, userDefinedSRE);

            IPositionProvider positionProvider = SeleniumEyes.GetPositionProviderForScrollRootElement_(logger_, driver_,
                                                                                                       stitchMode_, userAgent_, currentFrameSRE);

            Rectangle frameRect = EyesRemoteWebElement.GetClientBoundsWithoutBorders(frameElement, driver_, logger_);

            if (stitchMode_ == StitchModes.Scroll)
            {
                Point pageScrollPosition = positionProvider.GetCurrentPosition();
                frameRect.Offset(pageScrollPosition);
            }
            positionProvider.SetPosition(frameRect.Location);
        }
Пример #3
0
        public void MoveToRegion(IPositionProvider positionProvider, Location location)
        {
            Logger_.Verbose("Getting current position state..");
            OriginalPosition_ = positionProvider.GetState();
            Logger_.Verbose("Done! Setting position...");

            // We set the location to "almost" the location we were asked. This is because sometimes, moving the browser
            // to the specific pixel where the element begins, causes the element to be slightly out of the viewport.
            int dstX = location.X - VISIBILITY_OFFSET;

            dstX = dstX < 0 ? 0 : dstX;
            int dstY = location.Y - VISIBILITY_OFFSET;

            dstY = dstY < 0 ? 0 : dstY;
            positionProvider.SetPosition(new Point(dstX, dstY));

            Logger_.Verbose("Done!");
        }
        public override Bitmap GetImage()
        {
            logger_.Verbose("Getting current position...");
            Point  loc;
            double scaleRatio = eyes_.DevicePixelRatio;

            FrameChain        currentFrameChain = eyes_.GetDriver().GetFrameChain();
            IPositionProvider positionProvider  = null;

            if (currentFrameChain.Count == 0)
            {
                IWebElement scrollRootElement = eyes_.GetCurrentFrameScrollRootElement();
                positionProvider = eyes_.GetPositionProvider(logger_, StitchModes.Scroll,
                                                             jsExecutor_, scrollRootElement, userAgent_);
                loc = positionProvider.GetCurrentPosition();
            }
            else
            {
                loc = currentFrameChain.GetDefaultContentScrollPosition();
            }
            Point scaledLoc = new Point((int)Math.Round(loc.X * scaleRatio), (int)Math.Round(loc.Y * scaleRatio));

            Bitmap        image  = base.GetImage();
            EyesWebDriver driver = eyes_.GetDriver();
            RectangleSize originalViewportSize = EyesSeleniumUtils.GetViewportSize(logger_, driver);
            RectangleSize viewportSize         = originalViewportSize.Scale(scaleRatio);

            if (image.Height > viewportSize.Height || image.Width > viewportSize.Width)
            {
                //Damn IE driver returns full page screenshot even when not asked to!
                logger_.Verbose("seems IE returned full page screenshot rather than only the viewport.");
                eyes_.DebugScreenshotProvider.Save(image, "IE");
                if (!eyes_.IsCutProviderExplicitlySet)
                {
                    Bitmap croppedImage = BasicImageUtils.Crop(image, new Rectangle(scaledLoc, viewportSize));
                    image.Dispose();
                    image = croppedImage;
                }
            }

            positionProvider?.SetPosition(loc);
            return(image);
        }
Пример #5
0
        private void StitchScreenshot_(Size stitchOffset, IPositionProvider stitchProvider,
                                       ICollection <SubregionForStitching> screenshotParts, Bitmap stitchedImage, double scaleRatio,
                                       ICutProvider scaledCutProvider, float sizeRatio)
        {
            int index = 0;

            logger_.Verbose($"enter: {nameof(stitchOffset)}: {{0}} ; {nameof(screenshotParts)}.Count: {{1}}, {nameof(scaleRatio)}: {{2}}",
                            stitchOffset, screenshotParts.Count, scaleRatio);

            Stopwatch stopwatch = Stopwatch.StartNew();

            foreach (SubregionForStitching partRegion in screenshotParts)
            {
                if (stopwatch.Elapsed > TimeSpan.FromMinutes(5))
                {
                    logger_.Log("Still Running..."); // this is so CI systems won't kill the build due to lack of activity.
                    stopwatch.Restart();
                }

                logger_.Verbose("Part: {0}", partRegion);
                // Scroll to the part's top/left
                Point partAbsoluteLocationInCurrentFrame = partRegion.ScrollTo;
                partAbsoluteLocationInCurrentFrame += stitchOffset;
                Point scrollPosition = new Point(
                    (int)Math.Round(partAbsoluteLocationInCurrentFrame.X * sizeRatio),
                    (int)Math.Round(partAbsoluteLocationInCurrentFrame.Y * sizeRatio));
                Point originPosition = stitchProvider.SetPosition(scrollPosition);

                int dx = scrollPosition.X - originPosition.X;
                int dy = scrollPosition.Y - originPosition.Y;

                Point partPastePosition = partRegion.PasteLocation;
                //partPastePosition.Offset(-fullarea.Left, -fullarea.Top);
                partPastePosition.Offset(dx, dy);

                // Actually taking the screenshot.
                Thread.Sleep(waitBeforeScreenshots_);
                using (Bitmap partImage = imageProvider_.GetImage())
                    using (Bitmap cutPart = scaledCutProvider.Cut(partImage))
                    {
                        Bitmap    croppedPart;
                        Rectangle r = partRegion.PhysicalCropArea;

                        if ((r.Width * r.Height) != 0)
                        {
                            croppedPart = BasicImageUtils.Crop(cutPart, r);
                        }
                        else
                        {
                            croppedPart = cutPart;
                        }

                        Rectangle r2 = partRegion.LogicalCropArea;

                        using (Bitmap scaledPartImage = BasicImageUtils.ScaleImage(croppedPart, scaleRatio))
                            using (Bitmap scaledCroppedPartImage = BasicImageUtils.Crop(scaledPartImage, r2))
                                using (Graphics g = Graphics.FromImage(stitchedImage))
                                {
                                    debugScreenshotsProvider_.Save(partImage, "partImage-" + originPosition.X + "_" + originPosition.Y);
                                    debugScreenshotsProvider_.Save(cutPart, "cutPart-" + originPosition.X + "_" + originPosition.Y);
                                    debugScreenshotsProvider_.Save(croppedPart, "croppedPart-" + originPosition.X + "_" + originPosition.Y);
                                    debugScreenshotsProvider_.Save(scaledPartImage, "scaledPartImage-" + originPosition.X + "_" + originPosition.Y);
                                    debugScreenshotsProvider_.Save(scaledCroppedPartImage, "scaledCroppedPartImage-" + partPastePosition.X + "_" + partPastePosition.Y);
                                    logger_.Verbose("pasting part at {0}", partPastePosition);
                                    g.DrawImage(scaledCroppedPartImage, partPastePosition);
                                }
                        if (!object.ReferenceEquals(croppedPart, cutPart))
                        {
                            croppedPart.Dispose();
                        }
                        debugScreenshotsProvider_.Save(stitchedImage, $"stitched_{index}_({partPastePosition.X}_{partPastePosition.Y})");
                        index++;
                    }
            }

            debugScreenshotsProvider_.Save(stitchedImage, "stitched");
        }
Пример #6
0
        /// <summary>
        /// Encapsulates an algorithm for creating full-page images of a page.
        /// </summary>
        /// <param name="positionProvider">The position provider used for moving to the actual stitch points.</param>
        /// <param name="region">The region to stitch. If <see cref="Region.Empty"/>, the entire image will be stitched.</param>
        /// <param name="fullarea">The wanted area of the resulting image. If unknown, pass in <c>null</c> or <see cref="Region.Empty"/>.</param>
        /// <param name="originProvider">A position provider used for saving the state before
        /// starting the stitching, as well as moving to (0,0). The reason it is separated from
        /// the <c>stitchProvider</c>is that the stitchProvider might have side-effects
        /// (e.g., changing the CSS transform of the page can cause a layout change at the
        /// top of the page), which we can avoid for the first screenshot (since it might be a
        /// full page screenshot anyway).</param>
        /// <param name="stitchOffset"></param>
        /// <returns>The screenshot as Bitmap.</returns>
        public Bitmap GetStitchedRegion(Region region, Region fullarea, IPositionProvider positionProvider,
                                        IPositionProvider originProvider, Size stitchOffset)
        {
            ArgumentGuard.NotNull(region, nameof(region));
            ArgumentGuard.NotNull(positionProvider, nameof(positionProvider));

            logger_.Verbose("region: {0} ; fullarea: {1} ; positionProvider: {2}",
                            region, fullarea, positionProvider.GetType().Name);

            Point originalStitchedState = positionProvider.GetCurrentPosition();

            logger_.Verbose("region size: {0}, originalStitchedState: {1}", region, originalStitchedState);

            PositionMemento originProviderState = originProvider.GetState();

            logger_.Verbose("originProviderState: {0}", originProviderState);

            originProvider.SetPosition(Point.Empty);

            Thread.Sleep(waitBeforeScreenshots_);

            Bitmap initialScreenshot   = imageProvider_.GetImage();
            Size   initialPhysicalSize = initialScreenshot.Size;

            SaveDebugScreenshotPart_(initialScreenshot, region.ToRectangle(), "initial");

            IScaleProvider scaleProvider = scaleProviderFactory_.GetScaleProvider(initialScreenshot.Width);
            double         pixelRatio    = 1 / scaleProvider.ScaleRatio;

            Size initialSizeScaled = new Size((int)Math.Round(initialScreenshot.Width / pixelRatio), (int)Math.Round(initialScreenshot.Height / pixelRatio));

            ICutProvider scaledCutProvider = cutProvider_.Scale(pixelRatio);

            if (pixelRatio != 1 && !(scaledCutProvider is NullCutProvider))
            {
                initialScreenshot = cutProvider_.Cut(initialScreenshot);
                debugScreenshotsProvider_.Save(initialScreenshot, "original-cut");
            }

            Region regionInScreenshot       = GetRegionInScreenshot_(region, initialScreenshot, pixelRatio);
            Bitmap croppedInitialScreenshot = CropScreenshot_(initialScreenshot, regionInScreenshot);

            debugScreenshotsProvider_.Save(croppedInitialScreenshot, "cropped");

            Bitmap scaledInitialScreenshot = BasicImageUtils.ScaleImage(croppedInitialScreenshot, scaleProvider);

            if (!object.ReferenceEquals(scaledInitialScreenshot, croppedInitialScreenshot))
            {
                SaveDebugScreenshotPart_(scaledInitialScreenshot, regionInScreenshot.ToRectangle(), "scaled");
            }

            if (fullarea.IsEmpty)
            {
                Size entireSize;
                try
                {
                    entireSize = positionProvider.GetEntireSize();
                    logger_.Verbose("Entire size of region context: {0}", entireSize);
                }
                catch (EyesException e)
                {
                    logger_.Log("WARNING: Failed to extract entire size of region context" + e.Message);
                    logger_.Log("Using image size instead: " + scaledInitialScreenshot.Width + "x" + scaledInitialScreenshot.Height);
                    entireSize = new Size(scaledInitialScreenshot.Width, scaledInitialScreenshot.Height);
                }

                // Notice that this might still happen even if we used
                // "getImagePart", since "entirePageSize" might be that of a frame.
                if (scaledInitialScreenshot.Width >= entireSize.Width && scaledInitialScreenshot.Height >= entireSize.Height)
                {
                    logger_.Log("WARNING: Seems the image is already a full page screenshot.");
                    if (!object.ReferenceEquals(scaledInitialScreenshot, initialScreenshot))
                    {
                        initialScreenshot.Dispose();
                    }
                    return(scaledInitialScreenshot);
                }

                fullarea = new Region(Point.Empty, entireSize, CoordinatesTypeEnum.SCREENSHOT_AS_IS);
            }

            float currentFullWidth = fullarea.Width;

            fullarea = sizeAdjuster_.AdjustRegion(fullarea, initialSizeScaled);
            float sizeRatio = currentFullWidth / fullarea.Width;

            logger_.Verbose("adjusted fullarea: {0}", fullarea);

            Point scaledCropLocation = fullarea.Location;

            Point physicalCropLocation = new Point(
                (int)Math.Ceiling(scaledCropLocation.X * pixelRatio),
                (int)Math.Ceiling(scaledCropLocation.Y * pixelRatio));

            Rectangle sourceRegion;

            if (regionInScreenshot.IsSizeEmpty)
            {
                Size physicalCropSize = new Size(initialPhysicalSize.Width - physicalCropLocation.X, initialPhysicalSize.Height - physicalCropLocation.Y);
                sourceRegion = new Rectangle(physicalCropLocation, physicalCropSize);
            }
            else
            {
                // Starting with the screenshot we already captured at (0,0).
                sourceRegion = regionInScreenshot.ToRectangle();
            }

            Rectangle scaledCroppedSourceRect = cutProvider_.ToRectangle(sourceRegion.Size);

            scaledCroppedSourceRect.Offset(sourceRegion.Location);
            Rectangle scaledCroppedSourceRegion = new Rectangle(
                (int)Math.Ceiling(scaledCroppedSourceRect.X / pixelRatio),
                (int)Math.Ceiling(scaledCroppedSourceRect.Y / pixelRatio),
                (int)Math.Ceiling(scaledCroppedSourceRect.Width / pixelRatio),
                (int)Math.Ceiling(scaledCroppedSourceRect.Height / pixelRatio));

            Size scaledCropSize = scaledCroppedSourceRegion.Size;

            // The screenshot part is a bit smaller than the screenshot size, in order to eliminate
            // duplicate bottom/right-side scroll bars, as well as fixed position footers.
            Size screenshotPartSize = new Size(
                Math.Max(scaledCropSize.Width, MinScreenshotPartSize_),
                Math.Max(scaledCropSize.Height, MinScreenshotPartSize_)
                );

            logger_.Verbose("Screenshot part size: {0}", screenshotPartSize);

            // Getting the list of viewport regions composing the page (we'll take screenshot for each one).
            Rectangle rectInScreenshot;

            if (regionInScreenshot.IsSizeEmpty)
            {
                int x = Math.Max(0, fullarea.Left);
                int y = Math.Max(0, fullarea.Top);
                int w = Math.Min(fullarea.Width, scaledCropSize.Width);
                int h = Math.Min(fullarea.Height, scaledCropSize.Height);
                rectInScreenshot = new Rectangle(
                    (int)Math.Round(x * pixelRatio),
                    (int)Math.Round(y * pixelRatio),
                    (int)Math.Round(w * pixelRatio),
                    (int)Math.Round(h * pixelRatio));
            }
            else
            {
                rectInScreenshot = regionInScreenshot.Rectangle;
            }

            fullarea = CoerceImageSize_(fullarea);

            ICollection <SubregionForStitching> screenshotParts = fullarea.GetSubRegions(screenshotPartSize, stitchOverlap_, pixelRatio, rectInScreenshot, logger_);

            Bitmap stitchedImage = new Bitmap(fullarea.Width, fullarea.Height);

            // Take screenshot and stitch for each screenshot part.
            StitchScreenshot_(stitchOffset, positionProvider, screenshotParts, stitchedImage, scaleProvider.ScaleRatio, scaledCutProvider, sizeRatio);

            positionProvider.SetPosition(originalStitchedState);
            originProvider.RestoreState(originProviderState);

            croppedInitialScreenshot.Dispose();
            return(stitchedImage);
        }