PHPでは、 ImageOpenPolygon()は、オープンポリゴンラインを描くために使用できる非常に実用的な機能です。この関数は、小さなスケールで描画するときにうまく機能しますが、多数のポイントまたは大規模な描画タスクを伴う場合、そのパフォーマンスボトルネックが徐々に表示されます。この記事では、大規模な図面でImageOpenPolygon()のパフォーマンスを改善するいくつかの方法について説明します。
ImageOpenPolygon()は、[x1、y1、x2、y2、...、xn、yn]のような1次元配列の配列を受け入れます。これらのポイントデータを生成するとき:
すべてのポイントを事前に作成し、 ImageOpenPolygon()を呼び出すときに動的計算を避けてみてください。
配列がコンパクトで、追加のnull値や重複ポイントがないことを確認してください。
// お勧めしません:動的に生成されたポイント
$points = [];
for ($i = 0; $i < 1000; $i++) {
$points[] = rand(0, 500);
$points[] = rand(0, 500);
}
imageopenpolygon($image, $points, count($points) / 2, $color);
// 推薦する:事前に準備されたアレイを固定しました
$points = generatePoints(); // generatePoints()最適化された1次元配列を内部的に返します
imageopenpolygon($image, $points, count($points) / 2, $color);
図面に多くの重複または類似のポリゴンがある場合は、次のことを検討してください。
生成されたドットアレイをファイルまたはメモリ(Redisの使用など)にキャッシュします。
毎回再生するのではなく、描画するたびにこのデータを再利用します。
$cacheKey = 'polygon_points_large';
$points = apcu_fetch($cacheKey);
if ($points === false) {
$points = generateLargePolygonPoints();
apcu_store($cacheKey, $points);
}
imageopenpolygon($image, $points, count($points) / 2, $color);
注:APCUキャッシュを使用するには、APCU拡張機能を有効にするためにサーバーが必要です。
大規模に描画する場合、必ずしもすべての詳細を正確に表示する必要がありません。ポイントのセットの適切な簡素化は、パフォーマンスを大幅に改善できます。
Decimation Algorithmを使用して、ポイント数を減らします。
サンプリングレートは、ズームレベルに基づいて動的に決定されます。
単純な点の単純化例:
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);
GDライブラリはPHPに組み込まれており、使いやすいですが、GDのパフォーマンスは極端な描画要件では不十分である可能性があります。考慮する:
ImagicICK (ImageMagickに基づくPHP拡張)を使用して、大規模なグラフィックス処理により優れたパフォーマンスを発揮します。
CLIメソッドと組み合わせて、特別な図面プログラム(shell_exec()を介してImagemagickコマンドを呼び出すなど)を呼び出します。
例はimagicickを使用します:
$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');
描画コンテンツが非常に大きい場合は、キャンバスを複数の小片(タイル)に分割することを検討し、描画後に合成します。
目に見える領域のみが一度に描かれています。
一度限りのメモリオーバーヘッドを減らします。
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;
}
この方法により、各図面アクションの負担を大幅に削減し、全体的なパフォーマンスを改善できます。