From dc6e9a870875ab026a19bdc18a70946d910bcb96 Mon Sep 17 00:00:00 2001 From: Mikael Roos Date: Sun, 18 Oct 2015 14:52:17 +0200 Subject: [PATCH] test tag --- README.md | 6 +- REVISION.md | 2 +- cache/README.md | 1 - cache/dummy/README.md | 1 - webroot/img.php | 2 +- webroot/img_config.php | 1 - webroot/imgd.php | 242 +++++++++++++++++++++++++++++++---------- webroot/imgp.php | 242 +++++++++++++++++++++++++++++++---------- webroot/imgs.php | 242 +++++++++++++++++++++++++++++++---------- 9 files changed, 554 insertions(+), 185 deletions(-) delete mode 100644 cache/README.md delete mode 100644 cache/dummy/README.md diff --git a/README.md b/README.md index ecc1695..4c40fe9 100644 --- a/README.md +++ b/README.md @@ -45,14 +45,14 @@ There are several ways of installing. You either install the whole project which The [sourcode is available on GitHub](https://github.com/mosbth/cimage). Clone, fork or [download as zip](https://github.com/mosbth/cimage/archive/master.zip). -**Latest stable version is v0.7.4 released 2015-09-15.** +**Latest stable version is v0.7.5 released 2015-10-18.** I prefer cloning like this. Do switch to the latest stable version. ```bash git clone git://github.com/mosbth/cimage.git cd cimage -git checkout v0.7.4 +git checkout v0.7.5 ``` Make the cache-directory writable by the webserver. @@ -75,7 +75,7 @@ There are some all-included bundles of `img.php` that can be downloaded and used Dowload the version of your choice like this. ```bash -wget https://github.com/mosbth/cimage/tree/v0.7.4/webroot/imgp.php +wget https://github.com/mosbth/cimage/tree/v0.7.5/webroot/imgp.php ``` Open up the file in your editor and edit the array `$config`. Ensure that the paths to the image directory and the cache directory matches your environment, or create an own config-file for the script. diff --git a/REVISION.md b/REVISION.md index 1fc3ae1..8a8a4af 100644 --- a/REVISION.md +++ b/REVISION.md @@ -5,7 +5,7 @@ Revision history [![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.5x (latest) +v0.7.5 (2015-10-18) ------------------------------------- * Adding feature for creating dummy images `src=dummy`, #101. diff --git a/cache/README.md b/cache/README.md deleted file mode 100644 index 928392a..0000000 --- a/cache/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory must be writable by the webserver. diff --git a/cache/dummy/README.md b/cache/dummy/README.md deleted file mode 100644 index 347bc3a..0000000 --- a/cache/dummy/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory must be writable by the webserveri to enable the dummy feature. diff --git a/webroot/img.php b/webroot/img.php index 3c4e222..6ad34da 100644 --- a/webroot/img.php +++ b/webroot/img.php @@ -8,7 +8,7 @@ * */ -$version = "v0.7.4 (2015-09-15)"; +$version = "v0.7.5 (2015-10-18)"; diff --git a/webroot/img_config.php b/webroot/img_config.php index 88da39a..87ac152 100644 --- a/webroot/img_config.php +++ b/webroot/img_config.php @@ -13,7 +13,6 @@ return array( * Default values: * mode: 'production' */ - 'mode' => 'development', //'mode' => 'production', // 'development', 'strict' diff --git a/webroot/imgd.php b/webroot/imgd.php index 64d1f59..f890e57 100644 --- a/webroot/imgd.php +++ b/webroot/imgd.php @@ -1032,13 +1032,6 @@ class CImage - /** - * The root folder of images (only used in constructor to create $pathToImage?). - */ - private $imageFolder; - - - /** * Image filename, may include subdirectory, relative from $imageFolder */ @@ -1112,6 +1105,7 @@ class CImage * Path to command for filter optimize, for example optipng or null. */ private $pngFilter; + private $pngFilterCmd; @@ -1119,13 +1113,16 @@ class CImage * Path to command for deflate optimize, for example pngout or null. */ private $pngDeflate; + private $pngDeflateCmd; /** * Path to command to optimize jpeg images, for example jpegtran or null. */ - private $jpegOptimize; + private $jpegOptimize; + private $jpegOptimizeCmd; + /** @@ -1201,6 +1198,56 @@ class CImage private $fillToFit; + + /** + * To store value for option scale. + */ + private $scale; + + + + /** + * To store value for option. + */ + private $rotateBefore; + + + + /** + * To store value for option. + */ + private $rotateAfter; + + + + /** + * To store value for option. + */ + private $autoRotate; + + + + /** + * To store value for option. + */ + private $sharpen; + + + + /** + * To store value for option. + */ + private $emboss; + + + + /** + * To store value for option. + */ + private $blur; + + + /** * Used with option area to set which parts of the image to use. */ @@ -1274,9 +1321,7 @@ class CImage public $crop_x; public $crop_y; public $filters; - private $type; // Calculated from source image private $attr; // Calculated from source image - private $useOriginal; // Use original image if possible @@ -1333,9 +1378,7 @@ class CImage /** * Use cache or not. * - * @todo clean up how $this->noCache is used in other methods. - * - * @param string $use true or false to use cache. + * @param boolean $use true or false to use cache. * * @return $this */ @@ -1347,6 +1390,27 @@ class CImage + /** + * Create and save a dummy image. Use dimensions as stated in + * $this->newWidth, or $width or default to 100 (same for height. + * + * @param integer $width use specified width for image dimension. + * @param integer $height use specified width for image dimension. + * + * @return $this + */ + public function createDummyImage($width = null, $height = null) + { + $this->newWidth = $this->newWidth ?: $width ?: 100; + $this->newHeight = $this->newHeight ?: $height ?: 100; + + $this->image = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); + + return $this; + } + + + /** * Allow or disallow remote image download. * @@ -1497,16 +1561,18 @@ class CImage /** - * Set src file. + * Set source file to use as image source. * * @param string $src of image. - * @param string $dir as base directory where images are. + * @param string $dir as optional base directory where images are. * * @return $this */ public function setSource($src, $dir = null) { if (!isset($src)) { + $this->imageSrc = null; + $this->pathToImage = null; return $this; } @@ -1520,9 +1586,9 @@ class CImage $src = basename($src); } - $this->imageSrc = ltrim($src, '/'); - $this->imageFolder = rtrim($dir, '/'); - $this->pathToImage = $this->imageFolder . '/' . $this->imageSrc; + $this->imageSrc = ltrim($src, '/'); + $imageFolder = rtrim($dir, '/'); + $this->pathToImage = $imageFolder . '/' . $this->imageSrc; return $this; } @@ -1533,23 +1599,23 @@ class CImage * Set target file. * * @param string $src of target image. - * @param string $dir as base directory where images are stored. + * @param string $dir as optional base directory where images are stored. + * Uses $this->saveFolder if null. * * @return $this */ public function setTarget($src = null, $dir = null) { - if (!(isset($src) && isset($dir))) { + if (!isset($src)) { + $this->cacheFileName = null; return $this; } - $this->saveFolder = $dir; - $this->cacheFileName = $dir . '/' . $src; + if (isset($dir)) { + $this->saveFolder = rtrim($dir, '/'); + } - /* Allow readonly cache - is_writable($this->saveFolder) - or $this->raiseError('Target directory is not writable.'); - */ + $this->cacheFileName = $this->saveFolder . '/' . $src; // Sanitize filename $this->cacheFileName = preg_replace('/^a-zA-Z0-9\.-_/', '', $this->cacheFileName); @@ -1560,6 +1626,18 @@ class CImage + /** + * Get filename of target file. + * + * @return Boolean|String as filename of target or false if not set. + */ + public function getTarget() + { + return $this->cacheFileName; + } + + + /** * Set options to use when processing image. * @@ -1607,11 +1685,6 @@ class CImage // Output format 'outputFormat' => null, 'dpr' => 1, - - // Options for saving - //'quality' => null, - //'compress' => null, - //'saveAs' => null, ); // Convert crop settings from string to array @@ -2105,13 +2178,15 @@ class CImage /** * Generate filename to save file in cache. * - * @param string $base as basepath for storing file. + * @param string $base as optional basepath for storing file. + * @param boolean $useSubdir use or skip the subdir part when creating the + * filename. * * @return $this */ - public function generateFilename($base) + public function generateFilename($base = null, $useSubdir = true) { - $parts = pathinfo($this->pathToImage); + $filename = basename($this->pathToImage); $cropToFit = $this->cropToFit ? '_cf' : null; $fillToFit = $this->fillToFit ? '_ff' : null; $crop_x = $this->crop_x ? "_x{$this->crop_x}" : null; @@ -2153,16 +2228,6 @@ class CImage $autoRotate = $this->autoRotate ? 'ar' : null; - $this->extension = isset($this->extension) - ? $this->extension - : (isset($parts['extension']) - ? $parts['extension'] - : null); - - $extension = empty($this->extension) - ? null - : "." . $this->extension; - $optimize = $this->jpegOptimize ? 'o' : null; $optimize .= $this->pngFilter ? 'f' : null; $optimize .= $this->pngDeflate ? 'd' : null; @@ -2177,14 +2242,20 @@ class CImage $upscale = '_nu'; } - $subdir = str_replace('/', '-', dirname($this->imageSrc)); - $subdir = ($subdir == '.') ? '_.' : $subdir; - $file = $subdir . '_' . $parts['filename'] . '_' . $width . '_' + $subdir = null; + if ($useSubdir === true) { + $subdir = str_replace('/', '-', dirname($this->imageSrc)); + $subdir = ($subdir == '.') ? '_.' : $subdir; + $subdir .= '_'; + } + + $file = $subdir . $filename . '_' . $width . '_' . $height . $offset . $crop . $cropToFit . $fillToFit . $crop_x . $crop_y . $upscale - . $quality . $filters . $sharpen . $emboss . $blur . $palette . $optimize - . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor . $convolve - . $extension; + . $quality . $filters . $sharpen . $emboss . $blur . $palette + . $optimize . $compress + . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor + . $convolve; return $this->setTarget($file, $base); } @@ -2952,7 +3023,10 @@ class CImage imagealphablending($img, false); imagesavealpha($img, true); - $index = imagecolortransparent($this->image); + $index = $this->image + ? imagecolortransparent($this->image) + : -1; + if ($index != -1) { imagealphablending($img, true); @@ -3025,17 +3099,23 @@ class CImage /** * Save image. * - * @param string $src as target filename. - * @param string $base as base directory where to store images. + * @param string $src as target filename. + * @param string $base as base directory where to store images. + * @param boolean $overwrite or not, default to always overwrite file. * * @return $this or false if no folder is set. */ - public function save($src = null, $base = null) + public function save($src = null, $base = null, $overwrite = true) { if (isset($src)) { $this->setTarget($src, $base); } + if ($overwrite === false && is_file($this->cacheFileName)) { + $this->Log("Not overwriting file since its already exists and \$overwrite if false."); + return; + } + is_writable($this->saveFolder) or $this->raiseError('Target directory is not writable.'); @@ -3401,7 +3481,7 @@ EOD; * */ -$version = "v0.7.4 (2015-09-15)"; +$version = "v0.7.5 (2015-10-18)"; @@ -3766,10 +3846,20 @@ $imagePath = getConfig('image_path', __DIR__ . '/img/'); $imagePathConstraint = getConfig('image_path_constraint', true); $validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#'); +// Dumm image feature +$dummyEnabled = getConfig('dummy_enabled', true); +$dummyFilename = getConfig('dummy_filename', 'dummy'); +$dummyImage = false; + preg_match($validFilename, $srcImage) or errorPage('Filename contains invalid characters.'); -if ($allowRemote && $img->isRemoteSource($srcImage)) { +if ($dummyEnabled && $srcImage === $dummyFilename) { + + // Prepare to create a dummy image and use it as the source image. + $dummyImage = true; + +} elseif ($allowRemote && $img->isRemoteSource($srcImage)) { // If source is a remote file, ignore local file checks. @@ -4326,9 +4416,43 @@ if ($verboseFile) { - /** - * Load, process and output the image - */ +/** + * Set basic options for image processing. + */ + + +/** + * Prepare a dummy image and use it as source image. + */ +if ($dummyImage === true) { + + $dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename); + + is_writable($dummyDir) + or verbose("dummy dir not writable = $dummyDir"); + + $img->setSaveFolder($dummyDir) + ->setSource($dummyFilename, $dummyDir) + ->setOptions( + array( + 'bgColor' => $bgColor, + ) + ) + ->createDummyImage() + ->generateFilename(null, false) + ->save(null, null, false); + + $srcImage = $img->getTarget(); + $imagePath = null; + + verbose("src (updated) = $srcImage"); +} + + + +/** + * Load, process and output the image + */ $img->log("Incoming arguments: " . print_r(verbose(), 1)) ->setSaveFolder($cachePath) ->useCache($useCache) diff --git a/webroot/imgp.php b/webroot/imgp.php index 7f14821..2cad2c8 100644 --- a/webroot/imgp.php +++ b/webroot/imgp.php @@ -1032,13 +1032,6 @@ class CImage - /** - * The root folder of images (only used in constructor to create $pathToImage?). - */ - private $imageFolder; - - - /** * Image filename, may include subdirectory, relative from $imageFolder */ @@ -1112,6 +1105,7 @@ class CImage * Path to command for filter optimize, for example optipng or null. */ private $pngFilter; + private $pngFilterCmd; @@ -1119,13 +1113,16 @@ class CImage * Path to command for deflate optimize, for example pngout or null. */ private $pngDeflate; + private $pngDeflateCmd; /** * Path to command to optimize jpeg images, for example jpegtran or null. */ - private $jpegOptimize; + private $jpegOptimize; + private $jpegOptimizeCmd; + /** @@ -1201,6 +1198,56 @@ class CImage private $fillToFit; + + /** + * To store value for option scale. + */ + private $scale; + + + + /** + * To store value for option. + */ + private $rotateBefore; + + + + /** + * To store value for option. + */ + private $rotateAfter; + + + + /** + * To store value for option. + */ + private $autoRotate; + + + + /** + * To store value for option. + */ + private $sharpen; + + + + /** + * To store value for option. + */ + private $emboss; + + + + /** + * To store value for option. + */ + private $blur; + + + /** * Used with option area to set which parts of the image to use. */ @@ -1274,9 +1321,7 @@ class CImage public $crop_x; public $crop_y; public $filters; - private $type; // Calculated from source image private $attr; // Calculated from source image - private $useOriginal; // Use original image if possible @@ -1333,9 +1378,7 @@ class CImage /** * Use cache or not. * - * @todo clean up how $this->noCache is used in other methods. - * - * @param string $use true or false to use cache. + * @param boolean $use true or false to use cache. * * @return $this */ @@ -1347,6 +1390,27 @@ class CImage + /** + * Create and save a dummy image. Use dimensions as stated in + * $this->newWidth, or $width or default to 100 (same for height. + * + * @param integer $width use specified width for image dimension. + * @param integer $height use specified width for image dimension. + * + * @return $this + */ + public function createDummyImage($width = null, $height = null) + { + $this->newWidth = $this->newWidth ?: $width ?: 100; + $this->newHeight = $this->newHeight ?: $height ?: 100; + + $this->image = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); + + return $this; + } + + + /** * Allow or disallow remote image download. * @@ -1497,16 +1561,18 @@ class CImage /** - * Set src file. + * Set source file to use as image source. * * @param string $src of image. - * @param string $dir as base directory where images are. + * @param string $dir as optional base directory where images are. * * @return $this */ public function setSource($src, $dir = null) { if (!isset($src)) { + $this->imageSrc = null; + $this->pathToImage = null; return $this; } @@ -1520,9 +1586,9 @@ class CImage $src = basename($src); } - $this->imageSrc = ltrim($src, '/'); - $this->imageFolder = rtrim($dir, '/'); - $this->pathToImage = $this->imageFolder . '/' . $this->imageSrc; + $this->imageSrc = ltrim($src, '/'); + $imageFolder = rtrim($dir, '/'); + $this->pathToImage = $imageFolder . '/' . $this->imageSrc; return $this; } @@ -1533,23 +1599,23 @@ class CImage * Set target file. * * @param string $src of target image. - * @param string $dir as base directory where images are stored. + * @param string $dir as optional base directory where images are stored. + * Uses $this->saveFolder if null. * * @return $this */ public function setTarget($src = null, $dir = null) { - if (!(isset($src) && isset($dir))) { + if (!isset($src)) { + $this->cacheFileName = null; return $this; } - $this->saveFolder = $dir; - $this->cacheFileName = $dir . '/' . $src; + if (isset($dir)) { + $this->saveFolder = rtrim($dir, '/'); + } - /* Allow readonly cache - is_writable($this->saveFolder) - or $this->raiseError('Target directory is not writable.'); - */ + $this->cacheFileName = $this->saveFolder . '/' . $src; // Sanitize filename $this->cacheFileName = preg_replace('/^a-zA-Z0-9\.-_/', '', $this->cacheFileName); @@ -1560,6 +1626,18 @@ class CImage + /** + * Get filename of target file. + * + * @return Boolean|String as filename of target or false if not set. + */ + public function getTarget() + { + return $this->cacheFileName; + } + + + /** * Set options to use when processing image. * @@ -1607,11 +1685,6 @@ class CImage // Output format 'outputFormat' => null, 'dpr' => 1, - - // Options for saving - //'quality' => null, - //'compress' => null, - //'saveAs' => null, ); // Convert crop settings from string to array @@ -2105,13 +2178,15 @@ class CImage /** * Generate filename to save file in cache. * - * @param string $base as basepath for storing file. + * @param string $base as optional basepath for storing file. + * @param boolean $useSubdir use or skip the subdir part when creating the + * filename. * * @return $this */ - public function generateFilename($base) + public function generateFilename($base = null, $useSubdir = true) { - $parts = pathinfo($this->pathToImage); + $filename = basename($this->pathToImage); $cropToFit = $this->cropToFit ? '_cf' : null; $fillToFit = $this->fillToFit ? '_ff' : null; $crop_x = $this->crop_x ? "_x{$this->crop_x}" : null; @@ -2153,16 +2228,6 @@ class CImage $autoRotate = $this->autoRotate ? 'ar' : null; - $this->extension = isset($this->extension) - ? $this->extension - : (isset($parts['extension']) - ? $parts['extension'] - : null); - - $extension = empty($this->extension) - ? null - : "." . $this->extension; - $optimize = $this->jpegOptimize ? 'o' : null; $optimize .= $this->pngFilter ? 'f' : null; $optimize .= $this->pngDeflate ? 'd' : null; @@ -2177,14 +2242,20 @@ class CImage $upscale = '_nu'; } - $subdir = str_replace('/', '-', dirname($this->imageSrc)); - $subdir = ($subdir == '.') ? '_.' : $subdir; - $file = $subdir . '_' . $parts['filename'] . '_' . $width . '_' + $subdir = null; + if ($useSubdir === true) { + $subdir = str_replace('/', '-', dirname($this->imageSrc)); + $subdir = ($subdir == '.') ? '_.' : $subdir; + $subdir .= '_'; + } + + $file = $subdir . $filename . '_' . $width . '_' . $height . $offset . $crop . $cropToFit . $fillToFit . $crop_x . $crop_y . $upscale - . $quality . $filters . $sharpen . $emboss . $blur . $palette . $optimize - . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor . $convolve - . $extension; + . $quality . $filters . $sharpen . $emboss . $blur . $palette + . $optimize . $compress + . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor + . $convolve; return $this->setTarget($file, $base); } @@ -2952,7 +3023,10 @@ class CImage imagealphablending($img, false); imagesavealpha($img, true); - $index = imagecolortransparent($this->image); + $index = $this->image + ? imagecolortransparent($this->image) + : -1; + if ($index != -1) { imagealphablending($img, true); @@ -3025,17 +3099,23 @@ class CImage /** * Save image. * - * @param string $src as target filename. - * @param string $base as base directory where to store images. + * @param string $src as target filename. + * @param string $base as base directory where to store images. + * @param boolean $overwrite or not, default to always overwrite file. * * @return $this or false if no folder is set. */ - public function save($src = null, $base = null) + public function save($src = null, $base = null, $overwrite = true) { if (isset($src)) { $this->setTarget($src, $base); } + if ($overwrite === false && is_file($this->cacheFileName)) { + $this->Log("Not overwriting file since its already exists and \$overwrite if false."); + return; + } + is_writable($this->saveFolder) or $this->raiseError('Target directory is not writable.'); @@ -3401,7 +3481,7 @@ EOD; * */ -$version = "v0.7.4 (2015-09-15)"; +$version = "v0.7.5 (2015-10-18)"; @@ -3766,10 +3846,20 @@ $imagePath = getConfig('image_path', __DIR__ . '/img/'); $imagePathConstraint = getConfig('image_path_constraint', true); $validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#'); +// Dumm image feature +$dummyEnabled = getConfig('dummy_enabled', true); +$dummyFilename = getConfig('dummy_filename', 'dummy'); +$dummyImage = false; + preg_match($validFilename, $srcImage) or errorPage('Filename contains invalid characters.'); -if ($allowRemote && $img->isRemoteSource($srcImage)) { +if ($dummyEnabled && $srcImage === $dummyFilename) { + + // Prepare to create a dummy image and use it as the source image. + $dummyImage = true; + +} elseif ($allowRemote && $img->isRemoteSource($srcImage)) { // If source is a remote file, ignore local file checks. @@ -4326,9 +4416,43 @@ if ($verboseFile) { - /** - * Load, process and output the image - */ +/** + * Set basic options for image processing. + */ + + +/** + * Prepare a dummy image and use it as source image. + */ +if ($dummyImage === true) { + + $dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename); + + is_writable($dummyDir) + or verbose("dummy dir not writable = $dummyDir"); + + $img->setSaveFolder($dummyDir) + ->setSource($dummyFilename, $dummyDir) + ->setOptions( + array( + 'bgColor' => $bgColor, + ) + ) + ->createDummyImage() + ->generateFilename(null, false) + ->save(null, null, false); + + $srcImage = $img->getTarget(); + $imagePath = null; + + verbose("src (updated) = $srcImage"); +} + + + +/** + * Load, process and output the image + */ $img->log("Incoming arguments: " . print_r(verbose(), 1)) ->setSaveFolder($cachePath) ->useCache($useCache) diff --git a/webroot/imgs.php b/webroot/imgs.php index 64d1f59..f890e57 100644 --- a/webroot/imgs.php +++ b/webroot/imgs.php @@ -1032,13 +1032,6 @@ class CImage - /** - * The root folder of images (only used in constructor to create $pathToImage?). - */ - private $imageFolder; - - - /** * Image filename, may include subdirectory, relative from $imageFolder */ @@ -1112,6 +1105,7 @@ class CImage * Path to command for filter optimize, for example optipng or null. */ private $pngFilter; + private $pngFilterCmd; @@ -1119,13 +1113,16 @@ class CImage * Path to command for deflate optimize, for example pngout or null. */ private $pngDeflate; + private $pngDeflateCmd; /** * Path to command to optimize jpeg images, for example jpegtran or null. */ - private $jpegOptimize; + private $jpegOptimize; + private $jpegOptimizeCmd; + /** @@ -1201,6 +1198,56 @@ class CImage private $fillToFit; + + /** + * To store value for option scale. + */ + private $scale; + + + + /** + * To store value for option. + */ + private $rotateBefore; + + + + /** + * To store value for option. + */ + private $rotateAfter; + + + + /** + * To store value for option. + */ + private $autoRotate; + + + + /** + * To store value for option. + */ + private $sharpen; + + + + /** + * To store value for option. + */ + private $emboss; + + + + /** + * To store value for option. + */ + private $blur; + + + /** * Used with option area to set which parts of the image to use. */ @@ -1274,9 +1321,7 @@ class CImage public $crop_x; public $crop_y; public $filters; - private $type; // Calculated from source image private $attr; // Calculated from source image - private $useOriginal; // Use original image if possible @@ -1333,9 +1378,7 @@ class CImage /** * Use cache or not. * - * @todo clean up how $this->noCache is used in other methods. - * - * @param string $use true or false to use cache. + * @param boolean $use true or false to use cache. * * @return $this */ @@ -1347,6 +1390,27 @@ class CImage + /** + * Create and save a dummy image. Use dimensions as stated in + * $this->newWidth, or $width or default to 100 (same for height. + * + * @param integer $width use specified width for image dimension. + * @param integer $height use specified width for image dimension. + * + * @return $this + */ + public function createDummyImage($width = null, $height = null) + { + $this->newWidth = $this->newWidth ?: $width ?: 100; + $this->newHeight = $this->newHeight ?: $height ?: 100; + + $this->image = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); + + return $this; + } + + + /** * Allow or disallow remote image download. * @@ -1497,16 +1561,18 @@ class CImage /** - * Set src file. + * Set source file to use as image source. * * @param string $src of image. - * @param string $dir as base directory where images are. + * @param string $dir as optional base directory where images are. * * @return $this */ public function setSource($src, $dir = null) { if (!isset($src)) { + $this->imageSrc = null; + $this->pathToImage = null; return $this; } @@ -1520,9 +1586,9 @@ class CImage $src = basename($src); } - $this->imageSrc = ltrim($src, '/'); - $this->imageFolder = rtrim($dir, '/'); - $this->pathToImage = $this->imageFolder . '/' . $this->imageSrc; + $this->imageSrc = ltrim($src, '/'); + $imageFolder = rtrim($dir, '/'); + $this->pathToImage = $imageFolder . '/' . $this->imageSrc; return $this; } @@ -1533,23 +1599,23 @@ class CImage * Set target file. * * @param string $src of target image. - * @param string $dir as base directory where images are stored. + * @param string $dir as optional base directory where images are stored. + * Uses $this->saveFolder if null. * * @return $this */ public function setTarget($src = null, $dir = null) { - if (!(isset($src) && isset($dir))) { + if (!isset($src)) { + $this->cacheFileName = null; return $this; } - $this->saveFolder = $dir; - $this->cacheFileName = $dir . '/' . $src; + if (isset($dir)) { + $this->saveFolder = rtrim($dir, '/'); + } - /* Allow readonly cache - is_writable($this->saveFolder) - or $this->raiseError('Target directory is not writable.'); - */ + $this->cacheFileName = $this->saveFolder . '/' . $src; // Sanitize filename $this->cacheFileName = preg_replace('/^a-zA-Z0-9\.-_/', '', $this->cacheFileName); @@ -1560,6 +1626,18 @@ class CImage + /** + * Get filename of target file. + * + * @return Boolean|String as filename of target or false if not set. + */ + public function getTarget() + { + return $this->cacheFileName; + } + + + /** * Set options to use when processing image. * @@ -1607,11 +1685,6 @@ class CImage // Output format 'outputFormat' => null, 'dpr' => 1, - - // Options for saving - //'quality' => null, - //'compress' => null, - //'saveAs' => null, ); // Convert crop settings from string to array @@ -2105,13 +2178,15 @@ class CImage /** * Generate filename to save file in cache. * - * @param string $base as basepath for storing file. + * @param string $base as optional basepath for storing file. + * @param boolean $useSubdir use or skip the subdir part when creating the + * filename. * * @return $this */ - public function generateFilename($base) + public function generateFilename($base = null, $useSubdir = true) { - $parts = pathinfo($this->pathToImage); + $filename = basename($this->pathToImage); $cropToFit = $this->cropToFit ? '_cf' : null; $fillToFit = $this->fillToFit ? '_ff' : null; $crop_x = $this->crop_x ? "_x{$this->crop_x}" : null; @@ -2153,16 +2228,6 @@ class CImage $autoRotate = $this->autoRotate ? 'ar' : null; - $this->extension = isset($this->extension) - ? $this->extension - : (isset($parts['extension']) - ? $parts['extension'] - : null); - - $extension = empty($this->extension) - ? null - : "." . $this->extension; - $optimize = $this->jpegOptimize ? 'o' : null; $optimize .= $this->pngFilter ? 'f' : null; $optimize .= $this->pngDeflate ? 'd' : null; @@ -2177,14 +2242,20 @@ class CImage $upscale = '_nu'; } - $subdir = str_replace('/', '-', dirname($this->imageSrc)); - $subdir = ($subdir == '.') ? '_.' : $subdir; - $file = $subdir . '_' . $parts['filename'] . '_' . $width . '_' + $subdir = null; + if ($useSubdir === true) { + $subdir = str_replace('/', '-', dirname($this->imageSrc)); + $subdir = ($subdir == '.') ? '_.' : $subdir; + $subdir .= '_'; + } + + $file = $subdir . $filename . '_' . $width . '_' . $height . $offset . $crop . $cropToFit . $fillToFit . $crop_x . $crop_y . $upscale - . $quality . $filters . $sharpen . $emboss . $blur . $palette . $optimize - . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor . $convolve - . $extension; + . $quality . $filters . $sharpen . $emboss . $blur . $palette + . $optimize . $compress + . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor + . $convolve; return $this->setTarget($file, $base); } @@ -2952,7 +3023,10 @@ class CImage imagealphablending($img, false); imagesavealpha($img, true); - $index = imagecolortransparent($this->image); + $index = $this->image + ? imagecolortransparent($this->image) + : -1; + if ($index != -1) { imagealphablending($img, true); @@ -3025,17 +3099,23 @@ class CImage /** * Save image. * - * @param string $src as target filename. - * @param string $base as base directory where to store images. + * @param string $src as target filename. + * @param string $base as base directory where to store images. + * @param boolean $overwrite or not, default to always overwrite file. * * @return $this or false if no folder is set. */ - public function save($src = null, $base = null) + public function save($src = null, $base = null, $overwrite = true) { if (isset($src)) { $this->setTarget($src, $base); } + if ($overwrite === false && is_file($this->cacheFileName)) { + $this->Log("Not overwriting file since its already exists and \$overwrite if false."); + return; + } + is_writable($this->saveFolder) or $this->raiseError('Target directory is not writable.'); @@ -3401,7 +3481,7 @@ EOD; * */ -$version = "v0.7.4 (2015-09-15)"; +$version = "v0.7.5 (2015-10-18)"; @@ -3766,10 +3846,20 @@ $imagePath = getConfig('image_path', __DIR__ . '/img/'); $imagePathConstraint = getConfig('image_path_constraint', true); $validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#'); +// Dumm image feature +$dummyEnabled = getConfig('dummy_enabled', true); +$dummyFilename = getConfig('dummy_filename', 'dummy'); +$dummyImage = false; + preg_match($validFilename, $srcImage) or errorPage('Filename contains invalid characters.'); -if ($allowRemote && $img->isRemoteSource($srcImage)) { +if ($dummyEnabled && $srcImage === $dummyFilename) { + + // Prepare to create a dummy image and use it as the source image. + $dummyImage = true; + +} elseif ($allowRemote && $img->isRemoteSource($srcImage)) { // If source is a remote file, ignore local file checks. @@ -4326,9 +4416,43 @@ if ($verboseFile) { - /** - * Load, process and output the image - */ +/** + * Set basic options for image processing. + */ + + +/** + * Prepare a dummy image and use it as source image. + */ +if ($dummyImage === true) { + + $dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename); + + is_writable($dummyDir) + or verbose("dummy dir not writable = $dummyDir"); + + $img->setSaveFolder($dummyDir) + ->setSource($dummyFilename, $dummyDir) + ->setOptions( + array( + 'bgColor' => $bgColor, + ) + ) + ->createDummyImage() + ->generateFilename(null, false) + ->save(null, null, false); + + $srcImage = $img->getTarget(); + $imagePath = null; + + verbose("src (updated) = $srcImage"); +} + + + +/** + * Load, process and output the image + */ $img->log("Incoming arguments: " . print_r(verbose(), 1)) ->setSaveFolder($cachePath) ->useCache($useCache)