Files
ms1inscription-v5/php/inc_fx_kc_qr.php
stephan 54a7e1dae9 Add logo path function and enhance logo image creation for QR key chains
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.
2026-07-11 18:53:02 -04:00

206 lines
6.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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'),
];
}