图像操作API

图像操作API用于在执行中操作API,及自动化结果的验证,主要通过Image对象。此外虚拟控件也有相应的方法,根据图片实现判断。

Image对象

Image对象用于获得图片的属性信息,及针对图片的比较操作。

Image对象定义如下:

    class Image {
        width: number;
        height: number;

        clip(rect: {x: number, y: number, width: number, height: number}): Image;
        drawImage(image: Image, x: number, y: number): Image;
        getData(option?: {encoding: 'base64' | null}): Promise<Buffer | string>;

        static fromData(bufferOrString: Buffer | string): Promise<Image>;
        static fromFile(filePath: string): Promise<Image>;

        static imageEqual(image1: Buffer | string | Image,
            image2: Buffer | string | Image, 
            options?: CompareOptions,
            compareInfo?: ImageCompareInfo): Promise<boolean>;
        static imageCompare(image1: Buffer | string | Image,
            image2: Buffer | string | Image, 
            options?: CompareOptions): Promise<ImageCompareResult>
    }

获得一个Image对象的实例可以得到图片的属性,或将图片用于后继处理。

可以从Buffer、base64的字符串,或者一个文件路径生成Image实例,例如:

   const { Image } = require('leanpro.visual');
   const fs = require('fs');
   (async function() {
       let buf1 = fs.readFileSync('c:/temp/image1.png');
       let image1 = await Image.fromData(buf1);
       console.log(image1.width, image1.height);

       let image2 = await Image.fromFile('c:/temp/image2.png');
       console.log(image2.width, image2.height);
   })()

上面例子分别从Buffer和文件中读取图片数据并打印宽度和高度。

注意:无法直接通过new Image()创建对象,需要通过fromData或者fromFile生成Image实例。另外Image对象现只支持PNG格式的图片。

实例成员:

  • clip 用于剪切图片,返回另一个图片。传入矩形框,按照矩形框剪切图片,如果传入数据不合法导致剪切的图片宽度或高度为0,返回为null;
  • drawImage 用于将两幅绘制图片绘制到一幅图片上。返回为新绘制的图片。

    例如:

     this.screen1 = await model.getButton("Five").takeScreenshot();
     this.screen2 = await model.getButton("Six").takeScreenshot();
     let image1 = await Image.fromData(this.screen1);
     let image2 = await Image.fromData(this.screen2);
    
     image1 = image1.clip({ x: 10, y: 10, width: image1.width - 20, height: image1.height - 20 })
     image2 = image2.clip({ x: 10, y: 10, width: image2.width - 20, height: image2.height - 20  })
    
     let combinedImage = image1.drawImage(image2, image1.width + 5, 0);
    

    上面代码将两个按钮截屏剪切掉10像素的周围边缘,然后绘制到一张图片上,中间间隔5个像素。

    如果你想让两幅图片上下排列,你可以使用类似下面的代码:

    let combinedImage = image1.drawImage(image2, 0, image1.height + 5);
    

    您还可以使用为负值的x,y,以便第二个图像在第一个图像的另一侧绘制,例如,以下语句将在左侧绘制image2,在右侧绘制image1:

    let combinedImage = image1.drawImage(image2, -(image1.width + 5), 0);
    
  • getData返回图片的内容数据,可用于保存至文件,或添加到报表中。注意它返回的是Promise,所以在async函数中需要加await。

图片比较操作

在自动化过程中,为了验证结果的正确性,可以通过验证结果图片和期望图片的差异来判断执行结果是否正确。

图片判断主要有两种方式:

  • 比较图片差异,返回布尔值。
  • 将两幅图对应像素相减,产生结果图片,将差异点用色彩标出来,结果图片显示在报表中,可以由人工判断是否正确。

Image对象的imageEqual和imageCompare分别针对上面两种对比方式。

