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

major rearrange to prepare to move to PHP 5.4

This commit is contained in:
Mikael Roos
2015-12-05 14:50:49 +01:00
parent f9b149eb5d
commit 6a93f843be
24 changed files with 1137 additions and 915 deletions

5
.gitignore vendored
View File

@@ -1,6 +1,5 @@
# Cache files # Cache files
cache/* cache/*
# Test # Test and build
coverage/ build/
coverage.clover

View File

@@ -7,7 +7,8 @@
<file>autoload.php</file> <file>autoload.php</file>
<exclude-pattern>docs/*</exclude-pattern> <exclude-pattern>docs/*</exclude-pattern>
<exclude-pattern>coverage/*</exclude-pattern> <exclude-pattern>build/*</exclude-pattern>
<exclude-pattern>test/config.php</exclude-pattern>
<exclude-pattern>webroot/imgs.php</exclude-pattern> <exclude-pattern>webroot/imgs.php</exclude-pattern>
<exclude-pattern>webroot/imgp.php</exclude-pattern> <exclude-pattern>webroot/imgp.php</exclude-pattern>
<exclude-pattern>webroot/imgd.php</exclude-pattern> <exclude-pattern>webroot/imgd.php</exclude-pattern>

View File

@@ -9,8 +9,8 @@
</testsuites> </testsuites>
<logging> <logging>
<log type="coverage-html" target="coverage" charset="UTF-8" highlight="true" lowUpperBound="35" highLowerBound="70" /> <log type="coverage-html" target="build/coverage" charset="UTF-8" highlight="true" lowUpperBound="35" highLowerBound="70" />
<log type="coverage-clover" target="coverage.clover" /> <log type="coverage-clover" target="build/coverage.clover" />
</logging> </logging>
<filter> <filter>

View File

@@ -10,32 +10,34 @@ filter:
- webroot/imgs.php - webroot/imgs.php
- webroot/test/ - webroot/test/
checks: #checks:
php: # php:
code_rating: true # code_rating: true
duplication: true # duplication: true
tools: #tools:
# Copy/Paste Detector # Copy/Paste Detector
php_cpd: true #php_cpd: true
# Metrics # Metrics
php_pdepend: true #php_pdepend: true
# Some Metrics + Bug Detection/Auto-Fixes # Some Metrics + Bug Detection/Auto-Fixes
php_analyzer: true #php_analyzer: true
php_code_sniffer: #php_code_sniffer:
config: # config:
standard: "PSR2" # standard: "PSR2"
php_sim: #php_sim:
min_mass: 16 # Defaults to 16 # min_mass: 16 # Defaults to 16
php_mess_detector: #php_mess_detector:
#config: #config:
# ruleset: ../your-phpmd-ruleset/ruleset.xml # ruleset: ../your-phpmd-ruleset/ruleset.xml
build: build:
tests: tests:
override: override:

View File

@@ -1,4 +1,5 @@
language: php language: php
php: php:
- 5.4 - 5.4
- 5.5 - 5.5
@@ -7,11 +8,77 @@ php:
- nightly - nightly
- "7.0" - "7.0"
sudo: false
git:
submodules: false
addons:
apt:
packages:
#- php-codesniffer
#- phpmd
#- shellcheck
before_script:
# Store all files in your own bin
- mkdir bin
- export PATH=$PATH:$PWD/bin/
# Install validation tools
#- npm install -g htmlhint csslint jshint jscs jsonlint js-yaml html-minifier@0.8.0 clean-css uglify-js
# Install phpcs
- curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
- install --mode 0755 phpcs.phar $PWD/bin/phpcs
# Install phpmd
#- wget -c http://static.phpmd.org/php/latest/phpmd.phar
#- install --mode 0755 phpmd.phar $PWD/bin/phpmd
# Create a build directory for output
- mkdir build
script: script:
- phpunit # Check versions of validation tools
- node --version
- npm --version
#- htmlhint --version
#- csslint --version
#- jscs --version
#- jshint --version
- phpcs --version
#- phpmd --version
#- jsonlint --version
#- js-yaml --version
#- shellcheck --version
#- html-minifier --version
#- cleancss --version
#- uglifyjs --version
# Run validation & publish
- make phpunit
#- make phpcs
notifications: notifications:
irc: "irc.freenode.org#dbwebb" irc: "irc.freenode.org#dbwebb"
webhooks: webhooks:
urls: urls:
- https://webhooks.gitter.im/e/cce29c69604daa8a60ab - https://webhooks.gitter.im/e/cce29c69604daa8a60ab

View File

@@ -1,822 +0,0 @@
<?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;
/**
* Set as expected target image dimensions.
*/
private $targetWidth;
//private $targetWidthOrig; // Save original value
private $targetHeight;
//private $targetheightOrig; // Save original value
/**
* 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 = null;
/**
* Set aspect ratio for the target image.
*/
private $aspectRatio;
/**
* 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.
*
* @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) {
call_user_func($this->log, $str);
}
}
/**
* 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;
}
/**
* Get resize strategy as string.
*
* @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 setBaseDevicePixelRate($dpr = null)
{
$this->log("# Set base for device pixel rate.");
$this->dpr = $dpr;
if (!(is_null($dpr) || (is_numeric($this->dpr) && $this->dpr > 0))) {
throw new Exception("Device pixel rate out of range");
}
$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;
}
// 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");
}
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;
}
// 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;
}
if (isset($this->targetWidth)) {
$this->targetWidth = $this->targetWidth * $this->dpr;
$this->log(" Update target width to {$this->targetWidth}.");
}
if (isset($this->targetHeight)) {
$this->targetHeight = $this->targetHeight * $this->dpr;
$this->log(" Update target height to {$this->targetHeight}.");
}
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.
*
* @throws Exception
*
* @return $this
*/
public function prepareTargetDimensions()
{
$this->log("# Prepare target dimension (before): {$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 {
$th = $tw / $ar;
$this->log(" New th x{$th}");
}
}
/*
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;
}
/**
* Get target width.
*
* @return integer as target width
*/
public function getTargetwidth()
{
return $this->targetWidth ? round($this->targetWidth) : null;
}
/**
* Get target height.
*
* @return integer as target height
*/
public function getTargetheight()
{
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

@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2012 - 2014 Mikael Roos, me@mikaelroos.se Copyright (c) 2012 - 2015 Mikael Roos, me@mikaelroos.se
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.

162
Makefile Normal file
View File

@@ -0,0 +1,162 @@
#!/usr/bin/make -f
#
#
#
# Update codebase
#
.PHONY: build
build:
[ -d build ] || mkdir build
rm -rf build/*
#
# Various test to pass build
#
.PHONY: test
test: build phpunit phpcs
#
# phpcs
#
.PHONY: phpcs
phpcs:
phpcs --standard=.phpcs.xml | tee build/phpcs
#
# phpcbf
#
.PHONY: phpcbf
phpcbf:
phpcbf --standard=.phpcs.xml
#
# phpunit
#
.PHONY: phpunit
phpunit:
phpunit --configuration .phpunit.xml
#
# phpdoc
#
.PHONY: phpdoc
phpdoc:
phpdoc --config=.phpdoc.xml
# ------------------------- OBSOLETE TO BE REMOVED?
#
# Build and development environment using make
#
COMPOSER_PACKAGES = \
"phpunit/phpunit=4.*" \
"sebastian/phpcpd=2.*" \
"phploc/phploc=2.*" \
"phpdocumentor/phpdocumentor=2.*" \
"squizlabs/php_codesniffer=2.*" \
"phpmd/phpmd=@stable" \
NPM_PACKAGES = \
htmlhint \
csslint \
less \
APM_PACKAGES = \
linter \
linter-htmlhint \
linter-csslint \
linter-less \
linter-jscs \
linter-jshint \
linter-pep8 \
linter-pylint \
linter-php \
linter-phpcs \
linter-phpmd \
linter-shellcheck \
linter-xmllint \
block-travel \
#
# less
#
.PHONY: less
less:
lessc --clean-css app/css/style.less htdocs/css/style.css
#
# All developer tools
#
.PHONY: tools-config tools-install tools-update
tools-config: npm-config
tools-install: composer-require npm-install apm-install
tools-update: composer-update npm-update apm-update
#
# composer
#
.PHONY: composer-require composer-update
composer-require:
composer --sort-packages --update-no-dev global require $(COMPOSER_PACKAGES)
composer-update:
composer --no-dev global update
#
# npm
#
.PHONY: npm-config npm-installl npm-update
npm-config:
npm config set prefix '~/.npm-packages'
npm-install:
npm -g install $(NPM_PACKAGES)
npm-update:
npm -g update
#
# apm
#
.PHONY: apm-installl apm-update
apm-install:
apm install $(APM_PACKAGES)
apm-update:
apm update --confirm=false

View File

@@ -2,8 +2,10 @@ Image conversion on the fly using PHP
===================================== =====================================
[![Join the chat at https://gitter.im/mosbth/cimage](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mosbth/cimage?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/mosbth/cimage](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mosbth/cimage?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/mosbth/cimage.svg?branch=master)](https://travis-ci.org/mosbth/cimage) [![Build Status](https://travis-ci.org/mosbth/cimage.svg?branch=resize)](https://travis-ci.org/mosbth/cimage)
[![Build Status](https://scrutinizer-ci.com/g/mosbth/cimage/badges/build.png?b=master)](https://scrutinizer-ci.com/g/mosbth/cimage/build-status/master) [![Build Status](https://scrutinizer-ci.com/g/mosbth/cimage/badges/build.png?b=resize)](https://scrutinizer-ci.com/g/mosbth/cimage/build-status/resize)
About About
------------------------------------- -------------------------------------

View File

@@ -1,11 +1,18 @@
Revision history Revision history
===================================== =====================================
[![Build Status](https://travis-ci.org/mosbth/cimage.svg?branch=master)](https://travis-ci.org/mosbth/cimage)
[![Build Status](https://scrutinizer-ci.com/g/mosbth/cimage/badges/build.png?b=master)](https://scrutinizer-ci.com/g/mosbth/cimage/build-status/master)
v0.7.7* (2015-10-25) v0.8.* (2015-12-05) (branch resize)
-------------------------------------
* Improving build phase using travis and scrutinizer.
* Code validating with phpunit and phpcs.
* Moved classes to src/, adding namespace and support PSR-4.
* Require PHP 5.4.
v0.7.7* (2015-10-25) (branch master)
------------------------------------- -------------------------------------
* Added conversion to sRGB using option `?srgb`. #120. * Added conversion to sRGB using option `?srgb`. #120.

View File

@@ -3,20 +3,8 @@
* Autoloader for CImage and related class files. * Autoloader for CImage and related class files.
* *
*/ */
//include __DIR__ . "/../CHttpGet.php";
//include __DIR__ . "/../CRemoteImage.php";
//include __DIR__ . "/../CImage.php";
/**
* Autoloader for classes.
*
* @param string $class the fully-qualified class name.
*
* @return void
*/
spl_autoload_register(function ($class) { spl_autoload_register(function ($class) {
//$path = CIMAGE_SOURCE_PATH . "/{$class}.php"; $path = __DIR__ . "/src/CImage/{$class}.php";
$path = __DIR__ . "/{$class}.php";
if (is_file($path)) { if (is_file($path)) {
require($path); require($path);
} }

View File

@@ -1,8 +1,8 @@
{ {
"name": "mos/cimage", "name": "mos/cimage",
"type": "library", "type": "library",
"description": "Process, scale, resize, crop and filter images.", "description": "Serverside image processing with PHP GD. Process, scale, resize, crop and filter images.",
"keywords": ["image", "imageprocessing", "gd"], "keywords": ["image", "imageprocessing", "gd", "crop", "resize"],
"homepage": "http://dbwebb.se/opensource/cimage", "homepage": "http://dbwebb.se/opensource/cimage",
"license": "MIT", "license": "MIT",
"authors": [ "authors": [
@@ -18,15 +18,9 @@
"docs": "http://dbwebb.se/opensource/cimage" "docs": "http://dbwebb.se/opensource/cimage"
}, },
"require": { "require": {
"php": ">=5.3" "php": ">=5.4"
}, },
"autoload": { "autoload": {
"classmap": [ "classmap": [ "src/CImage/" ]
"CImage.php",
"CHttpGet.php",
"CRemoteImage.php",
"CWhitelist.php",
"CAsciiArt.php"
]
} }
} }

View File

@@ -175,7 +175,7 @@ class CAsciiArt
*/ */
public function getLuminance($red, $green, $blue) public function getLuminance($red, $green, $blue)
{ {
switch($this->luminanceStrategy) { switch ($this->luminanceStrategy) {
case 1: case 1:
$luminance = ($red * 0.2126 + $green * 0.7152 + $blue * 0.0722) / 255; $luminance = ($red * 0.2126 + $green * 0.7152 + $blue * 0.0722) / 255;
break; break;

View File

@@ -208,8 +208,8 @@ class CImage
/** /**
* Path to command to optimize jpeg images, for example jpegtran or null. * Path to command to optimize jpeg images, for example jpegtran or null.
*/ */
private $jpegOptimize; private $jpegOptimize;
private $jpegOptimizeCmd; private $jpegOptimizeCmd;
@@ -339,8 +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 $area; private $area;
private $offset; private $offset;
@@ -401,14 +401,14 @@ class CImage
*/ */
const RESIZE = 1; const RESIZE = 1;
const RESAMPLE = 2; const RESAMPLE = 2;
private $copyStrategy = NULL; private $copyStrategy = null;
/* /*
* Class for image resizer. * Class for image resizer.
*/ */
private $imageResizer = null; private $imageResizer = null;
/** /**
* Properties, the class is mutable and the method setOptions() * Properties, the class is mutable and the method setOptions()
@@ -637,7 +637,7 @@ class CImage
if ($extension == 'jpeg') { if ($extension == 'jpeg') {
$extension = 'jpg'; $extension = 'jpg';
} }
return $extension; return $extension;
} }
@@ -1343,7 +1343,7 @@ class CImage
$subdir .= '_'; $subdir .= '_';
} }
$file = $prefix . $subdir . $filename . $width . $height $file = $prefix . $subdir . $filename . $width . $height
. $offset . $crop . $cropToFit . $fillToFit . $offset . $crop . $cropToFit . $fillToFit
. $crop_x . $crop_y . $upscale . $crop_x . $crop_y . $upscale
. $quality . $filters . $sharpen . $emboss . $blur . $palette . $quality . $filters . $sharpen . $emboss . $blur . $palette
@@ -1484,7 +1484,7 @@ class CImage
$index = imagecolortransparent($this->image); $index = imagecolortransparent($this->image);
$transparent = null; $transparent = null;
if ($index != -1) { if ($index != -1) {
$transparent = " (transparent)"; $transparent = " (transparent)";
} }
switch ($pngType) { switch ($pngType) {
@@ -1594,11 +1594,11 @@ class CImage
* *
* @return $this * @return $this
*/ */
public function setCopyResizeStrategy($strategy) public function setCopyResizeStrategy($strategy)
{ {
$this->copyStrategy = $strategy; $this->copyStrategy = $strategy;
return $this; return $this;
} }
@@ -1609,7 +1609,7 @@ class CImage
*/ */
public function imageCopyResampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) public function imageCopyResampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
{ {
if($this->copyStrategy == self::RESIZE) { if ($this->copyStrategy == self::RESIZE) {
$this->log("Copy by resize"); $this->log("Copy by resize");
imagecopyresized($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); imagecopyresized($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
} else { } else {
@@ -2298,7 +2298,7 @@ class CImage
$type = $this->getTargetImageExtension(); $type = $this->getTargetImageExtension();
$this->Log("Saving image as " . $type); $this->Log("Saving image as " . $type);
switch($type) { switch ($type) {
case 'jpeg': case 'jpeg':
case 'jpg': case 'jpg':
@@ -2424,7 +2424,7 @@ class CImage
$colorspace = $image->getImageColorspace(); $colorspace = $image->getImageColorspace();
$this->log(" Current colorspace: " . $colorspace); $this->log(" Current colorspace: " . $colorspace);
$profiles = $image->getImageProfiles('*', false); $profiles = $image->getImageProfiles('*', false);
$hasICCProfile = (array_search('icc', $profiles) !== false); $hasICCProfile = (array_search('icc', $profiles) !== false);
$this->log(" Has ICC color profile: " . ($hasICCProfile ? "YES" : "NO")); $this->log(" Has ICC color profile: " . ($hasICCProfile ? "YES" : "NO"));
@@ -2535,7 +2535,7 @@ class CImage
header('Last-Modified: ' . $gmdate . " GMT"); header('Last-Modified: ' . $gmdate . " GMT");
} }
foreach($this->HTTPHeader as $key => $val) { foreach ($this->HTTPHeader as $key => $val) {
header("$key: $val"); header("$key: $val");
} }

View File

@@ -0,0 +1,822 @@
<?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;
/**
* Set as expected target image dimensions.
*/
private $targetWidth;
//private $targetWidthOrig; // Save original value
private $targetHeight;
//private $targetheightOrig; // Save original value
/**
* 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 = null;
/**
* Set aspect ratio for the target image.
*/
private $aspectRatio;
/**
* 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.
*
* @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) {
call_user_func($this->log, $str);
}
}
/**
* 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;
}
/**
* Get resize strategy as string.
*
* @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 setBaseDevicePixelRate($dpr = null)
{
$this->log("# Set base for device pixel rate.");
$this->dpr = $dpr;
if (!(is_null($dpr) || (is_numeric($this->dpr) && $this->dpr > 0))) {
throw new Exception("Device pixel rate out of range");
}
$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;
}
// 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");
}
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;
}
// 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;
}
if (isset($this->targetWidth)) {
$this->targetWidth = $this->targetWidth * $this->dpr;
$this->log(" Update target width to {$this->targetWidth}.");
}
if (isset($this->targetHeight)) {
$this->targetHeight = $this->targetHeight * $this->dpr;
$this->log(" Update target height to {$this->targetHeight}.");
}
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.
*
* @throws Exception
*
* @return $this
*/
public function prepareTargetDimensions()
{
$this->log("# Prepare target dimension (before): {$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 {
$th = $tw / $ar;
$this->log(" New th x{$th}");
}
}
/*
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;
}
/**
* Get target width.
*
* @return integer as target width
*/
public function getTargetwidth()
{
return $this->targetWidth ? round($this->targetWidth) : null;
}
/**
* Get target height.
*
* @return integer as target height
*/
public function getTargetheight()
{
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

@@ -44,21 +44,21 @@ class CImageResizerStrategyKeepAspectRatioTest extends \PHPUnit_Framework_TestCa
* *
* @return void * @return void
*/ */
public function testResize1($sw, $sh, $tw, $th, $twa, $tha, $cx, $cy, $cw, $ch) public function testResize1($sw, $sh, $tw, $th, $twa, $tha, $cx, $cy, $cw, $ch)
{ {
$img = new CImageResizer(/*'logger'/**/); $img = new CImageResizer(/*'logger'/**/);
$img->setSource($sw, $sh) $img->setSource($sw, $sh)
->setBaseWidthHeight($tw, $th) ->setBaseWidthHeight($tw, $th)
->setResizeStrategy(CImageResizer::KEEP_RATIO) ->setResizeStrategy(CImageResizer::KEEP_RATIO)
->calculateTargetWidthAndHeight(); ->calculateTargetWidthAndHeight();
$this->assertEquals($twa, $img->getTargetWidth(), "Target width not correct."); $this->assertEquals($twa, $img->getTargetWidth(), "Target width not correct.");
$this->assertEquals($tha, $img->getTargetHeight(), "Target height not correct."); $this->assertEquals($tha, $img->getTargetHeight(), "Target height not correct.");
$this->assertEquals($cx, $img->getCropX(), "CropX not correct."); $this->assertEquals($cx, $img->getCropX(), "CropX not correct.");
$this->assertEquals($cy, $img->getCropY(), "CropY not correct."); $this->assertEquals($cy, $img->getCropY(), "CropY not correct.");
$this->assertEquals($cw, $img->getCropWidth(), "CropWidth not correct."); $this->assertEquals($cw, $img->getCropWidth(), "CropWidth not correct.");
$this->assertEquals($ch, $img->getCropHeight(), "CropHeight not correct."); $this->assertEquals($ch, $img->getCropHeight(), "CropHeight not correct.");
} }
} }

View File

@@ -46,7 +46,7 @@ class CImageResizerStrategyStretchTest extends \PHPUnit_Framework_TestCase
*/ */
public function testResize1($sw, $sh, $tw, $th, $twa, $tha, $cx, $cy, $cw, $ch) public function testResize1($sw, $sh, $tw, $th, $twa, $tha, $cx, $cy, $cw, $ch)
{ {
$img = new CImageResizer(/*'logger'/**/); $img = new CImageResizer(/*'logger'/**/);
$img->setSource($sw, $sh) $img->setSource($sw, $sh)
->setBaseWidthHeight($tw, $th) ->setBaseWidthHeight($tw, $th)

View File

@@ -21,7 +21,7 @@ class CImageResizerTest extends \PHPUnit_Framework_TestCase
// $strategy // $strategy
// $srcWidth, $srcHeight, $targetWidth, $targetHeight, // $srcWidth, $srcHeight, $targetWidth, $targetHeight,
// $aspectRatio, $dpr, // $aspectRatio, $dpr,
// $expectedWidth, $expectedHeight, // $expectedWidth, $expectedHeight,
// $expectedWidth2, $expectedHeight2 // $expectedWidth2, $expectedHeight2
@@ -162,7 +162,7 @@ class CImageResizerTest extends \PHPUnit_Framework_TestCase
*/ */
public function testResizeStrategy($strategy, $str) public function testResizeStrategy($strategy, $str)
{ {
$img = new CImageResizer(/*'logger'*/); $img = new CImageResizer(/*'logger'*/);
$img->setResizeStrategy($strategy); $img->setResizeStrategy($strategy);
$res = $img->getResizeStrategyAsString(); $res = $img->getResizeStrategyAsString();

View File

@@ -38,7 +38,7 @@ class CImageSRGBTest extends \PHPUnit_Framework_TestCase
$img = new CImage(); $img = new CImage();
$filename = $img->convert2sRGBColorSpace( $filename = $img->convert2sRGBColorSpace(
'car.png', 'car.png',
IMAGE_PATH, IMAGE_PATH,
$this->cache, $this->cache,
$this->srgbColorProfile $this->srgbColorProfile
@@ -63,8 +63,8 @@ class CImageSRGBTest extends \PHPUnit_Framework_TestCase
$img = new CImage(); $img = new CImage();
$filename = $img->convert2sRGBColorSpace( $filename = $img->convert2sRGBColorSpace(
'car.jpg', 'car.jpg',
IMAGE_PATH, IMAGE_PATH,
$this->cache, $this->cache,
$this->srgbColorProfile $this->srgbColorProfile
); );

View File

@@ -244,7 +244,7 @@ $pwd = get(array('password', 'pwd'), null);
// Check if passwords match, if configured to use passwords // Check if passwords match, if configured to use passwords
$passwordMatch = null; $passwordMatch = null;
if ($pwd) { if ($pwd) {
switch($pwdType) { switch ($pwdType) {
case 'md5': case 'md5':
$passwordMatch = ($pwdConfig === md5($pwd)); $passwordMatch = ($pwdConfig === md5($pwd));
break; break;
@@ -996,8 +996,8 @@ if ($srgb || $srgbDefault) {
} }
$filename = $img->convert2sRGBColorSpace( $filename = $img->convert2sRGBColorSpace(
$srcImage, $srcImage,
$imagePath, $imagePath,
$srgbDir, $srgbDir,
$srgbColorProfile, $srgbColorProfile,
$useCache $useCache