我为 Laravel 创建了这个类,它利用 Intervention Image Cache 来处理和缓存用户上传的图像。此类通过 GET 端点调用,该端点传递图像 URI、目标宽度/高度和裁剪 w/h(如果适用)等内容。
图像被调整大小并裁剪到合适的尺寸;然而,这些图像似乎有点像素化,就好像它们可能被调整到更小的尺寸,然后又稍微放大了一样。我试图弄清楚我是否以错误的顺序执行调整大小/裁剪操作,以及这是否可能导致问题。无论是否传递裁剪参数,它似乎都会发生。我也尝试过使用 JPG 作为输出格式,但没有成功。有什么想法吗?
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Intervention\Image\Exception\NotReadableException;
use Intervention\Image\Facades\Image;
/**
* Class ImageCacheController
*
* Handles resizing, cropping and caching of modified images.
*/
class ImageCacheController extends Controller
{
/**
* Handles the image caching process.
*/
public function __invoke(Request $request, $width, $height, $crop_x, $crop_y, string $uri): mixed
{
// Set dimensions to null if they are 'null' string, and cast them to integers
$width = $this->convertNullString($width);
$height = $this->convertNullString($height);
$crop_x = $this->convertNullString($crop_x);
$crop_y = $this->convertNullString($crop_y);
// Get the image source
$src = storage_path('app') . '/public/uploads/' . $uri;
if (!file_exists($src)) {
// If the image doesn't exist, return a 404
return response('', 404);
}
try {
$cachedImage = Image::cache(function ($image) use ($src, $width, $height, $crop_x, $crop_y, $uri) {
$rawImage = Image::make($src);
$originalWidth = $rawImage->getWidth();
$originalHeight = $rawImage->getHeight();
// Calculate the ratio of the original image
$ratio = $originalWidth / $originalHeight;
// If the height is null, set it to 0
$cropHeight = $height === null ? 0 : $height;
$cropWidth = $width;
// If the cropHeight is less than 1, set it to the width divided by the ratio
if ($cropHeight < 1) {
$cropHeight = (int)floor($width / $ratio);
$height = null;
}
$image = $image->make($src);
$image = $image->resize($cropWidth === null ? null : $width, $height, function ($constraint) {
$constraint->aspectRatio();
});
// If the crop_x and crop_y are set, crop the image
if (isset($crop_x, $crop_y) && $cropHeight !== null) {
$image = $image->fit($width, $cropHeight)->trim();
}
// Encode the image to webp
return $image->encode('webp', 95);
}, 7776000, true);
return $cachedImage->response();
} catch (NotReadableException $e) {
// If there was an error reading the image, return a 404
return response($e->getMessage(), 404);
}
}
/**
* Converts the string 'null' to a real null value.
*
* @param mixed $value
* @return mixed|null
*/
private function convertNullString(mixed $value): ?int
{
return $value === 'null' ? null : (int)$value;
}
}
如果您在 Laravel 中使用 Intervention Image 调整大小/裁剪图像并且输出图像像素化,则可能是因为您没有正确设置图像质量。
调整图像大小或裁剪图像时,图像质量会受到影响。为保证输出图像的质量,保存图像时需要设置质量参数。这是一个例子:
use Intervention\Image\Facades\Image;
public function resizeImage()
{
$image = Image::make(public_path('images/image.jpg'));
$image->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
});
$image->save(public_path('images/resized-image.jpg'), 80);
}
在上面的示例中,我们在保存调整大小的图像时将质量参数设置为 80。这可确保输出图像具有高质量且不会像素化。
您还可以在裁剪图像时设置质量参数。这是一个例子:
use Intervention\Image\Facades\Image;
public function cropImage()
{
$image = Image::make(public_path('images/image.jpg'));
$image->crop(200, 200, 100, 100);
$image->save(public_path('images/cropped-image.jpg'), 80);
}
在这个例子中,我们在保存裁剪后的图像时将质量参数设置为80。
通过正确设置质量参数,您可以确保输出图像质量高且不像素化。您可以尝试不同的质量值来找到最适合您图像的设置。