由于操作系统、分辨率、颜色设置都可能影响图片的显示,同样的控件在不同的环境设置下可能显示不同,所以在比较截屏图片时,一般会设置比较容忍度。在容忍度阈值内认为两幅图片是相同的。容忍度有如下的分类:

  • 颜色容忍度:针对两幅图片的两个对应像素点,如果它们的RGB颜色按照特定的距离算法在一定的范围内认为是相同的。
  • 像素容忍度:针对两幅图整体而言,如果不同的像素点数量在一定的范围内,则认为两幅图是相同的。像素容忍度还可以根据百分比来设定,即不同的点占图片所有像素的百分比。

  • imageEqual

    imageEqual用来比较两幅图片的差异,返回布尔值的Promise,如果是true表示相同,false表示不同。如果您只想知道两个图像是否不同,请使用此API。 如果您想知道获取显示差异所在位置的结果图像,请使用另一个API imageCompare

    它的函数签名:

      imageEqual(image1: Buffer | string | Image,
                  image2: Buffer | string | Image, 
                  options?: CompareOptions,
                  compareInfo?: ImageCompareInfo): Promise<boolean>;
    
    • image1、image2可以是Buffer、base64的字符串,或者一个Image实例。
    • options用来指定图片比较的参数,它有如下的参数设置:

      interface CompareOptions {
              colorTolerance?: number,        //default to 0.1
              pixelNumberTolerance?: number,  //no default value
              pixelPercentTolerance?: number, //default 1, means 1% 
              ignoreExtraPart?: boolean       //default to false
          }
      

      其中:

      • colorTolerance:颜色容忍度,缺省为0.1。一般不用修改。
      • pixelNumberTolerance:像素数量容忍度,没有缺省值。
      • pixelPercentTolerance:像素百分比容忍度,缺省为1,即1%。例如,两幅图片分别有10000像素,如果允许少于150个像素不同的情况下认为图片相同,则设置为1.5。
      • ignoreExtraPart:是否忽略非重叠部分,缺省为false。两幅比较图片可以是不同尺寸,比较时左上角对齐,超出部分会当成是不同的点。如果设成true,则会忽略超出部分。

      当pixelNumberTolerance和pixelPercentTolerance有一个超出了设定值(或缺省值)比较就会返回false。如果只需要使用其中一个设定,可以将另一个设定设为比较大的值。例如只需要pixelNumberTolerance,并忽略pixelPercentTolerance,可以把pixelPercentTolerance设成100。

    • 除了返回值表示是否相同外,有时需要知道详细的信息,例如像素尺寸,有多少点不同,不同的点的百分比等,这时可以通过传出compareInfo对象获得相关信息。

      compareInfo的类型:

      interface ImageCompareInfo {
              image1: {
                  width: number,
                  height: number
              },
              image2: {
                  width: number,
                  height: number
              }
              diffPixels: number,
              diffPercentage: number
          }
      

      使用时,如果compareInfo传入一个空的对象,调用imageEqual后compareInfo会填充如上结构的数据。

      下面是调用样例:

      (async function() {
          try {
              let pngSource = await Image.fromFile(__dirname + '/../source.png');
              let pngTargt = await Image.fromFile(__dirname + '/../target.png');
      
              let compareInfo = {};
              let isEqual = await Image.imageEqual(pngSource, pngTargt, 
                  {pixelNumberTolerance: 300, ignoreExtraPart: true}, compareInfo);
              console.log('isEqual', isEqual, JSON.stringify(compareInfo, null, 2));
          } catch(err) {
              console.log(err)
          }
      
      })()
      

      执行时它传入两个图片,比较是否相同,同时会忽略没有重叠部分。如果不同的像素点超过300个,则返回false,同时它返回了compareInfo的详细数据。打印的内容如下:

          isEqual false {
          "image1": {
              "width": 375,
              "height": 266
          },
          "image2": {
              "width": 402,
              "height": 224
          },
          "diffPixels": 3502,
          "diffPercentage": 3.3100814760203408
          }
      

  • imageCompare

    impageCompare,比较两者图片,返回详细信息的数据,特别是两幅图片差异部分的图片。如果您想获得显示差异所在位置的结果图像,请使用此API。

    它有如下的签名:

      imageCompare(image1: Buffer | string | Image,
                  image2: Buffer | string | Image, 
                  options?: CompareOptions): Promise<ImageCompareResult>
    
    • image1、image2可以是Buffer、base64的string,或者一个Image实例。
    • options 的设置与imageEqual的options设置相同。此外,如果ignoreExtraPart是false,对生成的差分图片有影响。如果ignoreExtraPart为false,图片非重叠部分会设置为红色,否则非重叠不设置颜色。

    返回值是名为ImpageCompareResult的结构:

      interface ImageCompareResult {
              equal: boolean,
              info: ImageCompareInfo,
              diffImage: Image
          }
    

    其中:

    • equal表示是否根据容忍度设置认为图片相同。
    • info的结构与imageEqual的compareInfo结构相同,包括像素尺寸,有多少点不同,不同的点的百分比等。
    • diffImage是返回的差分图片的Image对象,相同的像素点以缺省白色表示,不同的点显示为红色。图像中原有的图案会以浅色显示在目标图片中,方便定位差异部分所在的位置。

这两个图片比较API中,imageEqual是imageCompare的封装,为了更直观的返回两个图片是否相等的判断结果。如果只想知道是否相等就用imageEqual,如果除了是否相等外,还想知道更详细的就用imageCompare。

示例

下面是比较两个图片并生成差分图片的样例:

      (async function() {
        try {
            let pngSource = await Image.fromFile(__dirname + '/../image1.png');
            let pngTargt = await Image.fromFile(__dirname + '/../image2.png');

            let result = await Image.imageCompare(pngSource, pngTargt, {pixelNumberTolerance: 300});
            let diffImage = result.diffImage;
            console.log('resultMeta', JSON.stringify(result.info, null, 2));
            let imageData = await diffImage.getData();
            fs.writeFileSync(__dirname + '/../diff.png', imageData)

        } catch(err) {
            console.log(err)
        }
      })()

该样例打印出差异信息,并把结果图片保存成文件"diff.png"。

假如我们有下面两幅图片:

image1 (375 * 266) image2 (402 * 224)

根据参数的不同,可以生成下面的差分图片:

ignoreExtraPart = true ignoreExtraPart = false

左边是ignoreExtraPart = true的情况,超出部分也标记为红色,右边是ignoreExtraPart = false,忽略了超出部分。

控件与模型图片比较

Windows自动化中一个常见的场景是,将运行时控件的截屏与模型中的保存的对象截屏相比较。这可以通过调用模型对象的modelImage方法获得模型对象的截屏png图片,以base64字符串数据返回。如果模型中该对象没有对应的截屏图片,则返回null。

下面的样例从对象模型中获取按钮对象,同时拿到控件截屏和模型中的截屏,并做对比,将对比信息打印出来,同时将差分图片保存到目录中。

const { Image } = require('leanpro.visual');
const { AppModel } = require('leanpro.win');
const fs = require('fs');

const model = AppModel.loadModel(__dirname + "\\test.tmodel");

(async function () {
    let five = model.getButton("Five");
    let controlImage = await five.takeScreenshot();
    let modelImage = await five.modelImage();
    let result = await Image.imageCompare(modelImage, controlImage);
    fs.writeFileSync(__dirname + '/diff.png', await result.diffImage.getData());
    //print the diff information
    console.log(result.info)
})();

虚拟控件上的图片操作

虚拟控件的图片相关操作有:

  • findSnapshot
  • matchSnapshot

请参见虚拟控件API获得相关帮助。

results matching ""

    No results matching ""