Я пытаюсь генерировать изображения (jpg или png) из HTML, и я уже пробовал PhantomJS (через jonnyw/php-phantomjs в php) и wkhtmltoimage, но они оба имеют одинаковую проблему при создании изображения. Любой радиус границы, изображения или шрифты имеют очень плохие зубчатые края и совсем не хрустящие.
Сначала я думал, что это не шрифты, загружаемые, но мои значки шрифтов работают нормально, они просто очень низкого качества. У меня есть 100 наборов качества, и я получаю те же результаты при использовании Phantomjs или wkhtmltoimage на любом веб-сайте.
Кто-нибудь знает, что может быть причиной этого?
UPDATE
ОБНОВЛЕНИЕ 2
Здесь код, используемый из jonnyw/php-phantomjs:
$client = Client::getInstance();
$client->isLazy();
$client->getEngine()->setPath('phantomjs');
$client->getEngine()->debug(true);
$width = 560;
$height = 670;
$top = 1;
$left = 1;
$request = $client->getMessageFactory()->createCaptureRequest('https://myurltoscreengrab.com', 'GET');
$request->setOutputFile('uploads/stats/test.png');
$request->setFormat('png');
$request->setViewportSize($width, $height);
$request->setCaptureDimensions($width, $height, $top, $left);
$response = $client->getMessageFactory()->createResponse();
// Send the request
$client->send($request, $response);
Используемый JS
/**
* 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 & height of capture
*/
var rectTop = 1,
rectLeft = 1,
rectWidth = 530,
rectHeight = 670;
if(rectWidth && 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 && 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(' -> ' + (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(' -> ' + (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();
};