Skip to content
This repository has been archived by the owner on Oct 25, 2023. It is now read-only.

Commit

Permalink
fix ratio potential issue
Browse files Browse the repository at this point in the history
  • Loading branch information
KazuCocoa committed Mar 2, 2019
1 parent 7c09a98 commit 17cb7da
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
37 changes: 34 additions & 3 deletions lib/basedriver/commands/find.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,19 +363,50 @@ helpers.getScreenshotForImageFind = async function (screenWidth, screenHeight) {
// of coordinates returned by the image match algorithm, since we match based
// on the screenshot coordinates not the device coordinates themselves. There
// are two potential types of mismatch: aspect ratio mismatch and scale
// mismatch.
// mismatch. we need to detect and fix both

let scale = {xScale: 1.0, yScale: 1.0};

const screenAR = screenWidth / screenHeight;
const shotAR = shotWidth / shotHeight;
if (screenAR === shotAR) {
log.info('Screenshot aspect ratio matched screen aspect ratio');
} else {
log.warn(`When trying to find an element, determined that the screen ` +
`aspect ratio and screenshot aspect ratio are different. Screen ` +
`is ${screenWidth}x${screenHeight} whereas screenshot is ` +
`${shotWidth}x${shotHeight}.`);

// Select smaller ratio
// this.getScreenshot is 540x397, this.getDeviceSize is 1080x1920.
// The ratio is {xScale: 2, yScale: 4.83}.
// In this case, we must choose `xScale: 2` as scaleFactor.
// Because if Appium selects the both ratio, the screenshot will be distorted.
// If Appium selects the yScale, width will be bigger than real screenshot.
const _xScale = (1.0 * shotWidth) / screenWidth;
const _yScale = (1.0 * shotHeight) / screenHeight;
const scaleFactor = _xScale >= _yScale ? _yScale : _xScale;

log.warn(`Resizing screenshot to ${shotWidth * scaleFactor}x${shotHeight * scaleFactor} to match ` +
`screen aspect ratio so that image element coordinates have a ` +
`greater chance of being correct.`);
imgObj = imgObj.resize(shotWidth * scaleFactor, shotHeight * scaleFactor);

scale.xScale *= scaleFactor;
scale.yScale *= scaleFactor;
}

// Resize based on the screen dimensions only if both width and height are mismatched
// since except for that, it might be a situation which is different window rect and
// screenshot size like `@driver.window_rect #=>x=0, y=0, width=1080, height=1794` and
// `"deviceScreenSize"=>"1080x1920"`
let scale;
if (screenWidth !== shotWidth && screenHeight !== shotHeight) {
log.info(`Scaling screenshot from ${shotWidth}x${shotHeight} to match ` +
`screen at ${screenWidth}x${screenHeight}`);
imgObj = imgObj.resize(screenWidth, screenHeight);

scale = {xScale: (1.0 * screenWidth) / shotWidth, yScale: (1.0 * screenHeight) / shotHeight};
scale.xScale *= (1.0 * screenWidth) / shotWidth;
scale.yScale *= (1.0 * screenHeight) / shotHeight;
}

b64Screenshot = (await imgObj.getBuffer(imageUtil.MIME_PNG)).toString('base64');
Expand Down
10 changes: 8 additions & 2 deletions test/basedriver/commands/find-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,21 +281,27 @@ describe('finding elements by image', function () {

// try first with portrait screen
let screen = [TINY_PNG_DIMS[0] * 2, TINY_PNG_DIMS[1] * 3];
let expectedScale = { xScale: 0.67, yScale: 1 };

const {b64Screenshot, scale} = await d.getScreenshotForImageFind(...screen);
b64Screenshot.should.not.eql(TINY_PNG);
let screenshotObj = await imageUtil.getJimpImage(b64Screenshot);
screenshotObj.bitmap.width.should.eql(screen[0]);
screenshotObj.bitmap.height.should.eql(screen[1]);
scale.should.eql({ xScale: 2, yScale: 3 });
scale.xScale.toFixed(2).should.eql(expectedScale.xScale.toString());
scale.yScale.should.eql(expectedScale.yScale);

// then with landscape screen
screen = [TINY_PNG_DIMS[0] * 3, TINY_PNG_DIMS[1] * 2];
expectedScale = { xScale: 1, yScale: 0.67 };

const {b64Screenshot: newScreen, scale: newScale} = await d.getScreenshotForImageFind(...screen);
newScreen.should.not.eql(TINY_PNG);
screenshotObj = await imageUtil.getJimpImage(newScreen);
screenshotObj.bitmap.width.should.eql(screen[0]);
screenshotObj.bitmap.height.should.eql(screen[1]);
newScale.should.eql({ xScale: 3, yScale: 2 });
newScale.xScale.should.eql(expectedScale.xScale);
newScale.yScale.toFixed(2).should.eql(expectedScale.yScale.toString());
});
});
});
Expand Down

0 comments on commit 17cb7da

Please sign in to comment.