Import initial de Vivier depuis l'hebergement OVH
This commit is contained in:
commit
839e5e57c5
126 files changed
+22447
No files matched your search
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
// Tests de la recherche de photo dans un CV : php tests/test_photo.php
|
||||
declare(strict_types=1);
|
||||
const VIVIER_RACINE = __DIR__ . '/..';
|
||||
require __DIR__ . '/../src/i18n.php';
|
||||
require __DIR__ . '/../src/Photo.php';
|
||||
|
||||
$ok = 0; $ko = 0;
|
||||
function verifier(string $nom, bool $cond): void {
|
||||
global $ok, $ko;
|
||||
if ($cond) { $ok++; } else { $ko++; echo "ECHEC : $nom\n"; }
|
||||
}
|
||||
if (!Photo::disponible()) { echo "Extension GD absente : tests ignorés.\n"; exit(0); }
|
||||
|
||||
/** Image aux teintes variées, comme une photo. */
|
||||
function portrait(int $l, int $h, string $format = 'jpeg'): string {
|
||||
$img = imagecreatetruecolor($l, $h);
|
||||
mt_srand(7);
|
||||
for ($y = 0; $y < $h; $y += 4) {
|
||||
for ($x = 0; $x < $l; $x += 4) {
|
||||
imagefilledrectangle($img, $x, $y, $x + 3, $y + 3, imagecolorallocate($img, ($x * 255 / $l + mt_rand(0, 60)) % 256, ($y * 255 / $h + mt_rand(0, 60)) % 256, mt_rand(60, 200)));
|
||||
}
|
||||
}
|
||||
ob_start(); $format === 'png' ? imagepng($img) : imagejpeg($img, null, 90); return (string) ob_get_clean();
|
||||
}
|
||||
/** Image à deux couleurs, comme un logo. */
|
||||
function logo(int $l, int $h): string {
|
||||
$img = imagecreatetruecolor($l, $h);
|
||||
imagefill($img, 0, 0, imagecolorallocate($img, 255, 255, 255));
|
||||
imagefilledrectangle($img, (int) ($l / 4), (int) ($h / 4), (int) ($l * 3 / 4), (int) ($h * 3 / 4), imagecolorallocate($img, 206, 183, 59));
|
||||
ob_start(); imagepng($img); return (string) ob_get_clean();
|
||||
}
|
||||
function dimensions(?string $jpeg): array { $t = $jpeg ? getimagesizefromstring($jpeg) : [0, 0, 0]; return [$t[0], $t[1], $t[2]]; }
|
||||
|
||||
$tmp = sys_get_temp_dir() . '/vivier-test-' . bin2hex(random_bytes(4));
|
||||
mkdir($tmp);
|
||||
|
||||
// --- Word : la photo parmi un logo et un bandeau
|
||||
$zip = new ZipArchive(); $zip->open("$tmp/cv.docx", ZipArchive::CREATE);
|
||||
$zip->addFromString('word/document.xml', '<w:document/>');
|
||||
$zip->addFromString('word/media/image1.png', logo(400, 400));
|
||||
$zip->addFromString('word/media/image2.jpeg', portrait(600, 760));
|
||||
$zip->addFromString('word/media/image3.jpeg', portrait(900, 120));
|
||||
$zip->addFromString('word/media/image4.png', portrait(40, 50, 'png'));
|
||||
$zip->close();
|
||||
[$l, $h, $type] = dimensions(Photo::extraire("$tmp/cv.docx", 'docx'));
|
||||
verifier('Word : le portrait est retenu, pas le logo ni le bandeau', $type === IMAGETYPE_JPEG && abs($l / max($h, 1) - 600 / 760) < 0.02);
|
||||
verifier('Word : photo réduite à 480 px au plus', max($l, $h) === 480);
|
||||
|
||||
$zip = new ZipArchive(); $zip->open("$tmp/sans.docx", ZipArchive::CREATE);
|
||||
$zip->addFromString('word/document.xml', '<w:document/>');
|
||||
$zip->addFromString('word/media/image1.png', logo(400, 400));
|
||||
$zip->close();
|
||||
verifier('Word sans photo : rien n\'est retenu', Photo::extraire("$tmp/sans.docx", 'docx') === null);
|
||||
|
||||
// --- PDF : image JPEG
|
||||
$jpeg = portrait(300, 380);
|
||||
$pdf = "%PDF-1.4\n1 0 obj\n<< /Type /XObject /Subtype /Image /Width 300 /Height 380 /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length " . strlen($jpeg) . " >>\nstream\n" . $jpeg . "\nendstream\nendobj\n%%EOF";
|
||||
file_put_contents("$tmp/jpeg.pdf", $pdf);
|
||||
[$l, $h] = dimensions(Photo::extraire("$tmp/jpeg.pdf", 'pdf'));
|
||||
verifier('PDF : image JPEG retrouvée', $l === 300 && $h === 380);
|
||||
|
||||
// --- PDF : image compressée sans perte, avec et sans prédicteur
|
||||
$img = imagecreatefromstring(portrait(200, 240));
|
||||
$brut = ''; $filtre = '';
|
||||
for ($y = 0; $y < 240; $y++) {
|
||||
$ligne = '';
|
||||
for ($x = 0; $x < 200; $x++) { $c = imagecolorat($img, $x, $y); $ligne .= chr(($c >> 16) & 255) . chr(($c >> 8) & 255) . chr($c & 255); }
|
||||
$brut .= $ligne; $filtre .= "\0" . $ligne;
|
||||
}
|
||||
$objet = static fn (string $donnees, string $plus = ''): string => "%PDF-1.4\n4 0 obj\n<< /Subtype /Image /Width 200 /Height 240 /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /FlateDecode $plus/Length 9 0 R >>\nstream\r\n" . $donnees . "\r\nendstream\nendobj\n%%EOF";
|
||||
file_put_contents("$tmp/flate.pdf", $objet(gzcompress($brut)));
|
||||
[$l, $h] = dimensions(Photo::extraire("$tmp/flate.pdf", 'pdf'));
|
||||
verifier('PDF : image sans perte retrouvée, longueur indirecte', $l === 200 && $h === 240);
|
||||
file_put_contents("$tmp/predicteur.pdf", $objet(gzcompress($filtre), '/DecodeParms << /Predictor 15 /Colors 3 /Columns 200 >> '));
|
||||
[$l, $h] = dimensions(Photo::extraire("$tmp/predicteur.pdf", 'pdf'));
|
||||
verifier('PDF : image sans perte avec prédicteur retrouvée', $l === 200 && $h === 240);
|
||||
|
||||
file_put_contents("$tmp/texte.pdf", "%PDF-1.4\n1 0 obj\n<< /Length 20 >>\nstream\nBT (Bonjour) Tj ET\nendstream\nendobj\n%%EOF");
|
||||
verifier('PDF sans image : rien n\'est retenu', Photo::extraire("$tmp/texte.pdf", 'pdf') === null);
|
||||
file_put_contents("$tmp/casse.pdf", "%PDF-1.4 << /Subtype /Image /Width 300 /Height 300 /Filter /DCTDecode >> stream\nceci n'est pas une image");
|
||||
verifier('PDF endommagé : aucune erreur', Photo::extraire("$tmp/casse.pdf", 'pdf') === null);
|
||||
verifier('format sans image (txt) : rien', Photo::extraire(__FILE__, 'txt') === null);
|
||||
|
||||
// --- Normalisation
|
||||
[$l, $h, $type] = dimensions(Photo::normaliser(portrait(1200, 800, 'png')));
|
||||
verifier('chargement manuel : PNG converti en JPEG réduit', $type === IMAGETYPE_JPEG && $l === 480 && $h === 320);
|
||||
verifier('fichier qui n\'est pas une image : refusé', Photo::normaliser('<?php echo 1;') === null);
|
||||
|
||||
array_map('unlink', glob("$tmp/*")); rmdir($tmp);
|
||||
echo "$ok réussis, $ko échoués\n";
|
||||
exit($ko > 0 ? 1 : 0);
|
||||
Reference in new issue
Block a user