Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
nickdekruijk committed Jul 11, 2018
0 parents commit abbc029
Show file tree
Hide file tree
Showing 8 changed files with 427 additions and 0 deletions.
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) Nick de Kruijk

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[![Latest Stable Version](https://poser.pugx.org/nickdekruijk/imageresize/v/stable)](https://packagist.org/packages/nickdekruijk/imageresize)
[![Latest Unstable Version](https://poser.pugx.org/nickdekruijk/imageresize/v/unstable)](https://packagist.org/packages/nickdekruijk/imageresize)
[![Monthly Downloads](https://poser.pugx.org/nickdekruijk/imageresize/d/monthly)](https://packagist.org/packages/nickdekruijk/imageresize)
[![Total Downloads](https://poser.pugx.org/nickdekruijk/imageresize/downloads)](https://packagist.org/packages/nickdekruijk/imageresize)
[![License](https://poser.pugx.org/nickdekruijk/imageresize/license)](https://packagist.org/packages/nickdekruijk/imageresize)

# ImageResize for Laravel
A simple, yet efficient solution for image resizing and caching with Laravel.
Based on my previous imageresize package, now renamed to [nickdekruijk/imageresize-legacy](https://github.com/nickdekruijk/imageresize-legacy).

## Installation
To install the package use

`composer require nickdekruijk/imageresize`

## Configuration
After installing for the first time publish the config file with

`php artisan vendor:publish --tag=config --provider="NickDeKruijk\ImageResize\ServiceProvider"`

A default config file called `imageresize.php` will be available in your Laravel `app/config` folder. See this file for more details.

## How does it work
Let's assume you have an image in /public/media/images/test.jpg and a template called 'thumbnail'. And have set the imageresize.route config to 'media/resized'.
Referring to /media/resized/thumbnail/images/test.jpg will trigger the imageresize route in laravel since the file doesn't exist. Imageresize then creates the resized image and saves it as /public/media/resized/thumbnail/images/test.jpg
So the next time you refer to /media/resized/thumbnail/images/test.jpg the file does exist and the image is served without triggering any php/laravel code for optimal performance.

## Drawbacks
There is however one disadvantage: if the original image is edited or removed the resized file will still remain the same since referring to it doesn't trigger the imageresize package. You will have to manually delete it or use the `php artisan imageresize:delete` command.
29 changes: 29 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "nickdekruijk/imageresize",
"description": "A simple, yet efficient solution for image resizing and caching with Laravel",
"license": "MIT",
"keywords": [ "image", "laravel", "resize", "php", "cache" ],
"homepage": "http://www.nickdekruijk.nl/packages/imageresize",
"authors": [
{
"name": "Nick de Kruijk",
"email": "[email protected]"
}
],
"minimum-stability": "dev",
"require": {
"php": ">=5.6.0",
},
"extra": {
"laravel": {
"providers": [
"NickDeKruijk\\ImageResize\\ServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"NickDeKruijk\\ImageResize\\": "src/"
}
}
}
174 changes: 174 additions & 0 deletions src/ResizeController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php

namespace NickDeKruijk\ImageResize;

use App\Http\Controllers\Controller;
use Cache;
use App;

class ResizeController extends Controller
{
private static function error($message = 'Undefined error')
{
if (config('app.debug') || App::runningInConsole()) {
throw new \Exception($message);
} else {
abort(404);
}
}

private static function path($append = null)
{
return public_path(rtrim(config('imageresize.route'), '/') . ($append ? '/' . $append : ''));
}

public static function delete($template = null)
{
if ($template && !config('imageresize.templates.'.$template)) {
self::error('Template ' . $template . ' not found');
}

if ($template) {
self::deleteDir(self::path($template));
} else {
foreach(config('imageresize.templates') as $template => $array) {
self::deleteDir(self::path($template));
}
}
}

private static function deleteDir($dir)
{
if (!file_exists($dir) || !is_dir($dir)) return false;
$h = opendir($dir);
while($f = readdir($h)) {
if ($f[0] != '.')
if (is_dir($dir . '/' . $f))
self::deleteDir($dir .'/'. $f);
else {
echo 'Deleting ' . $dir.'/' . $f . chr(10);
unlink($dir . '/' . $f);
}
}
echo 'Deleting dir ' . $dir . chr(10);
rmdir($dir);
closedir($h);
}

private function makepath($target)
{
$dir = explode('/', $target);
array_pop($dir);
$p = '';
foreach($dir as $d) {
$p .= $d . '/';
if (!file_exists($p)) {
mkdir($p) or $this->error('Unable to create ' . $p);
}
if (!is_dir($p)) {
$this->error('Not a directory: ' . $p);
}
if (!is_writable($p)) {
$this->error('Not writable: ' . $p);
}
}
}

private function resize($template, $original, $target)
{
$originalSize = getimagesize($original) or $this->error($original . ' is not a valid image');
$type = $originalSize['mime'];
$originalWidth = $originalSize[0];
$originalHeigth = $originalSize[1];

# Create new GD instance based on image type
if ($type == 'image/gif') {
$image_a = imagecreatefromgif($original) or $this->error();
} elseif ($type == 'image/png') {
$image_a = imagecreatefrompng($original) or $this->error();
} else {
$image_a = imagecreatefromjpeg($original) or $this->error();
}

if ($template['type'] == 'crop') {
$targetWidth = $template['width'];
$targetHeigth = $originalHeigth * ($targetWidth / $originalWidth);
if ($targetHeigth < $template['height']) {
$targetHeigth = $template['height'];
$targetWidth=$originalWidth * ($targetHeigth / $originalHeigth);
}
$dst_img = imagecreatetruecolor($targetWidth, $targetHeigth);
imagealphablending($dst_img, false);
imagesavealpha($dst_img, true);
imagecopyresampled($dst_img, $image_a, 0, 0, 0, 0, $targetWidth, $targetHeigth, imagesx($image_a), imagesy($image_a));
imagedestroy($image_a);
$image_p = imagecreatetruecolor($template['width'], $template['height']);
imagealphablending($image_p, false);
imagesavealpha($image_p, true);
imagecopy($image_p, $dst_img, 0, 0, round((imagesx($dst_img) - $template['width']) / 2), round((imagesy($dst_img) - $template['height']) / 2), $template['width'], $template['height']);
imagedestroy($dst_img);
} elseif ($template['type'] == 'fit') {
$ratio_orig = $originalWidth / $originalHeigth;
if ($template['width'] / $template['height'] > $ratio_orig) {
$template['width'] = $template['height'] * $ratio_orig;
} else {
$template['height'] = $template['width'] / $ratio_orig;
}
$image_p = imagecreatetruecolor($template['width'], $template['height']);
imagealphablending($image_p, false);
imagesavealpha($image_p, true);
imagecopyresampled($image_p, $image_a, 0, 0, 0, 0, $template['width'], $template['height'], $originalWidth, $originalHeigth);
imagedestroy($image_a);
} else {
$this->error('Invalid template type ' . $template['type']);
}

# Add blur filter if needed
if (isset($template['blur']) && $template['blur'] > 0) {
for ($x = 1; $x <= $template['blur']; $x++) {
imagefilter($image_p, IMG_FILTER_GAUSSIAN_BLUR);
}
}

# Add grayscale filter if needed
if (isset($template['grayscale']) && $template['grayscale']) {
imagefilter($image_p, IMG_FILTER_GRAYSCALE);
}

$this->makepath($target);

# Save the resized image in a variable
if ($type == 'image/gif') {
imagegif($image_p, $target) or $this->error('Write error');
} elseif ($type == 'image/png') {
imagepng($image_p, $target) or $this->error('Write error');
} else {
imagejpeg($image_p, $target, isset($template['quality']) ? $template['quality'] : config('imageresize.quality_jpeg')) or $this->error('Write error');
}

imagedestroy($image_p);
}

public function make($template, $image)
{
if (config('imageresize.templates.'.$template)) {

$target = rtrim(config('imageresize.route'), '/') . '/' . $template . '/' . $image;
$template = config('imageresize.templates.' . $template);

$original = rtrim(config('imageresize.originals'), '/') . '/' . $image;
if (!file_exists($original)) {
$this->error($original . ' does not exist');
}
if (is_dir($original)) {
$this->error($original . ' is a directory');
}

$this->resize($template, $original, $target);

return redirect($target);
} else {
$this->error('Template ' . $template . ' not found');
}
}
}
34 changes: 34 additions & 0 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace NickDeKruijk\ImageResize;

class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/config.php' => config_path('imageresize.php'),
], 'config');
$this->loadRoutesFrom(__DIR__.'/routes.php');
if ($this->app->runningInConsole()) {
$this->commands([
UserCommand::class,
]);
}
}

/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->mergeConfigFrom(__DIR__.'/config.php', 'imageresize');
}
}
46 changes: 46 additions & 0 deletions src/UserCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace NickDeKruijk\ImageResize;

use Illuminate\Console\Command;

class UserCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'imageresize:delete {template? : A valid template}';

/**
* The console command description.
*
* @var string
*/
protected $description = '';

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
$this->description = 'Delete the resized images from the "'.config('imageresize.route').'" folder.';
parent::__construct();
}

/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$arg = $this->arguments();
if ($arg['command'] == 'imageresize:delete') {
ResizeController::delete($arg['template']);
}
}
}
Loading

0 comments on commit abbc029

Please sign in to comment.