1
0
mirror of https://github.com/mosbth/cimage.git synced 2025-07-30 13:10:12 +02:00

Cleaning up code #23, added rotate and autoRotate #36

This commit is contained in:
Mikael Roos
2014-08-31 23:57:34 +02:00
parent 67524bd090
commit c96ed10f80
13 changed files with 480 additions and 167 deletions

4
.gitignore vendored
View File

@@ -1,4 +1,4 @@
# Cache files #
######################
cache/_*

cache/*

View File

@@ -6,7 +6,7 @@
* @example http://dbwebb.se/opensource/cimage
* @link https://github.com/mosbth/cimage
*/
class CImage
class CImage
{
/**
@@ -107,7 +107,7 @@ class CImage
/**
* Keep a log/trace on what happens
*/
private $log = array();
private $log = array();
@@ -148,36 +148,43 @@ class CImage
/**
* Path to command to optimize jpeg images, for example jpegtran or null.
*/
private $jpegOptimize;
private $jpegOptimize;
/**
* Image dimensions, calculated from loaded image.
*/
private $width; // Calculated from source image
private $height; // Calculated from source image
private $width; // Calculated from source image
private $height; // Calculated from source image
private $offset;
public $keepRatio;
public $cropToFit;
public $crop;
/**
* New image dimensions, incoming as argument or calculated.
*/
private $newWidth;
private $newWidthOrig; // Save original value
private $newHeight;
private $newHeightOrig; // Save original value
/**
* Properties (clean up these)
*/
private $offset;
public $keepRatio;
public $cropToFit;
public $crop;
/**
* Properties
*/
public $newWidth;
public $newHeight;
private $cropWidth;
private $cropHeight;
public $crop_x;
public $crop_y;
public $filters;
private $type; // Calculated from source image
private $attr; // Calculated from source image
private $useCache; // Use the cache if true, set to false to ignore the cached file.
private $useOriginal; // Use original image if possible
private $cropWidth;
private $cropHeight;
public $crop_x;
public $crop_y;
public $filters;
private $type; // Calculated from source image
private $attr; // Calculated from source image
private $useCache; // Use the cache if true, set to false to ignore the cached file.
private $useOriginal; // Use original image if possible
@@ -190,7 +197,7 @@ class CImage
* @param string $saveFolder path to folder where to save the new file or null to skip saving.
* @param string $saveName name of target file when saveing.
*/
public function __construct($imageSrc = null, $imageFolder = null, $saveFolder = null, $saveName = null)
public function __construct($imageSrc = null, $imageFolder = null, $saveFolder = null, $saveName = null)
{
$this->setSource($imageSrc, $imageFolder);
$this->setTarget($saveFolder, $saveName);
@@ -205,7 +212,7 @@ class CImage
*
* @return $this
*/
public function setVerbose($mode = true)
public function setVerbose($mode = true)
{
$this->verbose = $mode;
return $this;
@@ -220,11 +227,11 @@ class CImage
*
* @return $this
*/
private function checkFileExtension($extension)
private function checkFileExtension($extension)
{
$valid = array('jpg', 'jpeg', 'png', 'gif');
in_array($extension, $valid)
in_array($extension, $valid)
or $this->raiseError('Not a valid file extension.');
return $this;
@@ -267,7 +274,7 @@ class CImage
*
* @return $this
*/
public function setTarget($src = null, $dir = null)
public function setTarget($src = null, $dir = null)
{
if (!(isset($src) && isset($dir))) {
return $this;
@@ -295,9 +302,9 @@ class CImage
*
* @return $this
*/
public function setOptions($args)
public function setOptions($args)
{
$this->log("Set new options for processing image.");
$this->log("Set new options for processing image.");
$defaults = array(
// Options for calculate dimensions
@@ -306,15 +313,19 @@ class CImage
'aspectRatio' => null,
'keepRatio' => true,
'cropToFit' => false,
'crop' => null, //array('width'=>null, 'height'=>null, 'start_x'=>0, 'start_y'=>0),
'crop' => null, //array('width'=>null, 'height'=>null, 'start_x'=>0, 'start_y'=>0),
'area' => null, //'0,0,0,0',
// Options for caching or using original
'useCache' => true,
'useOriginal' => true,
'useOriginal' => true,
// Pre-processing, before resizing is done
'scale' => null,
'scale' => null,
'rotateBefore' => null,
// General options
'bgColor' => 0,
// Post-processing, after resizing is done
'palette' => null,
@@ -322,6 +333,8 @@ class CImage
'sharpen' => null,
'emboss' => null,
'blur' => null,
'rotateAfter' => null,
'autoRotate' => false,
// Options for saving
//'quality' => null,
@@ -357,11 +370,11 @@ class CImage
$parts = explode(',', $filterStr);
$filter = $this->mapFilter($parts[0]);
$filter['str'] = $filterStr;
for ($i=1;$i<=$filter['argc'];$i++) {
for ($i=1; $i<=$filter['argc']; $i++) {
if (isset($parts[$i])) {
$filter["arg{$i}"] = $parts[$i];
} else {
throw new Exception('Missing arg to filter, review how many arguments are needed at http://php.net/manual/en/function.imagefilter.php');
throw new Exception('Missing arg to filter, review how many arguments are needed at http://php.net/manual/en/function.imagefilter.php');
}
}
$args['filters'][$key] = $filter;
@@ -371,10 +384,13 @@ class CImage
// Merge default arguments with incoming and set properties.
//$args = array_merge_recursive($defaults, $args);
$args = array_merge($defaults, $args);
foreach ($defaults as $key=>$val) {
foreach ($defaults as $key => $val) {
$this->{$key} = $args[$key];
}
$this->newWidthOrig = $this->newWidth;
$this->newHeightOrig = $this->newHeight;
return $this;
}
@@ -388,10 +404,10 @@ class CImage
* @return array with filter settings
* @throws Exception
*/
private function mapFilter($name)
private function mapFilter($name)
{
$map = array(
'negate' => array('id'=>0, 'argc'=>0, 'type'=>IMG_FILTER_NEGATE),
'negate' => array('id'=>0, 'argc'=>0, 'type'=>IMG_FILTER_NEGATE),
'grayscale' => array('id'=>1, 'argc'=>0, 'type'=>IMG_FILTER_GRAYSCALE),
'brightness' => array('id'=>2, 'argc'=>1, 'type'=>IMG_FILTER_BRIGHTNESS),
'contrast' => array('id'=>3, 'argc'=>1, 'type'=>IMG_FILTER_CONTRAST),
@@ -405,9 +421,9 @@ class CImage
'pixelate' => array('id'=>11, 'argc'=>2, 'type'=>IMG_FILTER_PIXELATE),
);
if (isset($map[$name]))
if (isset($map[$name])) {
return $map[$name];
else {
} else {
throw new Exception('No such filter.');
}
}
@@ -415,15 +431,14 @@ class CImage
/**
* Init new width and height and do some sanity checks on constraints, before any
* processing can be done.
* Load image details from original image file.
*
* @return $this
* @throws Exception
*/
public function initDimensions()
public function loadImageDetails()
{
is_readable($this->pathToImage)
is_readable($this->pathToImage)
or $this->raiseError('Image file does not exist.');
// Get details on image
@@ -436,6 +451,20 @@ class CImage
$this->log("Image filesize: " . filesize($this->pathToImage) . " bytes.");
}
return $this;
}
/**
* Init new width and height and do some sanity checks on constraints, before any
* processing can be done.
*
* @return $this
* @throws Exception
*/
public function initDimensions()
{
// width as %
if ($this->newWidth[strlen($this->newWidth)-1] == '%') {
$this->newWidth = $this->width * substr($this->newWidth, 0, -1) / 100;
@@ -473,12 +502,12 @@ class CImage
}
// Check values to be within domain
is_null($this->newWidth)
or is_numeric($this->newWidth)
is_null($this->newWidth)
or is_numeric($this->newWidth)
or $this->raiseError('Width not numeric');
is_null($this->newHeight)
or is_numeric($this->newHeight)
is_null($this->newHeight)
or is_numeric($this->newHeight)
or $this->raiseError('Height not numeric');
return $this;
@@ -491,7 +520,7 @@ class CImage
*
* @return $this
*/
public function calculateNewWidthAndHeight()
public function calculateNewWidthAndHeight()
{
// Crop, use cropped width and height as base for calulations
$this->log("Calculate new width and height.");
@@ -523,7 +552,7 @@ class CImage
$this->crop['start_x'] = $this->width - $width;
} elseif ($this->crop['start_x'] == 'center') {
$this->crop['start_x'] = round($this->width / 2) - round($width / 2);
}
}
if ($this->crop['start_y'] == 'top') {
$this->crop['start_y'] = 0;
@@ -531,19 +560,24 @@ class CImage
$this->crop['start_y'] = $this->height - $height;
} elseif ($this->crop['start_y'] == 'center') {
$this->crop['start_y'] = round($this->height / 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.
// Calculate new width and height if keeping aspect-ratio.
if ($this->keepRatio) {
$this->log("Keep aspect ratio.");
// Crop-to-fit and both new width and height are set.
if ($this->cropToFit && isset($this->newWidth) && isset($this->newHeight)) {
// Use newWidth and newHeigh as width/height, image should fit in box.
;
$this->log("Use newWidth and newHeigh as width/height, image should fit in box.");
} elseif (isset($this->newWidth) && isset($this->newHeight)) {
// Both new width and height are set.
// Use newWidth and newHeigh as max width/height, image should not be larger.
$ratioWidth = $width / $this->newWidth;
@@ -551,35 +585,45 @@ class CImage
$ratio = ($ratioWidth > $ratioHeight) ? $ratioWidth : $ratioHeight;
$this->newWidth = round($width / $ratio);
$this->newHeight = round($height / $ratio);
$this->log("New width and height was set.");
} elseif (isset($this->newWidth)) {
// Use new width as max-width
$factor = (float)$this->newWidth / (float)$width;
$this->newHeight = round($factor * $height);
$this->log("New width was set.");
} elseif (isset($this->newHeight)) {
// Use new height as max-hight
$factor = (float)$this->newHeight / (float)$height;
$this->newWidth = round($factor * $width);
$this->log("New height was set.");
}
// Use newWidth and newHeigh as defined width/height, image should fit the area.
if ($this->cropToFit) {
$this->log("Crop to fit.");
$ratioWidth = $width / $this->newWidth;
$ratioHeight = $height / $this->newHeight;
$ratio = ($ratioWidth < $ratioHeight) ? $ratioWidth : $ratioHeight;
$this->cropWidth = round($width / $ratio);
$this->cropHeight = round($height / $ratio);
}
}
}
// Crop, ensure to set new width and height
if ($this->crop) {
$this->log("Crop.");
$this->newWidth = round(isset($this->newWidth) ? $this->newWidth : $this->crop['width']);
$this->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->crop['height']);
$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->newHeight = round(isset($this->newHeight) ? $this->newHeight : $this->height);
$this->log("Calculated new width x height as {$this->newWidth} x {$this->newHeight}.");
return $this;
@@ -587,6 +631,26 @@ class CImage
/**
* Re-calculate image dimensions when original image dimension has changed.
*
* @return $this
*/
public function reCalculateDimensions()
{
$this->log("Re-calculate image dimensions, newWidth x newHeigh was: " . $this->newWidth . " x " . $this->newHeight);
$this->newWidth = $this->newWidthOrig;
$this->newHeight = $this->newHeightOrig;
$this->initDimensions()
->calculateNewWidthAndHeight();
return $this;
}
/**
* Set extension for filename to save as.
*
@@ -594,7 +658,7 @@ class CImage
*
* @return $this
*/
public function setSaveAsExtension($saveAs = null)
public function setSaveAsExtension($saveAs = null)
{
if (isset($saveAs)) {
$this->checkFileExtension($saveAs);
@@ -622,7 +686,7 @@ class CImage
? $quality
: self::JPEG_QUALITY_DEFAULT;
(is_numeric($this->quality) and $this->quality > 0 and $this->quality <= 100)
(is_numeric($this->quality) and $this->quality > 0 and $this->quality <= 100)
or $this->raiseError('Quality not in range.');
$this->log("Setting JPEG quality to {$this->quality}.");
@@ -645,7 +709,7 @@ class CImage
? $compress
: self::PNG_COMPRESSION_DEFAULT;
(is_numeric($this->compress) and $this->compress >= -1 and $this->compress <= 9)
(is_numeric($this->compress) and $this->compress >= -1 and $this->compress <= 9)
or $this->raiseError('Quality not in range.');
$this->log("Setting PNG compression level to {$this->compress}.");
@@ -662,21 +726,25 @@ class CImage
*
* @return $this
*/
public function useOriginalIfPossible($useOrig = true)
public function useOriginalIfPossible($useOrig = true)
{
if ($useOrig
&& ($this->newWidth == $this->width)
&& ($this->newHeight == $this->height)
&& !$this->area
&& !$this->crop
&& !$this->filters
&& !$this->sharpen
&& !$this->emboss
&& !$this->blur
if ($useOrig
&& ($this->newWidth == $this->width)
&& ($this->newHeight == $this->height)
&& !$this->area
&& !$this->crop
&& !$this->filters
&& !$this->sharpen
&& !$this->emboss
&& !$this->blur
&& !$this->palette
&& !$this->quality
&& !$this->compress
&& !$this->saveAs
&& !$this->quality
&& !$this->compress
&& !$this->saveAs
&& !$this->rotateBefore
&& !$this->rotateAfter
&& !$this->autoRotate
&& !$this->bgColor
) {
$this->log("Using original image.");
$this->output($this->pathToImage);
@@ -693,21 +761,24 @@ class CImage
*
* @return $this
*/
public function generateFilename($base)
public function generateFilename($base)
{
$parts = pathinfo($this->pathToImage);
$cropToFit = $this->cropToFit ? '_cf' : null;
$crop_x = $this->crop_x ? "_x{$this->crop_x}" : null;
$crop_y = $this->crop_y ? "_y{$this->crop_y}" : null;
$scale = $this->scale ? "_s{$this->scale}" : null;
$quality = $this->quality ? "_q{$this->quality}" : null;
$compress = $this->compress ? "_co{$this->compress}" : null;
$parts = pathinfo($this->pathToImage);
$cropToFit = $this->cropToFit ? '_cf' : null;
$crop_x = $this->crop_x ? "_x{$this->crop_x}" : null;
$crop_y = $this->crop_y ? "_y{$this->crop_y}" : null;
$scale = $this->scale ? "_s{$this->scale}" : null;
$bgColor = $this->bgColor ? "_bgc{$this->bgColor}" : null;
$quality = $this->quality ? "_q{$this->quality}" : null;
$compress = $this->compress ? "_co{$this->compress}" : null;
$rotateBefore = $this->rotateBefore ? "_rb{$this->rotateBefore}" : null;
$rotateAfter = $this->rotateAfter ? "_ra{$this->rotateAfter}" : null;
$offset = isset($this->offset)
? '_o' . $this->offset['top'] . '-' . $this->offset['right'] . '-' . $this->offset['bottom'] . '-' . $this->offset['left']
$offset = isset($this->offset)
? '_o' . $this->offset['top'] . '-' . $this->offset['right'] . '-' . $this->offset['bottom'] . '-' . $this->offset['left']
: null;
$crop = $this->crop
$crop = $this->crop
? '_c' . $this->crop['width'] . '-' . $this->crop['height'] . '-' . $this->crop['start_x'] . '-' . $this->crop['start_y']
: null;
@@ -716,7 +787,7 @@ class CImage
foreach ($this->filters as $filter) {
if (is_array($filter)) {
$filters .= "_f{$filter['id']}";
for ($i=1;$i<=$filter['argc'];$i++) {
for ($i=1; $i<=$filter['argc']; $i++) {
$filters .= ":".$filter["arg{$i}"];
}
}
@@ -727,9 +798,11 @@ class CImage
$emboss = $this->emboss ? 'e' : null;
$blur = $this->blur ? 'b' : null;
$palette = $this->palette ? 'p' : null;
$autoRotate = $this->autoRotate ? 'ar' : null;
$this->extension = isset($this->extension)
? $this->extension
$this->extension = isset($this->extension)
? $this->extension
: $parts['extension'];
// Check optimizing options
@@ -738,15 +811,15 @@ class CImage
$optimize = $this->jpegOptimize ? 'o' : null;
} elseif ($this->extension == 'png') {
$optimize .= $this->pngFilter ? 'f' : null;
$optimize .= $this->pngDeflate ? 'd' : null;
$optimize .= $this->pngDeflate ? 'd' : null;
}
$subdir = str_replace('/', '-', dirname($this->imageSrc));
$subdir = ($subdir == '.') ? '_.' : $subdir;
$file = $subdir . '_' . $parts['filename'] . '_' . round($this->newWidth) . '_'
. round($this->newHeight) . $offset . $crop . $cropToFit . $crop_x . $crop_y
. $quality . $filters . $sharpen . $emboss . $blur . $palette . $optimize
. $scale . '.' . $this->extension;
$file = $subdir . '_' . $parts['filename'] . '_' . round($this->newWidth) . '_'
. round($this->newHeight) . $offset . $crop . $cropToFit . $crop_x . $crop_y
. $quality . $filters . $sharpen . $emboss . $blur . $palette . $optimize
. $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor . '.' . $this->extension;
return $this->setTarget($file, $base);
}
@@ -760,7 +833,7 @@ class CImage
*
* @return $this
*/
public function useCacheIfPossible($useCache = true)
public function useCacheIfPossible($useCache = true)
{
if ($useCache && is_readable($this->cacheFileName)) {
$fileTime = filemtime($this->pathToImage);
@@ -770,7 +843,7 @@ class CImage
if ($this->useCache) {
if ($this->verbose) {
$this->log("Use cached file.");
$this->log("Cached image filesize: " . filesize($this->cacheFileName) . " bytes.");
$this->log("Cached image filesize: " . filesize($this->cacheFileName) . " bytes.");
}
$this->output($this->cacheFileName);
} else {
@@ -885,9 +958,9 @@ class CImage
* @return int as the type of the png-image
*
*/
private function getPngType()
private function getPngType()
{
$pngType = ord (file_get_contents ($this->pathToImage, false, null, 25, 1));
$pngType = ord(file_get_contents($this->pathToImage, false, null, 25, 1));
switch ($pngType) {
@@ -895,11 +968,11 @@ class CImage
$this->log("PNG is type 0, Greyscale.");
break;
case self::PNG_RGB:
case self::PNG_RGB:
$this->log("PNG is type 2, RGB");
break;
case self::PNG_RGB_PALETTE:
case self::PNG_RGB_PALETTE:
$this->log("PNG is type 3, RGB with palette");
break;
@@ -927,7 +1000,7 @@ class CImage
*
* @return int
*/
private function colorsTotal($im)
private function colorsTotal($im)
{
if (imageistruecolor($im)) {
$h = imagesy($im);
@@ -951,10 +1024,24 @@ class CImage
*
* @return $this
*/
public function preResize()
public function preResize()
{
$this->log("Pre-process before resizing");
// Rotate image
if ($this->rotateBefore) {
$this->log("Rotating image.");
$this->rotate($this->rotateBefore, $this->bgColor)
->reCalculateDimensions();
}
// Auto-rotate image
if ($this->autoRotate) {
$this->log("Auto rotating image.");
$this->rotateExif()
->reCalculateDimensions();
}
// Scale the original image before starting
if (isset($this->scale)) {
$this->log("Scale by {$this->scale}%");
@@ -965,9 +1052,9 @@ class CImage
$this->image = $img;
$this->width = $newWidth;
$this->height = $newHeight;
}
}
return $this;
return $this;
}
@@ -977,7 +1064,7 @@ class CImage
*
* @return $this
*/
public function resize()
public function resize()
{
$this->log("Starting to Resize()");
@@ -991,7 +1078,7 @@ class CImage
$this->image = $img;
$this->width = $this->offset['width'];
$this->height = $this->offset['height'];
}
}
// SaveAs need to copy image to remove transparency, if any
if ($this->saveAs) {
@@ -1013,14 +1100,14 @@ class CImage
$this->image = $img;
$this->width = $this->crop['width'];
$this->height = $this->crop['height'];
}
}
// Resize by crop to fit
if ($this->cropToFit) {
$this->log("Crop to fit");
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
$imgPreCrop = $this->CreateImageKeepTransparency($this->cropWidth, $this->cropHeight);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopyresampled($imgPreCrop, $this->image, 0, 0, 0, 0, $this->cropWidth, $this->cropHeight, $this->width, $this->height);
@@ -1051,10 +1138,16 @@ class CImage
*
* @return $this
*/
public function postResize()
public function postResize()
{
$this->log("Post-process after resizing");
// Rotate image
if ($this->rotateAfter) {
$this->log("Rotating image.");
$this->rotate($this->rotateAfter, $this->bgColor);
}
// Apply filters
if (isset($this->filters) && is_array($this->filters)) {
@@ -1063,54 +1156,121 @@ class CImage
switch ($filter['argc']) {
case 0:
imagefilter($this->image, $filter['type']);
case 0:
imagefilter($this->image, $filter['type']);
break;
case 1:
imagefilter($this->image, $filter['type'], $filter['arg1']);
case 1:
imagefilter($this->image, $filter['type'], $filter['arg1']);
break;
case 2:
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2']);
case 2:
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2']);
break;
case 3:
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2'], $filter['arg3']);
case 3:
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2'], $filter['arg3']);
break;
case 4:
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2'], $filter['arg3'], $filter['arg4']);
case 4:
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2'], $filter['arg3'], $filter['arg4']);
break;
}
}
}
// Convert to palette image
if($this->palette) {
if ($this->palette) {
$this->log("Converting to palette image.");
$this->trueColorToPalette();
}
// Blur the image
if($this->blur) {
if ($this->blur) {
$this->log("Blur.");
$this->blurImage();
}
// Emboss the image
if($this->emboss) {
if ($this->emboss) {
$this->log("Emboss.");
$this->embossImage();
}
// Sharpen the image
if($this->sharpen) {
if ($this->sharpen) {
$this->log("Sharpen.");
$this->sharpenImage();
}
return $this;
return $this;
}
/**
* Rotate image using angle.
*
* @param float $angle to rotate image.
* @param int $anglebgColor to fill image with if needed.
*
* @return $this
*/
public function rotate($angle, $bgColor)
{
$this->log("Rotate image " . $angle . " degrees with filler color " . $bgColor);
$this->image = imagerotate($this->image, $angle, $bgColor);
$this->width = imagesx($this->image);
$this->height = imagesy($this->image);
$this->log("New image dimension width x height: " . $this->width . " x " . $this->height);
return $this;
}
/**
* Rotate image using information in EXIF.
*
* @return $this
*/
public function rotateExif()
{
if (!in_array($this->fileExtension, array('jpg', 'jpeg'))) {
$this->log("Autorotate ignored, EXIF not supported by this filetype.");
return $this;
}
$exif = exif_read_data($this->pathToImage);
if (!empty($exif['Orientation'])) {
switch ($exif['Orientation']) {
case 3:
$this->log("Autorotate 180.");
$this->rotate(180, $this->bgColor);
break;
case 6:
$this->log("Autorotate -90.");
$this->rotate(-90, $this->bgColor);
break;
case 8:
$this->log("Autorotate 90.");
$this->rotate(90, $this->bgColor);
break;
default:
$this->log("Autorotate ignored, unknown value as orientation.");
}
} else {
$this->log("Autorotate ignored, no orientation in EXIF.");
}
return $this;
}
@@ -1121,7 +1281,7 @@ class CImage
*
* @return void
*/
public function trueColorToPalette()
public function trueColorToPalette()
{
$img = imagecreatetruecolor($this->width, $this->height);
$bga = imagecolorallocatealpha($img, 0, 0, 0, 127);
@@ -1147,7 +1307,7 @@ class CImage
*
* @return $this
*/
public function sharpenImage()
public function sharpenImage()
{
$matrix = array(
array(-1,-1,-1,),
@@ -1170,7 +1330,7 @@ class CImage
*
* @return $this
*/
public function embossImage()
public function embossImage()
{
$matrix = array(
array( 1, 1,-1,),
@@ -1193,7 +1353,7 @@ class CImage
*
* @return $this
*/
public function blurImage()
public function blurImage()
{
$matrix = array(
array( 1, 1, 1,),
@@ -1218,12 +1378,12 @@ class CImage
* @param int $height of the new image.
* @return image resource.
*/
private function createImageKeepTransparency($width, $height)
private function createImageKeepTransparency($width, $height)
{
$this->log("Creating a new working image width={$width}px, height={$height}px.");
$img = imagecreatetruecolor($width, $height);
imagealphablending($img, false);
imagesavealpha($img, true);
imagesavealpha($img, true);
/*
$this->Log("Filling image with background color.");
@@ -1243,12 +1403,12 @@ class CImage
*
* @return $this
*/
public function setPostProcessingOptions($options)
public function setPostProcessingOptions($options)
{
if (isset($options['jpeg_optimize']) && $options['jpeg_optimize']) {
$this->jpegOptimizeCmd = $options['jpeg_optimize_cmd'];
} else {
$this->jpegOptimizeCmd = null;
$this->jpegOptimizeCmd = null;
}
if (isset($options['png_filter']) && $options['png_filter']) {
@@ -1291,9 +1451,9 @@ class CImage
// Use JPEG optimize if defined
if ($this->jpegOptimizeCmd) {
if ($this->verbose) {
clearstatcache();
$this->log("Filesize before optimize: " . filesize($this->cacheFileName) . " bytes.");
if ($this->verbose) {
clearstatcache();
$this->log("Filesize before optimize: " . filesize($this->cacheFileName) . " bytes.");
}
$res = array();
$cmd = $this->jpegOptimizeCmd . " -outfile $this->cacheFileName $this->cacheFileName";
@@ -1301,28 +1461,28 @@ class CImage
$this->log($cmd);
$this->log($res);
}
break;
break;
case 'gif':
if ($this->saveFolder) {
$this->Log("Saving image as GIF to cache.");
imagegif($this->image, $this->cacheFileName);
imagegif($this->image, $this->cacheFileName);
}
break;
break;
case 'png':
case 'png':
$this->Log("Saving image as PNG to cache using compression = {$this->compress}.");
// Turn off alpha blending and set alpha flag
imagealphablending($this->image, false);
imagesavealpha($this->image, true);
imagepng($this->image, $this->cacheFileName, $this->compress);
imagepng($this->image, $this->cacheFileName, $this->compress);
// Use external program to filter PNG, if defined
if ($this->pngFilterCmd) {
if ($this->verbose) {
clearstatcache();
$this->Log("Filesize before filter optimize: " . filesize($this->cacheFileName) . " bytes.");
if ($this->verbose) {
clearstatcache();
$this->Log("Filesize before filter optimize: " . filesize($this->cacheFileName) . " bytes.");
}
$res = array();
$cmd = $this->pngFilterCmd . " $this->cacheFileName";
@@ -1333,9 +1493,9 @@ class CImage
// Use external program to deflate PNG, if defined
if ($this->pngDeflateCmd) {
if ($this->verbose) {
clearstatcache();
$this->Log("Filesize before deflate optimize: " . filesize($this->cacheFileName) . " bytes.");
if ($this->verbose) {
clearstatcache();
$this->Log("Filesize before deflate optimize: " . filesize($this->cacheFileName) . " bytes.");
}
$res = array();
$cmd = $this->pngDeflateCmd . " $this->cacheFileName";
@@ -1343,16 +1503,16 @@ class CImage
$this->Log($cmd);
$this->Log($res);
}
break;
break;
default:
$this->RaiseError('No support for this file extension.');
break;
}
}
if ($this->verbose) {
clearstatcache();
$this->log("Cached image filesize: " . filesize($this->cacheFileName) . " bytes.");
$this->log("Cached image filesize: " . filesize($this->cacheFileName) . " bytes.");
$this->log("imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
$this->log("imagecolorstotal() : " . imagecolorstotal($this->image));
$this->log("Number of colors in image = " . $this->ColorsTotal($this->image));

View File

@@ -133,6 +133,13 @@ Revision history
v0.5.x (latest)
* Broke API when `initDimensions()` split into two methods, new `initDimensions()` and `loadImageDetails()`.
* Added `autoRotate,`aro` to auto rotate image based on EXIF information.
* Added `bgColor,`bgc` to use as backgroundcolor when needing a filler color.
* Added `rotate,`r` as an alias to `rotateAfter`.
* Added `rotateBefore,`rb` to rotate image a certain angle before processing.
* Added `rotateAfter,`ra` to rotate image a certain angle after processing.
* Cleaned up code formatting, removed trailing spaces.
* Removed @ from opening images, better to display correct warning when failing #34, but put it back again.
* Setting gd.jpeg_ignore_warning to true as default #34.
* `webroot/check_system.php` now outputs version of PHP and GD.

View File

@@ -306,7 +306,7 @@ verbose("save as = $saveAs");
$scale = get(array('scale', 's'));
is_null($scale)
or ($scale >= 0 and $quality <= 400)
or ($scale >= 0 and $scale <= 400)
or errorPage('Scale out of range');
verbose("scale = $scale");
@@ -349,6 +349,68 @@ verbose("blur = $blur");
/**
* rotate - Rotate the image with an angle, before processing
*/
/*
$rotate = get(array('rotate', 'r'));
is_null($rotate)
or ($rotate >= -360 and $rotate <= 360)
or errorPage('Rotate out of range');
verbose("rotate = $rotate");
*/
/**
* rotateBefore - Rotate the image with an angle, before processing
*/
$rotateBefore = get(array('rotateBefore', 'rb'));
is_null($rotateBefore)
or ($rotateBefore >= -360 and $rotateBefore <= 360)
or errorPage('RotateBefore out of range');
verbose("rotateBefore = $rotateBefore");
/**
* rotateAfter - Rotate the image with an angle, before processing
*/
$rotateAfter = get(array('rotateAfter', 'ra', 'rotate', 'r'));
is_null($rotateAfter)
or ($rotateAfter >= -360 and $rotateAfter <= 360)
or errorPage('RotateBefore out of range');
verbose("rotateAfter = $rotateAfter");
/**
* bgColor - Default background color to use
*/
$bgColor = hexdec(get(array('bgColor', 'bgc')));
is_null($bgColor)
or ($bgColor >= 0 and $bgColor <= hexdec("FFFFFF"))
or errorPage('Background color needs a hex value');
verbose("bgColor = $bgColor");
/**
* autoRotate - Auto rotate based on EXIF information
*/
$autoRotate = getDefined(array('autoRotate', 'aro'), true, false);
verbose("autoRotate = $autoRotate");
/**
* filter, f, f0-f9 - Processing option, post filter for various effects using imagefilter()
*/
@@ -400,26 +462,33 @@ $img->setVerbose($verbose)
->setSource($srcImage, $config['image_path'])
->setOptions(
array(
// Options for calculate dimensions
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'aspectRatio' => $aspectRatio,
'keepRatio' => $keepRatio,
'cropToFit' => $cropToFit,
'crop' => $crop,
'area' => $area,
// Options for calculate dimensions
'newWidth' => $newWidth,
'newHeight' => $newHeight,
'aspectRatio' => $aspectRatio,
'keepRatio' => $keepRatio,
'cropToFit' => $cropToFit,
'crop' => $crop,
'area' => $area,
// Pre-processing, before resizing is done
'scale' => $scale,
// Pre-processing, before resizing is done
'scale' => $scale,
'rotateBefore' => $rotateBefore,
// Post-processing, after resizing is done
'palette' => $palette,
'filters' => $filters,
'sharpen' => $sharpen,
'emboss' => $emboss,
'blur' => $blur,
// General processing options
'bgColor' => $bgColor,
// Post-processing, after resizing is done
'palette' => $palette,
'filters' => $filters,
'sharpen' => $sharpen,
'emboss' => $emboss,
'blur' => $blur,
'rotateAfter' => $rotateAfter,
'autoRotate' => $autoRotate,
)
)
->loadImageDetails()
->initDimensions()
->calculateNewWidthAndHeight()
->setSaveAsExtension($saveAs)

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

77
webroot/test_issue36.php Normal file
View File

@@ -0,0 +1,77 @@
<!doctype html>
<head>
<meta charset='utf-8'/>
<title>Testing img for issue 36</title>
<style>
body {background-color: #ccc;}
</style>
</head>
<body>
<h1>Testing issue 36</h1>
<?php
error_reporting(-1); // Report all type of errors
ini_set('display_errors', 1); // Display all errors
ini_set('output_buffering', 0); // Do not buffer outputs, write directly
$imgphp = "img.php?src=";
$images = array(
'issue36/me-0.jpg',
'issue36/me-90.jpg',
'issue36/me-180.jpg',
'issue36/me-270.jpg',
'issue36/flower-0.jpg',
'issue36/flower-90.jpg',
'issue36/flower-180.jpg',
'issue36/flower-270.jpg',
);
$testcase = array(
'&aro&nc',
'&aro&nc&w=200',
'&aro&nc&h=200',
'&aro&nc&w=200&h=200&cf',
);
?>
<h2>Images used in test</h2>
<p>The following images are used for this test.</p>
<?php foreach($images as $image) : ?>
<p><code><a href="img/<?=$image?>"><?=$image?></a></code><br>
<img src="<?=$imgphp . $image?>"></p>
<?php endforeach; ?>
<h2>Testcases used for each image</h2>
<p>The following testcases are used for each image.</p>
<?php foreach($testcase as $tc) : ?>
<code><?=$tc?></code><br>
<?php endforeach; ?>
<h2>Applying testcase for each image</h2>
<?php foreach($images as $image) : ?>
<h3><?=$image?></h3>
<p><code><a href="img/<?=$image?>"><?=$image?></a></code><br>
<img src="<?=$imgphp . $image?>"></p>
<?php foreach($testcase as $tc) : ?>
<h4><?=$tc?></h4>
<p><code><a href="<?=$imgphp . $image . $tc?>"><?=$image . $tc?></a></code><br>
<img src="<?=$imgphp . $image . $tc?>"></p>
<?php endforeach; ?>
<?php endforeach; ?>