wordpress文章内容生成图片的方法

请自行下载字体AlibabaPuHuiTi-3-45-Light.otf放在主题根目录下。

在主题函数文件functions.php中添加

function ii_get_content2image($imgwidth,$fontsize,$type = '0'){
ini_set('memory_limit', '512M');
$tid = get_the_ID();
$text = get_post_field('post_content', $tid); // 获取文章内容

// 设置文字内容
$textContent = preg_replace("/(<br\s*\/?>)/i", "\n", strip_tags($text,'<p> <br> <img>'));
$textContent = preg_replace('/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\x{1F1E0}-\x{1F1FF}\x{1F900}-\x{1F9FF}\x{1FA00}-\x{1FA6F}\x{1FA70}-\x{1FAFF}\x{1FBC0}-\x{1FBCF}\x{1FBD0}-\x{1FBD0}\x{1FBE0}-\x{1FBE0}\x{1FBF0}-\x{1FBF0}\x{1FC00}-\x{1FC00}\x{1FC70}-\x{1FC70}\x{1FD00}-\x{1FD3E}\x{1FD40}-\x{1FD40}\x{1FD50}-\x{1FD8F}\x{1FD92}-\x{1FD95}\x{1FD97}-\x{1FD97}\x{1FD99}-\x{1FDBF}\x{1FDC0}-\x{1FDCF}\x{1FDD0}-\x{1FDDF}\x{1FDE0}-\x{1FDFD}\x{1FDFE}-\x{1FDFE}\x{1FE00}-\x{1FE0F}\x{1FE10}-\x{1FE1F}\x{1FE20}-\x{1FE2F}\x{1FE30}-\x{1FE4F}\x{1FE50}-\x{1FE50}\x{1FE70}-\x{1FEFF}\x{1FF00}-\x{1FF00}\x{1FF01}-\x{1FF02}\x{1FF03}-\x{1FF03}\x{1FF04}-\x{1FF04}\x{1FF05}-\x{1FF05}\x{1FF06}-\x{1FF06}\x{1FF07}-\x{1FF07}\x{1FF08}-\x{1FF0A}\x{1FF0B}-\x{1FF0B}\x{1FF0C}-\x{1FF0E}\x{1FF0F}-\x{1FF0F}\x{1FF10}-\x{1FF10}\x{1FF11}-\x{1FF11}\x{1FF12}-\x{1FF12}\x{1FF13}-\x{1FF13}\x{1FF14}-\x{1FF14}\x{1FF15}-\x{1FF15}\x{1FF16}-\x{1FF16}\x{1FF17}-\x{1FF17}\x{1FF18}-\x{1FF18}\x{1FF19}-\x{1FF19}\x{1FF1A}-\x{1FF20}\x{1FF21}-\x{1FF21}\x{1FF22}-\x{1FF22}\x{1FF23}-\x{1FF23}\x{1FF24}-\x{1FF24}\x{1FF25}-\x{1FF25}\x{1FF26}-\x{1FF26}\x{1FF27}-\x{1FF27}\x{1FF28}-\x{1FF28}\x{1FF29}-\x{1FF29}\x{1FF2A}-\x{1FF2A}\x{1FF2B}-\x{1FF2B}\x{1FF2C}-\x{1FF2C}\x{1FF2D}-\x{1FF2D}\x{1FF2E}-\x{1FF2F}\x{1FF30}-\x{1FF30}\x{1FF31}-\x{1FF31}\x{1FF32}-\x{1FF32}\x{1FF33}-\x{1FF33}\x{1FF34}-\x{1FF34}\x{1FF35}-\x{1FF35}\x{1FF36}-\x{1FF36}\x{1FF37}-\x{1FF37}\x{1FF38}-\x{1FF38}\x{1FF39}-\x{1FF39}\x{1FF3A}-\x{1FF3A}\x{1FF3B}-\x{1FF3B}\x{1FF3C}-\x{1FF3C}\x{1FF3D}-\x{1FF3D}\x{1FF3E}-\x{1FF3E}\x{1FF3F}-\x{1FF3F}\x{1FF40}-\x{1FF40}\x{1FF41}-\x{1FF41}\x{1FF42}-\x{1FF42}\x{1FF43}-\x{1FF43}\x{1FF44}-\x{1FF44}\x{1FF45}-\x{1FF45}\x{1FF46}-\x{1FF46}\x{1FF47}-\x{1FF47}\x{1FF48}-\x{1FF48}\x{1FF49}-\x{1FF49}\x{1FF4A}-\x{1FF4A}\x{1FF4B}-\x{1FF4B}\x{1FF4C}-\x{1FF4C}\x{1FF4D}-\x{1FF4D}\x{1FF4E}-\x{1FF4F}\x{1FF50}-\x{1FF50}\x{1FF51}-\x{1FF51}\x{1FF52}-\x{1FF52}\x{1FF53}-\x{1FF53}\x{1FF54}-\x{1FF54}\x{1FF55}-\x{1FF55}\x{1FF56}-\x{1FF56}\x{1FF57}-\x{1FF57}\x{1FF58}-\x{1FF58}\x{1FF59}-\x{1FF59}\x{1FF5A}-\x{1FF5A}\x{1FF5B}-\x{1FF5B}\x{1FF5C}-\x{1FF5C}\x{1FF5D}-\x{1FF5D}\x{1FF5E}-\x{1FF5E}\x{1FF5F}-\x{1FF5F}\x{1FF60}-\x{1FF60}\x{1FF61}-\x{1FF61}]/u', '', $textContent);
$textContent = preg_replace('/<p(.*?)>(.*?)<\/p>/s', "$2\n", $textContent);
$textContent = preg_replace("/\s*[\r\n]+|\s*<br\s*\/?>\s*/i", "\n", $textContent);//多个换行替换成1个换行
$text = html_entity_decode($textContent);
// 设置字体文件路径
$font_file = get_template_directory() . '/AlibabaPuHuiTi-3-45-Light.otf'; // 确保这个路径是正确的
$max_width = $imgwidth; // 图片的最大宽度
$font_size = $fontsize; // 文字大小
$image_height = 10; // 初始化图片高度
$line_height = $font_size*2; // 行间距,这里简单加了一些额外空间
$outimg = ABSPATH . 'conimg/';
if (!(is_dir($outimg))) @mkdir($outimg, 0775);
if(!empty($tid)) $outimg .= md5($tid.'_'.$imgwidth.'_'.$fontsize.'_'.$type).'.webp';
else $outimg .= md5(strtotime(time()),1).'.webp';
if(file_exists($outimg)){
$outimg = site_url().'/conimg/'.basename($outimg);
$outimg = str_replace(ABSPATH,site_url(),$outimg);
return $outimg;
}

// 检查字体文件是否存在
if (!file_exists($font_file)) {
die('字体文件不存在');
}
// 创建一个真彩色图像(确保GD库已启用)
$image = imagecreatetruecolor($max_width, $image_height);
$white = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
imagefill($image, 0, 0, $white);
$parts = preg_split('/(<img[^>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
$isText = true; // 标记当前处理的是文本还是图片
// 精确版的文本分割以适应宽度
$lines = [];
$images = []; // 存储图片的服务器路径和尺寸信息
$current_line_width = 0;
$lines[] = '';//添加空行
foreach ($parts as $part) {
if ($isText) {
// 对文本进行必要的处理,计算内容,行数,高度
foreach (explode("\n", wordwrap($part, $max_width, "\n", true)) as $article) {
preg_match_all("/./u", $article, $words);
foreach ($words[0] as $word) {
if(trim($word) == "") continue;
$word_box = imagettfbbox($font_size, 0, $font_file, $word);
$word_width = $word_box[2] - $word_box[0];
if(preg_match('/[\x{3002}\x{ff01}\x{2018}\x{2019}\x{201c}\x{201d}\x{fe50}\x{fe51}\x{fe52}\x{ff08}\x{ff09}\x{ff0c}\x{ff1a}\x{ff1b}\x{ff1f}\x{ff0e}\x{2026}\x{2014}\x{fe41}\x{fe42}\x{fe43}\x{fe44}\x{ff5e}\x{301d}\x{3001}]/u', $word)) $word_width = $word_width*2;
// 如果加上新单词后超过最大宽度,则开始新的一行
if ($current_line_width + $word_width > $max_width) {
$lines[] = implode('', $current_line);
$current_line = [$word];
$current_line_width = $word_width;
} else {
$current_line[] = $word;
$current_line_width += $word_width + ($font_size /4); // 简单添加字间距
}
}
// 添加最后一行
if (!empty($current_line)) {
$lines[] = implode('', $current_line);
}
$current_line = [];
$current_line_width = 0;
$lines[] = '';//添加空行,隔开段落
}
} else {
// 对图片标签进行处理
// 处理图片标签并记录图片信息
preg_match_all('/<img[^>]*src=["\'](.*?)["\']/i', $part, $matches);
foreach ($matches[1] as $imageSrc) {
// 假设$imageSrc已经是服务器相对或绝对路径
if ((strpos($imageSrc, 'http') !== 0 || strpos($imageSrc, 'https') !== 0) && strpos($imageSrc, '//') !== 0) {
$imageSrc = site_url() . '/' .$imageSrc;
}
$imageSrc = str_replace(site_url(),ABSPATH,$imageSrc);
$imageSrc = str_replace('//','/',$imageSrc);
if (!file_exists($imageSrc)) continue;
list($width, $height) = @getimagesize($imageSrc);
if($width >= $max_width){
$newWidth = $max_width * 0.85;
$newHeight = $height * ($newWidth/$width);
}else{
$newWidth = $width;
$newHeight = $height;
}
$images[] = array(
'src' => $imageSrc,
'x' => ($max_width - $newWidth) / 2,
'y' => count($lines) * $line_height,
'w' => $width,
'h' => $height,
'nw' => $newWidth,
'nh' => $newHeight
);
}
if(count($images) > 0){
$imagesH = ceil($newHeight/$line_height);
for($i=0;$i<=$imagesH;$i++){
$lines[] = '';//添加空行
}
}
}
$isText = !$isText; // 切换到处理下一种类型(文本或图片)
}

// 计算总高度并重新创建图像以适应所有文字
$image_height = count($lines) * $line_height;
if($image_height > 10000) {
$image_height = '10000';//图片超高,仅返回图片前1万像素高度
$lines_len = ceil($image_height/$line_height) - 1;
$lines[$lines_len-3] = '';
$lines[$lines_len-2] = '图片超高,仅返回图片前1万像素高度';
$lines[$lines_len-1] = '';
$lines[$lines_len] = '';
$lines = array_slice($lines, 0, $lines_len);
}
$new_image = imagecreatetruecolor($max_width, $image_height);
imagefill($new_image, 0, 0, $white);
imagesavealpha($new_image, true);
$transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
//$backgroundColor = imagecolorallocate($new_image, 255, 255, 255); // 纯白色背景作为示例
imagefill($new_image, 0, 0, $transparent);

// 随机线条参数
$lineCount = 100; // 线条数量
$minLineWidth = 80; // 线条最小宽度
$maxLineWidth = 200; // 线条最大宽度
$minLineColor = 230; // 线条颜色范围下限
$maxLineColor = 255; // 线条颜色范围上限
// 绘制随机线条
for ($i = 0; $i < $lineCount; $i++) {
// 随机选择线条的起点和终点
$startX = rand(-50, $max_width+50);
$startY = rand(-50, $image_height+50);
$endX = rand(-50, $max_width+50);
$endY = rand(-50, $image_height+50);

// 随机选择线条的颜色和宽度
$lineColor = imagecolorallocate($new_image, rand($minLineColor, $maxLineColor), rand($minLineColor, $maxLineColor), rand($minLineColor, $maxLineColor));
$lineWidth = rand($minLineWidth, $maxLineWidth);
// 设置线条宽度
imagesetthickness($new_image, $lineWidth);
// 绘制线条
imageline($new_image, $startX, $startY, $endX, $endY, $lineColor);
}

// 在新图像上绘制文字
foreach ($lines as $i => $line) {
imagettftext($new_image, $font_size, 0, 10, ($i + 1) * $line_height-5, $black, $font_file, $line);
}

// 绘制图片到画布上
if(count($images) > 0){
foreach ($images as $imageInfo) {
// 计算图片在画布上的位置,这里以简单方式为例,实际可能需要更复杂的布局逻辑
$imagePath = $imageInfo['src'];
$imageX = $imageInfo['x'];
$imageY = $imageInfo['y'];
$imageW = $imageInfo['w'];
$imageH = $imageInfo['h'];
$imageNW = $imageInfo['nw'];
$imageNH = $imageInfo['nh'];
// 加载并复制图片到新图像
$imageToDraw = @imagecreatefromstring(file_get_contents($imagePath));
imagecopyresampled($new_image, $imageToDraw, $imageX, $imageY, 0, 0, $imageNW, $imageNH, $imageW, $imageH);
imagedestroy($imageToDraw); // 清理内存
}
}
imagewebp($new_image,$outimg,'80');
imagedestroy($new_image);
$outimg = site_url().'/conimg/'.basename($outimg);
$outimg = str_replace(ABSPATH,site_url(),$outimg);
return $outimg;
}

 

在内容页中添加

<?php if ( is_single() ) { ?>
<img src="<?php echo ii_get_content2image('650','14'); ?>" />
<?php } ?>

<img src="<?php echo ii_get_content2image('650','14'); ?>" />

 

 

 

 

 

Winodws 7/8与Server 2008/2012等系统frp服务无法启动的原因

谷歌Go语言发布1.21更新:放弃了对Winodws 7/8与Server 2008/2012,以及macOS 10.13和10.14的支持。

v0.51.3 开始支持 go 1.21
v0.55.0 支持的最低Go版本已更新为 1.22

新版frp不支持win7,建议win10及以上系统。

win7可以考虑下载v0.51.2版本及之前的版本。

报错信息示例:

Exception 0xc0000005 0x8 0x0 0x0
PC=0x0

runtime.asmstdcall(0x22fcf8)
runtime/sys_windows_amd64.s:75 +0x7a fp=0x22fc80 sp=0x22fc60 pc=0x47a37a

rax 0x0
rbx 0x11e2e78
rcx 0x126afe8
rdx 0x20
rdi 0x7fffffde000
rsi 0x22fe78
rbp 0x22fdc0
rsp 0x22fc58
r8 0x0
r9 0x22fee8
r10 0x13da2e8
r11 0xc000004000
r12 0x22fec8
r13 0x0
r14 0x11e1ec0
r15 0x3
rip 0x0
rflags 0x10293
cs 0x33
fs 0x53
gs 0x2b

360随身Wi-Fi在win10和win11中驱动不兼容的解决方法

设备管理器显示:

Windows 无法加载这个硬件的设备驱动程序。驱动程序可能已损坏或不见了。 (代码 39)
Windows 无法验证此文件的数字签名。此文件的签名证书已经吊销。

 

360官方的解决方法:https://bbs.360.cn/forum.php?mod=viewthread&tid=16096553&extra=page%3D1&page=1

 

 

解决steam注册问题

steam注册一直要求验证是真人。无限验证,不能通过。提示:

“您对 CAPTCHA 的响应似乎无效,请在下方重新验证您不是机器人”

有同学想了一下,用VPN,然后又提示:

请停用VPN再重新注册。

最后通过测试,得出一个方法:

0.使用网页注册

1.切换语言为英语

2.切换地区为Taiwan

然后顺利通过注册,进邮箱激活一下即可。

 

 

 

 

steam游戏平台

Steam 是一个由 Valve 公司开发和运营的全球最大的综合性数字发行平台,它不仅让玩家能够购买、下载和玩游戏,还提供了软件分发、社区功能、游戏成就、云存储等多种服务。自2003年推出以来,Steam 已经发展成为一个包含数万款游戏和应用程序的庞大生态系统,支持多种操作系统,包括Windows、macOS和Linux。

稞麦综合视频站下载器(xmlbar)

官网:https://www.xmlbar.net/cn

稞麦综合视频站下载器(xmlbar)是一个专门用于下载Bilibili, CNTV流媒体,乐视(Letv),百度贴吧(tieba.baidu),优酷(Youku),土豆(Tudou),酷6(Ku6),56等重要视频网站到本机硬盘上的小软件。它不但完全免费而且不含有任何第三方插件,可以完全干净卸载。用户只需输入需要下载的视频的网络地址并按下下载按钮,或者更方便的使用拖放方法将页面地址从浏览器地址栏拖到本软件的浮动窗口,它就会自动识别后进行下载。同时还支持Bilibili,优酷高清视频下载,支持土豆豆单列表下载,甚至可以通过Xmlbar提供的内部代理直接下载搜索和播放Bilibili视频,甚至可以直接下载CNTV/tv.sohu/ahtv等网站中采用RTMP/RTMPE/MMS/RTSP协议播放的视频。如果网站上视频分了块,本软件还能自动下载各分块并将分块视频合并成完整的一个文件保存。更好的是它还支持多个视频文件同时下载,并能显示出真实视频文件的下载地址,下载完后您还可以选择马上播放,而且它还有查看管理下载历史记录和视频搜索的功能。

html2canvas开源的网页生成图片js脚本

开源地址:https://github.com/niklasvh/html2canvas

该脚本允许您直接在用户浏览器上对网页或部分网页进行“截图”。截图是基于DOM的,因此可能不是100%准确的真实的表示,因为它没有制作实际的截图,而是基于页面上可用的信息构建截图。

例子:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML to Image Example</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.3.2/html2canvas.min.js"></script>
</head>
<body>

<div id="content">
<!-- 这里是你想要生成图片的HTML内容 -->
<h1>Hello World</h1>
<p>这是一个例子。</p>
</div>

<button onclick="convertToImage()">生成图片</button>

<script>
function convertToImage() {
html2canvas(document.querySelector("#content")).then(canvas => {
// 创建一个图片元素
var img = new Image();
// 将canvas转换为DataURL格式的图片
img.src = canvas.toDataURL("image/png");
// 将图片添加到DOM中以便查看
document.body.appendChild(img);
});
}
</script>

</body>
</html>

该脚本通过阅读DOM和应用于元素的不同样式,将当前页面呈现为画布图像。

它不需要服务器的任何渲染,因为整个图像都是在客户端的浏览器上创建的。然而,由于它严重依赖于浏览器,这个库不适合在nodejs中使用。它也不会神奇地规避任何浏览器内容策略限制,因此渲染跨源内容将需要一个代理将内容获取到同一个源。

该脚本仍处于非常实验性的状态,因此我不建议在生产环境中使用它,也不建议开始使用它构建应用程序,因为仍然会有重大的更改。

浏览器兼容性
该库应该在以下浏览器上工作正常(使用 Promise polyfill):

Firefox 3.5+
谷歌Chrome
Opera 12+
IE9+
Safari浏览器6+
由于每个CSS属性都需要手动构建才能支持,因此有许多属性尚未支持。

IPTVnator管理和播放IPTV内容

开源地址:https://github.com/4gray/iptvnator

支持中文。

IPTVnator 是一款免费的跨平台视频播放器应用程序,专门设计用于管理和播放IPTV内容。它支持播放IPTV播放列表格式,包括m3u和m3u8文件,用户可以通过输入远程URL或从本地文件系统上传来导入播放列表。此播放器还集成了对基于XMLTV的EPG(电子节目指南)的支持,意味着用户可以获取频道的节目信息。

IPTVnator可在多种操作系统上使用,包括Linux、macOS、和Windows,提供了一个统一的观看体验。此外,它还支持以Progressive Web App (PWA)的形式直接从浏览器使用,从而间接地支持了iOS和Android平台。这意味着用户不仅可以在桌面设备上享受服务,还可以在移动设备的浏览器上使用它。

值得注意的是,尽管IPTVnator提供了便利的功能,但它在播放某些特定流媒体地址时的性能可能不如其他专业播放器如PotPlayer。此外,它支持通过Docker部署到服务器或NAS(Network Attached Storage)设备上,为用户提供自托管的Web界面管理选项,增加了灵活性和便利性。

综上所述,IPTVnator是一个综合性的解决方案,适合那些需要在多平台上管理和播放IPTV内容的用户,尤其是偏好开源和自托管服务的用户群体。

frp服务端配置文件frps.toml参考

提示:新版frp不支持win7,建议win10及以上系统。win7可以考虑下载0.49.0版尝试。

frp服务端配置文件frps.toml参考

bindAddr = "10.1.5.1"
bindPort = 7000
kcpBindPort = 7000
vhostHTTPPort = 8080
vhostHTTPSPort = 8081
subDomainHost = "xxxx.net"
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "user"
webServer.password = "xxxx"
transport.maxPoolCount = 50
auth.token = "xxxx"
custom404Page = "/frps/404.html"

frps.service文件及路径

/etc/systemd/system/frps.service

[Unit]
Description = Frp Server Service
After = network.target syslog.target
Wants = network.target

[Service]
Type = simple
User=root
Group=root
Restart = on-failure
RestartSec = 5s
ExecStart = /frps/frps -c /frps/frps.toml
LimitNOFILE = 1048576

[Install]
WantedBy = multi-user.target