gpt4 book ai didi

php - 在 Docker 上使用 Phantomjs(或 wkhtmltoimage)屏幕截图时,边角模糊且渲染效果不佳

转载 作者:行者123 更新时间:2023-12-03 00:17:59 54 4
gpt4 key购买 nike

我正在尝试从 HTML 生成图像(jpg 或 png),并且我已经尝试过 PhantomJS(通过 php 中的 jonnyw/php-phantomjs)和 wkhtmltoimage,但它们在生成图像时都有相同的问题。任何边框半径、图像或字体都有非常糟糕的锯齿状边缘,而且一点也不清晰。

起初我以为没有加载字体,但我的字体图标工作正常,只是质量很差。我设置了 100 个质量,在任何网站上使用 Phantomjs 或 wkhtmltoimage 时都得到相同的结果。

enter image description here

有谁知道这是什么原因造成的?

更新

enter image description here

更新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();

};

最佳答案

在你的phantomjs中添加viewportSize和zoomFactor,如下所示:

await page.property('viewportSize', { height: 1600, width: 3600 });
await page.property('zoomFactor', 4);

和/或添加:

<script>
window.devicePixelRatio = 4;
</script>

尝试使用相对于屏幕 DPI 更高的纸张 DPI 设置缩放系数:

page.zoomFactor = 300 / 96;   // or use / 72

必须在定义页面大小后设置。

我还发现了 2 个函数试图处理此类问题...

函数1

var makeHighResScreenshot = function(srcEl, destIMG, dpi) {
var scaleFactor = Math.floor(dpi / 96);
// Save original size of element
var originalWidth = srcEl.offsetWidth;
var originalHeight = srcEl.offsetHeight;
// Save original document size
var originalBodyWidth = document.body.offsetWidth;
var originalBodyHeight = document.body.offsetHeight;

// Add style: transform: scale() to srcEl
srcEl.style.transform = "scale(" + scaleFactor + ", " + scaleFactor + ")";
srcEl.style.transformOrigin = "left top";

// create wrapper for srcEl to add hardcoded height/width
var srcElWrapper = document.createElement('div');
srcElWrapper.id = srcEl.id + '-wrapper';
srcElWrapper.style.height = originalHeight*scaleFactor + 'px';
srcElWrapper.style.width = originalWidth*scaleFactor + 'px';
// insert wrapper before srcEl in the DOM tree
srcEl.parentNode.insertBefore(srcElWrapper, srcEl);
// move srcEl into wrapper
srcElWrapper.appendChild(srcEl);

// Temporarily remove height/width constraints as necessary
document.body.style.width = originalBodyWidth*scaleFactor +"px";
document.body.style.height = originalBodyHeight*scaleFactor +"px";

window.scrollTo(0, 0); // html2canvas breaks when we're not at the top of the doc, see html2canvas#820
html2canvas(srcElWrapper, {
onrendered: function(canvas) {
destIMG.src = canvas.toDataURL("image/png");
srcElWrapper.style.display = "none";
// Reset height/width constraints
document.body.style.width = originalBodyWidth + "px";
document.body.style.height = originalBodyHeight + "px";
}
});
};

使用

var src = document.getElementById("screenshot-source");
var img = document.getElementById("screenshot-img");
makeHighResScreenshot(src, img, 192); // DPI of 192 is 4x resolution (2x normal DPI for both width and height)

函数2

function takeHighResScreenshot(srcEl, destIMG, scaleFactor) {
// Save original size of element
var originalWidth = srcEl.offsetWidth;
var originalHeight = srcEl.offsetHeight;
// Force px size (no %, EMs, etc)
srcEl.style.width = originalWidth + "px";
srcEl.style.height = originalHeight + "px";

// Position the element at the top left of the document because of bugs in html2canvas. The bug exists when supplying a custom canvas, and offsets the rendering on the custom canvas based on the offset of the source element on the page; thus the source element MUST be at 0, 0.
// See html2canvas issues #790, #820, #893, #922
srcEl.style.position = "absolute";
srcEl.style.top = "0";
srcEl.style.left = "0";

// Create scaled canvas
var scaledCanvas = document.createElement("canvas");
scaledCanvas.width = originalWidth * scaleFactor;
scaledCanvas.height = originalHeight * scaleFactor;
scaledCanvas.style.width = originalWidth + "px";
scaledCanvas.style.height = originalHeight + "px";
var scaledContext = scaledCanvas.getContext("2d");
scaledContext.scale(scaleFactor, scaleFactor);

html2canvas(srcEl, { canvas: scaledCanvas })
.then(function(canvas) {
destIMG.src = canvas.toDataURL("image/png");
srcEl.style.display = "none";
});
};

使用

var src = document.getElementById("screenshot-src");
var img = document.getElementById("screenshot-img");
takeHighResScreenshot(src, img, 2); // This time we provide desired scale factor directly, no more messing with DPI

希望这对您有帮助。现在让我告诉你我会做什么。我制作浏览器自动化脚本已经有一段时间了,但在我看来,PhantomJS 并不是那么好。考虑使用 NightmareJS。它比 Phantom 快得多并且更易于使用。

关于php - 在 Docker 上使用 Phantomjs(或 wkhtmltoimage)屏幕截图时,边角模糊且渲染效果不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41283543/

54 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com