ブログ
これまでに経験してきたプロジェクトで気になる技術の情報を紹介していきます。
Laravel で画像を編集する
Okuda
3 years
モジュールインストール
Intervention Image
が一般的なのでこれを使う
ここでは一部紹介するので、その他のファンクションは以下を参照
Intervention Image
composer require intervention/image
読み込み
use Image;
class CheckController extends Controller
{
public function index(Request $request)
{
$img = Image::make($request->file('photo'));
}
}
引数は以下に対応
- 画像のパス
- 画像のURL
- 画像データ(バイナリ)
- data URLの画像データ
- GDのリソース
- ImageMagickのインスタンス
- SplFileInfoのインスタンス
- UploadedFileのインスタンス
$image = storage_path('app\lion.jpg');
$image = Storage::disk('local')->path('lion.jpg');
$image = Storage::disk('local')->get('lion.jpg');
$image = 'https://picsum.photos/200/300';
$img = Image::make($image);
画像操作
保存、画質
save()
- param1: パス - string
- param2: 画質 - int
- デフォルト = 30
- 値 = 0 ~ 100
// デフォルト 画質30
$path = storage_path('app\lion1.jpg');
$img->save($path);
// 画質 100
$img->save($path, 100);
ぼかし
blur()
- param1: ぼかし - int
- 値 = -100 ~ 100
// ぼかし小
$img->blur(0);
// ぼかし大
$img->blur(100);
モザイク
pixelate()
- param1: モザイクの大きさ - int
$img->pixelate(10);
明るさ
brightness()
- param2: ボケ - int
- 値 = 0 ~ 100
// 暗い
$img->blur(0);
// 明るい
$img->blur(100);
色調
colorize()
- param1: 赤 - int
- 値 = -100 ~ 100
- param2: 緑 - int
- 値 = -100 ~ 100
- param3: 青 - int
- 値 = -100 ~ 100
コントラスト
contrast()
- param1: コントラスト - int
- 値 = -100 ~ 100
コントラスト
contrast()
- param1: コントラスト - int
- 値 = -100 ~ 100
トリミング
crop()
- param1: 幅 - int
- param2: 高さ - int
- param3: X座標 - int
- デフォルト = 0
- param4: Y座標 - int
- デフォルト = 0
$width = 200;
$height = 200;
$x = 50;
$y = 50;
$img->crop($width, $height, $x, $y);
フリップ
flip()
- param1: 向き - stirng
- デフォルト = h
- 値 = h: 上下、 v: 左右
$img->flip();
$img->flip('v');
サイズ
resize()
- param1: 幅 - int
- param2: 高さ - int
- param3: function
// 比率無視
$img->resize(100, 100);
$img->resize(100, null);
$img->resize(null, 100);
// 比率維持 幅は指定、高さは自動
$img->resize(100, null, function($constraint){
// 比率を維持
$constraint->aspectRatio();
});
サイズ 幅・高さを基準
$img->widen(); $img->highten();
- param1: 値 - int
- param2: function
// 横幅を基準
$img->widen(100);
// 高さを基準
$img->heighten(100);
// 自動調整
$img->widen(500, function ($constraint) {
// もとのサイズより大きくしない
$constraint->upsize();
});
回転
rotate()
- param1: 度数 - int
- param3: 背景 - string
- デフォルト = #ffffff
$img->rotate(-45);
// 背景赤
$img->rotate(-45, '#f44336');
透過度
rotate()
- param1: 度数 - int
- param2: 背景 - string
- デフォルト = #ffffff
$img->rotate(-45);
// 背景赤
$img->rotate(-45, '#f44336');
変換
encode()
- param1: フォーマット - string
- 値 = jpg、png、gif、tif、bmp、ico、psd、webp、data-url、
$jpg = $img->encode('jpg');
取得
// 幅
$value = $img->width();
// 高さ
$value = $img->height();
// ファイルサイズ
$value = $img->filesize();
// ファイルサイズ(バイト)
$value = $img->filesize();
// マイムタイプ
$value = $img->mime();
// 座標位置で色を取得
$value = $img->pickColor(10, 10); // デフォルトは配列を返す
$value = $img->pickColor(10, 10, 'rgba'); // rgba
$value = $img->pickColor(10, 10, 'hex'); // hex
$value = $img->pickColor(10, 10, 'int'); // int
$value = $img->pickColor(10, 10, 'obj'); // obj
// EXIFデータ
$value = $img->exif();
// でもこっちのほうが情報が多い
$value = exif_read_data($image)
// saveする前でもストリームを取得できる
$value = $img->stream(); // デフォルトは現在の画像のタイプでエンコード
$value = $img->stream('png', 50); // フォーマットと画質を指定
// 表示する
return response($value)->header('Content-type', $img->mime());
// responseを使うとこれだけで表示できる
return $img->response();
return $img->response('png', 50); // フォーマットと画質を指定
実用
ログインしないと見れないimage
s3に画像を保存
s3のphotosフォルダに保存、 public
はつけない
// get disk
$s3 = Storage::disk('s3');
// ファイルオブジェクト取得
$photo = $request->file('photo');
// 拡張子を取得
$ext = $photo->extension();
// s3にprivateで保存
$res = $s3->putFileAs('photos', $photo, "{$filename}.{$ext}");
コントローラ作成
s3に保存した画像をimageコントローラを作成してimageルートにする
php artisan make:controller ImageController --invokable
app\Http\Controllers\ImageController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class ImageController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request, $path)
{
// get disk
$s3 = Storage::disk('s3');
// ファイルの有無をチェック
if($s3->missing($path)){
// ない場合は404
abort(404);
}
// マイムタイプを取得
$mimeType = $s3->mimeType($path);
// コンテンツを取得
$content = $s3->get($path);
// イメージとしてリターン
return response($content)->header('Content-type', $mimeType);
}
}
ルート
routes\web.php
// auth
Route::group(['middleware' => ['auth:sanctum']], function () {
// image
Route::get('/image/{path}', ImageController::class)->where(['path' => '.*'])->name('image');
}
);
その他
EXIFからGPSデータを取る
$photo = $request->file('photo');
$img = Image::make($photo);
$exif = $img->exif();
$geo = getGeo($exif);
// [
// "lat" => 34.729144416667
// "lng" => 135.32888888889
// "alt" => 8.3793716656787
// ]
public function getGeo($exif)
{
// 返す値
$result = [
'lat' => null,
'lng' => null,
'alt' => null,
];
// 必要な情報を取得
$alt_ref = data_get($exif, 'GPSAltitudeRef');
$alt_gps = data_get($exif, 'GPSAltitude');
$lat_ref = data_get($exif, 'GPSLatitudeRef');
$lat_gps = data_get($exif, 'GPSLatitude');
$lng_ref = data_get($exif, 'GPSLongitudeRef');
$lng_gps = data_get($exif, 'GPSLongitude');
// 緯度経度がなければfalse
if (!($lat_ref && $lat_gps && $lng_ref && $lng_gps)) {
return false;
}
// 高度を取得
if ($alt_ref && $alt_gps) {
$segments = explode('/', $alt_gps);
$data = (isset($segments[1])) ? $segments[0] / $segments[1] : $alt_gps;
// 0 = 海抜、 1 =海面下
// $ref = ord($alt_ref) == 0 ? 'above' : 'Below';
data_set($result, 'alt', $data);
}
// 緯度経度を取得
$coordinates = [
'lat' => ["ref" => $lat_ref, "gps" => $lat_gps],
'lng' => ["ref" => $lng_ref, "gps" => $lng_gps],
];
foreach ($coordinates as $key => $coordinate) {
$ref = $coordinate['ref'];
$gps = $coordinate['gps'];
// 分数からフロートに変換
$floats = array_map(function ($gps) {
$segments = explode('/', $gps);
return (isset($segments[1])) ? $segments[0] / $segments[1] : $gps;
}, $gps);
$amount = $floats[0] + ($floats[1] / 60) + ($floats[2]) / 3600;
$data = ($ref == 'S' || $ref == 'W') ? ($amount * -1) : $amount;
// 値をセット
data_set($result, $key, $data);
}
return $result;
}
Laravel で画像を編集する
Laravel で画像を編集する
2021-11-18 09:15:34
2021-11-19 08:55:11
コメントはありません。