1
0
mirror of https://github.com/mosbth/cimage.git synced 2025-08-26 17:14:27 +02:00

Compare commits

..

53 Commits
079 ... v0.7.19

Author SHA1 Message Date
Mikael Roos
f9604518e4 prepare to tag v0.7.19 2017-03-31 00:47:55 +02:00
Mikael Roos
61aa52854e Move exception handler from functions.php to img.php. 2017-03-31 00:46:43 +02:00
Mikael Roos
401478c839 Correct XSS injection in check_system.php. 2016-08-31 15:26:14 +02:00
Mikael Roos
f0ab9479d6 read lena.tif, will need it in the future 2016-08-13 18:33:09 +02:00
Mikael Roos
9ff7a61ca9 remove tif version of lena 2016-08-13 17:49:36 +02:00
Mikael Roos
3170beb832 Composer suggests ext-imagick and ext-curl. 2016-08-11 17:39:45 +02:00
Mikael Roos
8001f72a1a prepare to tag v0.7.18 2016-08-09 13:27:46 +02:00
Mikael Roos
0f9e0220f1 Made &lossless a requirement to not use the original image. 2016-08-09 13:27:30 +02:00
Mikael Roos
e59ef91991 prepare to tag v0.7.17 2016-08-09 13:23:04 +02:00
Mikael Roos
2337dbe94c Made &lossless part of the generated cache filename. 2016-08-09 13:22:33 +02:00
Mikael Roos
c5de59a754 prepare to tag v0.7.16 2016-08-09 13:02:25 +02:00
Mikael Roos
7ab19d39d6 adding support for pngquant 2016-08-09 13:01:38 +02:00
Mikael Roos
9f6cba9292 changed date of release 2016-08-09 10:21:41 +02:00
Mikael Roos
21e53887b8 prepare to tag v0.7.15 2016-08-09 10:19:49 +02:00
Mikael Roos
66c5a07767 webp partly working 2016-08-09 09:32:02 +02:00
Mikael Roos
bbfd895c4c webp implemented but fail to verify 2016-08-08 16:49:29 +02:00
Mikael Roos
b5de49d601 add debug for test 2016-08-08 16:48:23 +02:00
Mikael Roos
7677fc772f remove debugging 2016-08-08 16:21:36 +02:00
Mikael Roos
3d0b25abe0 test support for webp images 2016-08-08 16:13:51 +02:00
Mikael Roos
1e5de9d225 Added the [Lenna/Lena sample
image](http://www.cs.cmu.edu/~chuck/lennapg/) as tif and created a png,
jpeg and webp version using Imagick convert `convert lena.tif
lena.{png,jpg,webp}`.
2016-08-08 14:42:12 +02:00
Mikael Roos
43cb5b79b2 prepare to tag v0.7.14 2016-08-08 12:20:01 +02:00
Mikael Roos
8e10e9ba5c Re-add removed cache directory. 2016-08-08 12:19:31 +02:00
Mikael Roos
1738680301 Make fast track cache disabled by default in the config file. 2016-08-08 12:19:04 +02:00
Mikael Roos
9b110037b4 prepare to tag v0.7.13 2016-08-08 11:35:12 +02:00
Mikael Roos
9a912e7f01 prepare to merge 2016-08-08 11:33:04 +02:00
Mikael Roos
689865a8b2 even more testing 2016-08-08 11:19:53 +02:00
Mikael Roos
493ed45311 more test 2016-08-08 10:44:27 +02:00
Mikael Roos
72c04632b8 more test 2016-08-08 10:39:11 +02:00
Mikael Roos
b1d0cb1506 prepare to test 2016-08-08 09:29:26 +02:00
Mikael Roos
c637fa23ef test with imgf 2016-07-18 16:38:57 +02:00
Mikael Roos
6cccf5497d added and fixed fast track cache script version 2016-07-18 01:00:55 +02:00
Mikael Roos
0dd562aa61 add really fast track cache script 2016-07-18 00:44:46 +02:00
Mikael Roos
9a0a9429db make debug depend on file exists 2016-07-10 22:57:58 +02:00
Mikael Roos
6118f298ff prepare to test fast track cache 2016-07-10 22:54:11 +02:00
Mikael Roos
32a23894d1 cleanup, removed code comments, codestyle 2016-06-01 10:11:44 +02:00
Mikael Roos
cde8bab6e7 tagging v0.7.12 2016-06-01 09:37:28 +02:00
Mikael Roos
5edbfc9b54 prepare to tag v0.7.12 2016-06-01 09:34:30 +02:00
Mikael Roos
9e9c44c935 Fixed to correctly display image when using a resize strategy without height or width. 2016-06-01 09:31:28 +02:00
Mikael Roos
9088647d3a Fixed background color for option , #144. 2016-06-01 09:30:18 +02:00
Mikael Roos
8ad324b4f5 update readme with latest version number 2016-04-18 16:09:49 +02:00
Mikael Roos
3b16b4b79d prepare to tag v0.7.11 2016-04-18 15:58:39 +02:00
Mikael Roos
4e940164f9 Add option for skip_original to config file to always skip original, #118. 2016-04-18 15:53:55 +02:00
Mikael Roos
1943d6606b update years in license 2016-04-01 11:25:36 +02:00
Mikael Roos
5eebaa66ce update to latest version 2016-04-01 10:32:44 +02:00
Mikael Roos
c5cc0314c2 prepare to tag v0.7.10 2016-04-01 10:30:25 +02:00
Mikael Roos
71816261f2 prepare to merge master 2016-04-01 10:27:33 +02:00
Mikael Roos
a62d7cb6c2 Add backup option for images src-alt, #141. 2016-04-01 10:24:24 +02:00
Mikael Roos
ccbd08949f add for testcase #134 2016-01-26 17:40:10 +01:00
Mikael Roos
6467fcc748 Add require of ext-gd in composer.json, #133. 2016-01-14 16:19:00 +01:00
Mikael Roos
14d22a18e5 Merge pull request #133 from abcdmitry/patch-1
Add GD extension to the composer requiremets
2016-01-14 16:17:43 +01:00
Dmitry Lukashin
6d3687d838 Add PHP extensions to the composer requirements 2016-01-14 16:03:13 +03:00
Mikael Roos
ad8f6c12ee creating bundles 2015-12-07 17:40:00 +01:00
Mikael Roos
ad4930c3ae Fix strict mode only reporting 404 when failure, #127. 2015-12-07 17:39:34 +01:00
30 changed files with 2595 additions and 672 deletions

238
CFastTrackCache.php Normal file
View File

@@ -0,0 +1,238 @@
<?php
/**
* Enable a fast track cache with a json representation of the image delivery.
*
*/
class CFastTrackCache
{
/**
* Cache is disabled to start with.
*/
private $enabled = false;
/**
* Path to the cache directory.
*/
private $path;
/**
* Filename of current cache item.
*/
private $filename;
/**
* Container with items to store as cached item.
*/
private $container;
/**
* Enable or disable cache.
*
* @param boolean $enable set to true to enable, false to disable
*
* @return $this
*/
public function enable($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Set the path to the cache dir which must exist.
*
* @param string $path to the cache dir.
*
* @throws Exception when $path is not a directory.
*
* @return $this
*/
public function setCacheDir($path)
{
if (!is_dir($path)) {
throw new Exception("Cachedir is not a directory.");
}
$this->path = rtrim($path, "/");
return $this;
}
/**
* Set the filename to store in cache, use the querystring to create that
* filename.
*
* @param array $clear items to clear in $_GET when creating the filename.
*
* @return string as filename created.
*/
public function setFilename($clear)
{
$query = $_GET;
// Remove parts from querystring that should not be part of filename
foreach ($clear as $value) {
unset($query[$value]);
}
arsort($query);
$queryAsString = http_build_query($query);
$this->filename = md5($queryAsString);
if (CIMAGE_DEBUG) {
$this->container["query-string"] = $queryAsString;
}
return $this->filename;
}
/**
* Add header items.
*
* @param string $header add this as header.
*
* @return $this
*/
public function addHeader($header)
{
$this->container["header"][] = $header;
return $this;
}
/**
* Add header items on output, these are not output when 304.
*
* @param string $header add this as header.
*
* @return $this
*/
public function addHeaderOnOutput($header)
{
$this->container["header-output"][] = $header;
return $this;
}
/**
* Set path to source image to.
*
* @param string $source path to source image file.
*
* @return $this
*/
public function setSource($source)
{
$this->container["source"] = $source;
return $this;
}
/**
* Set last modified of source image, use to check for 304.
*
* @param string $lastModified
*
* @return $this
*/
public function setLastModified($lastModified)
{
$this->container["last-modified"] = $lastModified;
return $this;
}
/**
* Get filename of cached item.
*
* @return string as filename.
*/
public function getFilename()
{
return $this->path . "/" . $this->filename;
}
/**
* Write current item to cache.
*
* @return boolean if cache file was written.
*/
public function writeToCache()
{
if (!$this->enabled) {
return false;
}
if (is_dir($this->path) && is_writable($this->path)) {
$filename = $this->getFilename();
return file_put_contents($filename, json_encode($this->container)) !== false;
}
return false;
}
/**
* Output current item from cache, if available.
*
* @return void
*/
public function output()
{
$filename = $this->getFilename();
if (!is_readable($filename)) {
return;
}
$item = json_decode(file_get_contents($filename), true);
if (!is_readable($item["source"])) {
return;
}
foreach ($item["header"] as $value) {
header($value);
}
if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])
&& strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]) == $item["last-modified"]) {
header("HTTP/1.0 304 Not Modified");
if (CIMAGE_DEBUG) {
trace(__CLASS__ . " 304");
}
exit;
}
foreach ($item["header-output"] as $value) {
header($value);
}
if (CIMAGE_DEBUG) {
trace(__CLASS__ . " 200");
}
readfile($item["source"]);
exit;
}
}

