1
0
mirror of https://github.com/mosbth/cimage.git synced 2025-08-01 14:00:08 +02:00

intermediate

This commit is contained in:
Mikael Roos
2015-11-25 09:58:09 +01:00
parent 9bf94e9cf6
commit 5673ce4f55
5 changed files with 864 additions and 158 deletions

View File

@@ -339,7 +339,8 @@ class CImage
/** /**
* Used with option area to set which parts of the image to use. * Used with option area to set which parts of the image to use.
*/ */
private $offset; private $area;
private $offset;
@@ -440,11 +441,12 @@ class CImage
{ {
$this->setSource($imageSrc, $imageFolder); $this->setSource($imageSrc, $imageFolder);
$this->setTarget($saveFolder, $saveName); $this->setTarget($saveFolder, $saveName);
$this->imageResizer = new CImageResizer(); $this->imageResizer = new CImageResizer(array($this, 'log'));
} }
/** /**
* Set verbose mode. * Set verbose mode.
* *
@@ -931,7 +933,7 @@ class CImage
$this->imageResizer->setSource($this->width, $this->height); $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}");
$this->log(" Image width x height (type): {$this->width} x {$this->height} ({$this->fileType})."); $this->log(" Image width x height (type): {$this->width} x {$this->height} ({$this->fileType}).");
$this->log(" Image filesize: " . filesize($file) . " bytes."); $this->log(" Image filesize: " . filesize($file) . " bytes.");
$this->log(" Image mimetype: " . image_type_to_mime_type($this->fileType)); $this->log(" Image mimetype: " . image_type_to_mime_type($this->fileType));
@@ -951,66 +953,10 @@ class CImage
*/ */
public function initDimensions() public function initDimensions()
{ {
$this->log("Init dimension (before) newWidth x newHeight is {$this->newWidth} x {$this->newHeight}."); $this->imageResizer->setBaseWidthHeight($this->newWidth, $this->newHeight)
->setBaseAspecRatio($this->aspectRatio)
// width as % ->setBaseDevicePixelRate($this->dpr)
if ($this->newWidth[strlen($this->newWidth)-1] == '%') { ->prepareTargetDimensions();
$this->newWidth = $this->width * substr($this->newWidth, 0, -1) / 100;
$this->log("Setting new width based on % to {$this->newWidth}");
}
// height as %
if ($this->newHeight[strlen($this->newHeight)-1] == '%') {
$this->newHeight = $this->height * substr($this->newHeight, 0, -1) / 100;
$this->log("Setting new height based on % to {$this->newHeight}");
}
is_null($this->aspectRatio) or is_numeric($this->aspectRatio) or $this->raiseError('Aspect ratio out of range');
// width & height from aspect ratio
if ($this->aspectRatio && is_null($this->newWidth) && is_null($this->newHeight)) {
if ($this->aspectRatio >= 1) {
$this->newWidth = $this->width;
$this->newHeight = $this->width / $this->aspectRatio;
$this->log("Setting new width & height based on width & aspect ratio (>=1) to (w x h) {$this->newWidth} x {$this->newHeight}");
} else {
$this->newHeight = $this->height;
$this->newWidth = $this->height * $this->aspectRatio;
$this->log("Setting new width & height based on width & aspect ratio (<1) to (w x h) {$this->newWidth} x {$this->newHeight}");
}
} elseif ($this->aspectRatio && is_null($this->newWidth)) {
$this->newWidth = $this->newHeight * $this->aspectRatio;
$this->log("Setting new width based on aspect ratio to {$this->newWidth}");
} elseif ($this->aspectRatio && is_null($this->newHeight)) {
$this->newHeight = $this->newWidth / $this->aspectRatio;
$this->log("Setting new height based on aspect ratio to {$this->newHeight}");
}
// Change width & height based on dpr
if ($this->dpr != 1) {
if (!is_null($this->newWidth)) {
$this->newWidth = round($this->newWidth * $this->dpr);
$this->log("Setting new width based on dpr={$this->dpr} - w={$this->newWidth}");
}
if (!is_null($this->newHeight)) {
$this->newHeight = round($this->newHeight * $this->dpr);
$this->log("Setting new height based on dpr={$this->dpr} - h={$this->newHeight}");
}
}
// Check values to be within domain
is_null($this->newWidth)
or is_numeric($this->newWidth)
or $this->raiseError('Width not numeric');
is_null($this->newHeight)
or is_numeric($this->newHeight)
or $this->raiseError('Height not numeric');
$this->log("Init dimension (after) newWidth x newHeight is {$this->newWidth} x {$this->newHeight}.");
return $this; return $this;
} }
@@ -1024,6 +970,26 @@ class CImage
*/ */
public function calculateNewWidthAndHeight() public function calculateNewWidthAndHeight()
{ {
$imres = $this->imageResizer;
$strategy = null;
if ($this->keepRatio == true) {
$strategy = $imres::KEEP_RATIO;
}
if ($this->cropToFit == true) {
$strategy = $imres::CROP_TO_FIT;
}
if ($this->fillToFit == true) {
$strategy = $imres::FILL_TO_FIT;
}
$imres->setResizeStrategy($strategy)
->calculateTargetWidthAndHeight();
$this->newWidth = $imres->width();
$this->newHeight = $imres->height();
/*
// Crop, use cropped width and height as base for calulations // Crop, use cropped width and height as base for calulations
$this->log("Calculate new width and height."); $this->log("Calculate new width and height.");
$this->log("Original width x height is {$this->width} x {$this->height}."); $this->log("Original width x height is {$this->width} x {$this->height}.");
@@ -1145,18 +1111,12 @@ class CImage
$this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->crop['height']); $this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->crop['height']);
} }
// Fill to fit, ensure to set new width and height
/*if ($this->fillToFit) {
$this->log("FillToFit.");
$this->newWidth = round(isset($this->newWidth) ? $this->newWidth : $this->crop['width']);
$this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->crop['height']);
}*/
// No new height or width is set, use existing measures. // No new height or width is set, use existing measures.
$this->newWidth = round(isset($this->newWidth) ? $this->newWidth : $this->width); $this->newWidth = round(isset($this->newWidth) ? $this->newWidth : $this->width);
$this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->height); $this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->height);
$this->log("Calculated new width x height as {$this->newWidth} x {$this->newHeight}."); $this->log("Calculated new width x height as {$this->newWidth} x {$this->newHeight}.");
*/
return $this; return $this;
} }
@@ -1667,6 +1627,7 @@ class CImage
*/ */
public function resize() public function resize()
{ {
$imgres = $this->imageResizer;
$this->log("### Starting to Resize()"); $this->log("### Starting to Resize()");
$this->log("Upscale = '$this->upscale'"); $this->log("Upscale = '$this->upscale'");
@@ -1724,11 +1685,21 @@ class CImage
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); $imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopy($imageResized, $this->image, $posX, $posY, $cropX, $cropY, $this->newWidth, $this->newHeight); imagecopy($imageResized, $this->image, $posX, $posY, $cropX, $cropY, $this->newWidth, $this->newHeight);
} else { } else {
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2)); $cropX = $imgres->getCropX();
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2)); $cropY = $imgres->getCropY();
$imgPreCrop = $this->CreateImageKeepTransparency($this->cropWidth, $this->cropHeight); $cropWidth = $imgres->getCropWidth();
$cropHeight = $imgres->getCropHeight();
$this->log(" Crop from $cropX x $cropY by $cropWidth x $cropHeight.");
//$cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
//$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
//$imgPreCrop = $this->CreateImageKeepTransparency($this->cropWidth, $this->cropHeight);
$imgPreCrop = $this->CreateImageKeepTransparency($cropWidth, $cropHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); $imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
$this->imageCopyResampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height); // $this->imageCopyResampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
$this->imageCopyResampled($imgPreCrop, $this->image, 0, 0, 0, 0, $cropWidth, $cropHeight, $this->width, $this->height);
imagecopy($imageResized, $imgPreCrop, 0, 0, $cropX, $cropY, $this->newWidth, $this->newHeight); imagecopy($imageResized, $imgPreCrop, 0, 0, $cropX, $cropY, $this->newWidth, $this->newHeight);
} }
@@ -2507,7 +2478,7 @@ class CImage
/** /**
* Add HTTP header for putputting together with image. * Add HTTP header for outputting together with image.
* *
* @param string $type the header type such as "Cache-Control" * @param string $type the header type such as "Cache-Control"
* @param string $value the value to use * @param string $value the value to use

View File

@@ -24,7 +24,7 @@ class CImageResizer
/** /**
* Target image dimensions. * Set as expected target image dimensions.
*/ */
private $targetWidth; private $targetWidth;
//private $targetWidthOrig; // Save original value //private $targetWidthOrig; // Save original value
@@ -33,11 +33,21 @@ class CImageResizer
/**
* Which parts to crop from the source.
*/
private $cropX;
private $cropY;
private $cropWidth;
private $cropHeight;
/** /**
* Change target height & width when different dpr, dpr 2 means double * Change target height & width when different dpr, dpr 2 means double
* image dimensions. * image dimensions.
*/ */
private $dpr; private $dpr = null;
@@ -48,6 +58,66 @@ class CImageResizer
/**
* Array with details on how to crop.
* Array contains xxxxxx
*/
public $crop;
public $cropOrig; // Save original value?
/**
* Area to use for target image, crop out parts not in area.
* Array with top, right, bottom, left percentage values to crop out.
*/
private $area;
/**
* Pixel offset in source image to decide which part of image is used.
* Array with top, right, bottom, left percentage values to crop out.
*/
private $offset;
/**
* Resize strategy, image should keep its original ratio.
*/
const KEEP_RATIO = 1;
/**
* Resize strategy, image should crop and fill area.
*/
const CROP_TO_FIT = 2;
/**
* Resize strategy, image should fit in area and fill remains.
*/
const FILL_TO_FIT = 3;
/**
* Resize strategy, image should stretch to fit in area.
*/
const STRETCH = 4;
/**
* The currently selected resize strategy.
*/
private $resizeStrategy;
/** /**
* Constructor, set log function to use for verbose logging or null * Constructor, set log function to use for verbose logging or null
* to disable logging. * to disable logging.
@@ -69,7 +139,7 @@ class CImageResizer
public function log($str) public function log($str)
{ {
if ($this->log) { if ($this->log) {
echo $str . "\n"; call_user_func($this->log, $str);
} }
} }
@@ -89,7 +159,7 @@ class CImageResizer
{ {
$this->srcWidth = $width; $this->srcWidth = $width;
$this->srcHeight = $height; $this->srcHeight = $height;
$this->log("Source image dimension: {$this->srcWidth} x {$this->srcHeight}."); $this->log("# Source image dimension: {$this->srcWidth}x{$this->srcHeight}.");
return $this; return $this;
} }
@@ -97,57 +167,237 @@ class CImageResizer
/** /**
* Set the basis to consider when calculating target dimensions. * Get resize strategy as string.
* *
* @param numeric|null $width as requested target width * @return string
* @param numeric|null $height as requested density pixel rate */
* @param float|null $aspectRatio as requested aspect ratio public function getResizeStrategyAsString()
* @param float $dpr as requested density pixel rate {
switch ($this->resizeStrategy) {
case self::KEEP_RATIO:
return "KEEP_RATIO";
break;
case self::CROP_TO_FIT:
return "CROP_TO_FIT";
break;
case self::FILL_TO_FIT:
return "FILL_TO_FIT";
break;
default:
return "UNKNOWN";
}
}
/**
* Set resize strategy as KEEP_RATIO, CROP_TO_FIT or FILL_TO_FIT.
*
* @param integer $strategy
*
* @return $this
*/
public function setResizeStrategy($strategy)
{
$this->resizeStrategy = $strategy;
$this->log("# Resize strategy is " . $this->getResizeStrategyAsString());
return $this;
}
/**
* Set base for requested width and height.
*
* @param numeric|null $width as requested target width
* @param numeric|null $height as requested target height
*
* @throws Exception
*
* @return $this
*/
public function setBaseWidthHeight($width = null, $height = null)
{
$this->log("# Set base for width and height.");
$this->targetWidth = $width;
$this->targetHeight = $height;
// Width specified as %
if ($this->targetWidth[strlen($this->targetWidth)-1] == '%') {
$this->targetWidth = $this->srcWidth * substr($this->targetWidth, 0, -1) / 100;
$this->log(" Setting new width based on $width to {$this->targetWidth}.");
}
// Height specified as %
if ($this->targetHeight[strlen($this->targetHeight)-1] == '%') {
$this->targetHeight = $this->srcHeight * substr($this->targetHeight, 0, -1) / 100;
$this->log(" Setting new height based on $height to {$this->targetHeight}.");
}
if (!(is_null($this->targetWidth) || is_numeric($this->targetWidth))) {
throw new Exception('Width not numeric');
}
if (!(is_null($this->targetHeight) || is_numeric($this->targetHeight))) {
throw new Exception('Height not numeric');
}
$this->log(" Requested target dimension as: {$this->targetWidth}x{$this->targetHeight}.");
return $this;
}
/**
* Set base for requested aspect ratio.
*
* @param float|null $aspectRatio as requested aspect ratio
*
* @throws Exception
*
* @return $this
*/
public function setBaseAspecRatio($aspectRatio = null)
{
$this->log("# Set base for aspect ratio.");
$this->aspectRatio = $aspectRatio;
if (!(is_null($this->aspectRatio) || is_numeric($this->aspectRatio))) {
throw new Exception("Aspect ratio out of range");
}
$this->log(" Requested aspectRatio={$this->aspectRatio}.");
return $this;
}
/**
* Set base for requested device pixel ratio.
*
* @param float $dpr as requested density pixel rate
* *
* @throws Exception * @throws Exception
* *
* @return $this * @return $this
*/ */
public function setBaseForCalculateTarget($width = null, $height = null, $aspectRatio = null, $dpr = 1) public function setBaseDevicePixelRate($dpr = null)
{ {
$this->targetWidth = $width; $this->log("# Set base for device pixel rate.");
$this->targetheight = $height;
$this->aspectRatio = $aspectRatio;
$this->dpr = $dpr;
// Width specified as % $this->dpr = $dpr;
if ($this->targetWidth[strlen($this->targetWidth)-1] == '%') {
$this->targetWidth = $this->width * substr($this->targetWidth, 0, -1) / 100; if (!(is_null($dpr) || (is_numeric($this->dpr) && $this->dpr > 0))) {
$this->log("Setting new width based on $width% to {$this->targetWidth}px."); throw new Exception("Device pixel rate out of range");
} }
// Height specified as % $this->log(" Requested dpr={$this->dpr}.");
if ($this->targetheight[strlen($this->targetheight)-1] == '%') {
$this->targetheight = $this->height * substr($this->targetheight, 0, -1) / 100; return $this;
$this->log("Setting new height based on $height% to {$this->targetheight}px."); }
/**
* Calculate target width and height by considering the selected
* aspect ratio.
*
* @throws Exception
*
* @return $this
*/
public function prepareByConsiderAspectRatio()
{
$this->log(" Prepare by aspect ratio {$this->aspectRatio}.");
if (is_null($this->aspectRatio)) {
return $this;
} }
// Width is valid // Both null, use source as base for target
if (!(is_null($this->targetWidth) || is_numeric($this->targetWidth))) { if (is_null($this->targetWidth) && is_null($this->targetHeight)) {
throw new Exception('Width not numeric');
$this->targetWidth = ($this->aspectRatio >= 1)
? $this->srcWidth
: null;
$this->targetHeight = ($this->aspectRatio >= 1)
? null
: $this->srcHeight;
$this->log(" Using source as base {$this->targetWidth}x{$this->targetHeight}");
}
// Both or either set, calculate the other
if (isset($this->targetWidth) && isset($this->targetHeight)) {
$this->targetWidth = ($this->aspectRatio >= 1)
? $this->targetWidth
: $this->targetHeight * $this->aspectRatio;
$this->targetHeight = ($this->aspectRatio >= 1)
? $this->targetWidth / $this->aspectRatio
: $this->targetHeight;
$this->log(" New target width height {$this->targetWidth}x{$this->targetHeight}");
} elseif (isset($this->targetWidth)) {
$this->targetHeight = $this->targetWidth / $this->aspectRatio;
$this->log(" New target height x{$this->targetHeight}");
} elseif (isset($this->targetHeight)) {
$this->targetWidth = $this->targetHeight * $this->aspectRatio;
$this->log(" New target width {$this->targetWidth}x");
} }
// Height is valid return $this;
if (!(is_null($this->targetheight) || is_numeric($this->targetheight))) { }
throw new Exception('Height not numeric');
/**
* Calculate target width and height by considering the selected
* dpr.
*
* @throws Exception
*
* @return $this
*/
public function prepareByConsiderDpr()
{
$this->log(" Prepare by dpr={$this->dpr}.");
if (is_null($this->dpr)) {
return $this;
} }
// Aspect ratio is valid // If both not set, use source as base
if (!(is_null($this->aspectRatio) || is_numeric($this->aspectRatio))) { if (is_null($this->targetWidth) && is_null($this->targetHeight)) {
throw new Exception('Aspect ratio out of range'); $this->targetWidth = $this->srcWidth;
$this->targetHeight = $this->srcHeight;
} }
// Device pixel ratio is valid if (isset($this->targetWidth)) {
if (!(is_numeric($this->dpr) && $this->dpr > 0)) { $this->targetWidth = $this->targetWidth * $this->dpr;
throw new Exception('Device pixel rate out of range'); $this->log(" Update target width to {$this->targetWidth}.");
} }
$this->log("Requested target dimension as: {$this->targetWidth} x {$this->targetheight} aspectRatio={$this->aspectRatio}, dpr={$this->dpr}."); if (isset($this->targetHeight)) {
$this->targetHeight = $this->targetHeight * $this->dpr;
$this->log(" Update target height to {$this->targetHeight}.");
}
return $this; return $this;
} }
@@ -159,52 +409,309 @@ class CImageResizer
* After this method the $targetWidth and $targetHeight will have * After this method the $targetWidth and $targetHeight will have
* the expected dimensions on the target image. * the expected dimensions on the target image.
* *
* @param integer $width of source image.
* @param integer $height of source image.
*
* @throws Exception * @throws Exception
* *
* @return $this * @return $this
*/ */
public function prepareTargetDimensions() public function prepareTargetDimensions()
{ {
$this->log("Prepate target dimension before calculate: {$this->targetWidth} x {$this->targetheight}."); $this->log("# Prepare target dimension (before): {$this->targetWidth}x{$this->targetHeight}.");
// width & height from aspect ratio $this->prepareByConsiderAspectRatio()
if ($this->aspectRatio && is_null($this->targetWidth) && is_null($this->targetheight)) { ->prepareByConsiderDpr();
if ($this->aspectRatio >= 1) {
$this->targetWidth = $this->width; $this->log(" Prepare target dimension (after): {$this->targetWidth}x{$this->targetHeight}.");
$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}");
return $this;
}
/**
* Calculate new width and height of image.
*
* @return $this
*/
public function calculateTargetWidthAndHeight()
{
$this->log("# Calculate new width and height.");
$this->log(" Source size {$this->srcWidth}x{$this->srcHeight}.");
$this->log(" Target dimension (before) {$this->targetWidth}x{$this->targetHeight}.");
/*
// Set default values to crop area to be whole source image
$aspectRatio = $this->srcWidth / $this->srcHeight;
$this->cropX = 0;
$this->cropY = 0;
$this->cropWidth = $this->srcWidth;
$this->cropHeight = $this->srcHeight;
// Get relations of original & target image
$width = $this->srcWidth;
$height = $this->srcHeight;
*/
// Set default values to crop area to be whole source image
$sw = $this->srcWidth;
$sh = $this->srcHeight;
$ar = $sw / $sh;
$tw = $this->targetWidth;
$th = $this->targetHeight;
$cx = 0;
$cy = 0;
$cw = $this->srcWidth;
$ch = $this->srcHeight;
if (is_null($tw) && is_null($th)) {
// No tw/th use sw/sh
$tw = $sw;
$th = $sh;
$this->log(" New tw x th {$tw}x{$th}");
} elseif (isset($tw) && is_null($th)) {
// Keep aspect ratio, make th based on tw
$th = $tw / $ar;
$this->log(" New th x{$th}");
} elseif (is_null($tw) && isset($th)) {
// Keep aspect ratio, make tw based on th
$tw = $th * $ar;
$this->log(" New tw {$tw}x");
} elseif (isset($tw) && isset($th)) {
// Keep aspect ratio, make fit in imaginary box
if ($ar < 1) {
$tw = $th * $ar;
$this->log(" New tw {$tw}x");
} else { } else {
$this->targetheight = $this->height; $th = $tw / $ar;
$this->targetWidth = $this->height * $this->aspectRatio; $this->log(" New th x{$th}");
$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}."); /*
if (isset($tw) && isset($th)) {
// Both new width and height are set.
// Use targetWidth and targetHeight as max width/height, image
// should not be larger.
$ratioWidth = $width / $this->targetWidth;
$ratioHeight = $height / $this->targetHeight;
$ratio = ($ratioWidth > $ratioHeight) ? $ratioWidth : $ratioHeight;
$this->targetWidth = round($width / $ratio);
$this->targetHeight = round($height / $ratio);
$this->log(" New width and height was set.");
} elseif (isset($this->targetWidth)) {
// Use new width as max-width
$factor = (float)$this->targetWidth / (float)$width;
$this->targetHeight = round($factor * $height);
$this->log(" New height x$this->targetHeight.");
} elseif (isset($this->targetHeight)) {
// Use new height as max-hight
$factor = (float)$this->targetHeight / (float)$height;
$this->targetWidth = round($factor * $width);
$this->log(" New width {$this->targetWidth}x.");
}
*/
// No new height or width is set, use existing measures.
/*
$this->targetWidth = isset($this->targetWidth)
? $this->targetWidth
: $this->srcWidth;
$this->targetHeight = isset($this->targetHeight)
? $this->targetHeight
: $this->srcHeight;
*/
$this->targetWidth = round($tw);
$this->targetHeight = round($th);
$this->cropX = round($cx);
$this->cropY = round($cy);
$this->cropWidth = round($cw);
$this->cropHeight = round($ch);
$this->log(" Target dimension (after) {$this->targetWidth}x{$this->targetHeight}.");
$this->log(" Crop {$this->cropX}x{$this->cropY} by {$this->cropWidth}x{$this->cropHeight}.");
/*
$ratioWidth = $this->srcWidth / $this->targetWidth;
$ratioHeight = $this->srcHeight / $this->targetHeight;
if ($this->resizeStrategy === self::CROP_TO_FIT) {
// Use targetWidth and targetHeight as defined
// width/height, image should fit the area.
$this->log(" Crop to fit.");
$ratio = ($ratioWidth < $ratioHeight) ? $ratioWidth : $ratioHeight;
$this->cropWidth = round($width / $ratio);
$this->cropHeight = round($height / $ratio);
$this->log(" Crop width, height, ratio: $this->cropWidth x $this->cropHeight ($ratio).");
} elseif ($this->resizeStrategy === self::FILL_TO_FIT) {
// Use targetWidth and targetHeight as defined
// width/height, image should fit the area.
$this->log(" Fill to fit.");
$ratio = ($ratioWidth < $ratioHeight) ? $ratioHeight : $ratioWidth;
$this->fillWidth = round($width / $ratio);
$this->fillHeight = round($height / $ratio);
$this->log(" Fill width, height, ratio: $this->fillWidth x $this->fillHeight ($ratio).");
}
*/
// Check if there is an area to crop off
if (isset($this->area)) {
$this->offset['top'] = round($this->area['top'] / 100 * $this->srcHeight);
$this->offset['right'] = round($this->area['right'] / 100 * $this->srcWidth);
$this->offset['bottom'] = round($this->area['bottom'] / 100 * $this->srcHeight);
$this->offset['left'] = round($this->area['left'] / 100 * $this->srcWidth);
$this->offset['width'] = $this->srcWidth - $this->offset['left'] - $this->offset['right'];
$this->offset['height'] = $this->srcHeight - $this->offset['top'] - $this->offset['bottom'];
$this->srcWidth = $this->offset['width'];
$this->srcHeight = $this->offset['height'];
$this->log("The offset for the area to use is top {$this->area['top']}%, right {$this->area['right']}%, bottom {$this->area['bottom']}%, left {$this->area['left']}%.");
$this->log("The offset for the area to use is top {$this->offset['top']}px, right {$this->offset['right']}px, bottom {$this->offset['bottom']}px, left {$this->offset['left']}px, width {$this->offset['width']}px, height {$this->offset['height']}px.");
}
// Check if crop is set
if ($this->crop) {
$width = $this->crop['width'] = $this->crop['width'] <= 0 ? $this->srcWidth + $this->crop['width'] : $this->crop['width'];
$height = $this->crop['height'] = $this->crop['height'] <= 0 ? $this->srcHeight + $this->crop['height'] : $this->crop['height'];
if ($this->crop['start_x'] == 'left') {
$this->crop['start_x'] = 0;
} elseif ($this->crop['start_x'] == 'right') {
$this->crop['start_x'] = $this->srcWidth - $width;
} elseif ($this->crop['start_x'] == 'center') {
$this->crop['start_x'] = round($this->srcWidth / 2) - round($width / 2);
}
if ($this->crop['start_y'] == 'top') {
$this->crop['start_y'] = 0;
} elseif ($this->crop['start_y'] == 'bottom') {
$this->crop['start_y'] = $this->srcHeight - $height;
} elseif ($this->crop['start_y'] == 'center') {
$this->crop['start_y'] = round($this->srcHeight / 2) - round($height / 2);
}
$this->log(" Crop area is width {$width}px, height {$height}px, start_x {$this->crop['start_x']}px, start_y {$this->crop['start_y']}px.");
}
/*
// Calculate new width and height if keeping aspect-ratio.
if ($this->resizeStrategy === self::KEEP_RATIO) {
$this->log(" Keep aspect ratio.");
// Crop-to-fit and both new width and height are set.
if (($this->resizeStrategy === self::CROP_TO_FIT
|| $this->resizeStrategy === self::FILL_TO_FIT)
&& isset($this->targetWidth)
&& isset($this->targetHeight)
) {
// Use targetWidth and targetHeight as width/height, image should
// fit in box.
$this->log(" Use targetWidth and targetHeight as width/height, image should fit in box.");
} elseif (isset($this->targetWidth) && isset($this->targetHeight)) {
// Both new width and height are set.
// Use targetWidth and targetHeight as max width/height, image
// should not be larger.
$ratioWidth = $width / $this->targetWidth;
$ratioHeight = $height / $this->targetHeight;
$ratio = ($ratioWidth > $ratioHeight) ? $ratioWidth : $ratioHeight;
$this->targetWidth = round($width / $ratio);
$this->targetHeight = round($height / $ratio);
$this->log(" New width and height was set.");
} elseif (isset($this->targetWidth)) {
// Use new width as max-width
$factor = (float)$this->targetWidth / (float)$width;
$this->targetHeight = round($factor * $height);
$this->log(" New height x$this->targetHeight.");
} elseif (isset($this->targetHeight)) {
// Use new height as max-hight
$factor = (float)$this->targetHeight / (float)$height;
$this->targetWidth = round($factor * $width);
$this->log(" New width {$this->targetWidth}x.");
}
}
/*
// Get image dimensions for pre-resize image.
if ($this->resizeStrategy === self::CROP_TO_FIT
|| $this->resizeStrategy === self::FILL_TO_FIT
) {
// Get relations of original & target image
$ratioWidth = $width / $this->targetWidth;
$ratioHeight = $height / $this->targetHeight;
if ($this->resizeStrategy === self::CROP_TO_FIT) {
// Use targetWidth and targetHeight as defined
// width/height, image should fit the area.
$this->log(" Crop to fit.");
$ratio = ($ratioWidth < $ratioHeight) ? $ratioWidth : $ratioHeight;
$this->cropWidth = round($width / $ratio);
$this->cropHeight = round($height / $ratio);
$this->log(" Crop width, height, ratio: $this->cropWidth x $this->cropHeight ($ratio).");
} elseif ($this->resizeStrategy === self::FILL_TO_FIT) {
// Use targetWidth and targetHeight as defined
// width/height, image should fit the area.
$this->log(" Fill to fit.");
$ratio = ($ratioWidth < $ratioHeight) ? $ratioHeight : $ratioWidth;
$this->fillWidth = round($width / $ratio);
$this->fillHeight = round($height / $ratio);
$this->log(" Fill width, height, ratio: $this->fillWidth x $this->fillHeight ($ratio).");
}
}
*/
// Crop, ensure to set new width and height
if ($this->crop) {
$this->log(" Crop.");
$this->targetWidth = round(isset($this->targetWidth)
? $this->targetWidth
: $this->crop['width']);
$this->targetHeight = round(isset($this->targetHeight)
? $this->targetHeight
: $this->crop['height']);
}
// Fill to fit, ensure to set new width and height
/*if ($this->fillToFit) {
$this->log("FillToFit.");
$this->targetWidth = round(isset($this->targetWidth) ? $this->targetWidth : $this->crop['width']);
$this->targetHeight = round(isset($this->targetHeight) ? $this->targetHeight : $this->crop['height']);
}*/
return $this; return $this;
} }
@@ -214,11 +721,11 @@ class CImageResizer
/** /**
* Get target width. * Get target width.
* *
* @return $integer as target width * @return integer as target width
*/ */
public function width() public function getTargetwidth()
{ {
return $this->targetWidth; return $this->targetWidth ? round($this->targetWidth) : null;
} }
@@ -226,13 +733,90 @@ class CImageResizer
/** /**
* Get target height. * Get target height.
* *
* @return $integer as target height * @return integer as target height
*/ */
public function height() public function getTargetheight()
{ {
return $this->targetHeight; return $this->targetHeight ? round($this->targetHeight) : null;
} }
/**
* Get crop position x.
*
* @return integer
*/
public function getCropX()
{
return $this->cropX;
/*
$cropX = 0;
if ($this->cropWidth) {
$cropX = round(($this->cropWidth/2) - ($this->targetWidth/2));
};
return $cropX;*/
}
/**
* Get crop position y.
*
* @return integer
*/
public function getCropY()
{
return $this->cropY;
/*
$cropY = 0;
if ($this->cropHeight) {
$cropY = round(($this->cropHeight/2) - ($this->targetHeight/2));
}
return $cropY;*/
}
/**
* Get crop width.
*
* @return integer
*/
public function getCropWidth()
{
return $this->cropWidth;
/*
$cropWidth = $this->srcWidth;
if ($this->cropWidth) {
$cropWidth = round($this->cropWidth);
}
return $cropWidth;*/
}
/**
* Get crop height.
*
* @return integer
*/
public function getCropHeight()
{
return $this->cropHeight;
/*
$cropHeight = $this->srcHeight;
if ($this->cropHeight) {
$cropHeight = round($this->cropHeight);
}
return $cropHeight;*/
}
} }

