Phantomjs: set window.devicePixelRatio for 'retina' screenshots

Created on 6 Jan 2013  路  62Comments  路  Source: ariya/phantomjs

_[email protected] commented:_

Is is possible to set or emulate window.devicePixelRatio=2 for rendering retina screenshots. I want to emulate a retina iphone and take a screenshot, I've tried scaling the page by 2, and doubling the viewport but this isnt the same.

Disclaimer:
This issue was migrated on 2013-03-15 from the project's former issue tracker on Google Code, Issue #964.
:star2:   3 people had starred this issue at the time of migration.

Most helpful comment

Landed in master! Thank you, @DeviaVir !

All 62 comments

I'm also interested in this as a possible way for hacking high-resolution printing for retina-aware sites.

/subscribe I am working on a test harness that needs to run across multiple screen outputs and test mobile UX and we need to be able to emulate devicePixelRatio (media queries for instance will not run as expected when coded for pixel ratio)

@ariya If you have any suggestions for whether this would be accepted and what layers I should/shouldn't hook into I'll look at writing a patch.

@mikemcquaid You need to check if QtWebKit supports it or not.

@ariya Pretty sure I checked and it doesn't directly but could be hacked in. Would this be, then, a candidate for getting it fixed upstream first? Thanks.

Very interested in this.. Don't have the chops to implement it but would certainly appreciate using it!

Please implement this!

:+1: yes please! @mikemcquaid has there been any progress on this if not could you provide a starting point for what to look at should somebody else want to give it a go? Would appreciate any help even if it's just a short explanation.

@juliankrispel I've changed jobs I'm afraid so I no longer need this.

@mikemcquaid do you remember getting anywhere with it? Any idea what I should look at should I decide to work on this?

I didn't. It'd need to be a patch on upstream QtWebkit basically to expose and/or set this.

thanks dude, appreciate the quick reply

Would love to see this also

defiantly looking for this config.

+1, any update on this issue?

:+1:, please add this

:+1:, when it is added?

:+1: I would really need it to write a script to screenshot Cordova App for Google Play Store and AppStore.

:star2: this would be great!

+1

Would love this feature. +1

Another way to think about this, printers are already much higher DPI then screen... so having as high a DPI possible for exporting screenshots to print would be great.

PR #12827 features an example of how to pass pixelratio and get a screenshot returned with the supplied pixelratio. The implementation is not perfect, but the output has the desired effect!

Moved to its own project: https://github.com/DeviaVir/pixelratio-screenshots

Expect the PhantomJS team to include this feature in the 2.0 release as it's in QtWebkit 5. But for now, you can use my hacky solution.

I have got a working code. Will be sending a PR.

PR sent.

Allows the following code:-

var webPage = require('webpage');
var page = webPage.create();

// An example url that supports @2x background-image with the following css:-
/* body {
     background-image: background-image: url('http://retinajs.s3.amazonaws.com/images/backgrounds/bg.jpg');
  }
  @media all and (-webkit-min-device-pixel-ratio: 1.5) {
     body {
       background-image: background-image: url('http://retinajs.s3.amazonaws.com/images/backgrounds/[email protected]');
    }
} */
var examplePage = 'http://imulus.github.io/retinajs/';

//Pass a dpr of your choosing
page.devicePixelRatio = 1.5; // in this case, >=1.5 to get the retina-supporting bg-image

page.open(examplePage, function() {
   var backgroundImage = page.evaluate(function() {
     return window.getComputedStyle(document.body).backgroundImage;
   });
   console.log(backgroundImage); // returns http://retinajs.s3.amazonaws.com/images/backgrounds/[email protected]
   page.render('2x.png');
});

To get a bigger screenshot, picked up from @DeviaVir 's code, below could be added :-

page.viewportSize = {
  width: 1440 * page.devicePixelRatio,
  height: 900 * page.devicePixelRatio
};

@ariya Let me know if I got the implementation right. I will add test cases to the PR.

@pholmstr does the above fit your use case?

Looks promising but I haven't tested... Not sure how to go about doing a build using your version.

Would love to see it become part of release phantomjs.

This is the generated screenshot.

output

@vegetableman: I'd recommend you try to upstream this as the fix looks very simple.

@ashkulz sure but is that a public repo? I don't see any git url to clone.

Uhm, I'd recommend that you read Contributing to Qt and Introduction to Gerrit and try to get your change accepted in the dev branch of qt/qtwebkit.

