Skip to content
This repository has been archived by the owner on Nov 16, 2022. It is now read-only.

Commit

Permalink
Swapped out Imagine for Intervention. Updated the transform class to …
Browse files Browse the repository at this point in the history
…introduce new transformation methods, and a new fit option type
  • Loading branch information
David Yell committed Jun 28, 2016
1 parent 9e12dc4 commit 800c819
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 105 deletions.
12 changes: 8 additions & 4 deletions README.md
Expand Up @@ -4,17 +4,21 @@ An upload plugin for CakePHP 3.
![Proffer definition](http://i.imgur.com/OaAqQ6x.png)

##What is it?
So I needed a way to upload images in [CakePHP 3](http://github.com/cakephp/cakephp), and as I couldn't find anything that I liked I decided to write my own
in a similar vein to how [@josegonzalez](https://github.com/josegonzalez) had written his
[CakePHP-Upload](https://github.com/josegonzalez/cakephp-upload) plugin for CakePHP 2.
So I needed a way to upload images in [CakePHP 3](http://github.com/cakephp/cakephp), and as I couldn't find anything
that I liked I decided to write my own in a similar vein to how [@josegonzalez](https://github.com/josegonzalez) had
written his [CakePHP-Upload](https://github.com/josegonzalez/cakephp-upload) plugin for CakePHP 2.

##Requirements
* PHP 5.4.16+
* PHP 5.6+
* Database
* CakePHP 3
* [Composer](http://getcomposer.org/)
* [File Info is enabled](http://php.net/manual/en/book.fileinfo.php) for mimetype validation

For more requirements, please check the `composer.json` file in the repository.

This plugin implements the [Intervention](http://image.intervention.io/) image library.

##Status
[![Build Status](https://travis-ci.org/davidyell/CakePHP3-Proffer.svg?branch=master)](https://travis-ci.org/davidyell/CakePHP3-Proffer)
[![Coverage Status](https://coveralls.io/repos/davidyell/CakePHP3-Proffer/badge.png)](https://coveralls.io/r/davidyell/CakePHP3-Proffer)
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Expand Up @@ -18,8 +18,8 @@
},
"require": {
"php": ">=5.6",
"imagine/imagine": "^0.6",
"cakephp/orm": "3.*"
"cakephp/orm": "3.*",
"intervention/image": "^2.3"
},
"require-dev": {
"phpunit/phpunit": "^5.4",
Expand Down
35 changes: 30 additions & 5 deletions docs/configuration.md
Expand Up @@ -18,16 +18,14 @@ $this->addBehavior('Proffer.Proffer', [
'square' => [ // Define the prefix of your thumbnail
'w' => 200, // Width
'h' => 200, // Height
'crop' => true, // Crop will crop the image as well as resize it
'jpeg_quality' => 100,
'png_compression_level' => 9
'jpeg_quality' => 100
],
'portrait' => [ // Define a second thumbnail
'w' => 100,
'h' => 300
],
],
'thumbnailMethod' => 'imagick' // Options are Imagick, Gd or Gmagick
'thumbnailMethod' => 'gd' // Options are Imagick or Gd
]
]);
```
Expand All @@ -39,6 +37,33 @@ directory in.
* By default generated thumbnail images will be set to the highest image quality in the `ImageTransform` class.
* By default files will be uploaded to `/webroot/files/<table alias>/<uuid>/<filename>`.

### Thumbnail methods
Additional thumbnail generation types are available using the `crop` and `fit` options, in the thumbnail configuration.

```php
'square' => [
'w' => 200,
'h' => 200,
'fit' => true
],
'portrait' => [
'w' => 150,
'h' => 300,
'crop' => true
]
```

#### Fit
> Combine cropping and resizing to format image in a smart way. The method will find the best fitting aspect ratio of
> your given width and height on the current image automatically, cut it out and resize it to the given dimension.
See [Intervention Fit method](http://image.intervention.io/api/fit)

#### Crop
> Cut out a rectangular part of the current image with given width and height.
By default, will be the centre of the image.
See [Intervention Crop method](http://image.intervention.io/api/crop)

## Template
In order to upload a file to your application you will need to add the form fields to your view.
```php
echo $this->Form->create($entity, ['type' => 'file']); // Dont miss this out or no files will upload
Expand Down Expand Up @@ -67,7 +92,7 @@ Allows you to customise the root folder in which all the file upload folders and

###thumbnailMethod
**optional:** defaults to, `gd`
Which Imagine engine to use to convert the images. Defaults to PHP's GD library. Can also be `imagick` and `gmagick`.
Which Intervention engine to use to convert the images. Defaults to PHP's GD library. Can also be `imagick`.

###pathClass
**optional**
Expand Down
159 changes: 67 additions & 92 deletions src/Lib/ImageTransform.php
@@ -1,86 +1,47 @@
<?php
/**
* ImageTransform class
* This class deals with creating thumbnails for image uploads using the Imagine library
* This class deals with creating thumbnails for image uploads using the a library
*
* @author David Yell <neon1024@gmail.com>
*/

namespace Proffer\Lib;

use Cake\ORM\Table;
use Imagine\Filter\Transformation;
use Imagine\Gd\Imagine as Gd;
use Imagine\Gmagick\Imagine as Gmagick;
use Imagine\Image\Box;
use Imagine\Image\ImageInterface;
use Imagine\Image\Point;
use Imagine\Imagick\Imagine as Imagick;
use Intervention\Image\Image;
use Intervention\Image\ImageManager;

class ImageTransform implements ImageTransformInterface
{

/**
* Store our instance of Imagine
*
* @var ImagineInterface $Imagine
* @var \Cake\ORM\Table $table Instance of the table being used
*/
private $Imagine;
protected $Table;

/**
* @var Table $table Instance of the table being used
* @var \Proffer\Lib\ProfferPathInterface $Path Instance of the path class
*/
protected $Table;
protected $Path;

/**
* @var ProfferPathInterface $Path Instance of the path class
* @var \Intervention\Image\ImageManager Intervention image manager instance
*/
protected $Path;
protected $ImageManager;

/**
* Construct the transformation class
*
* @param Table $table The table instance
* @param ProfferPathInterface $path Instance of the path class
* @param \Cake\ORM\Table $table The table instance
* @param \Proffer\Lib\ProfferPathInterface $path Instance of the path class
*/
public function __construct(Table $table, ProfferPathInterface $path)
{
$this->Table = $table;
$this->Path = $path;
}

/**
* Get the specified Imagine engine class
*
* @return ImagineInterface
*/
protected function getImagine()
{
return $this->Imagine;
}

/**
* Set the Imagine engine class
*
* @param string $engine The name of the image engine to use
* @return void
*/
protected function setImagine($engine = 'gd')
{
switch ($engine) {
default:
case 'gd':
$this->Imagine = new Gd();
break;
case 'gmagick':
$this->Imagine = new Gmagick();
break;
case 'imagick':
$this->Imagine = new Imagick();
break;
}
}

/**
* Take an upload fields configuration and create all the thumbnails
*
Expand All @@ -95,14 +56,16 @@ public function processThumbnails(array $config)
}

foreach ($config['thumbnailSizes'] as $prefix => $thumbnailConfig) {
$method = null;
$method = 'gd';
if (!empty($config['thumbnailMethod'])) {
$method = $config['thumbnailMethod'];
}

$thumbnailPath = $this->makeThumbnail($prefix, $thumbnailConfig, $method);
$thumbnailPaths[] = $thumbnailPath;
$this->ImageManager = new ImageManager(['driver' => $method]);

$thumbnailPaths[] = $this->makeThumbnail($prefix, $thumbnailConfig);
}

return $thumbnailPaths;
}

Expand All @@ -111,69 +74,81 @@ public function processThumbnails(array $config)
*
* @param string $prefix The thumbnail prefix
* @param array $config Array of thumbnail config
* @param string $thumbnailMethod Which engine to use to make thumbnails
* @return string
*/
public function makeThumbnail($prefix, array $config, $thumbnailMethod = 'gd')
public function makeThumbnail($prefix, array $config)
{
$defaultConfig = [
'jpeg_quality' => 100,
'png_compression_level' => 9
'jpeg_quality' => 100
];
$config = array_merge($defaultConfig, $config);
$this->setImagine($thumbnailMethod);

$image = $this->getImagine()->open($this->Path->fullPath());
$width = $config['w'];
$height = $config['h'];

$image = $this->ImageManager->make($this->Path->fullPath());

if (isset($config['crop']) && $config['crop'] === true) {
$image = $this->thumbnailCropScale($image, $config['w'], $config['h']);
if (!empty($config['crop'])) {
$image = $this->thumbnailCrop($image, $width, $height);
} elseif (!empty($config['fit'])) {
$image = $this->thumbnailFit($image, $width, $height);
} else {
$image = $this->thumbnailScale($image, $config['w'], $config['h']);
$image = $this->thumbnailResize($image, $width, $height);
}

unset($config['crop'], $config['w'], $config['h']);

$image->save($this->Path->fullPath($prefix), $config);
$image->save($this->Path->fullPath($prefix), $config['jpeg_quality']);

return $this->Path->fullPath($prefix);
}

/**
* Scale an image to best fit a thumbnail size
* Crop an image to a certain size from the centre of the image
*
* @see http://image.intervention.io/api/crop
*
* @param ImageInterface $image The ImageInterface instance from Imagine
* @param int $width The width in pixels
* @param int $height The height in pixels
* @return ImageInterface
* @param \Intervention\Image\Image $image Image instance
* @param int $width Desired width in pixels
* @param int $height Desired height in pixels
*
* @return \Intervention\Image\Image
*/
protected function thumbnailScale(ImageInterface $image, $width, $height)
protected function thumbnailCrop(Image $image, $width, $height)
{
$transformation = new Transformation();
$transformation->thumbnail(new Box($width, $height));
return $transformation->apply($image);
return $image->crop($width, $height);
}

/**
* Create a thumbnail by scaling an image and cropping it to fit the exact dimensions
* Resize and crop to find the best fitting aspect ratio
*
* @see http://image.intervention.io/api/fit
*
* @param \Intervention\Image\Image $image Image instance
* @param int $width Desired width in pixels
* @param int $height Desired height in pixels
*
* @param ImageInterface $image The ImageInterface instance from Imagine
* @param int $targetWidth The width in pixels
* @param int $targetHeight The height in pixels
* @return ImageInterface
* @return \Intervention\Image\Image
*/
protected function thumbnailCropScale(ImageInterface $image, $targetWidth, $targetHeight)
protected function thumbnailFit(Image $image, $width, $height)
{
$target = new Box($targetWidth, $targetHeight);
$sourceSize = $image->getSize();
if ($sourceSize->getWidth() > $sourceSize->getHeight()) {
$width = $sourceSize->getWidth() * ($target->getHeight() / $sourceSize->getHeight());
$height = $targetHeight;
$cropPoint = new Point((int)(max($width - $target->getWidth(), 0) / 2), 0);
} else {
$height = $sourceSize->getHeight() * ($target->getWidth() / $sourceSize->getWidth());
$width = $targetWidth;
$cropPoint = new Point(0, (int)(max($height - $target->getHeight(), 0) / 2));
}
$box = new Box($width, $height);
return $image->thumbnail($box, ImageInterface::THUMBNAIL_OUTBOUND)
->crop($cropPoint, $target);
return $image->fit($width, $height);
}

/**
* Resize current image
*
* @see http://image.intervention.io/api/resize
*
* @param \Intervention\Image\Image $image Image instance
* @param int $width Desired width in pixels
* @param int $height Desired height in pixels
*
* @return \Intervention\Image\Image
*/
protected function thumbnailResize(Image $image, $width, $height)
{
return $image->resize($width, $height);
}

}
3 changes: 1 addition & 2 deletions src/Lib/ImageTransformInterface.php
Expand Up @@ -26,8 +26,7 @@ public function processThumbnails(array $config);
*
* @param string $prefix The prefix name for the thumbnail
* @param array $dimensions The thumbnail dimensions
* @param string $thumbnailMethod Which method to use to create the thumbnail
* @return string
*/
public function makeThumbnail($prefix, array $dimensions, $thumbnailMethod = 'gd');
public function makeThumbnail($prefix, array $dimensions);
}

0 comments on commit 800c819

Please sign in to comment.