1
0
mirror of https://github.com/mosbth/cimage.git synced 2025-07-23 17:51:34 +02:00

calculate target dimensions

This commit is contained in:
Mikael Roos
2015-10-27 00:21:36 +01:00
parent f9a4205579
commit 9bf94e9cf6
3 changed files with 291 additions and 2 deletions

View File

@@ -404,6 +404,11 @@ class CImage
/*
* Class for image resizer.
*/
private $imageResizer = null;
/** /**
* Properties, the class is mutable and the method setOptions() * Properties, the class is mutable and the method setOptions()
* decides (partly) what properties are created. * decides (partly) what properties are created.
@@ -435,6 +440,7 @@ class CImage
{ {
$this->setSource($imageSrc, $imageFolder); $this->setSource($imageSrc, $imageFolder);
$this->setTarget($saveFolder, $saveName); $this->setTarget($saveFolder, $saveName);
$this->imageResizer = new CImageResizer();
} }
@@ -921,6 +927,8 @@ class CImage
if (empty($info)) { if (empty($info)) {
throw new Exception("The file doesn't seem to be a valid image."); throw new Exception("The file doesn't seem to be a valid image.");
} }
$this->imageResizer->setSource($this->width, $this->height);
if ($this->verbose) { if ($this->verbose) {
$this->log("Loading image details for: {$file}"); $this->log("Loading image details for: {$file}");
@@ -935,8 +943,8 @@ class CImage
/** /**
* Init new width and height and do some sanity checks on constraints, before any * Init new width and height and do some sanity checks on constraints,
* processing can be done. * before any processing can be done.
* *
* @return $this * @return $this
* @throws Exception * @throws Exception

238
CImageResizer.php Normal file
View File

@@ -0,0 +1,238 @@
<?php
/**
* Resize and crop images.
*
* @author Mikael Roos mos@dbwebb.se
* @example http://dbwebb.se/opensource/cimage
* @link https://github.com/mosbth/cimage
*/
class CImageResizer
{
/**
* Log function.
*/
private $log;
/**
* Source image dimensions, calculated from loaded image.
*/
private $srcWidth;
private $srcHeight;
/**
* Target image dimensions.
*/
private $targetWidth;
//private $targetWidthOrig; // Save original value
private $targetHeight;
//private $targetheightOrig; // Save original value
/**
* Change target height & width when different dpr, dpr 2 means double
* image dimensions.
*/
private $dpr;
/**
* Set aspect ratio for the target image.
*/
private $aspectRatio;
/**
* Constructor, set log function to use for verbose logging or null
* to disable logging.
*
* @param callable $log function to call for logging.
*/
public function __construct($log = null)
{
$this->log = $log;
}
/**
* Log string using logger.
*
* @param string $str to log.
*/
public function log($str)
{
if ($this->log) {
echo $str . "\n";
}
}
/**
* Set source dimensions.
*
* @param integer $width of source image.
* @param integer $height of source image.
*
* @throws Exception
*
* @return $this
*/
public function setSource($width, $height)
{
$this->srcWidth = $width;
$this->srcHeight = $height;
$this->log("Source image dimension: {$this->srcWidth} x {$this->srcHeight}.");
return $this;
}
/**
* Set the basis to consider when calculating target dimensions.
*
* @param numeric|null $width as requested target width
* @param numeric|null $height as requested density pixel rate
* @param float|null $aspectRatio as requested aspect ratio
* @param float $dpr as requested density pixel rate
*
* @throws Exception
*
* @return $this
*/
public function setBaseForCalculateTarget($width = null, $height = null, $aspectRatio = null, $dpr = 1)
{
$this->targetWidth = $width;
$this->targetheight = $height;
$this->aspectRatio = $aspectRatio;
$this->dpr = $dpr;
// Width specified as %
if ($this->targetWidth[strlen($this->targetWidth)-1] == '%') {
$this->targetWidth = $this->width * substr($this->targetWidth, 0, -1) / 100;
$this->log("Setting new width based on $width% to {$this->targetWidth}px.");
}
// Height specified as %
if ($this->targetheight[strlen($this->targetheight)-1] == '%') {
$this->targetheight = $this->height * substr($this->targetheight, 0, -1) / 100;
$this->log("Setting new height based on $height% to {$this->targetheight}px.");
}
// Width is valid
if (!(is_null($this->targetWidth) || is_numeric($this->targetWidth))) {
throw new Exception('Width not numeric');
}
// Height is valid
if (!(is_null($this->targetheight) || is_numeric($this->targetheight))) {
throw new Exception('Height not numeric');
}
// Aspect ratio is valid
if (!(is_null($this->aspectRatio) || is_numeric($this->aspectRatio))) {
throw new Exception('Aspect ratio out of range');
}
// Device pixel ratio is valid
if (!(is_numeric($this->dpr) && $this->dpr > 0)) {
throw new Exception('Device pixel rate out of range');
}
$this->log("Requested target dimension as: {$this->targetWidth} x {$this->targetheight} aspectRatio={$this->aspectRatio}, dpr={$this->dpr}.");
return $this;
}
/**
* Calculate target width and height and do sanity checks on constraints.
* After this method the $targetWidth and $targetHeight will have
* the expected dimensions on the target image.
*
* @param integer $width of source image.
* @param integer $height of source image.
*
* @throws Exception
*
* @return $this
*/
public function prepareTargetDimensions()
{
$this->log("Prepate target dimension before calculate: {$this->targetWidth} x {$this->targetheight}.");
// width & height from aspect ratio
if ($this->aspectRatio && is_null($this->targetWidth) && is_null($this->targetheight)) {
if ($this->aspectRatio >= 1) {
$this->targetWidth = $this->width;
$this->targetheight = $this->width / $this->aspectRatio;
$this->log("Setting new width & height based on width & aspect ratio (>=1) to (w x h) {$this->targetWidth} x {$this->targetheight}");
} else {
$this->targetheight = $this->height;
$this->targetWidth = $this->height * $this->aspectRatio;
$this->log("Setting new width & height based on width & aspect ratio (<1) to (w x h) {$this->targetWidth} x {$this->targetheight}");
}
} elseif ($this->aspectRatio && is_null($this->targetWidth)) {
$this->targetWidth = $this->targetheight * $this->aspectRatio;
$this->log("Setting new width based on aspect ratio to {$this->targetWidth}");
} elseif ($this->aspectRatio && is_null($this->targetheight)) {
$this->targetheight = $this->targetWidth / $this->aspectRatio;
$this->log("Setting new height based on aspect ratio to {$this->targetheight}");
}
// Change width & height based on dpr
if ($this->dpr != 1) {
if (!is_null($this->targetWidth)) {
$this->targetWidth = round($this->targetWidth * $this->dpr);
$this->log("Setting new width based on dpr={$this->dpr} - w={$this->targetWidth}");
}
if (!is_null($this->targetheight)) {
$this->targetheight = round($this->targetheight * $this->dpr);
$this->log("Setting new height based on dpr={$this->dpr} - h={$this->targetheight}");
}
}
$this->log("prepare target dimension after calculate: {$this->targetWidth} x {$this->targetheight}.");
return $this;
}
/**
* Get target width.
*
* @return $integer as target width
*/
public function width()
{
return $this->targetWidth;
}
/**
* Get target height.
*
* @return $integer as target height
*/
public function height()
{
return $this->targetHeight;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* A testclass
*
*/
class CImageResizerTest extends \PHPUnit_Framework_TestCase
{
/**
* Provider
*
* @return array
*/
public function providerImages()
{
return array(
// Same as source, does not set target
array(100, 100, null, null, null, 1, null, null),
array(100, 150, null, null, null, 1, null, null),
array(150, 100, null, null, null, 1, null, null),
);
}
/**
* Test
*
* @dataProvider providerImages
*
* @return void
*/
public function testResize1($srcWidth, $srcHeight, $targetWidth, $targetHeigth, $aspectRatio, $dpr, $expectedWidth, $expectedHeight)
{
$img = new CImageResizer();
$img->setSource($srcWidth, $srcHeight)
->setBaseForCalculateTarget($targetWidth, $targetHeigth, $aspectRatio, $dpr)
->prepareTargetDimensions();
$this->assertEquals($expectedWidth, $img->width(), "Width not correct.");
$this->assertEquals($expectedHeight, $img->height(), "Heigth not correct.");
}
}