LoginSignup
2
3

More than 5 years have passed since last update.

laravel パラメータ指定で簡単画像Resize&Crop

Last updated at Posted at 2019-01-17

http://hoge.com/path/to/abc.jpg

http://hoge.com/path/to/abc.jpg.cnv?thumb=300x200 でサムネイル
http://hoge.com/path/to/abc.jpg.cnv?crop=300x200 で切り出し
http://hoge.com/path/to/abc.jpg.cnv?fit=300x200-top で最適切り出し
したりします。

2019/01/23 追加

  • サムネイルを無限生成できちゃうので、ファイル単位で制限を設定しましたー
  • laravelのcache機構を導入しましたー

@mikkame さんありがとございます

2019/01/24 追加

  • cacheに関する記述追加

設定方法

初期設定

interventionインストール

$ php composer.phar require intervention/image #interventionインストール

.env の設定

.env
CACHE_DRIVER=array #ローカルでキャッシュを無効にする場合
CACHE_DRIVER=file #fileベースでキャッシュする場合
CACHE_DRIVER=redis #redisを使う場合

ImageRouting.php

どこかに配置します。

app/Services/ImageRouting.php
<?php

namespace App\Services;

use Cache;
use Illuminate\Http\Request;
use Intervention\Image\Image;

class ImageRouting
{
    /**
     * @param string $imagePath 画像のフルパス
     * @param Request $request
     * @param string $extension 識別用の拡張子
     * @param int $limit 生成件数制限
     * @param int $cacheDays キャッシュ保持期間
     * @return mixed
     */
    function __invoke(
        string $imagePath,
        Request $request,
        string $extension = '.cnv',
        int $limit = 10,
        int $cacheDays = 3
    )
    {
        $imagePath = str_replace($extension, '', $imagePath);

        $counterCache = md5($imagePath);
        $fileCache = md5(json_encode([$imagePath, $request->all()]));

        if (Cache::get($counterCache, 0) < $limit) {

            $image = Cache::remember($fileCache, 60 * 24 * $cacheDays,
                function () use ($request, $imagePath, $counterCache) {

                    $image = \Image::make(public_path($imagePath));

                    $image = $this->fitIfNeeded($image, $request);
                    $image = $this->cropIfNeeded($image, $request);
                    $image = $this->thumbnailIfNeeded($image, $request);

                    Cache::increment($counterCache);

                    return $image->response('jpg');
                });

            return $image;
        } else {
            abort(404);
        }
    }

    /**
     * hoge.cnv.jpg?fit=300x200-top (収まるようにトリミング)
     * @param $image
     * @param $request
     * @return Image
     */
    private function fitIfNeeded(Image $image, Request $request): Image
    {
        //chukyo.jpg_?fit=300x200-top (収まるようにトリミング)
        $fit = $request->f ?: $request->fit;
        if ($fit && preg_match('/([0-9]+)x([0-9]+)(:?-([-a-z]+))?/', $fit, $mc)) {

            $image->fit($mc[1], $mc[2], function ($constraint) {
                $constraint->upsize();
            }, !empty($mc[3]) ? $mc[3] : 'center');
        }

        return $image;
    }

    /**
     * hoge.cnv.jpg?crop=300x200 (切り出す)
     * @param $image
     * @param $request
     * @return Image
     */
    private function cropIfNeeded(Image $image, Request $request): Image
    {
        //chukyo.jpg_?crop=300x200 (切り出す)
        $crop = $request->c ?: $request->crop;
        if ($crop && preg_match('/([0-9]+)x([0-9]+)/', $crop, $mc)) {
            $image->crop($mc[1], $mc[2]);
        }

        return $image;
    }

    /**
     * hoge.cnv.jpg?thumb=300x200 (収まるように縮小)
     * @param Image $image
     * @param Request $request
     * @return Image
     */
    private function thumbnailIfNeeded(Image $image, Request $request): Image
    {
        $thumb = $request->t ?: $request->thumb;
        if ($thumb && preg_match('/([0-9]+)x([0-9]+)/', $thumb, $mc)) {

            if ($image->width() < $image->height()) {
                $image->resize($mc[1], null, function ($constraint) {
                    $constraint->aspectRatio();
                    $constraint->upsize();
                });
            } else {
                $image->resize(null, $mc[2], function ($constraint) {
                    $constraint->aspectRatio();
                    $constraint->upsize();
                });
            }
        }

        return $image;
    }
}

routes/web.php に追加

routes/web.php

use Illuminate\Http\Request;

Route::get('{imagePath}', function ($imagePath, Request $request, \App\Services\ImageRouting $service) {

    return $service($imagePath, $request);

})->where('imagePath', '(.*).cnv.(jpg|jpeg|png|gif)$');
2
3
14

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3