diff --git a/CImage.php b/CImage.php
index eb014d5..09c812d 100644
--- a/CImage.php
+++ b/CImage.php
@@ -339,7 +339,8 @@ class CImage
/**
* 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->setTarget($saveFolder, $saveName);
- $this->imageResizer = new CImageResizer();
+ $this->imageResizer = new CImageResizer(array($this, 'log'));
}
+
/**
* Set verbose mode.
*
@@ -931,7 +933,7 @@ class CImage
$this->imageResizer->setSource($this->width, $this->height);
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 filesize: " . filesize($file) . " bytes.");
$this->log(" Image mimetype: " . image_type_to_mime_type($this->fileType));
@@ -951,66 +953,10 @@ class CImage
*/
public function initDimensions()
{
- $this->log("Init dimension (before) newWidth x newHeight is {$this->newWidth} x {$this->newHeight}.");
-
- // width as %
- if ($this->newWidth[strlen($this->newWidth)-1] == '%') {
- $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}.");
+ $this->imageResizer->setBaseWidthHeight($this->newWidth, $this->newHeight)
+ ->setBaseAspecRatio($this->aspectRatio)
+ ->setBaseDevicePixelRate($this->dpr)
+ ->prepareTargetDimensions();
return $this;
}
@@ -1024,6 +970,26 @@ class CImage
*/
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
$this->log("Calculate new width and 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']);
}
- // 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.
$this->newWidth = round(isset($this->newWidth) ? $this->newWidth : $this->width);
$this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->height);
$this->log("Calculated new width x height as {$this->newWidth} x {$this->newHeight}.");
+ */
return $this;
}
@@ -1667,6 +1627,7 @@ class CImage
*/
public function resize()
{
+ $imgres = $this->imageResizer;
$this->log("### Starting to Resize()");
$this->log("Upscale = '$this->upscale'");
@@ -1724,11 +1685,21 @@ class CImage
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopy($imageResized, $this->image, $posX, $posY, $cropX, $cropY, $this->newWidth, $this->newHeight);
} else {
- $cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
- $cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
- $imgPreCrop = $this->CreateImageKeepTransparency($this->cropWidth, $this->cropHeight);
+ $cropX = $imgres->getCropX();
+ $cropY = $imgres->getCropY();
+ $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);
- $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);
}
@@ -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 $value the value to use
diff --git a/CImageResizer.php b/CImageResizer.php
index 19c4031..d8e0fdc 100644
--- a/CImageResizer.php
+++ b/CImageResizer.php
@@ -24,7 +24,7 @@ class CImageResizer
/**
- * Target image dimensions.
+ * Set as expected target image dimensions.
*/
private $targetWidth;
//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
* 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
* to disable logging.
@@ -69,7 +139,7 @@ class CImageResizer
public function log($str)
{
if ($this->log) {
- echo $str . "\n";
+ call_user_func($this->log, $str);
}
}
@@ -89,7 +159,7 @@ class CImageResizer
{
$this->srcWidth = $width;
$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;
}
@@ -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
- * @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
+ * @return string
+ */
+ public function getResizeStrategyAsString()
+ {
+ 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
*
* @return $this
*/
- public function setBaseForCalculateTarget($width = null, $height = null, $aspectRatio = null, $dpr = 1)
+ public function setBaseDevicePixelRate($dpr = null)
{
- $this->targetWidth = $width;
- $this->targetheight = $height;
- $this->aspectRatio = $aspectRatio;
- $this->dpr = $dpr;
+ $this->log("# Set base for device pixel rate.");
- // 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.");
+ $this->dpr = $dpr;
+
+ if (!(is_null($dpr) || (is_numeric($this->dpr) && $this->dpr > 0))) {
+ throw new Exception("Device pixel rate out of range");
}
- // 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.");
+ $this->log(" Requested dpr={$this->dpr}.");
+
+ return $this;
+ }
+
+
+
+ /**
+ * 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
- if (!(is_null($this->targetWidth) || is_numeric($this->targetWidth))) {
- throw new Exception('Width not numeric');
+ // Both null, use source as base for target
+ if (is_null($this->targetWidth) && is_null($this->targetHeight)) {
+
+ $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
- if (!(is_null($this->targetheight) || is_numeric($this->targetheight))) {
- throw new Exception('Height not numeric');
+ return $this;
+ }
+
+
+
+ /**
+ * 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 (!(is_null($this->aspectRatio) || is_numeric($this->aspectRatio))) {
- throw new Exception('Aspect ratio out of range');
+ // If both not set, use source as base
+ if (is_null($this->targetWidth) && is_null($this->targetHeight)) {
+ $this->targetWidth = $this->srcWidth;
+ $this->targetHeight = $this->srcHeight;
}
- // Device pixel ratio is valid
- if (!(is_numeric($this->dpr) && $this->dpr > 0)) {
- throw new Exception('Device pixel rate out of range');
+ if (isset($this->targetWidth)) {
+ $this->targetWidth = $this->targetWidth * $this->dpr;
+ $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;
}
@@ -159,52 +409,309 @@ class CImageResizer
* 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}.");
+ $this->log("# Prepare target dimension (before): {$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}");
+ $this->prepareByConsiderAspectRatio()
+ ->prepareByConsiderDpr();
+
+ $this->log(" Prepare target dimension (after): {$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 {
- $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}");
+ $th = $tw / $ar;
+ $this->log(" New th x{$th}");
}
}
- $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;
}
@@ -214,11 +721,11 @@ class CImageResizer
/**
* 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.
*
- * @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;*/
+ }
}
diff --git a/phpunit.xml b/phpunit.xml
index e406494..aadeeec 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -13,4 +13,14 @@
+
+
+ .
+
+ test
+ webroot
+
+
+
+
diff --git a/test/CImageResizerTest.php b/test/CImageResizerTest.php
index bbb8e80..3da2e0f 100644
--- a/test/CImageResizerTest.php
+++ b/test/CImageResizerTest.php
@@ -3,6 +3,11 @@
* A testclass
*
*/
+function logger($str)
+{
+ echo "$str\n";
+}
+
class CImageResizerTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -13,10 +18,51 @@ class CImageResizerTest extends \PHPUnit_Framework_TestCase
public function providerImages()
{
return array(
+
+ // $strategy
+ // $srcWidth, $srcHeight, $targetWidth, $targetHeight,
+ // $aspectRatio, $dpr,
+ // $expectedWidth, $expectedHeight,
+ // $expectedWidth2, $expectedHeight2
+
// 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),
+
+ // ===== Keep aspect ratio
+/*
+ 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
*/
- 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)
- ->setBaseForCalculateTarget($targetWidth, $targetHeigth, $aspectRatio, $dpr)
+ ->setResizeStrategy($strategy)
+ ->setBaseWidthHeight($targetWidth, $targetHeight)
+ ->setBaseAspecRatio($aspectRatio)
+ ->setBaseDevicePixelRate($dpr)
->prepareTargetDimensions();
- $this->assertEquals($expectedWidth, $img->width(), "Width not correct.");
- $this->assertEquals($expectedHeight, $img->height(), "Heigth not correct.");
+ $this->assertEquals($expectedWidth, $img->getTargetWidth(), "Width 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.");
}
}
diff --git a/webroot/img_config.php b/webroot/img_config.php
index ae555e4..c05432a 100644
--- a/webroot/img_config.php
+++ b/webroot/img_config.php
@@ -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
* configuration options and before processing the image using CImage.