This commit introduces a new function to define the logo path for QR key chains and enhances the image creation process by adding functionality to load, resize, and center the logo within a specified size. If the logo file is missing, a fallback to a text drawing is implemented. These changes improve the visual presentation of QR codes with logos.
206 lines
6.9 KiB
PHP
206 lines
6.9 KiB
PHP
<?php
|
||
|
||
require_once __DIR__ . '/../libs/phpqrcode-master/qrlib.php';
|
||
|
||
/**
|
||
* Chemin du logo MS1 pour le centre des QR key_chain.
|
||
*/
|
||
function fxKcQrLogoPath()
|
||
{
|
||
return __DIR__ . '/../images/ms1-kc-logo.png';
|
||
}
|
||
|
||
/**
|
||
* Charge et redimensionne le logo PNG (carré de sortie $intSize).
|
||
* Repli : dessin texte si le fichier est absent.
|
||
*/
|
||
function fxKcQrCreateLogoImage($intSize)
|
||
{
|
||
$intSize = max(24, (int) $intSize);
|
||
$strLogoPath = fxKcQrLogoPath();
|
||
|
||
if (is_file($strLogoPath)) {
|
||
$imgSrc = @imagecreatefrompng($strLogoPath);
|
||
if ($imgSrc !== false) {
|
||
$intSrcW = imagesx($imgSrc);
|
||
$intSrcH = imagesy($imgSrc);
|
||
$img = imagecreatetruecolor($intSize, $intSize);
|
||
imagealphablending($img, false);
|
||
imagesavealpha($img, true);
|
||
$colTransparent = imagecolorallocatealpha($img, 0, 0, 0, 127);
|
||
imagefilledrectangle($img, 0, 0, $intSize, $intSize, $colTransparent);
|
||
imagealphablending($img, true);
|
||
|
||
// Conserve le ratio (158×180) dans le carré cible.
|
||
$fltScale = min($intSize / max(1, $intSrcW), $intSize / max(1, $intSrcH));
|
||
$intDstW = max(1, (int) round($intSrcW * $fltScale));
|
||
$intDstH = max(1, (int) round($intSrcH * $fltScale));
|
||
$intDstX = (int) floor(($intSize - $intDstW) / 2);
|
||
$intDstY = (int) floor(($intSize - $intDstH) / 2);
|
||
|
||
imagecopyresampled(
|
||
$img,
|
||
$imgSrc,
|
||
$intDstX,
|
||
$intDstY,
|
||
0,
|
||
0,
|
||
$intDstW,
|
||
$intDstH,
|
||
$intSrcW,
|
||
$intSrcH
|
||
);
|
||
imagedestroy($imgSrc);
|
||
|
||
return $img;
|
||
}
|
||
}
|
||
|
||
// Repli : dessin texte (si PNG manquant).
|
||
$img = imagecreatetruecolor($intSize, $intSize);
|
||
imagealphablending($img, true);
|
||
imagesavealpha($img, true);
|
||
|
||
$colBlack = imagecolorallocate($img, 0, 0, 0);
|
||
$colWhite = imagecolorallocate($img, 255, 255, 255);
|
||
imagefilledrectangle($img, 0, 0, $intSize, $intSize, $colBlack);
|
||
|
||
$strFont = __DIR__ . '/../fonts/arial.ttf';
|
||
if (!is_file($strFont)) {
|
||
$strFont = 'C:/Windows/Fonts/arial.ttf';
|
||
}
|
||
|
||
if (is_file($strFont)) {
|
||
$intLeftX = (int) round($intSize * 0.12);
|
||
$intRightX = (int) round($intSize * 0.52);
|
||
$intFontSmall = max(8, (int) round($intSize * 0.16));
|
||
$intFontBig = max(12, (int) round($intSize * 0.42));
|
||
|
||
imagettftext($img, $intFontSmall, 0, $intLeftX, (int) round($intSize * 0.30), $colWhite, $strFont, 'm');
|
||
imagettftext($img, (int) round($intFontSmall * 0.55), 0, $intLeftX + (int) round($intSize * 0.04), (int) round($intSize * 0.46), $colWhite, $strFont, chr(183));
|
||
imagettftext($img, $intFontSmall, 0, $intLeftX, (int) round($intSize * 0.62), $colWhite, $strFont, 's');
|
||
imagettftext($img, $intFontBig, 0, $intRightX, (int) round($intSize * 0.68), $colWhite, $strFont, '1');
|
||
} else {
|
||
imagestring($img, 5, (int) round($intSize * 0.18), (int) round($intSize * 0.28), 'm.s', $colWhite);
|
||
imagestring($img, 5, (int) round($intSize * 0.55), (int) round($intSize * 0.40), '1', $colWhite);
|
||
}
|
||
|
||
return $img;
|
||
}
|
||
|
||
/**
|
||
* Superpose le logo au centre d'un PNG QR existant.
|
||
*/
|
||
function fxKcQrOverlayLogo($strQrPath, $fltLogoRatio = 0.22)
|
||
{
|
||
$imgQr = imagecreatefrompng($strQrPath);
|
||
if ($imgQr === false) {
|
||
return false;
|
||
}
|
||
|
||
$intQrW = imagesx($imgQr);
|
||
$intQrH = imagesy($imgQr);
|
||
$intLogoSize = (int) max(24, round(min($intQrW, $intQrH) * $fltLogoRatio));
|
||
$intPad = (int) max(2, round($intLogoSize * 0.08));
|
||
|
||
$imgLogo = fxKcQrCreateLogoImage($intLogoSize);
|
||
$imgBlock = imagecreatetruecolor($intLogoSize + ($intPad * 2), $intLogoSize + ($intPad * 2));
|
||
$colWhite = imagecolorallocate($imgBlock, 255, 255, 255);
|
||
imagefilledrectangle($imgBlock, 0, 0, $intLogoSize + ($intPad * 2), $intLogoSize + ($intPad * 2), $colWhite);
|
||
imagecopy($imgBlock, $imgLogo, $intPad, $intPad, 0, 0, $intLogoSize, $intLogoSize);
|
||
|
||
$intX = (int) floor(($intQrW - $intLogoSize - ($intPad * 2)) / 2);
|
||
$intY = (int) floor(($intQrH - $intLogoSize - ($intPad * 2)) / 2);
|
||
imagecopy($imgQr, $imgBlock, $intX, $intY, 0, 0, $intLogoSize + ($intPad * 2), $intLogoSize + ($intPad * 2));
|
||
|
||
imagepng($imgQr, $strQrPath, 0);
|
||
|
||
imagedestroy($imgQr);
|
||
imagedestroy($imgLogo);
|
||
imagedestroy($imgBlock);
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Génère un QR key_chain prêt pour l'impression.
|
||
*/
|
||
function fxKcQrGeneratePng($intParam1, $strBaseUrl, $strOutputFile, $intModuleSize = 18, $blnWithLogo = true)
|
||
{
|
||
$strUrl = rtrim($strBaseUrl, '/') . '/kc.php?param1=' . intval($intParam1);
|
||
$strDir = dirname($strOutputFile);
|
||
if (!is_dir($strDir)) {
|
||
mkdir($strDir, 0755, true);
|
||
}
|
||
|
||
QRcode::png(
|
||
$strUrl,
|
||
$strOutputFile,
|
||
QR_ECLEVEL_H,
|
||
$intModuleSize,
|
||
2
|
||
);
|
||
|
||
if ($blnWithLogo) {
|
||
fxKcQrOverlayLogo($strOutputFile);
|
||
}
|
||
|
||
return [
|
||
'param1' => intval($intParam1),
|
||
'url' => $strUrl,
|
||
'file' => $strOutputFile,
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Génère une série de QR codes key_chain.
|
||
*/
|
||
function fxKcQrGenerateBatch(array $options)
|
||
{
|
||
$intStart = intval($options['start'] ?? 500);
|
||
$intCount = max(1, intval($options['count'] ?? 100));
|
||
$strBaseUrl = rtrim($options['base_url'] ?? 'https://ms1inscription.com', '/');
|
||
$strOutputDir = rtrim($options['output_dir'] ?? (__DIR__ . '/../output/kc_qr'), DIRECTORY_SEPARATOR);
|
||
$intModuleSize = max(6, intval($options['module_size'] ?? 18));
|
||
$blnWithLogo = !empty($options['with_logo']);
|
||
|
||
if (!is_dir($strOutputDir)) {
|
||
mkdir($strOutputDir, 0755, true);
|
||
}
|
||
|
||
$tabGenerated = [];
|
||
for ($i = 0; $i < $intCount; $i++) {
|
||
$intParam1 = $intStart + $i;
|
||
$strFile = $strOutputDir . DIRECTORY_SEPARATOR . 'qr_kc_' . $intParam1 . '.png';
|
||
$tabGenerated[] = fxKcQrGeneratePng($intParam1, $strBaseUrl, $strFile, $intModuleSize, $blnWithLogo);
|
||
}
|
||
|
||
$strManifest = $strOutputDir . DIRECTORY_SEPARATOR . 'manifest.csv';
|
||
$fh = fopen($strManifest, 'w');
|
||
if ($fh !== false) {
|
||
fputcsv($fh, ['param1', 'vehicule_no', 'url', 'filename']);
|
||
foreach ($tabGenerated as $row) {
|
||
$intVehicule = $row['param1'];
|
||
if (defined('KEYCHAIN_HTTP_EDIT_SHIFT')) {
|
||
$intVehicule = $row['param1'] - KEYCHAIN_HTTP_EDIT_SHIFT;
|
||
}
|
||
fputcsv($fh, [
|
||
$row['param1'],
|
||
$intVehicule,
|
||
$row['url'],
|
||
basename($row['file']),
|
||
]);
|
||
}
|
||
fclose($fh);
|
||
}
|
||
|
||
return [
|
||
'output_dir' => $strOutputDir,
|
||
'count' => count($tabGenerated),
|
||
'start' => $intStart,
|
||
'end' => $intStart + $intCount - 1,
|
||
'manifest' => $strManifest,
|
||
'files' => array_column($tabGenerated, 'file'),
|
||
];
|
||
}
|