View File

@@ -13,4 +13,14 @@
<log type="coverage-clover" target="coverage.clover" /> <log type="coverage-clover" target="coverage.clover" />
</logging> </logging>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">.</directory>
<exclude>
<directory suffix=".php">test</directory>
<directory suffix=".php">webroot</directory>
</exclude>
</whitelist>
</filter>
</phpunit> </phpunit>

View File

@@ -3,6 +3,11 @@
* A testclass * A testclass
* *
*/ */
function logger($str)
{
echo "$str\n";
}
class CImageResizerTest extends \PHPUnit_Framework_TestCase class CImageResizerTest extends \PHPUnit_Framework_TestCase
{ {
/** /**
@@ -13,10 +18,51 @@ class CImageResizerTest extends \PHPUnit_Framework_TestCase
public function providerImages() public function providerImages()
{ {
return array( return array(
// $strategy
// $srcWidth, $srcHeight, $targetWidth, $targetHeight,
// $aspectRatio, $dpr,
// $expectedWidth, $expectedHeight,
// $expectedWidth2, $expectedHeight2
// Same as source, does not set target // 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), // ===== Keep aspect ratio
array(150, 100, null, null, null, 1, null, null), /*
array(1, 100, 100, null, null, null, 1, null, null, 100, 100),
array(1, 100, 150, null, null, null, 1, null, null, 100, 150),
array(1, 150, 100, null, null, null, 1, null, null, 150, 100),
// Width & Height as %
array(1, 100, 100, '200%', null, null, 1, 200, null, 200, 200),
array(1, 100, 100, null, '50%', null, 1, null, 50, 50, 50),
// dpr
//array(1, 100, 100, null, null, null, 2, null, null, 100, 100), // do dpr?
/*
array(1, 100, 100, 100, null, null, 2, 200, null, 200, 200),
array(1, 100, 100, null, 100, null, 2, null, 200, 200, 200),
array(1, 100, 100, 100, 100, null, 2, 200, 200, 200, 200),
*/
// ===== Need crop to fit or fill to fit
// Aspect ratio
/*
array(2, 100, 100, null, null, 2, 1, 100, 50, 100, 50),
array(2, 100, 200, null, null, 4, 1, 100, 25, 100, 25),
array(2, 200, 100, null, null, 4, 1, 200, 50, 200, 50),
// Aspect ratio inverted
array(2, 100, 100, null, null, 1/2, 1, 50, 100, 50, 100),
array(2, 100, 200, null, null, 1/4, 1, 50, 200, 50, 200),
array(2, 200, 100, null, null, 1/4, 1, 25, 100, 25, 100),
// Aspect ratio & width
array(2, 100, 100, 200, null, 2, 1, 200, 100, 200, 100),
// Aspect ratio & height
array(2, 100, 100, null, 200, 1/2, 1, 100, 200, 100, 200),
*/
); );
} }
@@ -29,15 +75,98 @@ class CImageResizerTest extends \PHPUnit_Framework_TestCase
* *
* @return void * @return void
*/ */
public function testResize1($srcWidth, $srcHeight, $targetWidth, $targetHeigth, $aspectRatio, $dpr, $expectedWidth, $expectedHeight) /*
public function testResize1($strategy, $srcWidth, $srcHeight, $targetWidth, $targetHeight, $aspectRatio, $dpr, $expectedWidth, $expectedHeight, $expectedWidth2, $expectedHeight2)
{ {
$img = new CImageResizer(); $img = new CImageResizer(/*'logger'*/ /*);
//$img = new CImageResizer('logger');
$img->setSource($srcWidth, $srcHeight) $img->setSource($srcWidth, $srcHeight)
->setBaseForCalculateTarget($targetWidth, $targetHeigth, $aspectRatio, $dpr) ->setResizeStrategy($strategy)
->setBaseWidthHeight($targetWidth, $targetHeight)
->setBaseAspecRatio($aspectRatio)
->setBaseDevicePixelRate($dpr)
->prepareTargetDimensions(); ->prepareTargetDimensions();
$this->assertEquals($expectedWidth, $img->width(), "Width not correct."); $this->assertEquals($expectedWidth, $img->getTargetWidth(), "Width not correct.");
$this->assertEquals($expectedHeight, $img->height(), "Heigth not correct."); $this->assertEquals($expectedHeight, $img->getTargetHeight(), "Height not correct.");
$img->calculateTargetWidthAndHeight();
$this->assertEquals($expectedWidth2, $img->getTargetWidth(), "Width not correct.");
$this->assertEquals($expectedHeight2, $img->getTargetHeight(), "Height not correct.");
}
*/
/**
* Provider
*
* @return array
*/
public function providerFaultImages()
{
return array(
array('xx', 100, null, 1),
array( 100, 'yy', null, 1),
array( 100, 100, 'zz', 1),
array( 100, 100, null, -1),
);
}
/**
* Test
*
* @dataProvider providerFaultImages
*
* @expectedException Exception
*
* @return void
*/
public function testResizeFaults($targetWidth, $targetHeight, $aspectRatio, $dpr)
{
$img = new CImageResizer(/*'logger'*/);
$img->setBaseWidthHeight($targetWidth, $targetHeight)
->setBaseAspecRatio($aspectRatio)
->setBaseDevicePixelRate($dpr);
}
/**
* Provider
*
* @return array
*/
public function providerResizeStrategy()
{
return array(
array(CImageResizer::KEEP_RATIO, "KEEP_RATIO"),
array(CImageResizer::CROP_TO_FIT, "CROP_TO_FIT"),
array(CImageResizer::FILL_TO_FIT, "FILL_TO_FIT"),
array(-1, "UNKNOWN"),
);
}
/**
* Test
*
* @dataProvider providerResizeStrategy
*
* @return void
*/
public function testResizeStrategy($strategy, $str)
{
$img = new CImageResizer(/*'logger'*/);
$img->setResizeStrategy($strategy);
$res = $img->getResizeStrategyAsString();
$this->assertEquals($str, $res, "Strategy not matching.");
} }
} }

View File

@@ -140,6 +140,18 @@ return array(
/**
* Set skip-original to true to always process the image and use
* the cached version. Default is false and to use the original
* image when its no processing needed.
*
* Default value:
* skip_original: false
*/
//'skip_original' => false,
/** /**
* A function (hook) can be called after img.php has processed all * A function (hook) can be called after img.php has processed all
* configuration options and before processing the image using CImage. * configuration options and before processing the image using CImage.