View File

@@ -155,6 +155,13 @@ class CImage
/**
* Do lossy output using external postprocessing tools.
*/
private $lossy = null;
/** /**
* Verbose mode to print out a trace and display the created image * Verbose mode to print out a trace and display the created image
*/ */
@@ -190,7 +197,15 @@ class CImage
/** /**
* Path to command for filter optimize, for example optipng or null. * Path to command for lossy optimize, for example pngquant.
*/
private $pngLossy;
private $pngLossyCmd;
/**
* Path to command for filter optimize, for example optipng.
*/ */
private $pngFilter; private $pngFilter;
private $pngFilterCmd; private $pngFilterCmd;
@@ -198,7 +213,7 @@ class CImage
/** /**
* Path to command for deflate optimize, for example pngout or null. * Path to command for deflate optimize, for example pngout.
*/ */
private $pngDeflate; private $pngDeflate;
private $pngDeflateCmd; private $pngDeflateCmd;
@@ -379,6 +394,12 @@ class CImage
private $useCache = true; private $useCache = true;
/**
* Disable the fasttrackCacke to start with, inject an object to enable it.
*/
private $fastTrackCache = null;
/* /*
* Set whitelist for valid hostnames from where remote source can be * Set whitelist for valid hostnames from where remote source can be
@@ -446,6 +467,25 @@ class CImage
/**
* Inject object and use it, must be available as member.
*
* @param string $property to set as object.
* @param object $object to set to property.
*
* @return $this
*/
public function injectDependency($property, $object)
{
if (!property_exists($this, $property)) {
$this->raiseError("Injecting unknown property.");
}
$this->$property = $object;
return $this;
}
/** /**
* Set verbose mode. * Set verbose mode.
* *
@@ -615,7 +655,7 @@ class CImage
*/ */
private function checkFileExtension($extension) private function checkFileExtension($extension)
{ {
$valid = array('jpg', 'jpeg', 'png', 'gif'); $valid = array('jpg', 'jpeg', 'png', 'gif', 'webp');
in_array(strtolower($extension), $valid) in_array(strtolower($extension), $valid)
or $this->raiseError('Not a valid file extension.'); or $this->raiseError('Not a valid file extension.');
@@ -802,6 +842,9 @@ class CImage
// Output format // Output format
'outputFormat' => null, 'outputFormat' => null,
'dpr' => 1, 'dpr' => 1,
// Postprocessing using external tools
'lossy' => null,
); );
// Convert crop settings from string to array // Convert crop settings from string to array
@@ -916,17 +959,34 @@ class CImage
is_readable($file) is_readable($file)
or $this->raiseError('Image file does not exist.'); or $this->raiseError('Image file does not exist.');
// Get details on image $info = list($this->width, $this->height, $this->fileType) = getimagesize($file);
$info = list($this->width, $this->height, $this->fileType, $this->attr) = getimagesize($file);
if (empty($info)) { if (empty($info)) {
throw new Exception("The file doesn't seem to be a valid image."); // To support webp
$this->fileType = false;
if (function_exists("exif_imagetype")) {
$this->fileType = exif_imagetype($file);
if ($this->fileType === false) {
if (function_exists("imagecreatefromwebp")) {
$webp = imagecreatefromwebp($file);
if ($webp !== false) {
$this->width = imagesx($webp);
$this->height = imagesy($webp);
$this->fileType = IMG_WEBP;
}
}
}
}
}
if (!$this->fileType) {
throw new Exception("Loading image details, the file doesn't seem to be a valid image.");
} }
if ($this->verbose) { if ($this->verbose) {
$this->log("Loading image details for: {$file}"); $this->log("Loading image details for: {$file}");
$this->log(" Image width x height (type): {$this->width} x {$this->height} ({$this->fileType})."); $this->log(" Image width x height (type): {$this->width} x {$this->height} ({$this->fileType}).");
$this->log(" Image filesize: " . filesize($file) . " bytes."); $this->log(" Image filesize: " . filesize($file) . " bytes.");
$this->log(" Image mimetype: " . image_type_to_mime_type($this->fileType)); $this->log(" Image mimetype: " . $this->getMimeType());
} }
return $this; return $this;
@@ -934,6 +994,23 @@ class CImage
/**
* Get mime type for image type.
*
* @return $this
* @throws Exception
*/
protected function getMimeType()
{
if ($this->fileType === IMG_WEBP) {
return "image/webp";
}
return image_type_to_mime_type($this->fileType);
}
/** /**
* Init new width and height and do some sanity checks on constraints, before any * Init new width and height and do some sanity checks on constraints, before any
* processing can be done. * processing can be done.
@@ -1098,8 +1175,14 @@ class CImage
$this->newWidth = round($factor * $width); $this->newWidth = round($factor * $width);
$this->log("New height was set."); $this->log("New height was set.");
} else {
// Use existing width and height as new width and height.
$this->newWidth = $width;
$this->newHeight = $height;
} }
// Get image dimensions for pre-resize image. // Get image dimensions for pre-resize image.
if ($this->cropToFit || $this->fillToFit) { if ($this->cropToFit || $this->fillToFit) {
@@ -1282,6 +1365,7 @@ class CImage
&& !$this->autoRotate && !$this->autoRotate
&& !$this->bgColor && !$this->bgColor
&& ($this->upscale === self::UPSCALE_DEFAULT) && ($this->upscale === self::UPSCALE_DEFAULT)
&& !$this->lossy
) { ) {
$this->log("Using original image."); $this->log("Using original image.");
$this->output($this->pathToImage); $this->output($this->pathToImage);
@@ -1315,6 +1399,7 @@ class CImage
$compress = $this->compress ? "_co{$this->compress}" : null; $compress = $this->compress ? "_co{$this->compress}" : null;
$rotateBefore = $this->rotateBefore ? "_rb{$this->rotateBefore}" : null; $rotateBefore = $this->rotateBefore ? "_rb{$this->rotateBefore}" : null;
$rotateAfter = $this->rotateAfter ? "_ra{$this->rotateAfter}" : null; $rotateAfter = $this->rotateAfter ? "_ra{$this->rotateAfter}" : null;
$lossy = $this->lossy ? "_l" : null;
$saveAs = $this->normalizeFileExtension(); $saveAs = $this->normalizeFileExtension();
$saveAs = $saveAs ? "_$saveAs" : null; $saveAs = $saveAs ? "_$saveAs" : null;
@@ -1381,7 +1466,7 @@ class CImage
. $quality . $filters . $sharpen . $emboss . $blur . $palette . $quality . $filters . $sharpen . $emboss . $blur . $palette
. $optimize . $compress . $optimize . $compress
. $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor . $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor
. $convolve . $copyStrat . $saveAs; . $convolve . $copyStrat . $lossy . $saveAs;
return $this->setTarget($file, $base); return $this->setTarget($file, $base);
} }
@@ -1439,9 +1524,14 @@ class CImage
$this->setSource($src, $dir); $this->setSource($src, $dir);
} }
$this->loadImageDetails($this->pathToImage); $this->loadImageDetails();
$this->image = imagecreatefromstring(file_get_contents($this->pathToImage)); if ($this->fileType === IMG_WEBP) {
$this->image = imagecreatefromwebp($this->pathToImage);
} else {
$imageAsString = file_get_contents($this->pathToImage);
$this->image = imagecreatefromstring($imageAsString);
}
if ($this->image === false) { if ($this->image === false) {
throw new Exception("Could not load image."); throw new Exception("Could not load image.");
} }
@@ -1696,25 +1786,41 @@ class CImage
// Resize by crop to fit // Resize by crop to fit
$this->log("Resizing using strategy - Crop to fit"); $this->log("Resizing using strategy - Crop to fit");
if (!$this->upscale && ($this->width < $this->newWidth || $this->height < $this->newHeight)) { if (!$this->upscale
&& ($this->width < $this->newWidth || $this->height < $this->newHeight)) {
$this->log("Resizing - smaller image, do not upscale."); $this->log("Resizing - smaller image, do not upscale.");
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
$posX = 0; $posX = 0;
$posY = 0; $posY = 0;
$cropX = 0;
$cropY = 0;
if ($this->newWidth > $this->width) { if ($this->newWidth > $this->width) {
$posX = round(($this->newWidth - $this->width) / 2); $posX = round(($this->newWidth - $this->width) / 2);
} }
if ($this->newWidth < $this->width) {
$cropX = round(($this->width/2) - ($this->newWidth/2));
}
if ($this->newHeight > $this->height) { if ($this->newHeight > $this->height) {
$posY = round(($this->newHeight - $this->height) / 2); $posY = round(($this->newHeight - $this->height) / 2);
} }
if ($this->newHeight < $this->height) {
$cropY = round(($this->height/2) - ($this->newHeight/2));
}
$this->log(" cwidth: $this->cropWidth");
$this->log(" cheight: $this->cropHeight");
$this->log(" nwidth: $this->newWidth");
$this->log(" nheight: $this->newHeight");
$this->log(" width: $this->width");
$this->log(" height: $this->height");
$this->log(" posX: $posX");
$this->log(" posY: $posY");
$this->log(" cropX: $cropX");
$this->log(" cropY: $cropY");
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); $imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopy($imageResized, $this->image, $posX, $posY, $cropX, $cropY, $this->newWidth, $this->newHeight); imagecopy($imageResized, $this->image, $posX, $posY, $cropX, $cropY, $this->width, $this->height);
} else { } else {
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2)); $cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2)); $cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
@@ -1747,14 +1853,14 @@ class CImage
} }
if (!$this->upscale if (!$this->upscale
&& ($this->width < $this->newWidth || $this->height < $this->newHeight) && ($this->width < $this->newWidth && $this->height < $this->newHeight)
) { ) {
$this->log("Resizing - smaller image, do not upscale."); $this->log("Resizing - smaller image, do not upscale.");
$posX = round(($this->fillWidth - $this->width) / 2); $posX = round(($this->newWidth - $this->width) / 2);
$posY = round(($this->fillHeight - $this->height) / 2); $posY = round(($this->newHeight - $this->height) / 2);
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); $imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopy($imageResized, $this->image, $posX, $posY, 0, 0, $this->fillWidth, $this->fillHeight); imagecopy($imageResized, $this->image, $posX, $posY, 0, 0, $this->width, $this->height);
} else { } else {
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight); $imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
@@ -1796,9 +1902,8 @@ class CImage
$cropX = round(($this->width - $this->newWidth) / 2); $cropX = round(($this->width - $this->newWidth) / 2);
} }
//$this->log("posX=$posX, posY=$posY, cropX=$cropX, cropY=$cropY.");
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight); $imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
imagecopy($imageResized, $this->image, $posX, $posY, $cropX, $cropY, $this->newWidth, $this->newHeight); imagecopy($imageResized, $this->image, $posX, $posY, $cropX, $cropY, $this->width, $this->height);
$this->image = $imageResized; $this->image = $imageResized;
$this->width = $this->newWidth; $this->width = $this->newWidth;
$this->height = $this->newHeight; $this->height = $this->newHeight;
@@ -2260,6 +2365,14 @@ class CImage
$this->jpegOptimizeCmd = null; $this->jpegOptimizeCmd = null;
} }
if (array_key_exists("png_lossy", $options)
&& $options['png_lossy'] !== false) {
$this->pngLossy = $options['png_lossy'];
$this->pngLossyCmd = $options['png_lossy_cmd'];
} else {
$this->pngLossyCmd = null;
}
if (isset($options['png_filter']) && $options['png_filter']) { if (isset($options['png_filter']) && $options['png_filter']) {
$this->pngFilterCmd = $options['png_filter_cmd']; $this->pngFilterCmd = $options['png_filter_cmd'];
} else { } else {
@@ -2287,9 +2400,11 @@ class CImage
// switch on mimetype // switch on mimetype
if (isset($this->extension)) { if (isset($this->extension)) {
return strtolower($this->extension); return strtolower($this->extension);
} else { } elseif ($this->fileType === IMG_WEBP) {
return substr(image_type_to_extension($this->fileType), 1); return "webp";
} }
return substr(image_type_to_extension($this->fileType), 1);
} }
@@ -2345,6 +2460,11 @@ class CImage
imagegif($this->image, $this->cacheFileName); imagegif($this->image, $this->cacheFileName);
break; break;
case 'webp':
$this->Log("Saving image as WEBP to cache using quality = {$this->quality}.");
imagewebp($this->image, $this->cacheFileName, $this->quality);
break;
case 'png': case 'png':
default: default:
$this->Log("Saving image as PNG to cache using compression = {$this->compress}."); $this->Log("Saving image as PNG to cache using compression = {$this->compress}.");
@@ -2354,6 +2474,24 @@ class CImage
imagesavealpha($this->image, true); imagesavealpha($this->image, true);
imagepng($this->image, $this->cacheFileName, $this->compress); imagepng($this->image, $this->cacheFileName, $this->compress);
// Use external program to process lossy PNG, if defined
$lossyEnabled = $this->pngLossy === true;
$lossySoftEnabled = $this->pngLossy === null;
$lossyActiveEnabled = $this->lossy === true;
if ($lossyEnabled || ($lossySoftEnabled && $lossyActiveEnabled)) {
if ($this->verbose) {
clearstatcache();
$this->log("Lossy enabled: $lossyEnabled");
$this->log("Lossy soft enabled: $lossySoftEnabled");
$this->Log("Filesize before lossy optimize: " . filesize($this->cacheFileName) . " bytes.");
}
$res = array();
$cmd = $this->pngLossyCmd . " $this->cacheFileName $this->cacheFileName";
exec($cmd, $res);
$this->Log($cmd);
$this->Log($res);
}
// Use external program to filter PNG, if defined // Use external program to filter PNG, if defined
if ($this->pngFilterCmd) { if ($this->pngFilterCmd) {
if ($this->verbose) { if ($this->verbose) {
@@ -2499,7 +2637,7 @@ class CImage
/** /**
* Add HTTP header for putputting together with image. * Add HTTP header for output together with image.
* *
* @param string $type the header type such as "Cache-Control" * @param string $type the header type such as "Cache-Control"
* @param string $value the value to use * @param string $value the value to use
@@ -2533,6 +2671,7 @@ class CImage
$format = $this->outputFormat; $format = $this->outputFormat;
} }
$this->log("### Output");
$this->log("Output format is: $format"); $this->log("Output format is: $format");
if (!$this->verbose && $format == 'json') { if (!$this->verbose && $format == 'json') {
@@ -2550,17 +2689,24 @@ class CImage
// Get image modification time // Get image modification time
clearstatcache(); clearstatcache();
$lastModified = filemtime($file); $lastModified = filemtime($file);
$gmdate = gmdate("D, d M Y H:i:s", $lastModified); $lastModifiedFormat = "D, d M Y H:i:s";
$gmdate = gmdate($lastModifiedFormat, $lastModified);
if (!$this->verbose) { if (!$this->verbose) {
header('Last-Modified: ' . $gmdate . " GMT"); $header = "Last-Modified: $gmdate GMT";
header($header);
$this->fastTrackCache->addHeader($header);
$this->fastTrackCache->setLastModified($lastModified);
} }
foreach ($this->HTTPHeader as $key => $val) { foreach ($this->HTTPHeader as $key => $val) {
header("$key: $val"); $header = "$key: $val";
header($header);
$this->fastTrackCache->addHeader($header);
} }
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified) { if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
&& strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified) {
if ($this->verbose) { if ($this->verbose) {
$this->log("304 not modified"); $this->log("304 not modified");
@@ -2569,13 +2715,14 @@ class CImage
} }
header("HTTP/1.0 304 Not Modified"); header("HTTP/1.0 304 Not Modified");
if (CIMAGE_DEBUG) {
trace(__CLASS__ . " 304");
}
} else { } else {
// Get details on image $this->loadImageDetails($file);
$info = getimagesize($file); $mime = $this->getMimeType();
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
$mime = $info['mime'];
$size = filesize($file); $size = filesize($file);
if ($this->verbose) { if ($this->verbose) {
@@ -2589,8 +2736,19 @@ class CImage
} }
} }
header("Content-type: $mime"); $header = "Content-type: $mime";
header("Content-length: $size"); header($header);
$this->fastTrackCache->addHeaderOnOutput($header);
$header = "Content-length: $size";
header($header);
$this->fastTrackCache->addHeaderOnOutput($header);
$this->fastTrackCache->setSource($file);
$this->fastTrackCache->writeToCache();
if (CIMAGE_DEBUG) {
trace(__CLASS__ . " 200");
}
readfile($file); readfile($file);
} }
@@ -2625,7 +2783,7 @@ class CImage
$this->load($file); $this->load($file);
$details['filename'] = basename($file); $details['filename'] = basename($file);
$details['mimeType'] = image_type_to_mime_type($this->fileType); $details['mimeType'] = $this->getMimeType($this->fileType);
$details['width'] = $this->width; $details['width'] = $this->width;
$details['height'] = $this->height; $details['height'] = $this->height;
$details['aspectRatio'] = round($this->width / $this->height, 3); $details['aspectRatio'] = round($this->width / $this->height, 3);
@@ -2727,6 +2885,7 @@ class CImage
private function verboseOutput() private function verboseOutput()
{ {
$log = null; $log = null;
$this->log("### Summary of verbose log");
$this->log("As JSON: \n" . $this->json()); $this->log("As JSON: \n" . $this->json());
$this->log("Memory peak: " . round(memory_get_peak_usage() /1024/1024) . "M"); $this->log("Memory peak: " . round(memory_get_peak_usage() /1024/1024) . "M");
$this->log("Memory limit: " . ini_get('memory_limit')); $this->log("Memory limit: " . ini_get('memory_limit'));

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 - 2016 Mikael Roos, https://mikaelroos.se, mos@dbwebb.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

View File

@@ -8,7 +8,7 @@ Image conversion on the fly using PHP
About About
------------------------------------- -------------------------------------
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim07.png&w=200&c=140,140,520,340&sharpen"/> <img src="https://cimage.se/cimage/imgd.php?src=example/kodim07.png&w=200&c=140,140,520,340&sharpen"/>
`CImage` is a PHP class enabling resizing of images through scaling, cropping and filtering effects -- using PHP GD. The script `img.php` uses `CImage` to enable server-side image processing utilizing caching and optimization of the processed images. `CImage` is a PHP class enabling resizing of images through scaling, cropping and filtering effects -- using PHP GD. The script `img.php` uses `CImage` to enable server-side image processing utilizing caching and optimization of the processed images.
@@ -22,7 +22,10 @@ Documentation
-------------------------------------- --------------------------------------
Read full documentation at: Read full documentation at:
http://dbwebb.se/opensource/cimage <strike>http://dbwebb.se/opensource/cimage</strike>
New website is being setup at [cimage.se](https://cimage.se), to improve documentation (work is ongoing).
@@ -46,14 +49,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). 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.9 released 2015-12-07.** **Latest stable version is v0.7.18 released 2016-08-09.**
I prefer cloning like this. Do switch to the latest stable version. I prefer cloning like this. Do switch to the latest stable version.
```bash ```bash
git clone git://github.com/mosbth/cimage.git git clone git://github.com/mosbth/cimage.git
cd cimage cd cimage
git checkout v0.7.9 git checkout v0.7.18
``` ```
Make the cache-directory writable by the webserver. Make the cache-directory writable by the webserver.
@@ -76,7 +79,7 @@ There are some all-included bundles of `img.php` that can be downloaded and used
Dowload the version of your choice like this. Dowload the version of your choice like this.
```bash ```bash
wget https://raw.githubusercontent.com/mosbth/cimage/v0.7.9/webroot/imgp.php wget https://raw.githubusercontent.com/mosbth/cimage/v0.7.18/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. 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.
@@ -98,7 +101,7 @@ Lets take some use cases to let you know when and how `img.php` might be useful.
### Make a thumbnail ### Make a thumbnail
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim04.png&w=80&h=80&cf"> <img src="https://cimage.se/cimage/imgd.php?src=example/kodim04.png&w=80&h=80&cf">
Lets say you have a larger image and you want to make a smaller thumbnail of it with a size of 80x80 pixels. You simply take the image and add constraints on `width`, `height` and you use the resize strategy `crop-to-fit` to crops out the parts of the image that does not fit. Lets say you have a larger image and you want to make a smaller thumbnail of it with a size of 80x80 pixels. You simply take the image and add constraints on `width`, `height` and you use the resize strategy `crop-to-fit` to crops out the parts of the image that does not fit.
@@ -112,7 +115,7 @@ To produce such a thumbnail, create a link like this:
Perhaps you got an image from a friend. The image was taken with the iPhone and thus rotated. Perhaps you got an image from a friend. The image was taken with the iPhone and thus rotated.
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=issue36/me-270.jpg&w=250"> <img src="https://cimage.se/cimage/imgd.php?src=example/issue36/me-270.jpg&w=250">
The original image is looking like this one, scaled down to a width of 250 pixels. The original image is looking like this one, scaled down to a width of 250 pixels.
@@ -125,7 +128,7 @@ Lets call this *the URL-Photoshopper*. This is how the magic looks like.
> `img.php?src=issue36/me-270.jpg&w=100&h=100&cf&aro` > `img.php?src=issue36/me-270.jpg&w=100&h=100&cf&aro`
> `&rb=-25&a=8,30,30,38&f=grayscale&convolve=sharpen-alt` > `&rb=-25&a=8,30,30,38&f=grayscale&convolve=sharpen-alt`
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=issue36/me-270.jpg&w=100&h=100&cf&aro&rb=-25&a=8,30,30,38&f=grayscale&convolve=sharpen-alt"> <img src="https://cimage.se/cimage/imgd.php?src=example/issue36/me-270.jpg&w=100&h=100&cf&aro&rb=-25&a=8,30,30,38&f=grayscale&convolve=sharpen-alt">
For myself, I use `img.php` to put up all images on my website, it gives me the power of affecting the resulting images - without opening up a photo-editing application. For myself, I use `img.php` to put up all images on my website, it gives me the power of affecting the resulting images - without opening up a photo-editing application.
@@ -144,7 +147,7 @@ Try it out by pointing your browser to the test file `webroot/test/test.php`. It
###Process your first image ###Process your first image
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim04.png&amp;w=w2&amp;a=40,0,50,0" alt=''> <img src="https://cimage.se/cimage/imgd.php?src=example/kodim04.png&amp;w=w2&amp;a=40,0,50,0" alt=''>
Try it yourself by opening up an image in your browser. Start with Try it yourself by opening up an image in your browser. Start with
@@ -198,7 +201,7 @@ Open an image through `img.php` by using its `src` attribute.
It looks like this. It looks like this.
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=w1&save-as=jpg"> <img src="https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=w1&save-as=jpg">
All images are stored in a directory structure and you access them as: All images are stored in a directory structure and you access them as:
@@ -212,7 +215,7 @@ Create a thumbnail of the image by applying constraints on width and height, or
| `&width=150` | `&height=150` | `&w=150&h=150` | | `&width=150` | `&height=150` | `&w=150&h=150` |
|---------------------|---------------------|---------------------| |---------------------|---------------------|---------------------|
| <img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=150 alt=''> | <img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&h=150 alt=''> | <img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=150&h=150 alt=''> | | <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=150 alt=''> | <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&h=150 alt=''> | <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=150&h=150 alt=''> |
By setting `width`, `height` or both, the image gets resized to be *not larger* than the defined dimensions *and* keeping its original aspect ratio. By setting `width`, `height` or both, the image gets resized to be *not larger* than the defined dimensions *and* keeping its original aspect ratio.
@@ -227,10 +230,10 @@ Creating a thumbnail with a certain dimension of width and height, usually invol
| What | The image | | What | The image |
|---------------------|---------------------| |---------------------|---------------------|
| **Original.** The original image resized with a max width and max height.<br>`?w=300&h=150` | <img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=300&h=150 alt=''> | | **Original.** The original image resized with a max width and max height.<br>`?w=300&h=150` | <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=300&h=150 alt=''> |
| **Stretch.** Stretch the image so that the resulting image has the defined width and height.<br>`?w=300&h=150&stretch` | <img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=300&h=150&stretch alt=''> | | **Stretch.** Stretch the image so that the resulting image has the defined width and height.<br>`?w=300&h=150&stretch` | <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=300&h=150&stretch alt=''> |
| **Crop to fit.** Keep the aspect ratio and crop out the parts of the image that does not fit.<br>`?w=300&h=150&crop-to-fit` | <img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=300&h=150&crop-to-fit alt=''> | | **Crop to fit.** Keep the aspect ratio and crop out the parts of the image that does not fit.<br>`?w=300&h=150&crop-to-fit` | <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=300&h=150&crop-to-fit alt=''> |
| **Fill to fit.** Keep the aspect ratio and fill then blank space with a background color.<br>`?w=300&h=150&fill-to-fit=006600` | <img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=300&h=150&fill-to-fit=006600 alt=''> | | **Fill to fit.** Keep the aspect ratio and fill then blank space with a background color.<br>`?w=300&h=150&fill-to-fit=006600` | <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=300&h=150&fill-to-fit=006600 alt=''> |
Learn to crop your images, creative cropping can make wonderful images from appearingly useless originals. Learn to crop your images, creative cropping can make wonderful images from appearingly useless originals.
@@ -247,7 +250,7 @@ Fill to fit is useful when you have some image that must fit in a certain dimens
> `img.php?src=kodim13.png&w=600&aspect-ratio=4` > `img.php?src=kodim13.png&w=600&aspect-ratio=4`
> `&crop-to-fit&sharpen&save-as=jpg&q=30` > `&crop-to-fit&sharpen&save-as=jpg&q=30`
<img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=600&aspect-ratio=4&crop-to-fit&sharpen&save-as=jpg&q=30 alt=''> <img src=https://cimage.se/cimage/imgd.php?src=example/kodim13.png&w=600&aspect-ratio=4&crop-to-fit&sharpen&save-as=jpg&q=30 alt=''>
Here is a list of all parameters that you can use together with `img.php`, grouped by its basic intent of usage. Here is a list of all parameters that you can use together with `img.php`, grouped by its basic intent of usage.
@@ -430,7 +433,7 @@ For example, the following image is created like this:
> `&w=300&save-as=jpg` > `&w=300&save-as=jpg`
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim24.png&w=300&save-as=jpg" alt=''> <img src="https://cimage.se/cimage/imgd.php?src=example/kodim24.png&w=300&save-as=jpg" alt=''>
Its JSON-representation is retrieved like this: Its JSON-representation is retrieved like this:

View File

@@ -5,6 +5,82 @@ 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) [![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.19 (2017-03-31)
-------------------------------------
* Move exception handler from functions.php to img.php.
* Correct XSS injection in `check_system.php`.
* Composer suggests ext-imagick and ext-curl.
v0.7.18 (2016-08-09)
-------------------------------------
* Made `&lossless` a requirement to not use the original image.
v0.7.17 (2016-08-09)
-------------------------------------
* Made `&lossless` part of the generated cache filename.
v0.7.16 (2016-08-09)
-------------------------------------
* Fix default mode to be production.
* Added pngquant as extra postprocessing utility for PNG-images, #154.
* Bug `&status` wrong variable name for fast track cache.
v0.7.15 (2016-08-09)
-------------------------------------
* Added the [Lenna/Lena sample image](http://www.cs.cmu.edu/~chuck/lennapg/) as tif and created a png, jpeg and webp version using Imagick convert `convert lena.tif lena.{png,jpg,webp}`, #152.
* Limited and basic support for WEBP format, se #132.
v0.7.14 (2016-08-08)
-------------------------------------
* Re-add removed cache directory.
* Make fast track cache disabled by default in the config file.
v0.7.13 (2016-08-08)
-------------------------------------
* Moved functions from img.php to `functions.php`.
* Added function `trace()` to measure speed and memory consumption, only for development.
* Added fast cache #149.
* Added `imgf.php` as shortcut to check for fast cache, before loading `img.php` as usual, adding `imgf_config.php` as symlink to `img_config.php`.
* Created `defines.php` and moved definition av version there.
* Fixed images in README, #148.
* Initiated dependency injection to `CImage`, class names can be set in config file and will be injected to `CImage` from `img.php`. Not implemented for all classes. #151.
* Enabled debug mode to make it easier to trace what actually happens while processing the image, #150.
v0.7.12 (2016-06-01)
-------------------------------------
* Fixed to correctly display image when using a resize strategy without height or width.
* Fixed background color for option `no-upscale`, #144.
v0.7.11 (2016-04-18)
-------------------------------------
* Add option for `skip_original` to config file to always skip original, #118.
v0.7.10 (2016-04-01)
-------------------------------------
* Add backup option for images `src-alt`, #141.
* Add require of ext-gd in composer.json, #133.
* Fix strict mode only reporting 404 when failure, #127.
v0.7.9 (2015-12-07) v0.7.9 (2015-12-07)
------------------------------------- -------------------------------------

View File

@@ -3,9 +3,10 @@
* Autoloader for CImage and related class files. * Autoloader for CImage and related class files.
* *
*/ */
//include __DIR__ . "/../CHttpGet.php"; require_once __DIR__ . "/defines.php";
//include __DIR__ . "/../CRemoteImage.php"; require_once __DIR__ . "/functions.php";
//include __DIR__ . "/../CImage.php";
/** /**
* Autoloader for classes. * Autoloader for classes.

View File

@@ -34,12 +34,15 @@ fi
$ECHO "Creating '$TARGET_D', '$TARGET_P' and '$TARGET_S' by combining the following files:" $ECHO "Creating '$TARGET_D', '$TARGET_P' and '$TARGET_S' by combining the following files:"
$ECHO "\n" $ECHO "\n"
$ECHO "\n webroot/img_header.php" $ECHO "\n webroot/img_header.php"
$ECHO "\n defines.php"
$ECHO "\n functions.php"
$ECHO "\n CHttpGet.php" $ECHO "\n CHttpGet.php"
$ECHO "\n CRemoteImage.php" $ECHO "\n CRemoteImage.php"
$ECHO "\n CWhitelist.php" $ECHO "\n CWhitelist.php"
$ECHO "\n CAsciiArt.php" $ECHO "\n CAsciiArt.php"
$ECHO "\n CImage.php" $ECHO "\n CImage.php"
$ECHO "\n CCache.php" $ECHO "\n CCache.php"
$ECHO "\n CFastTrackCache.php"
$ECHO "\n webroot/img.php" $ECHO "\n webroot/img.php"
$ECHO "\n" $ECHO "\n"
$ECHO "\n'$TARGET_D' is for development mode." $ECHO "\n'$TARGET_D' is for development mode."
@@ -60,6 +63,12 @@ cat webroot/img_header.php | sed "s|//'mode' => 'production',|'mode'
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null $ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
tail -n +2 defines.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
tail -n +2 functions.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
tail -n +2 CHttpGet.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null tail -n +2 CHttpGet.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null $ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
@@ -78,6 +87,9 @@ $ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
tail -n +2 CCache.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null tail -n +2 CCache.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null $ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
tail -n +2 CFastTrackCache.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
tail -n +2 webroot/img.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null tail -n +2 webroot/img.php | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null $ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null

4
cache/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

0
cache/README.md vendored
View File

View File

@@ -18,16 +18,27 @@
"docs": "http://dbwebb.se/opensource/cimage" "docs": "http://dbwebb.se/opensource/cimage"
}, },
"require": { "require": {
"php": ">=5.3" "php": ">=5.3",
"ext-gd": "*"
},
"suggest": {
"ext-exif": "*",
"ext-curl": "*",
"ext-imagick": "*"
}, },
"autoload": { "autoload": {
"files": [
"defines.php",
"functions.php"
],
"classmap": [ "classmap": [
"CImage.php", "CImage.php",
"CHttpGet.php", "CHttpGet.php",
"CRemoteImage.php", "CRemoteImage.php",
"CWhitelist.php", "CWhitelist.php",
"CAsciiArt.php", "CAsciiArt.php",
"CCache.php" "CCache.php",
"CFastTrackCache.php"
] ]
} }
} }

11
defines.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
// Version of cimage and img.php
define("CIMAGE_VERSION", "v0.7.19 (2017-03-31)");
// For CRemoteImage
define("CIMAGE_USER_AGENT", "CImage/" . CIMAGE_VERSION);
// Image type IMG_WEBP is only defined from 5.6.25
if (!defined("IMG_WEBP")) {
define("IMG_WEBP", -1);
}

170
functions.php Normal file
View File

@@ -0,0 +1,170 @@
<?php
/**
* General functions to use in img.php.
*/
/**
* Trace and log execution to logfile, useful for debugging and development.
*
* @param string $msg message to log to file.
*
* @return void
*/
function trace($msg)
{
$file = CIMAGE_DEBUG_FILE;
if (!is_writable($file)) {
return;
}
$timer = number_format((microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"]), 6);
$details = "{$timer}ms";
$details .= ":" . round(memory_get_peak_usage()/1024/1024, 3) . "MB";
$details .= ":" . count(get_included_files());
file_put_contents($file, "$details:$msg\n", FILE_APPEND);
}
/**
* Display error message.
*
* @param string $msg to display.
* @param int $type of HTTP error to display.
*
* @return void
*/
function errorPage($msg, $type = 500)
{
global $mode;
switch ($type) {
case 403:
$header = "403 Forbidden";
break;
case 404:
$header = "404 Not Found";
break;
default:
$header = "500 Internal Server Error";
}
if ($mode == "strict") {
$header = "404 Not Found";
}
header("HTTP/1.0 $header");
if ($mode == "development") {
die("[img.php] $msg");
}
error_log("[img.php] $msg");
die("HTTP/1.0 $header");
}
/**
* Get input from query string or return default value if not set.
*
* @param mixed $key as string or array of string values to look for in $_GET.
* @param mixed $default value to return when $key is not set in $_GET.
*
* @return mixed value from $_GET or default value.
*/
function get($key, $default = null)
{
if (is_array($key)) {
foreach ($key as $val) {
if (isset($_GET[$val])) {
return $_GET[$val];
}
}
} elseif (isset($_GET[$key])) {
return $_GET[$key];
}
return $default;
}
/**
* Get input from query string and set to $defined if defined or else $undefined.
*
* @param mixed $key as string or array of string values to look for in $_GET.
* @param mixed $defined value to return when $key is set in $_GET.
* @param mixed $undefined value to return when $key is not set in $_GET.
*
* @return mixed value as $defined or $undefined.
*/
function getDefined($key, $defined, $undefined)
{
return get($key) === null ? $undefined : $defined;
}
/**
* Get value from config array or default if key is not set in config array.
*
* @param string $key the key in the config array.
* @param mixed $default value to be default if $key is not set in config.
*
* @return mixed value as $config[$key] or $default.
*/
function getConfig($key, $default)
{
global $config;
return isset($config[$key])
? $config[$key]
: $default;
}
/**
* Log when verbose mode, when used without argument it returns the result.
*
* @param string $msg to log.
*
* @return void or array.
*/
function verbose($msg = null)
{
global $verbose, $verboseFile;
static $log = array();
if (!($verbose || $verboseFile)) {
return;
}
if (is_null($msg)) {
return $log;
}
$log[] = $msg;
}
/**
* Log when verbose mode, when used without argument it returns the result.
*
* @param string $msg to log.
*
* @return void or array.
*/
function checkExternalCommand($what, $enabled, $commandString)
{
$no = $enabled ? null : 'NOT';
$text = "Post processing $what is $no enabled.<br>";
list($command) = explode(" ", $commandString);
$no = is_executable($command) ? null : 'NOT';
$text .= "The command for $what is $no an executable.<br>";
return $text;
}

View File

@@ -2,7 +2,7 @@
echo 'Current PHP version: ' . phpversion() . '<br><br>'; echo 'Current PHP version: ' . phpversion() . '<br><br>';
echo 'Running on: ' . $_SERVER['SERVER_SOFTWARE'] . '<br><br>'; echo 'Running on: ' . htmlentities($_SERVER['SERVER_SOFTWARE']) . '<br><br>';
$no = extension_loaded('exif') ? null : 'NOT'; $no = extension_loaded('exif') ? null : 'NOT';
echo "Extension exif is $no loaded.<br>"; echo "Extension exif is $no loaded.<br>";
@@ -15,13 +15,15 @@ echo "Extension imagick is $no loaded.<br>";
$no = extension_loaded('gd') ? null : 'NOT'; $no = extension_loaded('gd') ? null : 'NOT';
echo "Extension gd is $no loaded.<br>"; echo "Extension gd is $no loaded.<br>";
if (!$no) { if (!$no) {
echo "<pre>", var_dump(gd_info()), "</pre>"; echo "<pre>", var_dump(gd_info()), "</pre>";
} }
echo "<strong>Checking path for postprocessing tools</strong>"; echo "<strong>Checking path for postprocessing tools</strong>";
echo "<br>pngquant: ";
system("which pngquant");
echo "<br>optipng: "; echo "<br>optipng: ";
system("which optipng"); system("which optipng");

View File

@@ -8,52 +8,6 @@
* *
*/ */
$version = "v0.7.9 (2015-12-07)";
// For CRemoteImage
define("CIMAGE_USER_AGENT", "CImage/$version");
/**
* Display error message.
*
* @param string $msg to display.
* @param int $type of HTTP error to display.
*
* @return void
*/
function errorPage($msg, $type = 500)
{
global $mode;
switch ($type) {
case 403:
$header = "403 Forbidden";
break;
case 404:
$header = "404 Not Found";
break;
default:
$header = "500 Internal Server Error";
}
header("HTTP/1.0 $header");
if ($mode == "development") {
die("[img.php] $msg");
}
if ($mode == "strict") {
$header = "404 Not Found";
}
error_log("[img.php] $msg");
die("HTTP/1.0 $header");
}
/** /**
* Custom exception handler. * Custom exception handler.
*/ */
@@ -70,89 +24,6 @@ set_exception_handler(function ($exception) {
/**
* Get input from query string or return default value if not set.
*
* @param mixed $key as string or array of string values to look for in $_GET.
* @param mixed $default value to return when $key is not set in $_GET.
*
* @return mixed value from $_GET or default value.
*/
function get($key, $default = null)
{
if (is_array($key)) {
foreach ($key as $val) {
if (isset($_GET[$val])) {
return $_GET[$val];
}
}
} elseif (isset($_GET[$key])) {
return $_GET[$key];
}
return $default;
}
/**
* Get input from query string and set to $defined if defined or else $undefined.
*
* @param mixed $key as string or array of string values to look for in $_GET.
* @param mixed $defined value to return when $key is set in $_GET.
* @param mixed $undefined value to return when $key is not set in $_GET.
*
* @return mixed value as $defined or $undefined.
*/
function getDefined($key, $defined, $undefined)
{
return get($key) === null ? $undefined : $defined;
}
/**
* Get value from config array or default if key is not set in config array.
*
* @param string $key the key in the config array.
* @param mixed $default value to be default if $key is not set in config.
*
* @return mixed value as $config[$key] or $default.
*/
function getConfig($key, $default)
{
global $config;
return isset($config[$key])
? $config[$key]
: $default;
}
/**
* Log when verbose mode, when used without argument it returns the result.
*
* @param string $msg to log.
*
* @return void or array.
*/
function verbose($msg = null)
{
global $verbose, $verboseFile;
static $log = array();
if (!($verbose || $verboseFile)) {
return;
}
if (is_null($msg)) {
return $log;
}
$log[] = $msg;
}
/** /**
* Get configuration options from file, if the file exists, else use $config * Get configuration options from file, if the file exists, else use $config
* if its defined or create an empty $config. * if its defined or create an empty $config.
@@ -165,6 +36,24 @@ if (is_file($configFile)) {
$config = array(); $config = array();
} }
// Make CIMAGE_DEBUG false by default, if not already defined
if (!defined("CIMAGE_DEBUG")) {
define("CIMAGE_DEBUG", false);
}
/**
* Setup the autoloader, but not when using a bundle.
*/
if (!defined("CIMAGE_BUNDLE")) {
if (!isset($config["autoloader"])) {
die("CImage: Missing autoloader.");
}
require $config["autoloader"];
}
/** /**
@@ -173,7 +62,7 @@ if (is_file($configFile)) {
*/ */
$verbose = getDefined(array('verbose', 'v'), true, false); $verbose = getDefined(array('verbose', 'v'), true, false);
$verboseFile = getDefined('vf', true, false); $verboseFile = getDefined('vf', true, false);
verbose("img.php version = $version"); verbose("img.php version = " . CIMAGE_VERSION);
@@ -331,24 +220,11 @@ verbose("referer host = $refererHost");
/**
* Get the source files.
*/
$autoloader = getConfig('autoloader', false);
$cimageClass = getConfig('cimage_class', false);
if ($autoloader) {
require $autoloader;
} elseif ($cimageClass) {
require $cimageClass;
}
/** /**
* Create the class for the image. * Create the class for the image.
*/ */
$img = new CImage(); $CImage = getConfig('CImage', 'CImage');
$img = new $CImage();
$img->setVerbose($verbose || $verboseFile); $img->setVerbose($verbose || $verboseFile);
@@ -356,12 +232,49 @@ $img->setVerbose($verbose || $verboseFile);
/** /**
* Get the cachepath from config. * Get the cachepath from config.
*/ */
$CCache = getConfig('CCache', 'CCache');
$cachePath = getConfig('cache_path', __DIR__ . '/../cache/'); $cachePath = getConfig('cache_path', __DIR__ . '/../cache/');
$cache = new CCache(); $cache = new $CCache();
$cache->setDir($cachePath); $cache->setDir($cachePath);
/**
* no-cache, nc - skip the cached version and process and create a new version in cache.
*/
$useCache = getDefined(array('no-cache', 'nc'), false, true);
verbose("use cache = $useCache");
/**
* Prepare fast track cache for swriting cache items.
*/
$fastTrackCache = "fasttrack";
$allowFastTrackCache = getConfig('fast_track_allow', false);
$CFastTrackCache = getConfig('CFastTrackCache', 'CFastTrackCache');
$ftc = new $CFastTrackCache();
$ftc->setCacheDir($cache->getPathToSubdir($fastTrackCache))
->enable($allowFastTrackCache)
->setFilename(array('no-cache', 'nc'));
$img->injectDependency("fastTrackCache", $ftc);
/**
* Load and output images from fast track cache, if items are available
* in cache.
*/
if ($useCache && $allowFastTrackCache) {
if (CIMAGE_DEBUG) {
trace("img.php fast track cache enabled and used");
}
$ftc->output();
}
/** /**
* Allow or disallow remote download of images from other servers. * Allow or disallow remote download of images from other servers.
@@ -409,18 +322,28 @@ if (isset($shortcut)
$srcImage = urldecode(get('src')) $srcImage = urldecode(get('src'))
or errorPage('Must set src-attribute.', 404); or errorPage('Must set src-attribute.', 404);
// Get settings for src-alt as backup image
$srcAltImage = urldecode(get('src-alt', null));
$srcAltConfig = getConfig('src_alt', null);
if (empty($srcAltImage)) {
$srcAltImage = $srcAltConfig;
}
// Check for valid/invalid characters // Check for valid/invalid characters
$imagePath = getConfig('image_path', __DIR__ . '/img/'); $imagePath = getConfig('image_path', __DIR__ . '/img/');
$imagePathConstraint = getConfig('image_path_constraint', true); $imagePathConstraint = getConfig('image_path_constraint', true);
$validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#'); $validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#');
// Source is remote
$remoteSource = false;
// Dummy image feature // Dummy image feature
$dummyEnabled = getConfig('dummy_enabled', true); $dummyEnabled = getConfig('dummy_enabled', true);
$dummyFilename = getConfig('dummy_filename', 'dummy'); $dummyFilename = getConfig('dummy_filename', 'dummy');
$dummyImage = false; $dummyImage = false;
preg_match($validFilename, $srcImage) preg_match($validFilename, $srcImage)
or errorPage('Filename contains invalid characters.', 404); or errorPage('Source filename contains invalid characters.', 404);
if ($dummyEnabled && $srcImage === $dummyFilename) { if ($dummyEnabled && $srcImage === $dummyFilename) {
@@ -430,19 +353,40 @@ if ($dummyEnabled && $srcImage === $dummyFilename) {
} elseif ($allowRemote && $img->isRemoteSource($srcImage)) { } elseif ($allowRemote && $img->isRemoteSource($srcImage)) {
// If source is a remote file, ignore local file checks. // If source is a remote file, ignore local file checks.
$remoteSource = true;
} elseif ($imagePathConstraint) { } else {
// Check that the image is a file below the directory 'image_path'. // Check if file exists on disk or try using src-alt
$pathToImage = realpath($imagePath . $srcImage); $pathToImage = realpath($imagePath . $srcImage);
$imageDir = realpath($imagePath);
if (!is_file($pathToImage) && !empty($srcAltImage)) {
// Try using the src-alt instead
$srcImage = $srcAltImage;
$pathToImage = realpath($imagePath . $srcImage);
preg_match($validFilename, $srcImage)
or errorPage('Source (alt) filename contains invalid characters.', 404);
if ($dummyEnabled && $srcImage === $dummyFilename) {
// Check if src-alt is the dummy image
$dummyImage = true;
}
}
if (!$dummyImage) {
is_file($pathToImage) is_file($pathToImage)
or errorPage( or errorPage(
'Source image is not a valid file, check the filename and that a 'Source image is not a valid file, check the filename and that a
matching file exists on the filesystem.', matching file exists on the filesystem.',
404 404
); );
}
}
if ($imagePathConstraint && !$dummyImage && !$remoteSource) {
// Check that the image is a file below the directory 'image_path'.
$imageDir = realpath($imagePath);
substr_compare($imageDir, $pathToImage, 0, strlen($imageDir)) == 0 substr_compare($imageDir, $pathToImage, 0, strlen($imageDir)) == 0
or errorPage( or errorPage(
@@ -668,23 +612,14 @@ $useOriginal = getDefined(array('skip-original', 'so'), false, true);
$useOriginalDefault = getConfig('skip_original', false); $useOriginalDefault = getConfig('skip_original', false);
if ($useOriginalDefault === true) { if ($useOriginalDefault === true) {
verbose("use original is default ON"); verbose("skip original is default ON");
$useOriginal = true; $useOriginal = false;
} }
verbose("use original = $useOriginal"); verbose("use original = $useOriginal");
/**
* no-cache, nc - skip the cached version and process and create a new version in cache.
*/
$useCache = getDefined(array('no-cache', 'nc'), false, true);
verbose("use cache = $useCache");
/** /**
* quality, q - set level of quality for jpeg images * quality, q - set level of quality for jpeg images
*/ */
@@ -921,6 +856,9 @@ verbose("upscale = $upscale");
* Get details for post processing * Get details for post processing
*/ */
$postProcessing = getConfig('postprocessing', array( $postProcessing = getConfig('postprocessing', array(
'png_lossy' => false,
'png_lossy_cmd' => '/usr/local/bin/pngquant --force --output',
'png_filter' => false, 'png_filter' => false,
'png_filter_cmd' => '/usr/local/bin/optipng -q', 'png_filter_cmd' => '/usr/local/bin/optipng -q',
@@ -933,6 +871,15 @@ $postProcessing = getConfig('postprocessing', array(
/**
* lossy - Do lossy postprocessing, if available.
*/
$lossy = getDefined(array('lossy'), true, null);
verbose("lossy = $lossy");
/** /**
* alias - Save resulting image to another alias name. * alias - Save resulting image to another alias name.
* Password always apply, must be defined. * Password always apply, must be defined.
@@ -1034,7 +981,7 @@ if ($srgb || $srgbDefault) {
* Display status * Display status
*/ */
if ($status) { if ($status) {
$text = "img.php version = $version\n"; $text = "img.php version = " . CIMAGE_VERSION . "\n";
$text .= "PHP version = " . PHP_VERSION . "\n"; $text .= "PHP version = " . PHP_VERSION . "\n";
$text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n"; $text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n";
$text .= "Allow remote images = $allowRemote\n"; $text .= "Allow remote images = $allowRemote\n";
@@ -1051,6 +998,9 @@ if ($status) {
$res = $cache->getStatusOfSubdir("srgb"); $res = $cache->getStatusOfSubdir("srgb");
$text .= "Cache srgb $res\n"; $text .= "Cache srgb $res\n";
$res = $cache->getStatusOfSubdir($fastTrackCache);
$text .= "Cache fasttrack $res\n";
$text .= "Alias path writable = " . is_writable($aliasPath) . "\n"; $text .= "Alias path writable = " . is_writable($aliasPath) . "\n";
$no = extension_loaded('exif') ? null : 'NOT'; $no = extension_loaded('exif') ? null : 'NOT';
@@ -1065,6 +1015,11 @@ if ($status) {
$no = extension_loaded('gd') ? null : 'NOT'; $no = extension_loaded('gd') ? null : 'NOT';
$text .= "Extension gd is $no loaded.<br>"; $text .= "Extension gd is $no loaded.<br>";
$text .= checkExternalCommand("PNG LOSSY", $postProcessing["png_lossy"], $postProcessing["png_lossy_cmd"]);
$text .= checkExternalCommand("PNG FILTER", $postProcessing["png_filter"], $postProcessing["png_filter_cmd"]);
$text .= checkExternalCommand("PNG DEFLATE", $postProcessing["png_deflate"], $postProcessing["png_deflate_cmd"]);
$text .= checkExternalCommand("JPEG OPTIMIZE", $postProcessing["jpeg_optimize"], $postProcessing["jpeg_optimize_cmd"]);
if (!$no) { if (!$no) {
$text .= print_r(gd_info(), 1); $text .= print_r(gd_info(), 1);
} }
@@ -1133,6 +1088,7 @@ if (is_callable($hookBeforeCImage)) {
// Other // Other
'postProcessing' => $postProcessing, 'postProcessing' => $postProcessing,
'lossy' => $lossy,
)); ));
verbose(print_r($allConfig, 1)); verbose(print_r($allConfig, 1));
extract($allConfig); extract($allConfig);
@@ -1217,6 +1173,9 @@ $img->log("Incoming arguments: " . print_r(verbose(), 1))
// Output format // Output format
'outputFormat' => $outputFormat, 'outputFormat' => $outputFormat,
'dpr' => $dpr, 'dpr' => $dpr,
// Postprocessing using external tools
'lossy' => $lossy,
) )
) )
->loadImageDetails() ->loadImageDetails()

BIN
webroot/img/apple.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
webroot/img/duke.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

BIN
webroot/img/lena.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

BIN
webroot/img/lena.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

BIN
webroot/img/lena.tif Normal file

Binary file not shown.

BIN
webroot/img/lena.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
webroot/img/planet.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
webroot/img/webp/1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -5,11 +5,38 @@
* config-file imgtest_config.php. * config-file imgtest_config.php.
* *
*/ */
/**
* Change to true to enable debug mode which logs additional information
* to file. Only use for test and development. You must create the logfile
* and make it writable by the webserver or log entries will silently fail.
*
* CIMAGE_DEBUG will be false by default, if its not defined.
*/
if (!defined("CIMAGE_DEBUG")) {
define("CIMAGE_DEBUG", false);
//define("CIMAGE_DEBUG", true);
define("CIMAGE_DEBUG_FILE", "/tmp/cimage");
}
return array( return array(
/** /**
* Set mode as 'strict', 'production' or 'development'. * Set mode as 'strict', 'production' or 'development'.
* *
* development: Development mode with verbose error reporting. Option
* &verbose and &status enabled.
* production: Production mode logs all errors to file, giving server
* error 500 for bad usage. Option &verbose and &status
* disabled.
* strict: Strict mode logs few errors to file, giving server error
* 500 for bad usage. Stripped from comments and spaces.
* Option &verbose and &status disabled.
*
* Default values: * Default values:
* mode: 'production' * mode: 'production'
*/ */
@@ -20,14 +47,12 @@ return array(
/** /**
* Where are the sources for the classfiles. * Where to find the autoloader.
* *
* Default values: * Default values:
* autoloader: null // used from v0.6.2 * autoloader: null
* cimage_class: null // used until v0.6.1
*/ */
'autoloader' => __DIR__ . '/../autoload.php', 'autoloader' => __DIR__ . '/../autoload.php',
//'cimage_class' => __DIR__ . '/../CImage.php',
@@ -46,6 +71,34 @@ return array(
/**
* Fast track cache. Save a json representation of the image as a
* fast track to the cached version of the image. This avoids some
* processing and allows for quicker load times of cached images.
*
* Default values:
* fast_track_allow: false
*/
//'fast_track_allow' => true,
/**
* Class names to use, to ease dependency injection. You can change Class
* name if you want to use your own class instead. This is a way to extend
* the codebase.
*
* Default values:
* CImage: CImage
* CCache: CCache
* CFastTrackCache: CFastTrackCache
*/
//'CImage' => 'CImage',
//'CCache' => 'CCache',
//'CFastTrackCache' => 'CFastTrackCache',
/** /**
* Use password to protect from missusage, send &pwd=... or &password=.. * Use password to protect from missusage, send &pwd=... or &password=..
* with the request to match the password or set to false to disable. * with the request to match the password or set to false to disable.
@@ -98,6 +151,20 @@ return array(
/**
* Use backup image if src-image is not found on disk. The backup image
* is only available for local images and based on wether the original
* image is found on disk or not. The backup image must be a local image
* or the dummy image.
*
* Default value:
* src_alt: null //disabled by default
*/
//'src_alt' => 'car.png',
//'src_alt' => 'dummy',
/** /**
* A regexp for validating characters in the image or alias filename. * A regexp for validating characters in the image or alias filename.
* *
@@ -139,6 +206,18 @@ return array(
/**
* Set skip-original to true to always process the image and use
* the cached version. Default is false and to use the original
* image when its no processing needed.
*
* Default value:
* skip_original: false
*/
//'skip_original' => true,
/** /**
* A function (hook) can be called after img.php has processed all * A function (hook) can be called after img.php has processed all
* configuration options and before processing the image using CImage. * configuration options and before processing the image using CImage.
@@ -188,7 +267,8 @@ return array(
/** /**
* Check that the imagefile is a file below 'image_path' using realpath(). * Check that the imagefile is a file below 'image_path' using realpath().
* Security constraint to avoid reaching images outside image_path. * Security constraint to avoid reaching images outside image_path.
* This means that symbolic links to images outside the image_path will fail. * This means that symbolic links to images outside the image_path will
* fail.
* *
* Default value: * Default value:
* image_path_constraint: true * image_path_constraint: true
@@ -241,8 +321,16 @@ return array(
* Post processing of images using external tools, set to true or false * Post processing of images using external tools, set to true or false
* and set command to be executed. * and set command to be executed.
* *
* The png_lossy can alos have a value of null which means that its
* enabled but not used as default. Each image having the option
* &lossy will be processed. This means one can individually choose
* when to use the lossy processing.
*
* Default values. * Default values.
* *
* png_lossy: false
* png_lossy_cmd: '/usr/local/bin/pngquant --force --output'
*
* png_filter: false * png_filter: false
* png_filter_cmd: '/usr/local/bin/optipng -q' * png_filter_cmd: '/usr/local/bin/optipng -q'
* *
@@ -254,6 +342,9 @@ return array(
*/ */
/* /*
'postprocessing' => array( 'postprocessing' => array(
'png_lossy' => null,
'png_lossy_cmd' => '/usr/local/bin/pngquant --force --output',
'png_filter' => false, 'png_filter' => false,
'png_filter_cmd' => '/usr/local/bin/optipng -q', 'png_filter_cmd' => '/usr/local/bin/optipng -q',
@@ -379,7 +470,7 @@ return array(
/** /**
* default options for ascii image. * Default options for ascii image.
* *
* Default values as specified below in the array. * Default values as specified below in the array.
* ascii-options: * ascii-options:

View File

@@ -10,6 +10,7 @@
* @link https://github.com/mosbth/cimage * @link https://github.com/mosbth/cimage
* *
*/ */
define("CIMAGE_BUNDLE", true);
/** /**

File diff suppressed because it is too large Load Diff

91
webroot/imgf.php Normal file
View File

@@ -0,0 +1,91 @@
<?php
/**
* Fast track cache, read entries from the cache before processing image
* the ordinary way.
*/
// Load the config file or use defaults
$configFile = __DIR__
. "/"
. basename(__FILE__, ".php")
. "_config.php";
if (is_file($configFile) && is_readable($configFile)) {
$config = require $configFile;
} elseif (!isset($config)) {
$config = array(
"fast_track_allow" => true,
"autoloader" => __DIR__ . "/../autoload.php",
"cache_path" => __DIR__ . "/../cache/",
);
}
// Make CIMAGE_DEBUG false by default, if not already defined
if (!defined("CIMAGE_DEBUG")) {
define("CIMAGE_DEBUG", false);
}
// Debug mode needs additional functions
if (CIMAGE_DEBUG) {
require $config["autoloader"];
}
// Cache path must be valid
$cacheIsReadable = is_dir($config["cache_path"]) && is_readable($config["cache_path"]);
if (!$cacheIsReadable) {
die("imgf.php: Cache is not readable, check path in configfile.");
}
// Prepare to check if fast cache should be used
$cachePath = $config["cache_path"] . "/fasttrack";
$query = $_GET;
// Do not use cache when no-cache is active
$useCache = !(array_key_exists("no-cache", $query) || array_key_exists("nc", $query));
// Only use cache if enabled by configuration
$useCache = $useCache && isset($config["fast_track_allow"]) && $config["fast_track_allow"] === true;
// Remove parts from querystring that should not be part of filename
$clear = array("nc", "no-cache");
foreach ($clear as $value) {
unset($query[$value]);
}
// Create the cache filename
arsort($query);
$queryAsString = http_build_query($query);
$filename = md5($queryAsString);
$filename = "$cachePath/$filename";
// Check cached item, if any
if ($useCache && is_readable($filename)) {
$item = json_decode(file_get_contents($filename), true);
if (is_readable($item["source"])) {
foreach ($item["header"] as $value) {
header($value);
}
if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])
&& strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]) == $item["last-modified"]) {
header("HTTP/1.0 304 Not Modified");
if (CIMAGE_DEBUG) {
trace("imgf 304");
}
exit;
}
foreach ($item["header-output"] as $value) {
header($value);
}
if (CIMAGE_DEBUG) {
trace("imgf 200");
}
readfile($item["source"]);
exit;
}
}
// No fast track cache, proceed as usual
include __DIR__ . "/img.php";

1
webroot/imgf_config.php Symbolic link
View File

@@ -0,0 +1 @@
img_config.php

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -17,12 +17,13 @@ $description = "Do not upscale image when original image (slice) is smaller than
// Use these images in the test // Use these images in the test
$images = array( $images = array(
'car.png', 'car.png',
'apple.jpg',
); );
// For each image, apply these testcases // For each image, apply these testcases
$nc = null; //"&nc"; //null; //&nc'; $nc = "&bgc=660000"; //null; //"&nc"; //null; //&nc';
$testcase = array( $testcase = array(
$nc . '&w=600', $nc . '&w=600',
$nc . '&w=600&no-upscale', $nc . '&w=600&no-upscale',
@@ -34,16 +35,20 @@ $testcase = array(
$nc . '&w=700&h=400&no-upscale&stretch', $nc . '&w=700&h=400&no-upscale&stretch',
$nc . '&w=700&h=200&stretch', $nc . '&w=700&h=200&stretch',
$nc . '&w=700&h=200&no-upscale&stretch', $nc . '&w=700&h=200&no-upscale&stretch',
$nc . '&w=300&h=400&stretch', $nc . '&w=250&h=400&stretch',
$nc . '&w=300&h=400&no-upscale&stretch', $nc . '&w=250&h=400&no-upscale&stretch',
$nc . '&w=600&h=400&crop-to-fit', $nc . '&w=700&h=400&crop-to-fit',
$nc . '&w=600&h=400&no-upscale&crop-to-fit', $nc . '&w=700&h=400&no-upscale&crop-to-fit',
$nc . '&w=600&h=200&crop-to-fit', $nc . '&w=700&h=200&crop-to-fit',
$nc . '&w=600&h=200&no-upscale&crop-to-fit', $nc . '&w=700&h=200&no-upscale&crop-to-fit',
$nc . '&w=300&h=400&crop-to-fit', $nc . '&w=250&h=400&crop-to-fit',
$nc . '&w=300&h=400&no-upscale&crop-to-fit', $nc . '&w=250&h=400&no-upscale&crop-to-fit',
$nc . '&w=600&h=400&fill-to-fit', $nc . '&w=600&h=500&fill-to-fit',
$nc . '&w=600&h=400&no-upscale&fill-to-fit', $nc . '&w=600&h=500&no-upscale&fill-to-fit',
$nc . '&w=250&h=400&fill-to-fit',
$nc . '&w=250&h=400&no-upscale&fill-to-fit',
$nc . '&w=700&h=400&fill-to-fit',
$nc . '&w=700&h=400&no-upscale&fill-to-fit',
/* /*
$nc . '&w=600&ar=1.6', $nc . '&w=600&ar=1.6',
$nc . '&w=600&ar=1.6&no-upscale', $nc . '&w=600&ar=1.6&no-upscale',