diff --git a/CImage.php b/CImage.php index 7535a72..5a1f09b 100644 --- a/CImage.php +++ b/CImage.php @@ -186,6 +186,7 @@ class CImage * Path to command for filter optimize, for example optipng or null. */ private $pngFilter; + private $pngFilterCmd; @@ -193,13 +194,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; + /** @@ -275,6 +279,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. */ @@ -405,7 +459,7 @@ class CImage /** * Use cache or not. * - * @param string $use true or false to use cache. + * @param boolean $use true or false to use cache. * * @return $this */ @@ -418,20 +472,20 @@ class CImage /** - * Create and save a dummy image. + * Create and save a dummy image. Use dimensions as stated in + * $this->newWidth, or $width or default to 100 (same for height. * - * @param boolean $allow true or false to enable and disable. - * @param string $pattern to use to detect if its a remote file. + * @param integer $width use specified width for image dimension. + * @param integer $height use specified width for image dimension. * * @return $this */ - public function createDummyImage($width = 100, $height = 100) + public function createDummyImage($width = null, $height = null) { - $img = $this->CreateImageKeepTransparency($width, $height); + $this->newWidth = $this->newWidth ?: $width ?: 100; + $this->newHeight = $this->newHeight ?: $height ?: 100; - $this->generateFilename($cachePath); - - $this->save(); + $this->image = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); return $this; } @@ -626,18 +680,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, '/'); + } + + $this->cacheFileName = $this->saveFolder . '/' . $src; // Sanitize filename $this->cacheFileName = preg_replace('/^a-zA-Z0-9\.-_/', '', $this->cacheFileName); @@ -648,6 +707,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. * @@ -1188,13 +1259,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; @@ -1236,16 +1309,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; @@ -1260,16 +1323,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 . $compress . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor - . $convolve - . $extension; + . $convolve; return $this->setTarget($file, $base); } @@ -2037,7 +2104,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); @@ -2110,17 +2180,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.'); diff --git a/REVISION.md b/REVISION.md index bb6765a..2d988ab 100644 --- a/REVISION.md +++ b/REVISION.md @@ -8,7 +8,9 @@ Revision history v0.7.5x (latest) ------------------------------------- -* Add option for png compression to generade filename, fix #103. +* Add png compression to generated cache filename, fix #103. +* Removed file prefix from storing images in cache, breaking filenamestructure for cache images. +* Minor code cleaning in `CImage.php`. v0.7.4 (2015-09-15) diff --git a/cache/dummy/README.md b/cache/dummy/README.md new file mode 100644 index 0000000..347bc3a --- /dev/null +++ b/cache/dummy/README.md @@ -0,0 +1 @@ +This directory must be writable by the webserveri to enable the dummy feature. diff --git a/test/CImageDummyTest.php b/test/CImageDummyTest.php new file mode 100644 index 0000000..6d831ee --- /dev/null +++ b/test/CImageDummyTest.php @@ -0,0 +1,49 @@ +setSaveFolder(CACHE_PATH . "/dummy"); + $img->setSource('dummy', CACHE_PATH . "/dummy"); + $img->createDummyImage(); + $img->generateFilename(null, false); + $img->save(null, null, false); + + $filename = $img->getTarget(); + + $this->assertEquals(basename($filename), "dummy_100_100", "Filename not as expected on dummy image."); + } + + + + /** + * Test + * + * @return void + */ + public function testCreate2() + { + $img = new CImage(); + + $img->setSaveFolder(CACHE_PATH . "/dummy"); + $img->setSource('dummy', CACHE_PATH . "/dummy"); + $img->createDummyImage(200, 400); + $img->generateFilename(null, false); + $img->save(null, null, false); + + $filename = $img->getTarget(); + + $this->assertEquals(basename($filename), "dummy_200_400", "Filename not as expected on dummy image."); + } +} diff --git a/test/config.php b/test/config.php index e53e4b1..4933b03 100644 --- a/test/config.php +++ b/test/config.php @@ -4,3 +4,6 @@ * */ require __DIR__ . "/../autoload.php"; + +define('IMAGE_PATH', __DIR__ . '/../webroot/img/'); +define('CACHE_PATH', __DIR__ . '/../cache/'); diff --git a/webroot/img.php b/webroot/img.php index 2e962cf..3c4e222 100644 --- a/webroot/img.php +++ b/webroot/img.php @@ -373,10 +373,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. @@ -933,9 +943,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/img_config.php b/webroot/img_config.php index 64223a2..88da39a 100644 --- a/webroot/img_config.php +++ b/webroot/img_config.php @@ -109,6 +109,28 @@ return array( + /** + * The name representing a dummy image which is automatically created + * and stored at the defined path. The dummy image can then be used + * inplace of an original image as a placeholder. + * The dummy_dir must be writable and it defaults to a subdir of the + * cache directory. + * Write protect the dummy_dir to prevent creation of new dummy images, + * but continue to use the existing ones. + * + * Default value: + * dummy_enabled: true as default, disable dummy feature by setting + * to false. + * dummy_filename: 'dummy' use this as ?src=dummy to create a dummy image. + * dummy_dir: Defaults to subdirectory of 'cache_path', + * named the same as 'dummy_filename' + */ + //'dummy_enabled' => true, + //'dummy_filename' => 'dummy', + //'dummy_dir' => 'some writable directory', + + + /** * Check that the imagefile is a file below 'image_path' using realpath(). * Security constraint to avoid reaching images outside image_path.