Thanks @ashkulz for the links. Will try to send a PR sometime this week.

Will this be in 2.0?

Since 2.0 has been released, nope :frowning:

Any interest in getting this feature implemented?

@vegetableman Hey, any way you could quickly list build instructions for those of us who need this now?

+1 @Bellardia @vegetableman It would indeed be helpful for some of us.

The build instructions are the same as mentioned on the phantomjs docs. http://phantomjs.org/build.html
The changes are really minute.

Thank you for the feedback then ;)

Ok, I got it built and everything works fine. Except one thing though : I intended to use the page.render function; but it seems @vegetableman's fix does not influence the rendering. (ex: media queries don't get called properly) There might be something to do there...

@tiesselune did you try the code at https://github.com/ariya/phantomjs/issues/10964#issuecomment-67550290? you are supposed to set page.devicePixelRatio in order for it to work.

Yes, I pretty much did ^^. The problem lies elswhere : after my tests, when rendering, the image was always the viewport's size with an obvious pixel ratio of 1... I've looked at the code, and I believe we should change some of QtWebkit rendering functions for it to work... ?

My media-queries are of this kind :

@media screen and (min-width : 567px) and (min-height : 340px)

But using a pixel ratio of 2, the minimum real width of the viewport to enter the media query should be 1134px but it does not enter it, neither does it double the size of the on-screen html elements like it would on a real-world device...

Anyway, I've found another solution by applying a scale transform on the body element, and pre-compute the media-queries in the <style> tags with a regex to change its values according to the desired pixel ratio _before_ it takes the screencap. I was not able to do it another way. :/

@tiesselune you are right, now that I remember it, the code (more of a hack) only handles setting the device pixel ratio to the desired value, with no effects on rendering of the page whatsoever. It only allows getting past the css media queries using -webkit-min-device-pixel-ratio. So, the feature is still very much incomplete :(.

Hey guys,

Is the bounty on this still alive? :)

I will still honor bounty if someone can get this in phantomjs

Would be nice to have this feature

I try this page.devicePixelRatio = 2;, but seen that it is not work with media queries

Im sorry to ask this.. but.. is not good enough the "solution" posted by @tiesselune?
It's a bit hard to understand the current stage of this problem and related files (demo files or whatever).

As I understand, you got a solution, but wanna get it coded in the PhantomJS itself instead of hack the js file, right?

@erm3nda don't mean to sound like an asshole but he's basically suggesting what
I wrote a year ago, which is also in this comment thread:
https://github.com/ariya/phantomjs/issues/10964#issuecomment-67542804

Just wanted to point that out.

Don't meant to be dumb, but maybe you can compile a PhantomJS with your js file builtin and accepting a new parameter --retina=x so if you pass that, PhantomJS would chain internally the file.
As i understand they only want a capable "PhantomJS", meaning no using external file. If you put it inside is not external anymore and you can claim that bounty. You did a clean work on that retina-screenshot.

I've never tried to do that, but never is late to try out.

@erm3nda that's the first thing I tried, but since this needs to be fixed upstream first, and I don't know enough about Qt, I threw together this working hack.

See this other comment, also in this thread, who also pointed this out: https://github.com/ariya/phantomjs/issues/10964#issuecomment-70423243

Doh, you were right at "but since this needs to be fixed upstream first". Seems is the Qt:WebPage which has to do the main work, but also needed to add the params on the render. I'll read more untill talk more about it :+1:

https://github.com/DeviaVir/pixelratio-screenshots seems like most deserving of bounty, but I really wanted this in phantomjs proper :(

I'm curious if getting https://github.com/Vitallium/qtwebkit/issues/5 and https://github.com/ariya/phantomjs/issues/13942 in PhantomJS will make the hack less hacky. Might still have to do some scaling but at least not so much JS hackery.

webkit PR reopened against a new repo:
https://github.com/annulen/webkit/pull/515

https://github.com/ariya/phantomjs/pull/13942 still depends on that PR to be merged first...

Landed in master! Thank you, @DeviaVir !

What happened to this? 2.1 is the latest version that's downloadable? The 2.5 branch seems gone?
How/when can we use page.devicePixelRatio = x ?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

h4wlt picture h4wlt  路  5Comments

dhilipsiva picture dhilipsiva  路  4Comments

Snowlav picture Snowlav  路  3Comments

naitsirch picture naitsirch  路  3Comments

julmot picture julmot  路  5Comments