Dans PHP, ImageOpenPolygon () est une fonction très pratique qui peut être utilisée pour tracer des lignes de polygone ouvertes. Cette fonction fonctionne bien lors du dessin à petites échelles, mais lorsqu'elle implique un grand nombre de points ou de tâches de dessin à grande échelle, son goulot d'étranglement des performances apparaît progressivement. Cet article explorera certaines façons d'améliorer les performances de ImageOpenPolygon () dans le dessin à grande échelle.
ImageOpenPolygon () accepte un tableau de points, généralement un tableau unidimensionnel, comme [x1, y1, x2, y2, ..., xn, yn] . Lors de la génération de ces données ponctuelles:
Essayez de pré-créer tous les points et évitez les calculs dynamiques lorsque vous appelez ImageOpenPolygon () .
Assurez-vous que le tableau est compact et n'a pas de valeurs nulles supplémentaires ni de points en double.
// Pas recommandé:Points générés dynamiquement
$points = [];
for ($i = 0; $i < 1000; $i++) {
$points[] = rand(0, 500);
$points[] = rand(0, 500);
}
imageopenpolygon($image, $points, count($points) / 2, $color);
// recommander:Tableau fixe préparé à l'avance
$points = generatePoints(); // generatePoints()Retourner un tableau unidimensionnel optimisé en interne
imageopenpolygon($image, $points, count($points) / 2, $color);
S'il y a beaucoup de polygones en double ou similaires dans votre dessin, pensez:
Cache le tableau de points généré dans un fichier ou une mémoire (comme l'utilisation de redis).
Réutilisez ces données à chaque fois que vous dessinez, plutôt que de régénérer à chaque fois.
$cacheKey = 'polygon_points_large';
$points = apcu_fetch($cacheKey);
if ($points === false) {
$points = generateLargePolygonPoints();
apcu_store($cacheKey, $points);
}
imageopenpolygon($image, $points, count($points) / 2, $color);
Remarque: L'utilisation du cache APCU nécessite que le serveur permette des extensions APCU.
Lors du dessin à grande échelle, tous les détails ne doivent pas nécessairement être affichés avec précision. Une simplification appropriée de l'ensemble des points peut considérablement améliorer les performances:
Utilisez l'algorithme de décimation pour réduire le nombre de points.
Le taux d'échantillonnage est déterminé dynamiquement en fonction du niveau de zoom.
Exemple de simplification de point simple:
function simplifyPoints(array $points, int $threshold = 5): array {
$simplified = [];
for ($i = 0; $i < count($points) - 2; $i += 2) {
if ($i % ($threshold * 2) == 0) {
$simplified[] = $points[$i];
$simplified[] = $points[$i + 1];
}
}
return $simplified;
}
$originalPoints = generateVeryLargePolygon();
$points = simplifyPoints($originalPoints, 10);
imageopenpolygon($image, $points, count($points) / 2, $color);
Bien que la bibliothèque GD soit intégrée à PHP et soit facile à utiliser, les performances de GD peuvent être insuffisantes sous des exigences de dessin extrêmes. Considérer:
En utilisant Imagick (extension PHP basée sur ImageMagick), il fonctionne mieux sur le traitement graphique à grande échelle.
En combinaison avec la méthode CLI, appelez un programme de dessin spécial (comme appeler la commande ImageMagick via shell_exec ()).
Exemples Utiliser Imagick:
$draw = new ImagickDraw();
$draw->setStrokeColor('black');
$draw->setFillColor('none');
$draw->setStrokeWidth(1);
$draw->polyline([
['x' => 10, 'y' => 10],
['x' => 100, 'y' => 30],
['x' => 50, 'y' => 100],
]);
$image = new Imagick();
$image->newImage(200, 200, "white");
$image->drawImage($draw);
$image->setImageFormat("png");
$image->writeImage('/var/www/html/uploads/output.png');
Si le contenu de dessin est très grand, vous pouvez envisager de diviser la toile en plusieurs petites pièces (carreaux), puis les synthétiser après le dessin:
Seules les zones visibles sont dessinées à la fois.
Réduisez les frais généraux uniques de mémoire.
function renderTile($startX, $startY, $width, $height, $points) {
$image = imagecreatetruecolor($width, $height);
$background = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 0, 0, $background);
$color = imagecolorallocate($image, 0, 0, 0);
$tilePoints = filterPointsForTile($points, $startX, $startY, $width, $height);
if (!empty($tilePoints)) {
imageopenpolygon($image, $tilePoints, count($tilePoints) / 2, $color);
}
return $image;
}
Grâce à cette méthode, la charge de chaque action de dessin peut être considérablement réduite et les performances globales peuvent être améliorées.