C#裁剪图片return坐标错误
C# Cropping image return wrong coordinates
几天来,我一直在尝试使用 Selenium 和不同的裁剪方法来裁剪特定图像。
我的代码之前的重要说明 - 以下方法在 2 周前有效,但由于某种原因现在有效 returns 坐标错误的图像
// Go to site
Driver.Navigate().GoToUrl("http://google.com");
Screenshot screenshot = driver.GetScreenshot();
using (var ms = new MemoryStream(screenshot.AsByteArray))
using (var imgShot = Image.FromStream(ms))
using (var src = new Bitmap(imgShot))
{
IWebElement element = driver.FindElement(By.XPath("//canvas"));
Rectangle cropRect = new Rectangle(element.Location.X, element.Location.Y, element.Size.Width, element.Size.Height);
var clone = src.Clone(cropRect, src.PixelFormat);
clone.Save(filePath);
}
我尝试过的事情:
1) 我通常为此目的使用 Firefox 驱动程序,我尝试改用 ChromeDriver 并得到相同的结果。
2) 我使用以下控制台命令检查了元素的坐标:$0.getBoundingClientRect() 并且我在代码中得到的位置与它匹配。
3) 我尝试了 4 种不同的裁剪方法,包括这个:
IWebElement element = Driver.FindElement(By.XPath("//canvas"));
string filename = @"C:\Users\User\Desktop\test.png";
Screenshot screenshot = Driver.GetScreenshot();
screenshot.SaveAsFile(filename, ImageFormat.Png);
Rectangle cropRect = new Rectangle(element.Location.X, element.Location.Y,
element.Size.Width, element.Size.Height);
using (Image imgShot = Image.FromFile(filename))
using (Bitmap original = new Bitmap(imgShot))
using (Bitmap target = new Bitmap(original, new Size(cropRect.Width, cropRect.Height)))
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(original, new Rectangle(0, 0, target.Width, target.Height),
cropRect,
GraphicsUnit.Pixel);
target.Save(@"C:\Users\User\Desktop\test1.png", ImageFormat.Png);
}
需要说明的是,我得到的图像是完全空白的。在不同的网站上,我得到的图像不是空白的,所以我可以看出它只是在错误的坐标中。
4) 我尝试了不同的网站和不同的元素,但它们都在错误的坐标中。
5) 我尝试 Google 它并发现许多不同的方法都不起作用。然而,这个 answer 说了一些关于分辨率的事情,这是我最好的猜测。我尝试同时使用原始分辨率和目标分辨率,但没有发现任何区别。在创建 Graphics 变量之前或之后调用了设置分辨率方法,并且仍然是零变化。
有趣的是,它曾经在 2 周前工作,但我从未更改过代码...
您得到一张空白图像可能是因为调用 GetScreenshot
时该区域尚未渲染。
试试看是不是这样:
Thread.Sleep(3000);
Screenshot screenshot = ((ITakesScreenshot)element).GetScreenshot();
这也可能是由于页面中的实施阻止了网络抓取,在这种情况下,如果不深入研究代码,您将无能为力。
请注意,您不应使用 element.Location
,因为它 returns 是相对于文档而非视口的坐标。
如果驱动程序支持,您还应该考虑直接在 IWebElement
上调用 GetScreenshot
。
这是一个捕获页脚的工作示例:
var options = new ChromeOptions();
options.AddArgument("disable-infobars");
var driver = new ChromeDriver(options);
driver.Url = "https://whosebug.com/questions";
IWebElement element = driver.FindElement(By.CssSelector("#footer"));
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), @"screenshot.png");
try {
Thread.Sleep(500);
Screenshot screenshot = ((ITakesScreenshot)element).GetScreenshot();
screenshot.SaveAsFile(filePath, ScreenshotImageFormat.Png);
}
catch (WebDriverException) {
var result = ((IJavaScriptExecutor)driver).ExecuteScript(
"var elm = arguments[0];" +
"elm.scrollIntoView(true);" +
"var rect = elm.getBoundingClientRect();" +
"return [rect.left, rect.top, rect.width, rect.height];"
, element);
int[] pts = Array.ConvertAll(((IReadOnlyCollection<object>)result).ToArray(), Convert.ToInt32);
var rect = new Rectangle(pts[0], pts[1], pts[2], pts[3]);
Screenshot screenshot = ((ITakesScreenshot)driver).GetScreenshot();
using (var mstream = new MemoryStream(screenshot.AsByteArray))
using (var bitmap = (Bitmap)Image.FromStream(mstream, false, false)) {
rect.Intersect(new Rectangle(0, 0, bitmap.Width, bitmap.Height));
if (rect.IsEmpty)
throw new ArgumentOutOfRangeException("Cropping rectangle is out of range.");
var clone = bitmap.Clone(rect, bitmap.PixelFormat);
clone.Save(filePath);
}
}
很明显,2 周前实际更改的不是我的代码,而是我机器上安装的 Firefox 版本。当前版本 - v52,return 元素坐标错误。
卸载它并重新安装以前的版本 - v47 解决了这个问题
几天来,我一直在尝试使用 Selenium 和不同的裁剪方法来裁剪特定图像。
我的代码之前的重要说明 - 以下方法在 2 周前有效,但由于某种原因现在有效 returns 坐标错误的图像
// Go to site
Driver.Navigate().GoToUrl("http://google.com");
Screenshot screenshot = driver.GetScreenshot();
using (var ms = new MemoryStream(screenshot.AsByteArray))
using (var imgShot = Image.FromStream(ms))
using (var src = new Bitmap(imgShot))
{
IWebElement element = driver.FindElement(By.XPath("//canvas"));
Rectangle cropRect = new Rectangle(element.Location.X, element.Location.Y, element.Size.Width, element.Size.Height);
var clone = src.Clone(cropRect, src.PixelFormat);
clone.Save(filePath);
}
我尝试过的事情:
1) 我通常为此目的使用 Firefox 驱动程序,我尝试改用 ChromeDriver 并得到相同的结果。
2) 我使用以下控制台命令检查了元素的坐标:$0.getBoundingClientRect() 并且我在代码中得到的位置与它匹配。
3) 我尝试了 4 种不同的裁剪方法,包括这个:
IWebElement element = Driver.FindElement(By.XPath("//canvas"));
string filename = @"C:\Users\User\Desktop\test.png";
Screenshot screenshot = Driver.GetScreenshot();
screenshot.SaveAsFile(filename, ImageFormat.Png);
Rectangle cropRect = new Rectangle(element.Location.X, element.Location.Y,
element.Size.Width, element.Size.Height);
using (Image imgShot = Image.FromFile(filename))
using (Bitmap original = new Bitmap(imgShot))
using (Bitmap target = new Bitmap(original, new Size(cropRect.Width, cropRect.Height)))
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(original, new Rectangle(0, 0, target.Width, target.Height),
cropRect,
GraphicsUnit.Pixel);
target.Save(@"C:\Users\User\Desktop\test1.png", ImageFormat.Png);
}
需要说明的是,我得到的图像是完全空白的。在不同的网站上,我得到的图像不是空白的,所以我可以看出它只是在错误的坐标中。
4) 我尝试了不同的网站和不同的元素,但它们都在错误的坐标中。
5) 我尝试 Google 它并发现许多不同的方法都不起作用。然而,这个 answer 说了一些关于分辨率的事情,这是我最好的猜测。我尝试同时使用原始分辨率和目标分辨率,但没有发现任何区别。在创建 Graphics 变量之前或之后调用了设置分辨率方法,并且仍然是零变化。
有趣的是,它曾经在 2 周前工作,但我从未更改过代码...
您得到一张空白图像可能是因为调用 GetScreenshot
时该区域尚未渲染。
试试看是不是这样:
Thread.Sleep(3000);
Screenshot screenshot = ((ITakesScreenshot)element).GetScreenshot();
这也可能是由于页面中的实施阻止了网络抓取,在这种情况下,如果不深入研究代码,您将无能为力。
请注意,您不应使用 element.Location
,因为它 returns 是相对于文档而非视口的坐标。
如果驱动程序支持,您还应该考虑直接在 IWebElement
上调用 GetScreenshot
。
这是一个捕获页脚的工作示例:
var options = new ChromeOptions();
options.AddArgument("disable-infobars");
var driver = new ChromeDriver(options);
driver.Url = "https://whosebug.com/questions";
IWebElement element = driver.FindElement(By.CssSelector("#footer"));
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), @"screenshot.png");
try {
Thread.Sleep(500);
Screenshot screenshot = ((ITakesScreenshot)element).GetScreenshot();
screenshot.SaveAsFile(filePath, ScreenshotImageFormat.Png);
}
catch (WebDriverException) {
var result = ((IJavaScriptExecutor)driver).ExecuteScript(
"var elm = arguments[0];" +
"elm.scrollIntoView(true);" +
"var rect = elm.getBoundingClientRect();" +
"return [rect.left, rect.top, rect.width, rect.height];"
, element);
int[] pts = Array.ConvertAll(((IReadOnlyCollection<object>)result).ToArray(), Convert.ToInt32);
var rect = new Rectangle(pts[0], pts[1], pts[2], pts[3]);
Screenshot screenshot = ((ITakesScreenshot)driver).GetScreenshot();
using (var mstream = new MemoryStream(screenshot.AsByteArray))
using (var bitmap = (Bitmap)Image.FromStream(mstream, false, false)) {
rect.Intersect(new Rectangle(0, 0, bitmap.Width, bitmap.Height));
if (rect.IsEmpty)
throw new ArgumentOutOfRangeException("Cropping rectangle is out of range.");
var clone = bitmap.Clone(rect, bitmap.PixelFormat);
clone.Save(filePath);
}
}
很明显,2 周前实际更改的不是我的代码,而是我机器上安装的 Firefox 版本。当前版本 - v52,return 元素坐标错误。 卸载它并重新安装以前的版本 - v47 解决了这个问题