title: Blurry corners and poor rendering when using Phantomjs (or wkhtmltoimage) screengrab on Docker
body: <p>I'm trying to generate images (jpg or png) from HTML and I've already tried PhantomJS (via jonnyw/php-phantomjs in php) and wkhtmltoimage but they both have the same problem when generating the image. Any border radius, images, or fonts all have really bad jagged edges and aren't crisp at all. </p>
  
  <p>At first I thought it was no fonts being loaded but my font-icons work fine, they're just really poor quality. I have 100 quality set and I get the same results when using Phantomjs or wkhtmltoimage on any website.</p>
  
  <p><a href="https://i.stack.imgur.com/gQ9UZ.png"><img src="https://i.stack.imgur.com/gQ9UZ.png" alt="enter image description here"></a></p>
  
  <p>Does anyone know what could be causing this? </p>
  
  <p><strong>UPDATE</strong></p>
  
  <p><a href="https://i.stack.imgur.com/PTaim.png"><img src="https://i.stack.imgur.com/PTaim.png" alt="enter image description here"></a></p>
  
  <p><strong>UPDATE 2</strong></p>
  
  <p>Here's the code used from jonnyw/php-phantomjs:</p>
  
  <pre><code>        $client = Client::getInstance();
          $client-&gt;isLazy();
          $client-&gt;getEngine()-&gt;setPath('phantomjs');
          $client-&gt;getEngine()-&gt;debug(true);
  
          $width  = 560;
          $height = 670;
          $top    = 1;
          $left   = 1;
  
          $request = $client-&gt;getMessageFactory()-&gt;createCaptureRequest('https://myurltoscreengrab.com', 'GET');
          $request-&gt;setOutputFile('uploads/stats/test.png');
          $request-&gt;setFormat('png');
  
          $request-&gt;setViewportSize($width, $height);
          $request-&gt;setCaptureDimensions($width, $height, $top, $left);
  
          $response = $client-&gt;getMessageFactory()-&gt;createResponse();
  
          // Send the request
          $client-&gt;send($request, $response);
  </code></pre>
  
  <p><strong>JS Being Used</strong></p>
  
  <pre><code>/**
   * Set up page and script parameters
   */
  var page       = require('webpage').create(),
      system     = require('system'),
      response   = {},
      debug      = [],
      logs       = [],
      procedure  = {},
      resources  = 0,
      timeout;
  
  /**
   * Global variables
   */
  
  
  /**
   * Define width &amp; height of capture
   */
  
  
  var rectTop    = 1,
      rectLeft   = 1,
      rectWidth  = 530,
      rectHeight = 670;
  
  if(rectWidth &amp;&amp; rectHeight) {
  
      debug.push(new Date().toISOString().slice(0, -5) + ' [INFO] PhantomJS - Set capture clipping size ~ top: ' + rectTop + ' left: ' + rectLeft + ' ' + rectWidth + 'x' + rectHeight);
  
      page.clipRect = {
          top: rectTop,
          left: rectLeft,
          width: rectWidth,
          height: rectHeight
      };
  }
  
  
  /**
   * Define paper size.
   */
  
  
  /**
   * Define viewport size.
   */
  
  var viewportWidth  = 530,
      viewportHeight = 670;
  
  if(viewportWidth &amp;&amp; viewportHeight) {
  
      debug.push(new Date().toISOString().slice(0, -5) + ' [INFO] PhantomJS - Set viewport size ~ width: ' + viewportWidth + ' height: ' + viewportHeight);
  
      page.viewportSize = {
          width: viewportWidth,
          height: viewportHeight
      };
  }
  
  
  
  
  /**
   * Define custom headers.
   */
  
  page.customHeaders = {};
  
  
  
  /**
   * Page settings
   */
  
  page.settings.resourceTimeout = 5000;
  
  
  
  /**
   * On resource timeout
   */
  page.onResourceTimeout = function (error) {
  
  response        = error;
  response.status = error.errorCode;
  
  
  };
  
  /**
   * On resource requested
   */
  page.onResourceRequested = function (req) {
  
  
  
  
  
      resources++;
      window.clearTimeout(timeout);
  };
  
  /**
   * On resource received
   */
  page.onResourceReceived = function (res) {
  
      var resource = res; // To be removed in version 5.0
  
  
  if(!response.status) {
      response = resource;
  }
  
  
  
      if(!res.stage || res.stage === 'end') {
  
          resources--;
  
          if (resources === 0) {
  
              timeout = window.setTimeout(function() {
                  procedure.execute('success');
              }, 300);
          }
      }
  };
  
  /**
   * Handle page errors
   */
  page.onError = function (msg, trace) {
  
  var error = {
      message: msg,
      trace: []
  };
  
  trace.forEach(function(t) {
      error.trace.push(' -&gt; ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function + ')' : ''));
  });
  
  logs.push(error);
  
  
  };
  
  /**
   * Handle global errors
   */
  phantom.onError = function(msg, trace) {
  
  var stack = [];
  
  trace.forEach(function(t) {
      stack.push(' -&gt; ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function + ')' : ''));
  });
  
  response.status  = 500;
  response.content = msg;
  response.console = stack;
  
  system.stdout.write(JSON.stringify(response, undefined, 4));
  phantom.exit(1);
  
  
  };
  
  /**
   * Open page
   */
  page.open ('https://boxstat.co/widgets/image/stats/2898784/18/500/FFFFFF-EEEEEE-fafafa-333333-85bd4d-ffffff-e4f8cf-71b42f-fddfc1-bd6610-fad3c9-c85639-fac9c9-c52e2e', 'GET', '', function (status) {
  
  
  page.evaluate(function() {
  
      var styles = {};
  
      for(var property in styles) {
          document.body.style[property] = styles[property];
      }
  });
  
      window.setTimeout(function () { 
          procedure.execute(status); 
      }, 4800);
  });
  
  /**
   * Execute procedure
   */
  procedure.execute = function (status) {
  
  if (status === 'success') {
  
      try {
  
          page.render('uploads/stats/test.png', {
              format: 'png',
              quality: 100,
          });
  
          response.content = page.evaluate(function () {
              return document.getElementsByTagName('html')[0].innerHTML
          });
  
      } catch(e) {
  
          response.status  = 500;
          response.content = e.message;
      }
  }
  
  response.console = logs;
  
  system.stderr.write(debug.join('\\n') + '\\n');
  system.stdout.write(JSON.stringify(response, undefined, 4));
  
  phantom.exit();
  
  };
  </code></pre>