<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class PhotoController extends Controller
{
// 默认配置(可被请求参数覆盖)
protected $config = [
'paper_width' => 1500, // 5寸照片纸宽度 (5*300)
'paper_height' => 1050, // 5寸照片纸高度 (3.5*300)
'photo_width' => 280, // 1寸照片宽度
'photo_height' => 390, // 1寸照片高度
'margin' => 50, // 边距
'spacing' => 20, // 照片间距
'photos_per_row' => 5, // 每行照片数
'rows' => 2 // 行数
];
public function printOneInchPhotos(Request $request)
{
// $this->config['photo_width'] = 300;
try {
// 更新配置参数(从请求获取或使用默认值)
$this->updateConfig($request);
// 验证输入照片
$photoPath = '1cun.jpg';
// 创建画布
$canvas = $this->createCanvas();
// 加载并处理照片
$photo = $this->loadAndResizePhoto($photoPath);
// 在画布上排列照片
$this->arrangePhotosCompact($canvas, $photo);
// 输出结果
return $this->outputImage($canvas);
} catch (\Exception $e) {
return $this->handleError($e);
}
}
/**
* 从请求更新配置
*/
protected function updateConfig(Request $request)
{
$this->config = array_merge($this->config, [
'paper_width' => $request->input('paper_width', $this->config['paper_width']),
'paper_height' => $request->input('paper_height', $this->config['paper_height']),
'photo_width' => $request->input('photo_width', $this->config['photo_width']),
'photo_height' => $request->input('photo_height', $this->config['photo_height']),
'margin' => $request->input('margin', $this->config['margin']),
'spacing' => $request->input('spacing', $this->config['spacing']),
'photos_per_row' => $request->input('photos_per_row', $this->config['photos_per_row']),
'rows' => $request->input('rows', $this->config['rows'])
]);
}
/**
* 紧凑排列照片
*/
protected function arrangePhotosCompact($canvas, $photo)
{
// 计算总使用宽度和高度
$totalWidth = $this->config['photos_per_row'] * $this->config['photo_width']
+ ($this->config['photos_per_row'] - 1) * $this->config['spacing'];
$totalHeight = $this->config['rows'] * $this->config['photo_height']
+ ($this->config['rows'] - 1) * $this->config['spacing'];
// 计算起始位置(居中)
$startX = ($this->config['paper_width'] - $totalWidth) / 2;
$startY = ($this->config['paper_height'] - $totalHeight) / 2;
// 排列照片
for ($row = 0; $row < $this->config['rows']; $row++) {
for ($col = 0; $col < $this->config['photos_per_row']; $col++) {
$x = $startX + $col * ($this->config['photo_width'] + $this->config['spacing']);
$y = $startY + $row * ($this->config['photo_height'] + $this->config['spacing']);
imagecopy(
$canvas, $photo,
$x, $y,
0, 0,
$this->config['photo_width'], $this->config['photo_height']
);
}
}
imagedestroy($photo);
}
/**
* 创建画布
*/
protected function createCanvas()
{
$canvas = imagecreatetruecolor($this->config['paper_width'], $this->config['paper_height']);
$white = imagecolorallocate($canvas, 255, 255, 255);
imagefill($canvas, 0, 0, $white);
return $canvas;
}
/**
* 加载并调整照片尺寸
*/
protected function loadAndResizePhoto($path)
{
$photo = @imagecreatefromjpeg($path);
if (!$photo) {
throw new \RuntimeException("无法加载照片,可能不是有效的JPEG文件");
}
// 调整照片尺寸
$resized = imagecreatetruecolor($this->config['photo_width'], $this->config['photo_height']);
imagecopyresampled(
$resized, $photo,
0, 0, 0, 0,
$this->config['photo_width'], $this->config['photo_height'],
imagesx($photo), imagesy($photo)
);
imagedestroy($photo);
return $resized;
}
/**
* 验证照片路径
*/
protected function validatePhotoPath($path)
{
if (empty($path)) {
throw new \InvalidArgumentException("未提供照片路径");
}
$fullPath = storage_path('app/public/' . ltrim($path, '/'));
if (!file_exists($fullPath)) {
throw new \RuntimeException("照片文件不存在: " . $path);
}
return $fullPath;
}
/**
* 输出图像
*/
protected function outputImage($canvas)
{
ob_start();
imagejpeg($canvas, null, 95);
$imageData = ob_get_clean();
imagedestroy($canvas);
return response($imageData)
->header('Content-Type', 'image/jpeg')
->header('Content-Disposition', 'inline; filename="photo_print.jpg"');
}
/**
* 错误处理
*/
protected function handleError(\Exception $e)
{
$errorImage = imagecreatetruecolor(600, 100);
$bgColor = imagecolorallocate($errorImage, 255, 255, 255);
$textColor = imagecolorallocate($errorImage, 255, 0, 0);
imagefill($errorImage, 0, 0, $bgColor);
$lines = str_split($e->getMessage(), 80);
foreach ($lines as $i => $line) {
imagestring($errorImage, 5, 10, 20 + $i * 20, $line, $textColor);
}
ob_start();
imagejpeg($errorImage);
$imageData = ob_get_clean();
imagedestroy($errorImage);
return response($imageData)
->header('Content-Type', 'image/jpeg')
->header('Content-Disposition', 'inline; filename="error.jpg"');
}
}
路由
Route::get('cun','Api\PhotoController@printOneInchPhotos');