如何捕捉Photoshop的文档区域
how to capture the document area of Photoshop
我正在编写一个程序,我需要捕获下图中的红色区域:
问题是无论 photoshop window 有多大,它都应该捕捉那个部分,所以我不能硬编码坐标。
我也尝试了 inspect 和 FlaUInspect,它们都可以在该区域和完整 window 区域之间切换,还有 automationId 并且名称是动态的。
因为 ClassName 是 Photoshop,所以我用 flaui 尝试了下面的 c# 代码,但没有用:
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using FlaUI.UIA3;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Process[] AllProcesslist = Process.GetProcesses();
foreach (Process Proc in AllProcesslist)
{
if (!String.IsNullOrEmpty(Proc.MainWindowTitle) && Proc.MainModule.FileName == @"D:\photoshop\Adobe Photoshop CC 2015\Photoshop.exe")
{
Console.WriteLine("Window Found!");
var app = new FlaUI.Core.Application(Proc);
using (var automation = new UIA3Automation())
{
var window = app.GetMainWindow(automation);
Bitmap image = window.FindFirstDescendant(cf => cf.ByClassName("Photoshop")).Capture();
image.Save("sample.jpg", ImageFormat.Jpeg);
}
}
}
Console.Read();
}
}
}
我的程序是用 electron 编写的,但是如果你知道如何用任何编程语言来实现,我可以很容易地在我的 electron 程序中实现它。
photoshop 没有 ui 自动化框架,flaui 和 inspect.exe 不适用于 photoshop,所以我使用捕获方法获取 photoshop 的屏幕截图 window 然后裁剪它。
这是最终代码:
using FlaUI.UIA3;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Control
{
class Photoshop
{
public static int processId;
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int processId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public Point ptMinPosition;
public Point ptMaxPosition;
public Rectangle rcNormalPosition;
}
// take a screenshot of the document
public async Task<object> screen(int handle)
{
Bitmap final = null;
GetWindowThreadProcessId((IntPtr)handle, out processId);
Process Proc = Process.GetProcessById(processId);
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
GetWindowPlacement((IntPtr)Proc.MainWindowHandle, ref placement);
var app = new FlaUI.Core.Application(Proc);
var automation = new UIA3Automation();
Bitmap capture = app.GetMainWindow(automation).Capture();
if (placement.showCmd == 1) // 1- normal, 3- maximize
{
final = documentArea(capture);
}
else
{
Bitmap crop = cropImage(capture, new Rectangle(8, 8, capture.Width - 16, capture.Height - 16));
final = documentArea(crop);
}
return ImgtoBase64(final);
}
public static Bitmap documentArea(Bitmap b)
{
int x = 45;
int y = 87;
Rectangle area = new Rectangle(x, y, b.Width - x, b.Height - y);
return cropImage(b, area);
}
public static Bitmap cropImage(Bitmap b, Rectangle r)
{
Bitmap nb = new Bitmap(r.Width, r.Height);
using (Graphics g = Graphics.FromImage(nb))
{
g.DrawImage(b, -r.X, -r.Y);
return nb;
}
}
public static string ImgtoBase64(Bitmap img)
{
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Png);
byte[] byteImage = ms.ToArray();
return Convert.ToBase64String(byteImage);
}
}
}
我正在编写一个程序,我需要捕获下图中的红色区域:
问题是无论 photoshop window 有多大,它都应该捕捉那个部分,所以我不能硬编码坐标。
我也尝试了 inspect 和 FlaUInspect,它们都可以在该区域和完整 window 区域之间切换,还有 automationId 并且名称是动态的。
因为 ClassName 是 Photoshop,所以我用 flaui 尝试了下面的 c# 代码,但没有用:
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using FlaUI.UIA3;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Process[] AllProcesslist = Process.GetProcesses();
foreach (Process Proc in AllProcesslist)
{
if (!String.IsNullOrEmpty(Proc.MainWindowTitle) && Proc.MainModule.FileName == @"D:\photoshop\Adobe Photoshop CC 2015\Photoshop.exe")
{
Console.WriteLine("Window Found!");
var app = new FlaUI.Core.Application(Proc);
using (var automation = new UIA3Automation())
{
var window = app.GetMainWindow(automation);
Bitmap image = window.FindFirstDescendant(cf => cf.ByClassName("Photoshop")).Capture();
image.Save("sample.jpg", ImageFormat.Jpeg);
}
}
}
Console.Read();
}
}
}
我的程序是用 electron 编写的,但是如果你知道如何用任何编程语言来实现,我可以很容易地在我的 electron 程序中实现它。
photoshop 没有 ui 自动化框架,flaui 和 inspect.exe 不适用于 photoshop,所以我使用捕获方法获取 photoshop 的屏幕截图 window 然后裁剪它。
这是最终代码:
using FlaUI.UIA3;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Control
{
class Photoshop
{
public static int processId;
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int processId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public Point ptMinPosition;
public Point ptMaxPosition;
public Rectangle rcNormalPosition;
}
// take a screenshot of the document
public async Task<object> screen(int handle)
{
Bitmap final = null;
GetWindowThreadProcessId((IntPtr)handle, out processId);
Process Proc = Process.GetProcessById(processId);
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
GetWindowPlacement((IntPtr)Proc.MainWindowHandle, ref placement);
var app = new FlaUI.Core.Application(Proc);
var automation = new UIA3Automation();
Bitmap capture = app.GetMainWindow(automation).Capture();
if (placement.showCmd == 1) // 1- normal, 3- maximize
{
final = documentArea(capture);
}
else
{
Bitmap crop = cropImage(capture, new Rectangle(8, 8, capture.Width - 16, capture.Height - 16));
final = documentArea(crop);
}
return ImgtoBase64(final);
}
public static Bitmap documentArea(Bitmap b)
{
int x = 45;
int y = 87;
Rectangle area = new Rectangle(x, y, b.Width - x, b.Height - y);
return cropImage(b, area);
}
public static Bitmap cropImage(Bitmap b, Rectangle r)
{
Bitmap nb = new Bitmap(r.Width, r.Height);
using (Graphics g = Graphics.FromImage(nb))
{
g.DrawImage(b, -r.X, -r.Y);
return nb;
}
}
public static string ImgtoBase64(Bitmap img)
{
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Png);
byte[] byteImage = ms.ToArray();
return Convert.ToBase64String(byteImage);
}
}
}