我将为您创建一个完整的PHP脚本,用于批量生成NFT图片,这个脚本会结合多个图层组件(如背景、身体、眼睛、装饰等)来生成独特的NFT图片。

完整PHP NFT生成脚本
<?php
/**
* NFT图片批量生成器
* 通过组合不同图层生成独特的NFT图片
*/
class NFTGenerator {
private $layers = [];
private $outputDir;
private $width = 1000;
private $height = 1000;
private $totalSupply = 100;
private $rarityLevels = ['common' => 0.6, 'rare' => 0.25, 'epic' => 0.1, 'legendary' => 0.05];
public function __construct($outputDir = 'nft_output') {
$this->outputDir = $outputDir;
if (!file_exists($outputDir)) {
mkdir($outputDir, 0777, true);
}
if (!extension_loaded('gd')) {
die('需要启用GD库');
}
}
/**
* 配置图层
*
* 目录结构示例:
* layers/
* background/
* 红色背景.png
* 蓝色背景.png
* body/
* 标准身体.png
* 特殊身体.png
*/
public function loadLayers($layersDir) {
$directories = ['background', 'body', 'eyes', 'mouth', 'accessory'];
foreach ($directories as $dir) {
$path = $layersDir . '/' . $dir;
if (is_dir($path)) {
$files = glob($path . '/*.{png,jpg,jpeg}', GLOB_BRACE);
if (!empty($files)) {
$this->layers[$dir] = [];
foreach ($files as $file) {
$this->layers[$dir][] = [
'path' => $file,
'name' => pathinfo($file, PATHINFO_FILENAME),
'rarity' => $this->determineRarity($file)
];
}
}
}
}
if (empty($this->layers)) {
die('没有找到图层文件');
}
}
/**
* 根据文件名确定稀有度(可通过文件名包含关键字)
*/
private function determineRarity($file) {
$filename = strtolower(basename($file));
if (strpos($filename, 'legendary') !== false) return 'legendary';
if (strpos($filename, 'epic') !== false) return 'epic';
if (strpos($filename, 'rare') !== false) return 'rare';
return 'common';
}
/**
* 生成单个NFT
*/
public function generateSingle($id) {
$bg = imagecreatetruecolor($this->width, $this->height);
// 设置白色背景
$white = imagecolorallocate($bg, 255, 255, 255);
imagefill($bg, 0, 0, $white);
$selectedLayers = [];
$attributes = [];
// 后台优先
if (isset($this->layers['background'])) {
$layer = $this->selectLayer($this->layers['background']);
$this->applyLayer($bg, $layer);
$attributes[] = ['trait_type' => 'Background', 'value' => $layer['name']];
$selectedLayers[] = $layer;
}
// 身体
if (isset($this->layers['body'])) {
$layer = $this->selectLayer($this->layers['body']);
$this->applyLayer($bg, $layer);
$attributes[] = ['trait_type' => 'Body', 'value' => $layer['name']];
$selectedLayers[] = $layer;
}
// 眼睛
if (isset($this->layers['eyes'])) {
$layer = $this->selectLayer($this->layers['eyes']);
$this->applyLayer($bg, $layer);
$attributes[] = ['trait_type' => 'Eyes', 'value' => $layer['name']];
$selectedLayers[] = $layer;
}
// 嘴巴
if (isset($this->layers['mouth'])) {
$layer = $this->selectLayer($this->layers['mouth']);
$this->applyLayer($bg, $layer);
$attributes[] = ['trait_type' => 'Mouth', 'value' => $layer['name']];
$selectedLayers[] = $layer;
}
// 装饰品
if (isset($this->layers['accessory'])) {
$layer = $this->selectLayer($this->layers['accessory']);
$this->applyLayer($bg, $layer);
$attributes[] = ['trait_type' => 'Accessory', 'value' => $layer['name']];
$selectedLayers[] = $layer;
}
// 计算稀有度
$rarity = 'common';
$rarityScore = 1;
foreach ($selectedLayers as $layer) {
if ($layer['rarity'] === 'legendary') {
$rarity = 'legendary';
$rarityScore *= 0.5;
} elseif ($layer['rarity'] === 'epic' && $rarity !== 'legendary') {
$rarity = 'epic';
$rarityScore *= 0.7;
} elseif ($layer['rarity'] === 'rare' && $rarity === 'common') {
$rarity = 'rare';
$rarityScore *= 0.85;
}
}
// 保存图片
$filename = $this->outputDir . '/nft_' . $id . '.png';
imagepng($bg, $filename);
imagedestroy($bg);
// 生成元数据
$metadata = [
'name' => 'NFT #' . $id,
'description' => '独特的数字艺术品 NFT #' . $id,
'image' => $filename,
'attributes' => $attributes,
'rarity' => $rarity,
'rarity_score' => round($rarityScore, 3)
];
// 保存元数据
file_put_contents($this->outputDir . '/nft_' . $id . '.json', json_encode($metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
echo "生成 NFT #{$id} 成功 (稀有度: {$rarity})\n";
return $metadata;
}
/**
* 选择图层(带稀有度权重)
*/
private function selectLayer($layers) {
// 根据稀有度权重选择
$totalWeight = 0;
foreach ($layers as $layer) {
$weight = $this->rarityLevels[$layer['rarity']] ?? 0.1;
$totalWeight += $weight;
}
$random = mt_rand(0, $totalWeight * 100) / 100;
$cumulativeWeight = 0;
shuffle($layers); // 随机排序增加多样性
foreach ($layers as $layer) {
$weight = $this->rarityLevels[$layer['rarity']] ?? 0.1;
$cumulativeWeight += $weight;
if ($random <= $cumulativeWeight) {
return $layer;
}
}
return $layers[0]; // 默认返回第一个
}
/**
* 应用图层到图像
*/
private function applyLayer($base, $layer) {
$overlay = imagecreatefromstring(file_get_contents($layer['path']));
// 调整大小
$overlay = $this->resizeImage($overlay, $this->width, $this->height);
// 合并图像
imagecopy($base, $overlay, 0, 0, 0, 0, $this->width, $this->height);
imagedestroy($overlay);
}
/**
* 调整图像大小
*/
private function resizeImage($image, $width, $height) {
$newImage = imagecreatetruecolor($width, $height);
imagealphablending($newImage, true);
imagesavealpha($newImage, true);
$srcW = imagesx($image);
$srcH = imagesy($image);
imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $srcW, $srcH);
imagedestroy($image);
return $newImage;
}
/**
* 批量生成NFT
*/
public function generateBatch($count) {
$generated = [];
$usedCombinations = [];
echo "开始生成 {$count} 个NFT...\n";
for ($i = 1; $i <= $count; $i++) {
// 获取唯一组合
do {
$combination = $this->getRandomCombination();
$hash = md5(implode('|', $combination));
} while (in_array($hash, $usedCombinations));
$usedCombinations[] = $hash;
$this->generateSingle($i);
$generated[] = $i;
if ($i % 10 == 0) {
echo "已完成 {$i}/{$count} 个NFT\n";
}
}
echo "批量生成完成!共生成 " . count($generated) . " 个NFT\n";
}
/**
* 获取随机组合(用于唯一性检查)
*/
private function getRandomCombination() {
$combination = [];
foreach ($this->layers as $layerType => $layers) {
$combination[] = $this->selectLayer($layers)['name'];
}
return $combination;
}
/**
* 生成项目级元数据
*/
public function generateCollectionMetadata($name, $description) {
$metadata = [
'name' => $name,
'description' => $description,
'image' => 'https://example.com/logo.png',
'external_link' => 'https://example.com',
'seller_fee_basis_points' => 500,
'fee_recipient' => '0x0000000000000000000000000000000000000000'
];
file_put_contents($this->outputDir . '/collection.json', json_encode($metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
echo "项目元数据已生成\n";
}
/**
* 生成统计报告
*/
public function generateStatistics() {
$stats = [];
$jsonFiles = glob($this->outputDir . '/*.json');
foreach ($jsonFiles as $file) {
if (basename($file) === 'collection.json') continue;
$data = json_decode(file_get_contents($file), true);
if (isset($data['rarity'])) {
$stats[$data['rarity']] = ($stats[$data['rarity']] ?? 0) + 1;
}
}
echo "\n=== NFT稀有度统计 ===\n";
foreach ($stats as $rarity => $count) {
$percentage = round(($count / array_sum($stats)) * 100, 2);
echo "{$rarity}: {$count}个 ({$percentage}%)\n";
}
return $stats;
}
}
// ==================== 使用示例 ====================
// 初始化生成器
$generator = new NFTGenerator('my_nft_collection');
// 加载图层(请确保图层目录结构正确)
$generator->loadLayers('layers');
// 设置NFT数量
$totalNFTs = 100;
// 批量生成
$generator->generateBatch($totalNFTs);
// 生成项目元数据
$generator->generateCollectionMetadata(
'我的NFT收藏',
'这是一个由PHP自动生成的独特NFT收藏系列'
);
// 生成统计报告
$generator->generateStatistics();
echo "\nNFT生成完成!请检查 my_nft_collection 目录\n";
// 可以添加更多的自定义功能
?>
辅助脚本:创建示例图层
创建以下脚本来生成简单的示例图层:
<?php
/**
* 生成示例NFT图层
*/
class LayerCreator {
private $layersDir;
public function __construct() {
$this->layersDir = __DIR__ . '/layers';
$this->createDirectories();
}
private function createDirectories() {
$dirs = ['background', 'body', 'eyes', 'mouth', 'accessory'];
foreach ($dirs as $dir) {
if (!file_exists($this->layersDir . '/' . $dir)) {
mkdir($this->layersDir . '/' . $dir, 0777, true);
}
}
}
public function generateBackgrounds() {
$colors = [
'common' => ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'],
'rare' => ['#FFEAA7', '#DDA0DD', '#98FB98', '#FFDAB9'],
'epic' => ['#FFB6C1', '#87CEEB', '#DDA0DD', '#FF69B4'],
'legendary' => ['#FFD700', '#FF1493', '#00CED1', '#8A2BE2']
];
foreach ($colors as $rarity => $palette) {
foreach ($palette as $i => $color) {
$img = imagecreatetruecolor(1000, 1000);
$rgb = $this->hexToRgb($color);
$bg = imagecolorallocate($img, $rgb[0], $rgb[1], $rgb[2]);
imagefill($img, 0, 0, $bg);
// 添加简单的渐变效果
for ($y = 0; $y < 1000; $y += 10) {
$alpha = ($y / 1000) * 127;
$gradient = imagecolorallocatealpha($img, 255, 255, 255, $alpha);
imageline($img, 0, $y, 1000, $y, $gradient);
}
$filename = $this->layersDir . "/background/bg_{$rarity}_{$i}.png";
imagepng($img, $filename);
imagedestroy($img);
}
}
echo "生成背景图层完成\n";
}
public function generateBodies() {
$shapes = [
'circle', 'rounded', 'squared', 'star'
];
foreach ($shapes as $i => $shape) {
$img = imagecreatetruecolor(1000, 1000);
imagesavealpha($img, true);
$transparent = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $transparent);
$color = imagecolorallocate($img, 255, 128, 0);
switch ($shape) {
case 'circle':
imagefilledellipse($img, 500, 500, 700, 700, $color);
break;
case 'rounded':
imagefilledrectangle($img, 300, 300, 700, 700, $color);
break;
case 'squared':
imagefilledrectangle($img, 250, 250, 750, 750, $color);
break;
case 'star':
$points = $this->getStarPoints(5, 350, 500, 500);
imagefilledpolygon($img, $points, 5, $color);
break;
}
$rarity = $i < 2 ? 'common' : ($i < 3 ? 'rare' : 'epic');
$filename = $this->layersDir . "/body/body_{$rarity}_{$i}.png";
imagepng($img, $filename);
imagedestroy($img);
}
echo "生成身体图层完成\n";
}
public function generateEyes() {
$styles = [
'small', 'large', 'round', 'cat', 'robot', 'sleepy'
];
foreach ($styles as $i => $style) {
$img = imagecreatetruecolor(1000, 1000);
imagesavealpha($img, true);
$transparent = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $transparent);
$eyeColor = imagecolorallocate($img, 50, 50, 50);
$white = imagecolorallocate($img, 255, 255, 255);
switch ($style) {
case 'small':
imagefilledellipse($img, 400, 400, 40, 40, $eyeColor);
imagefilledellipse($img, 600, 400, 40, 40, $eyeColor);
break;
case 'large':
imagefilledellipse($img, 380, 380, 100, 100, $white);
imagefilledellipse($img, 620, 380, 100, 100, $white);
imagefilledellipse($img, 380, 380, 60, 60, $eyeColor);
imagefilledellipse($img, 620, 380, 60, 60, $eyeColor);
break;
case 'robot':
imagefilledrectangle($img, 360, 360, 440, 440, $eyeColor);
imagefilledrectangle($img, 560, 360, 640, 440, $eyeColor);
break;
default:
imagefilledellipse($img, 400, 400, 70, 70, $eyeColor);
imagefilledellipse($img, 600, 400, 70, 70, $eyeColor);
}
$rarity = $i < 3 ? 'common' : ($i < 5 ? 'rare' : 'legendary');
$filename = $this->layersDir . "/eyes/eyes_{$rarity}_{$i}.png";
imagepng($img, $filename);
imagedestroy($img);
}
echo "生成眼睛图层完成\n";
}
public function generateMouths() {
$styles = ['smile', 'grin', 'frown', 'surprised', 'neutral'];
foreach ($styles as $i => $style) {
$img = imagecreatetruecolor(1000, 1000);
imagesavealpha($img, true);
$transparent = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $transparent);
$mouthColor = imagecolorallocate($img, 150, 50, 50);
switch ($style) {
case 'smile':
imagearc($img, 500, 600, 200, 100, 0, 180, $mouthColor);
break;
case 'grin':
imagefilledellipse($img, 500, 600, 200, 100, $mouthColor);
break;
case 'frown':
imagearc($img, 500, 700, 200, 100, 180, 360, $mouthColor);
break;
case 'surprised':
imagefilledellipse($img, 500, 650, 50, 80, $mouthColor);
break;
default:
imageline($img, 400, 650, 600, 650, $mouthColor);
}
$rarity = $i < 3 ? 'common' : ($i < 4 ? 'rare' : 'epic');
$filename = $this->layersDir . "/mouth/mouth_{$rarity}_{$i}.png";
imagepng($img, $filename);
imagedestroy($img);
}
echo "生成嘴巴图层完成\n";
}
public function generateAccessories() {
$items = ['crown', 'hat', 'glasses', 'chain', 'hat_rare', 'crown_legendary'];
foreach ($items as $i => $item) {
$img = imagecreatetruecolor(1000, 1000);
imagesavealpha($img, true);
$transparent = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $transparent);
$color = imagecolorallocate($img, 255, 215, 0);
switch ($item) {
case 'crown':
imagefilledpolygon($img, [400,300, 450,200, 500,300, 550,200, 600,300], 5, $color);
break;
case 'hat':
imagefilledellipse($img, 500, 300, 300, 100, $color);
imagefilledrectangle($img, 420, 250, 580, 380, $color);
break;
case 'glasses':
imagesetthickness($img, 5);
imagearc($img, 400, 400, 100, 100, 0, 360, $color);
imagearc($img, 600, 400, 100, 100, 0, 360, $color);
break;
case 'chain':
imagesetthickness($img, 10);
imageline($img, 400, 700, 600, 700, $color);
imagefilledellipse($img, 500, 700, 30, 30, $color);
break;
case 'hat_rare':
imagefilledellipse($img, 500, 250, 250, 50, $color);
imagefilledrectangle($img, 450, 200, 550, 350, $color);
break;
case 'crown_legendary':
$points = [350,300, 400,150, 450,250, 500,100, 550,250, 600,150, 650,300];
imagefilledpolygon($img, $points, 7, $color);
break;
}
$rarity = strpos($item, 'legendary') !== false ? 'legendary' : (strpos($item, 'rare') !== false ? 'rare' : 'common');
$filename = $this->layersDir . "/accessory/acc_{$rarity}_{$i}.png";
imagepng($img, $filename);
imagedestroy($img);
}
echo "生成装饰品图层完成\n";
}
private function hexToRgb($hex) {
$hex = str_replace('#', '', $hex);
return [hexdec(substr($hex, 0, 2)), hexdec(substr($hex, 2, 2)), hexdec(substr($hex, 4, 2))];
}
private function getStarPoints($points, $radius, $centerX, $centerY) {
$coords = [];
for ($i = 0; $i < $points * 2; $i++) {
$angle = deg2rad($i * 180 / $points);
$r = $i % 2 == 0 ? $radius : $radius * 0.4;
$coords[] = $centerX + $r * cos($angle);
$coords[] = $centerY + $r * sin($angle);
}
return $coords;
}
public function generateAll() {
$this->generateBackgrounds();
$this->generateBodies();
$this->generateEyes();
$this->generateMouths();
$this->generateAccessories();
echo "所有示例图层生成完成!\n";
}
}
// 运行图层生成器
$creator = new LayerCreator();
$creator->generateAll();
?>
使用方法
-
准备环境
# 确保PHP已安装并启用GD库 php -m | grep gd
-
创建目录结构
project/ ├── generate_nft.php # 主生成脚本 ├── create_layers.php # 图层生成脚本 └── layers/ # 图层目录 -
运行脚本
# 1. 先生成示例图层 php create_layers.php
运行NFT生成器
php generate_nft.php
4. **查看输出**
my_nft_collection/ ├── nft_1.png ├── nft_1.json ├── nft_2.png ├── nft_2.json ├── ... ├── collection.json └── ...
## 高级功能
### 1. 自定义元数据格式
```php
// 添加更多属性
$attributes[] = ['display_type' => 'number', 'trait_type' => 'Level', 'value' => rand(1, 100)];
批量大小控制
// 分批次生成 $generator->generateBatch(200); // 先生成200个 $generator->generateBatch(300); // 再生成300个
集成智能合约
// 可以使用 ethers.js 或 web3.js 与合约交互 $whitelist = ['0x...', '0x...']; // 白名单地址
这个脚本为您提供了一个功能完整的NFT生成系统,您可以根据需要调整图层、添加更多属性、集成区块链功能等,记住要合理管理图层资源,确保每个图层都有足够的多样性!