资讯详情

资讯详情

PHP印章类实战:GD与Imagick生成电子印章并合成到图片和PDF

简介这是一份面向PHP开发者的电子印章生成类代码资源适合需要在中后台系统、合同签署或OA场景中动态生成圆形印章的开发者参考。资源包共3个文件包含2个PHP源码文件与1个TTF字体文件压缩包约2.24MB其中PHP文件封装了印章类的核心逻辑与调用示例TTF字体用于印章文字的渲染输出。该类围绕圆形印章绘制展开涵盖五角星绘制、文字旋转、字体加载、颜色与角度等属性配置以及创建印章、绘制星形、旋转文本、保存与显示图像等方法并附有实例化调用的完整演示。目前已有848人学习下载可帮助读者快速理解GD库绘图与面向对象封装的结合方式掌握印章尺寸、透明度与图像质量等细节处理思路直接复用到实际项目中。1. 印章类到底在做什么从一张报销单说起财务同事甩过来一张报销单PDF 上盖了红章但章是歪的、颜色发灰、边缘还有锯齿。业务方要求「电子章要跟真章一样」于是你打开搜索引擎敲下「php 印章类」——这就是多数人接触这个需求的起点。所谓印章类本质是用 PHP 在图片或 PDF 上合成一枚电子印章生成圆形或椭圆形的章面、把单位名称沿弧线排布、叠加五角星、再以合适的透明度和旋转角度盖到目标文档上。它解决的是合同、证明、票据在流转环节的「盖章」动作自动化适合做 OA、合同管理、电子档案的 PHP 开发者。别指望它替代合规的电子签章它更像一个图像合成工具把「盖章」这个视觉动作程序化。2. 用 GD 还是 Imagick先把技术选型定下来2.1 两种扩展的能力边界PHP 处理图像有两条路GD 和 Imagick。做印章类选型直接决定后面能走多远。GD 是 PHP 默认捆绑的扩展函数式 API上手快画圆、画线、写字、旋转、透明叠加都能做。缺点是字体渲染依赖 FreeType弧形文字要自己算坐标抗锯齿效果一般输出 PNG 时透明通道处理需要手动开imagealphablending和imagesavealpha稍不注意章底就是黑块。Imagick 基于 ImageMagick面向对象支持 SVG、PDF 直接读写弧形文字可以用ImagickDraw配合annotate逐字旋转抗锯齿和色彩管理更专业。代价是安装门槛高扩展和 ImageMagick 版本要匹配部分虚拟主机不提供。我的建议如果只是给 PNG/JPG 盖章GD 够用且部署简单如果要直接盖到 PDF、要矢量输出、要精细的弧形排版上 Imagick。下面两条路线都会给。2.2 环境准备与最小验证先确认扩展状态别写完代码才发现没装。# 查看 GD 是否启用及版本 php -m | grep -i gd php -r print_r(gd_info()); # 查看 Imagick 是否启用 php -m | grep -i imagick php -r echo Imagick::getVersion()[versionString];如果 GD 没开在 php.ini 里去掉extensiongd的注释Imagick 则通常需要extensionimagick.so并确保系统装了 ImageMagick 运行库。验证通过后再往下走。2.3 用 GD 画一枚基础圆章先做最核心的章面红色圆环、内圈细线、中间五角星。?php // 创建 400x400 真彩色画布留出边距 $size 400; $img imagecreatetruecolor($size, $size); // 开启透明通道否则 PNG 背景是黑的 imagealphablending($img, false); imagesavealpha($img, true); $transparent imagecolorallocatealpha($img, 0, 0, 0, 127); imagefill($img, 0, 0, $transparent); imagealphablending($img, true); // 印章红RGB 约 200,16,20可按需微调 $red imagecolorallocate($img, 200, 16, 20); // 外圆环中心 200,200半径 180线宽 6 imagesetthickness($img, 6); imageellipse($img, 200, 200, 360, 360, $red); // 内圈细线半径 150线宽 2 imagesetthickness($img, 2); imageellipse($img, 200, 200, 300, 300, $red); // 五角星用多边形顶点近似 $star []; $cx 200; $cy 200; $outer 70; $inner 28; for ($i 0; $i 10; $i) { $r ($i % 2 0) ? $outer : $inner; // 从 -90 度开始保证一个角朝上 $angle deg2rad(-90 $i * 36); $star[] $cx $r * cos($angle); $star[] $cy $r * sin($angle); } imagefilledpolygon($img, $star, $red); // 输出 PNG header(Content-Type: image/png); imagepng($img); imagedestroy($img);逻辑说明imagecreatetruecolor建的是真彩色画布透明必须靠imagecolorallocatealpha分配一个 alpha127 的颜色再填充同时imagesavealpha要在填充前设为 true。五角星用 10 个顶点交替取外半径和内半径角度步长 36 度起始 -90 度让尖角朝上。参数上imagesetthickness影响所有后续线条画完外圈记得改回细线再画内圈否则内圈也会变粗。2.4 弧形文字的坐标计算印章的灵魂是沿圆弧排布的单位名称。GD 没有现成的弧形文字函数得逐字旋转。?php // 假设 $img、$red 已由上一步创建 $text 某某技术服务有限公司; $fontFile __DIR__ . /simsun.ttc; // 需自备中文字体 $fontSize 22; $radius 130; // 文字基线所在圆半径 $startAngle -150; // 起始角度度 $totalChars mb_strlen($text, UTF-8); // 每个字占的角度按字数均分留出顶部缺口 $step 300 / max($totalChars - 1, 1); for ($i 0; $i $totalChars; $i) { $char mb_substr($text, $i, 1, UTF-8); $angle $startAngle $i * $step; $rad deg2rad($angle); // 计算该字中心坐标 $x 200 $radius * cos($rad); $y 200 $radius * sin($rad); // 用临时画布旋转单字避免直接旋转导致位置漂移 $tmp imagecreatetruecolor(60, 60); imagealphablending($tmp, false); imagesavealpha($tmp, true); $t imagecolorallocatealpha($tmp, 0, 0, 0, 127); imagefill($tmp, 0, 0, $t); imagealphablending($tmp, true); $tr imagecolorallocate($tmp, 200, 16, 20); imagettftext($tmp, $fontSize, 0, 8, 40, $tr, $fontFile, $char); // 旋转角度文字底部朝圆心所以旋转角 角度 90 $rotated imagerotate($tmp, -($angle 90), imagecolorallocatealpha($tmp, 0, 0, 0, 127)); imagealphablending($rotated, true); imagesavealpha($rotated, true); // 把旋转后的字贴到主画布偏移半个字宽高使其居中 imagecopy($img, $rotated, $x - 30, $y - 30, 0, 0, 60, 60); imagedestroy($tmp); imagedestroy($rotated); }逻辑说明核心是「先画正字再旋转最后贴到圆弧坐标」。旋转角取-(angle90)是因为 GD 的imagerotate逆时针为正而文字默认水平要让字底朝向圆心需要补 90 度。参数上$radius决定文字离中心的距离$startAngle和$step共同决定文字覆盖的弧段一般顶部留 60 度缺口放五角星。字体文件必须用支持中文的 TTF/TTC路径写绝对路径最稳。3. 把章盖到图片和 PDF 上合成与定位3.1 透明叠加与旋转角度章画好了盖的时候要控制透明度和轻微旋转太正反而假。?php // $seal 是上一步生成的印章 PNG 资源$target 是待盖章图片 $target imagecreatefromjpeg(__DIR__ . /contract.jpg); // 印章缩放到合适尺寸比如目标宽度的 25% $sealW imagesx($seal); $sealH imagesy($seal); $newW (int)(imagesx($target) * 0.25); $newH (int)($sealH * $newW / $sealW); $sealScaled imagescale($seal, $newW, $newH); // 随机旋转 -15 到 15 度模拟手工盖章 $angle mt_rand(-150, 150) / 10; $sealRot imagerotate($sealScaled, $angle, imagecolorallocatealpha($sealScaled, 0, 0, 0, 127)); imagealphablending($sealRot, true); imagesavealpha($sealRot, true); // 定位右下角往内缩 80 像素 $dstX imagesx($target) - imagesx($sealRot) - 80; $dstY imagesy($target) - imagesy($sealRot) - 80; // 叠加时开启 alpha 混合让章半透明 imagecopy($target, $sealRot, $dstX, $dstY, 0, 0, imagesx($sealRot), imagesy($sealRot)); imagejpeg($target, __DIR__ . /contract_sealed.jpg, 92);逻辑说明imagescale按目标宽度比例缩放保证不同分辨率下章的大小协调。旋转用imagerotate背景色必须传透明色否则旋转后四角是黑的。imagecopy前主画布要处于 alphablending 开启状态这样章的半透明像素才会和目标融合。参数上缩放比例 0.25、边距 80、旋转 ±15 度都是经验值合同类文档章一般占页面宽度 20% 到 30%。3.2 用 Imagick 直接盖到 PDF如果目标是 PDFGD 要先转图再转回画质损失大Imagick 一步到位。?php $pdf new Imagick(__DIR__ . /contract.pdf); $pdf-setImageFormat(png); // 先栅格化便于定位也可保持 pdf $page $pdf-getImage(); $seal new Imagick(__DIR__ . /seal.png); $seal-resizeImage(200, 0, Imagick::FILTER_LANCZOS, 1); $seal-rotateImage(new ImagickPixel(transparent), 8); $seal-setImageOpacity(0.85); // 合成到页面右下角 $page-compositeImage($seal, Imagick::COMPOSITE_OVER, 900, 1200); $page-setImageFormat(pdf); $page-writeImage(__DIR__ . /contract_sealed.pdf);逻辑说明resizeImage第二参数传 0 表示按宽度等比缩放FILTER_LANCZOS是质量较好的重采样滤镜。rotateImage的背景色用transparent保证透明。setImageOpacity控制整体不透明度0.85 比全不透明更自然。compositeImage的坐标是左上角起点需要根据页面尺寸算A4 在 150dpi 下约 1240x1754所以 900,1200 落在右下区域。3.3 参数速查表参数常用值作用章面直径页面宽 20%~30%太小看不清太大压正文旋转角-15°~15°完全水平显得假不透明度0.8~0.9太低像水印太高盖住文字红色 RGB200,16,20偏暗红更接近印泥边距60~100px避免贴边被裁切字体大小章直径 8%~12%保证弧形文字可读4. 避坑与排查那些让章变黑块的细节4.1 透明背景变成黑块现象生成的 PNG 章贴到图上四角是黑色方块。原因创建画布后没有imagesavealpha($img, true)或者填充透明色时 alphablending 还开着导致透明色被混合。解决先imagealphablending($img, false)再imagefill透明色最后imagesavealpha($img, true)顺序不能乱。4.2 中文显示成方框或乱码现象imagettftext输出一堆方块。原因字体文件不支持中文或字符串编码不是 UTF-8。解决换用支持中文的字体如宋体、黑体并确认 PHP 文件本身是 UTF-8 无 BOMmb_substr要显式传UTF-8。4.3 弧形文字位置整体偏移现象文字不在圆弧上挤成一团或散开。原因$step按字数均分角度时没考虑字符实际宽度或者旋转后贴图偏移量写死 30 导致错位。解决把每个字画在固定尺寸临时画布的中心贴图时用「目标坐标减去半个画布尺寸」计算偏移不要用固定值。4.4 Imagick 读取 PDF 报错现象new Imagick(x.pdf)抛异常。原因ImageMagick 的 PDF 委托被策略禁用或缺少 Ghostscript。解决检查policy.xml是否禁用了 PDF安装 Ghostscript必要时改用 GD 先栅格化再处理。4.5 盖章后图片体积暴涨现象一张 200KB 的 JPG 盖完章变 2MB。原因GD 输出 PNG 默认无损或 JPEG 质量参数给太高。解决输出 JPG 时质量设 85~92输出 PNG 时用imagepng($img, null, 9)提高压缩级别或直接输出 JPG。5. 进阶批量盖章与效果自检批量场景下把印章生成和盖章拆成两个函数印章只生成一次缓存起来避免每张图重画。?php function makeSeal(string $text, string $font): GdImage { // 生成一次返回资源调用方自行缓存 // ... 省略绘制细节同第 2 章 } function stampOn(string $src, string $dst, GdImage $seal, float $scale 0.25): void { $img imagecreatefromstring(file_get_contents($src)); $w (int)(imagesx($img) * $scale); $h (int)(imagesy($seal) * $w / imagesx($seal)); $s imagescale($seal, $w, $h); $s imagerotate($s, mt_rand(-120, 120) / 10, imagecolorallocatealpha($s, 0, 0, 0, 127)); imagealphablending($s, true); imagesavealpha($s, true); imagecopy($img, $s, imagesx($img) - $w - 60, imagesy($img) - $h - 60, 0, 0, $w, $h); imagejpeg($img, $dst, 90); imagedestroy($img); imagedestroy($s); } $seal makeSeal(某某技术服务有限公司, __DIR__ . /simsun.ttc); foreach (glob(__DIR__ . /batch/*.jpg) as $file) { stampOn($file, str_replace(.jpg, _sealed.jpg, $file), $seal); }逻辑说明makeSeal只跑一次stampOn里每次重新缩放和旋转保证每张图的章角度不同。参数$scale控制章占图宽比例批量时建议统一。注意imagerotate每次返回新资源旧的$s在旋转后应销毁这里为简洁省略了中间销毁生产环境要补上避免内存堆积。效果自检我一般做三件事一是把盖章结果缩到 50% 看章是否还清晰二是用取色器确认红色没有被目标图背景污染三是把章单独输出到白底和黑底各看一次透明边缘有没有白边或黑边。这三步能挡掉八成视觉翻车。最后说个血泪经验别在循环里反复imagecreatefrompng读同一个印章文件IO 和内存都吃不消缓存成资源或至少缓存文件内容。我早期做批量合同时没注意一千张图跑下来内存直接爆掉后来把印章预生成一次就再没出过事。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →