Issue 1:
Electron version: 2.0.0

Operating system: Mac OSX 10.13.3

I am using a MacBook Pro with a retina screen, don't know if this is the cause of the issue.

When executing the following code what I expect is the size of the image to be 1440px * 900px but the

resulting image is 2880px * 1800px.

let browserWindow = new remote.BrowserWindow({
width: 1440,
maxWidth: 1440,
height: 900,
maxHeight: 900,
show: false,
webPreferences: {
zoomFactor: 1
}
});
browserWindow.once('ready-to-show', () => {
browserWindow.webContents.once('did-finish-load', () => {
browserWindow.webContents.setZoomFactor(1);

browserWindow.webContents.getZoomFactor((zoomfactor) => {
console.log(zoomfactor);
});

browserWindow.webContents.getZoomLevel((zoomfactor) => {
console.log(zoomfactor);
});

console.log(browserWindow.getSize());

browserWindow.capturePage({
x: 0,
y: 0,
height: 900,
width: 1440
}, (image) => {
console.log(image.toDataURL());
});
});
});
browserWindow.loadURL('https://google.com');

The size and zoomFactor/level are all correct as far as I can see.

Could someone elaborate what I might be doing wrong?

Issue 2:
Electron version: 1.4.13

Operating system: MacOS 10.12.2 running on MacBook Pro (Retina, 13-inch, Early 2015)

Expected behavior

webview.capturePage() without specifying a dimension should return an image with the full viewable area on a Retina display. The dimensions of the resulting image should be either the actual pixels of the viewable area or perhaps the actual pixels * the device scale factor.

Specifying a dimension should return the viewable area of that dimension with the resulting image being sized correctly (and consistently with the use case of no rect specified).

Actual behavior

Calling webview.capturePage() without specifying a dimension returns in image that is the pixel size of the viewable area * the scale factor the area covered by the viewable area divided by the scale factor.

For example, on a webview that is 524 pixels wide, the resulting image of capturePage() is 1048 pixels wide, but only contains the image data from the first 262 pixels. That image is then upsized by the scale factor twice to get to the 1048 width. Not only does this not capture the full viewable page, it also introduces significant scaling artifacts.

Similar results occur if a rect is specified to capturePage.

How to reproduce

On a Retina display, create a page with a webview that loads some web site:

<webview id="webview" src="http://www.msn.com/" ></webview>

Capture the page:

// used to get the viewable dimensions of the webview
function getWebviewMeta(cb) {
var code = "var r = {}; \
r.totalHeight = document.body.offsetHeight; \
r.pageHeight = window.innerHeight; \
r.pageWidth = window.innerWidth; \
r;";
webview.executeJavaScript(code, false, function(r) {
let webviewMeta = {};
webviewMeta.captureHeight = r.pageHeight;
webviewMeta.captureWidth = r.pageWidth;
cb(webviewMeta);
});
}

getWebviewMeta(function(webviewMeta) {
let captureRect = {
x: 0, y: 0,
width: webviewMeta.captureWidth,
height: webviewMeta.captureHeight
};

webview.capturePage((img) => {
console.log("image size: ", img.getSize());
let jpgFile = img.toJPEG(90);
// save file as testDefault.jpg, I used jetpack.writeAsync
});

webview.capturePage(captureRect, (img) => {
console.log("image size: ", img.getSize());
let jpgFile = img.toJPEG(90);
// save file as testSetViewSize.jpg, I used jetpack.writeAsync
});

captureRect.width = +captureRect.width * electron.screen.getPrimaryDisplay().scaleFactor;
captureRect.height = +captureRect.height * electron.screen.getPrimaryDisplay().scaleFactor;

webview.capturePage(captureRect, (img) => {
console.log("image size: ", img.getSize());
let jpgFile = img.toJPEG(90);
// save file as testScaled.jpg, I used jetpack.writeAsync
});
});

The first two results, testDefault.jpg and testSetViewSize.jpg will be identical. They will be captureRect * scale factor in size but will only contain captureRect / scale factor from the webview.

The third result, testScaled.jpg, will contain the captureRect data from the webview but will be captureRect * scale factor * scale factor in size.

All images have upscaling artifacts in them.

Note

On non-retina displays (where the scale factor is 1), capturePage works as expected.

Also, using webview.capturePage or webview.getWebContents().capturePage makes no difference. It also does not matter if the code is executed in the main or renderer process. I wouldn't expect there to be a difference in either, but I did test both to make sure.

I have a discussion started about this but decided to enter an issue here because I believe there is a bug in how the scale factor is used. https://discuss.atom.io/t/webview-capturepage-doesnt-capture-full-page-on-retina-display/37560