mirror of
https://github.com/mosbth/cimage.git
synced 2025-07-22 17:21:36 +02:00
merged with master
This commit is contained in:
37
README.md
37
README.md
@@ -13,7 +13,7 @@ Image conversion on the fly using PHP
|
||||
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.
|
||||
|
||||
@@ -27,7 +27,10 @@ Documentation
|
||||
--------------------------------------
|
||||
|
||||
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).
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -51,14 +54,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.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.
|
||||
|
||||
```bash
|
||||
git clone git://github.com/mosbth/cimage.git
|
||||
cd cimage
|
||||
git checkout v0.7.9
|
||||
git checkout v0.7.18
|
||||
```
|
||||
|
||||
Make the cache-directory writable by the webserver.
|
||||
@@ -81,7 +84,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://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.
|
||||
@@ -103,7 +106,7 @@ Lets take some use cases to let you know when and how `img.php` might be useful.
|
||||
|
||||
### 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.
|
||||
|
||||
@@ -117,7 +120,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.
|
||||
|
||||
<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.
|
||||
|
||||
@@ -130,7 +133,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`
|
||||
> `&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.
|
||||
|
||||
@@ -149,7 +152,7 @@ Try it out by pointing your browser to the test file `webroot/test/test.php`. It
|
||||
|
||||
###Process your first image
|
||||
|
||||
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim04.png&w=w2&a=40,0,50,0" alt=''>
|
||||
<img src="https://cimage.se/cimage/imgd.php?src=example/kodim04.png&w=w2&a=40,0,50,0" alt=''>
|
||||
|
||||
Try it yourself by opening up an image in your browser. Start with
|
||||
|
||||
@@ -203,7 +206,7 @@ Open an image through `img.php` by using its `src` attribute.
|
||||
|
||||
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:
|
||||
|
||||
@@ -217,7 +220,7 @@ Create a thumbnail of the image by applying constraints on width and height, or
|
||||
|
||||
| `&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.
|
||||
|
||||
@@ -232,10 +235,10 @@ Creating a thumbnail with a certain dimension of width and height, usually invol
|
||||
|
||||
| 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=''> |
|
||||
| **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=''> |
|
||||
| **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=''> |
|
||||
| **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=''> |
|
||||
| **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=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=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=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.
|
||||
|
||||
@@ -252,7 +255,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`
|
||||
> `&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.
|
||||
|
||||
@@ -435,7 +438,7 @@ For example, the following image is created like this:
|
||||
|
||||
> `&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:
|
||||
|
||||
|
75
REVISION.md
75
REVISION.md
@@ -18,6 +18,81 @@ v0.7.9* (2015-12-07)
|
||||
* Fix strict mode only reporting 404 when failure, #127.
|
||||
|
||||
|
||||
v0.7.19* (2016-08-31)
|
||||
-------------------------------------
|
||||
|
||||
* 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)
|
||||
-------------------------------------
|
||||
|
||||
|
@@ -34,12 +34,15 @@ fi
|
||||
$ECHO "Creating '$TARGET_D', '$TARGET_P' and '$TARGET_S' by combining the following files:"
|
||||
$ECHO "\n"
|
||||
$ECHO "\n webroot/img_header.php"
|
||||
$ECHO "\n defines.php"
|
||||
$ECHO "\n functions.php"
|
||||
$ECHO "\n CHttpGet.php"
|
||||
$ECHO "\n CRemoteImage.php"
|
||||
$ECHO "\n CWhitelist.php"
|
||||
$ECHO "\n CAsciiArt.php"
|
||||
$ECHO "\n CImage.php"
|
||||
$ECHO "\n CCache.php"
|
||||
$ECHO "\n CFastTrackCache.php"
|
||||
$ECHO "\n webroot/img.php"
|
||||
$ECHO "\n"
|
||||
$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
|
||||
|
||||
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
|
||||
$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
|
||||
$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
|
||||
$ECHO "$NEWLINES" | tee -a $TARGET_D $TARGET_P $TARGET_S > /dev/null
|
||||
|
||||
|
4
cache/.gitignore
vendored
Normal file
4
cache/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
0
cache/README.md
vendored
0
cache/README.md
vendored
@@ -3,7 +3,7 @@
|
||||
"type": "library",
|
||||
"description": "Serverside image processing with PHP GD. Process, scale, resize, crop and filter images.",
|
||||
"keywords": ["image", "imageprocessing", "gd", "crop", "resize"],
|
||||
"homepage": "http://dbwebb.se/opensource/cimage",
|
||||
"homepage": "https://cimage.se/",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
@@ -16,14 +16,16 @@
|
||||
"support": {
|
||||
"source": "https://github.com/mosbth/cimage",
|
||||
"issues": "https://github.com/mosbth/cimage/issues",
|
||||
"docs": "http://dbwebb.se/opensource/cimage"
|
||||
"docs": "https://cimage.se/doc"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4",
|
||||
"ext-gd": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-exif": "*"
|
||||
"ext-exif": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-imagick": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "5.3.*",
|
||||
@@ -34,6 +36,12 @@
|
||||
"phpdocumentor/phpdocumentor": "2.*"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [ "src/CImage/" ]
|
||||
"psr-4": {
|
||||
"Mos\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/defines.php",
|
||||
"src/functions.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,18 @@
|
||||
* Autoloader for CImage and related class files.
|
||||
*
|
||||
*/
|
||||
require_once __DIR__ . "/defines.php";
|
||||
require_once __DIR__ . "/functions.php";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Autoloader for classes.
|
||||
*
|
||||
* @param string $class the fully-qualified class name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
spl_autoload_register(function ($class) {
|
||||
$path = __DIR__ . "/src/CImage/{$class}.php";
|
||||
if (is_file($path)) {
|
238
src/CImage/CFastTrackCache.php
Normal file
238
src/CImage/CFastTrackCache.php
Normal 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;
|
||||
}
|
||||
}
|
@@ -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
|
||||
*/
|
||||
@@ -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 $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 $pngDeflateCmd;
|
||||
@@ -380,6 +395,12 @@ class CImage
|
||||
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
|
||||
@@ -454,6 +475,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.
|
||||
*
|
||||
@@ -623,7 +663,7 @@ class CImage
|
||||
*/
|
||||
private function checkFileExtension($extension)
|
||||
{
|
||||
$valid = array('jpg', 'jpeg', 'png', 'gif');
|
||||
$valid = array('jpg', 'jpeg', 'png', 'gif', 'webp');
|
||||
|
||||
in_array(strtolower($extension), $valid)
|
||||
or $this->raiseError('Not a valid file extension.');
|
||||
@@ -810,6 +850,9 @@ class CImage
|
||||
// Output format
|
||||
'outputFormat' => null,
|
||||
'dpr' => 1,
|
||||
|
||||
// Postprocessing using external tools
|
||||
'lossy' => null,
|
||||
);
|
||||
|
||||
// Convert crop settings from string to array
|
||||
@@ -924,10 +967,27 @@ class CImage
|
||||
is_readable($file)
|
||||
or $this->raiseError('Image file does not exist.');
|
||||
|
||||
// Get details on image
|
||||
$info = list($this->width, $this->height, $this->fileType, $this->attr) = getimagesize($file);
|
||||
$info = list($this->width, $this->height, $this->fileType) = getimagesize($file);
|
||||
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.");
|
||||
}
|
||||
|
||||
$this->imageResizer->setSource($this->width, $this->height);
|
||||
@@ -936,7 +996,7 @@ class CImage
|
||||
$this->log("#Loading image details for: {$file}");
|
||||
$this->log(" Image width x height (type): {$this->width} x {$this->height} ({$this->fileType}).");
|
||||
$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;
|
||||
@@ -944,6 +1004,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 anyprocessing can be done.
|
||||
@@ -1077,8 +1154,14 @@ class CImage
|
||||
$this->newWidth = round($factor * $width);
|
||||
$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.
|
||||
if ($this->cropToFit || $this->fillToFit) {
|
||||
|
||||
@@ -1255,6 +1338,7 @@ class CImage
|
||||
&& !$this->autoRotate
|
||||
&& !$this->bgColor
|
||||
&& ($this->upscale === self::UPSCALE_DEFAULT)
|
||||
&& !$this->lossy
|
||||
) {
|
||||
$this->log("Using original image.");
|
||||
$this->output($this->pathToImage);
|
||||
@@ -1289,6 +1373,7 @@ class CImage
|
||||
$compress = $this->compress ? "_co{$this->compress}" : null;
|
||||
$rotateBefore = $this->rotateBefore ? "_rb{$this->rotateBefore}" : null;
|
||||
$rotateAfter = $this->rotateAfter ? "_ra{$this->rotateAfter}" : null;
|
||||
$lossy = $this->lossy ? "_l" : null;
|
||||
|
||||
$saveAs = $this->normalizeFileExtension();
|
||||
$saveAs = $saveAs ? "_$saveAs" : null;
|
||||
@@ -1355,7 +1440,7 @@ class CImage
|
||||
. $quality . $filters . $sharpen . $emboss . $blur . $palette
|
||||
. $optimize . $compress
|
||||
. $scale . $rotateBefore . $rotateAfter . $autoRotate . $bgColor
|
||||
. $convolve . $copyStrat . $saveAs;
|
||||
. $convolve . $copyStrat . $lossy . $saveAs;
|
||||
|
||||
return $this->setTarget($file, $base);
|
||||
}
|
||||
@@ -1412,9 +1497,14 @@ class CImage
|
||||
$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) {
|
||||
throw new Exception("Could not load image.");
|
||||
}
|
||||
@@ -1692,25 +1782,41 @@ class CImage
|
||||
// Resize by 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.");
|
||||
|
||||
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
|
||||
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
|
||||
|
||||
$posX = 0;
|
||||
$posY = 0;
|
||||
$cropX = 0;
|
||||
$cropY = 0;
|
||||
|
||||
if ($this->newWidth > $this->width) {
|
||||
$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) {
|
||||
$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);
|
||||
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 {
|
||||
$cropX = $imgres->getCropX();
|
||||
$cropY = $imgres->getCropY();
|
||||
@@ -1753,14 +1859,14 @@ class CImage
|
||||
}
|
||||
|
||||
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.");
|
||||
$posX = round(($this->fillWidth - $this->width) / 2);
|
||||
$posY = round(($this->fillHeight - $this->height) / 2);
|
||||
$posX = round(($this->newWidth - $this->width) / 2);
|
||||
$posY = round(($this->newHeight - $this->height) / 2);
|
||||
$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 {
|
||||
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
|
||||
@@ -1802,9 +1908,8 @@ class CImage
|
||||
$cropX = round(($this->width - $this->newWidth) / 2);
|
||||
}
|
||||
|
||||
//$this->log("posX=$posX, posY=$posY, cropX=$cropX, cropY=$cropY.");
|
||||
$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->width = $this->newWidth;
|
||||
$this->height = $this->newHeight;
|
||||
@@ -2266,6 +2371,14 @@ class CImage
|
||||
$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']) {
|
||||
$this->pngFilterCmd = $options['png_filter_cmd'];
|
||||
} else {
|
||||
@@ -2293,9 +2406,11 @@ class CImage
|
||||
// switch on mimetype
|
||||
if (isset($this->extension)) {
|
||||
return strtolower($this->extension);
|
||||
} else {
|
||||
return substr(image_type_to_extension($this->fileType), 1);
|
||||
} elseif ($this->fileType === IMG_WEBP) {
|
||||
return "webp";
|
||||
}
|
||||
|
||||
return substr(image_type_to_extension($this->fileType), 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -2351,6 +2466,11 @@ class CImage
|
||||
imagegif($this->image, $this->cacheFileName);
|
||||
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':
|
||||
default:
|
||||
$this->Log("Saving image as PNG to cache using compression = {$this->compress}.");
|
||||
@@ -2360,6 +2480,24 @@ class CImage
|
||||
imagesavealpha($this->image, true);
|
||||
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
|
||||
if ($this->pngFilterCmd) {
|
||||
if ($this->verbose) {
|
||||
@@ -2505,7 +2643,7 @@ class CImage
|
||||
|
||||
|
||||
/**
|
||||
* Add HTTP header for outputting together with image.
|
||||
* Add HTTP header for output together with image.
|
||||
*
|
||||
* @param string $type the header type such as "Cache-Control"
|
||||
* @param string $value the value to use
|
||||
@@ -2539,6 +2677,7 @@ class CImage
|
||||
$format = $this->outputFormat;
|
||||
}
|
||||
|
||||
$this->log("### Output");
|
||||
$this->log("Output format is: $format");
|
||||
|
||||
if (!$this->verbose && $format == 'json') {
|
||||
@@ -2556,17 +2695,24 @@ class CImage
|
||||
// Get image modification time
|
||||
clearstatcache();
|
||||
$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) {
|
||||
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) {
|
||||
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) {
|
||||
$this->log("304 not modified");
|
||||
@@ -2575,13 +2721,14 @@ class CImage
|
||||
}
|
||||
|
||||
header("HTTP/1.0 304 Not Modified");
|
||||
if (CIMAGE_DEBUG) {
|
||||
trace(__CLASS__ . " 304");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Get details on image
|
||||
$info = getimagesize($file);
|
||||
!empty($info) or $this->raiseError("The file doesn't seem to be an image.");
|
||||
$mime = $info['mime'];
|
||||
$this->loadImageDetails($file);
|
||||
$mime = $this->getMimeType();
|
||||
$size = filesize($file);
|
||||
|
||||
if ($this->verbose) {
|
||||
@@ -2595,8 +2742,19 @@ class CImage
|
||||
}
|
||||
}
|
||||
|
||||
header("Content-type: $mime");
|
||||
header("Content-length: $size");
|
||||
$header = "Content-type: $mime";
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2631,7 +2789,7 @@ class CImage
|
||||
$this->load($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['height'] = $this->height;
|
||||
$details['aspectRatio'] = round($this->width / $this->height, 3);
|
||||
@@ -2733,6 +2891,7 @@ class CImage
|
||||
private function verboseOutput()
|
||||
{
|
||||
$log = null;
|
||||
$this->log("### Summary of verbose log");
|
||||
$this->log("As JSON: \n" . $this->json());
|
||||
$this->log("Memory peak: " . round(memory_get_peak_usage() /1024/1024) . "M");
|
||||
$this->log("Memory limit: " . ini_get('memory_limit'));
|
||||
|
11
src/defines.php
Normal file
11
src/defines.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
// Version of cimage and img.php
|
||||
define("CIMAGE_VERSION", "v0.7.19* (2016-08-11)");
|
||||
|
||||
// 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);
|
||||
}
|
186
src/functions.php
Normal file
186
src/functions.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Custom exception handler.
|
||||
*/
|
||||
set_exception_handler(function ($exception) {
|
||||
errorPage(
|
||||
"<p><b>img.php: Uncaught exception:</b> <p>"
|
||||
. $exception->getMessage()
|
||||
. "</p><pre>"
|
||||
. $exception->getTraceAsString()
|
||||
. "</pre>",
|
||||
500
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
|
||||
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';
|
||||
echo "Extension exif is $no loaded.<br>";
|
||||
@@ -15,13 +15,15 @@ echo "Extension imagick is $no loaded.<br>";
|
||||
|
||||
$no = extension_loaded('gd') ? null : 'NOT';
|
||||
echo "Extension gd is $no loaded.<br>";
|
||||
|
||||
if (!$no) {
|
||||
echo "<pre>", var_dump(gd_info()), "</pre>";
|
||||
}
|
||||
|
||||
echo "<strong>Checking path for postprocessing tools</strong>";
|
||||
|
||||
echo "<br>pngquant: ";
|
||||
system("which pngquant");
|
||||
|
||||
echo "<br>optipng: ";
|
||||
system("which optipng");
|
||||
|
||||
|
314
webroot/img.php
314
webroot/img.php
@@ -8,151 +8,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
$version = "v0.8.0dev (2015-12-05)";
|
||||
|
||||
// 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";
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Custom exception handler.
|
||||
*/
|
||||
set_exception_handler(function ($exception) {
|
||||
errorPage(
|
||||
"<p><b>img.php: Uncaught exception:</b> <p>"
|
||||
. $exception->getMessage()
|
||||
. "</p><pre>"
|
||||
. $exception->getTraceAsString()
|
||||
. "</pre>",
|
||||
500
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* if its defined or create an empty $config.
|
||||
@@ -165,6 +20,24 @@ if (is_file($configFile)) {
|
||||
$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 +46,7 @@ if (is_file($configFile)) {
|
||||
*/
|
||||
$verbose = getDefined(array('verbose', 'v'), true, false);
|
||||
$verboseFile = getDefined('vf', true, false);
|
||||
verbose("img.php version = $version");
|
||||
verbose("img.php version = " . CIMAGE_VERSION);
|
||||
|
||||
|
||||
|
||||
@@ -200,36 +73,28 @@ if (!extension_loaded('gd')) {
|
||||
|
||||
// Specific settings for each mode
|
||||
if ($mode == 'strict') {
|
||||
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('log_errors', 1);
|
||||
$verbose = false;
|
||||
$status = false;
|
||||
$verboseFile = false;
|
||||
|
||||
} elseif ($mode == 'production') {
|
||||
|
||||
error_reporting(-1);
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('log_errors', 1);
|
||||
$verbose = false;
|
||||
$status = false;
|
||||
$verboseFile = false;
|
||||
|
||||
} elseif ($mode == 'development') {
|
||||
|
||||
error_reporting(-1);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('log_errors', 0);
|
||||
$verboseFile = false;
|
||||
|
||||
} elseif ($mode == 'test') {
|
||||
|
||||
error_reporting(-1);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('log_errors', 0);
|
||||
|
||||
} else {
|
||||
errorPage("Unknown mode: $mode", 500);
|
||||
}
|
||||
@@ -319,7 +184,6 @@ if (!$allowHotlinking) {
|
||||
} else {
|
||||
errorPage("Hotlinking/leeching not allowed by whitelist. Referer: $referer.", 403);
|
||||
}
|
||||
|
||||
} else {
|
||||
errorPage("Hotlinking/leeching not allowed.", 403);
|
||||
}
|
||||
@@ -331,21 +195,11 @@ verbose("referer host = $refererHost");
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the source files.
|
||||
*/
|
||||
$autoloader = getConfig('autoloader', false);
|
||||
|
||||
if ($autoloader) {
|
||||
require $autoloader;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create the class for the image.
|
||||
*/
|
||||
$img = new CImage();
|
||||
$CImage = getConfig('CImage', 'CImage');
|
||||
$img = new $CImage();
|
||||
$img->setVerbose($verbose || $verboseFile);
|
||||
|
||||
|
||||
@@ -353,12 +207,49 @@ $img->setVerbose($verbose || $verboseFile);
|
||||
/**
|
||||
* Get the cachepath from config.
|
||||
*/
|
||||
$CCache = getConfig('CCache', 'CCache');
|
||||
$cachePath = getConfig('cache_path', __DIR__ . '/../cache/');
|
||||
$cache = new CCache();
|
||||
$cache = new $CCache();
|
||||
$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.
|
||||
@@ -391,8 +282,8 @@ $shortcutConfig = getConfig('shortcut', array(
|
||||
verbose("shortcut = $shortcut");
|
||||
|
||||
if (isset($shortcut)
|
||||
&& isset($shortcutConfig[$shortcut])) {
|
||||
|
||||
&& isset($shortcutConfig[$shortcut])
|
||||
) {
|
||||
parse_str($shortcutConfig[$shortcut], $get);
|
||||
verbose("shortcut-constant = {$shortcutConfig[$shortcut]}");
|
||||
$_GET = array_merge($_GET, $get);
|
||||
@@ -406,40 +297,66 @@ if (isset($shortcut)
|
||||
$srcImage = urldecode(get('src'))
|
||||
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
|
||||
$imagePath = getConfig('image_path', __DIR__ . '/img/');
|
||||
$imagePathConstraint = getConfig('image_path_constraint', true);
|
||||
$validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#');
|
||||
|
||||
// Source is remote
|
||||
$remoteSource = false;
|
||||
|
||||
// Dummy image feature
|
||||
$dummyEnabled = getConfig('dummy_enabled', true);
|
||||
$dummyFilename = getConfig('dummy_filename', 'dummy');
|
||||
$dummyImage = false;
|
||||
|
||||
preg_match($validFilename, $srcImage)
|
||||
or errorPage('Filename contains invalid characters.', 404);
|
||||
or errorPage('Source filename contains invalid characters.', 404);
|
||||
|
||||
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.
|
||||
|
||||
} elseif ($imagePathConstraint) {
|
||||
|
||||
// Check that the image is a file below the directory 'image_path'.
|
||||
$remoteSource = true;
|
||||
} else {
|
||||
// Check if file exists on disk or try using src-alt
|
||||
$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)
|
||||
or errorPage(
|
||||
'Source image is not a valid file, check the filename and that a
|
||||
matching file exists on the filesystem.',
|
||||
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
|
||||
or errorPage(
|
||||
@@ -665,23 +582,14 @@ $useOriginal = getDefined(array('skip-original', 'so'), false, true);
|
||||
$useOriginalDefault = getConfig('skip_original', false);
|
||||
|
||||
if ($useOriginalDefault === true) {
|
||||
verbose("use original is default ON");
|
||||
$useOriginal = true;
|
||||
verbose("skip original is default ON");
|
||||
$useOriginal = false;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
@@ -918,6 +826,9 @@ verbose("upscale = $upscale");
|
||||
* Get details for post processing
|
||||
*/
|
||||
$postProcessing = getConfig('postprocessing', array(
|
||||
'png_lossy' => false,
|
||||
'png_lossy_cmd' => '/usr/local/bin/pngquant --force --output',
|
||||
|
||||
'png_filter' => false,
|
||||
'png_filter_cmd' => '/usr/local/bin/optipng -q',
|
||||
|
||||
@@ -930,6 +841,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.
|
||||
* Password always apply, must be defined.
|
||||
@@ -1031,7 +951,7 @@ if ($srgb || $srgbDefault) {
|
||||
* Display status
|
||||
*/
|
||||
if ($status) {
|
||||
$text = "img.php version = $version\n";
|
||||
$text = "img.php version = " . CIMAGE_VERSION . "\n";
|
||||
$text .= "PHP version = " . PHP_VERSION . "\n";
|
||||
$text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n";
|
||||
$text .= "Allow remote images = $allowRemote\n";
|
||||
@@ -1048,6 +968,9 @@ if ($status) {
|
||||
$res = $cache->getStatusOfSubdir("srgb");
|
||||
$text .= "Cache srgb $res\n";
|
||||
|
||||
$res = $cache->getStatusOfSubdir($fastTrackCache);
|
||||
$text .= "Cache fasttrack $res\n";
|
||||
|
||||
$text .= "Alias path writable = " . is_writable($aliasPath) . "\n";
|
||||
|
||||
$no = extension_loaded('exif') ? null : 'NOT';
|
||||
@@ -1062,6 +985,11 @@ if ($status) {
|
||||
$no = extension_loaded('gd') ? null : 'NOT';
|
||||
$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) {
|
||||
$text .= print_r(gd_info(), 1);
|
||||
}
|
||||
@@ -1130,6 +1058,7 @@ if (is_callable($hookBeforeCImage)) {
|
||||
|
||||
// Other
|
||||
'postProcessing' => $postProcessing,
|
||||
'lossy' => $lossy,
|
||||
));
|
||||
verbose(print_r($allConfig, 1));
|
||||
extract($allConfig);
|
||||
@@ -1214,6 +1143,9 @@ $res = $img->log("Incoming arguments: " . print_r(verbose(), 1))
|
||||
// Output format
|
||||
'outputFormat' => $outputFormat,
|
||||
'dpr' => $dpr,
|
||||
|
||||
// Postprocessing using external tools
|
||||
'lossy' => $lossy,
|
||||
)
|
||||
)
|
||||
->loadImageDetails()
|
||||
|
BIN
webroot/img/duke.png
Normal file
BIN
webroot/img/duke.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 228 KiB |
BIN
webroot/img/lena.jpg
Normal file
BIN
webroot/img/lena.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 395 KiB |
BIN
webroot/img/lena.png
Normal file
BIN
webroot/img/lena.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 464 KiB |
BIN
webroot/img/lena.tif
Normal file
BIN
webroot/img/lena.tif
Normal file
Binary file not shown.
BIN
webroot/img/lena.webp
Normal file
BIN
webroot/img/lena.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
BIN
webroot/img/planet.gif
Normal file
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
BIN
webroot/img/webp/1.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
@@ -5,6 +5,24 @@
|
||||
* 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 [
|
||||
|
||||
/**
|
||||
@@ -29,25 +47,13 @@ return [
|
||||
|
||||
|
||||
/**
|
||||
* Where are the sources for the classfiles.
|
||||
* Where to find the autoloader.
|
||||
*
|
||||
* Default values:
|
||||
* autoloader: null
|
||||
*/
|
||||
'autoloader' => __DIR__ . '/../autoload.php',
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Paths, where are the images stored and where is the cache.
|
||||
* End all paths with a slash.
|
||||
*
|
||||
* Default values:
|
||||
* image_path: __DIR__ . '/img/'
|
||||
* cache_path: __DIR__ . '/../cache/'
|
||||
*/
|
||||
'image_path' => __DIR__ . '/img/',
|
||||
'cache_path' => __DIR__ . '/../cache/',
|
||||
//'autoloader' => __DIR__ . '/../autoload.php',
|
||||
'autoloader' => __DIR__ . '/../vendor/autoload.php',
|
||||
|
||||
|
||||
|
||||
@@ -57,12 +63,44 @@ return [
|
||||
* End all paths with a slash.
|
||||
*
|
||||
* Default values:
|
||||
* image_path: __DIR__ . '/img/'
|
||||
* cache_path: __DIR__ . '/../cache/'
|
||||
* alias_path: null
|
||||
*/
|
||||
'image_path' => __DIR__ . '/img/',
|
||||
'cache_path' => __DIR__ . '/../cache/',
|
||||
//'alias_path' => __DIR__ . '/img/alias/',
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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=..
|
||||
* with the request to match the password or set to false to disable.
|
||||
@@ -105,13 +143,14 @@ return [
|
||||
* remote_whitelist: null // use default values from CImage which is to
|
||||
* // allow download from any hosts.
|
||||
*/
|
||||
//'remote_allow' => true,
|
||||
//'remote_pattern' => '#^https?://#',
|
||||
//'remote_whitelist' => array(
|
||||
// '\.facebook\.com$',
|
||||
// '^(?:images|photos-[a-z])\.ak\.instagram\.com$',
|
||||
// '\.google\.com$'
|
||||
//),
|
||||
/*
|
||||
'remote_allow' => true,
|
||||
'remote_pattern' => '#^https?://#',
|
||||
'remote_whitelist' => [
|
||||
'\.facebook\.com$',
|
||||
'^(?:images|photos-[a-z])\.ak\.instagram\.com$',
|
||||
'\.google\.com$'
|
||||
], */
|
||||
|
||||
|
||||
|
||||
@@ -180,7 +219,7 @@ return [
|
||||
* Default value:
|
||||
* skip_original: false
|
||||
*/
|
||||
//'skip_original' => false,
|
||||
//'skip_original' => true,
|
||||
|
||||
|
||||
|
||||
@@ -233,7 +272,8 @@ return [
|
||||
/**
|
||||
* Check that the imagefile is a file below 'image_path' using realpath().
|
||||
* 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:
|
||||
* image_path_constraint: true
|
||||
@@ -286,8 +326,16 @@ return [
|
||||
* Post processing of images using external tools, set to true or false
|
||||
* 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.
|
||||
*
|
||||
* png_lossy: false
|
||||
* png_lossy_cmd: '/usr/local/bin/pngquant --force --output'
|
||||
*
|
||||
* png_filter: false
|
||||
* png_filter_cmd: '/usr/local/bin/optipng -q'
|
||||
*
|
||||
@@ -299,6 +347,9 @@ return [
|
||||
*/
|
||||
/*
|
||||
'postprocessing' => [
|
||||
'png_lossy' => null,
|
||||
'png_lossy_cmd' => '/usr/local/bin/pngquant --force --output',
|
||||
|
||||
'png_filter' => false,
|
||||
'png_filter_cmd' => '/usr/local/bin/optipng -q',
|
||||
|
||||
@@ -317,13 +368,13 @@ return [
|
||||
* offset.
|
||||
*
|
||||
* Default values.
|
||||
* convolution_constant: array()
|
||||
* convolution_constant: []
|
||||
*/
|
||||
/*
|
||||
'convolution_constant' => array(
|
||||
'convolution_constant' => [
|
||||
//'sharpen' => '-1,-1,-1, -1,16,-1, -1,-1,-1, 8, 0',
|
||||
//'sharpen-alt' => '0,-1,0, -1,5,-1, 0,-1,0, 1, 0',
|
||||
),
|
||||
],
|
||||
*/
|
||||
|
||||
|
||||
@@ -340,13 +391,13 @@ return [
|
||||
*
|
||||
* Default values.
|
||||
* allow_hotlinking: true
|
||||
* hotlinking_whitelist: array()
|
||||
* hotlinking_whitelist: []
|
||||
*/
|
||||
/*
|
||||
'allow_hotlinking' => false,
|
||||
'hotlinking_whitelist' => array(
|
||||
'hotlinking_whitelist' => [
|
||||
'^dbwebb\.se$',
|
||||
),
|
||||
],
|
||||
*/
|
||||
|
||||
|
||||
@@ -384,10 +435,10 @@ return [
|
||||
'size_constant' => function () {
|
||||
|
||||
// Set sizes to map constant to value, easier to use with width or height
|
||||
$sizes = array(
|
||||
$sizes = [
|
||||
'w1' => 613,
|
||||
'w2' => 630,
|
||||
);
|
||||
];
|
||||
|
||||
// Add grid column width, useful for use as predefined size for width (or height).
|
||||
$gridColumnWidth = 30;
|
||||
@@ -410,7 +461,7 @@ return [
|
||||
* aspect_ratio_constant: As the function below.
|
||||
*/
|
||||
/*'aspect_ratio_constant' => function () {
|
||||
return array(
|
||||
return [
|
||||
'3:1' => 3/1,
|
||||
'3:2' => 3/2,
|
||||
'4:3' => 4/3,
|
||||
@@ -418,7 +469,7 @@ return [
|
||||
'16:10' => 16/10,
|
||||
'16:9' => 16/9,
|
||||
'golden' => 1.618,
|
||||
);
|
||||
];
|
||||
},*/
|
||||
|
||||
|
||||
@@ -434,11 +485,11 @@ return [
|
||||
* luminanceStrategy: Choose any strategy available in CAsciiArt.
|
||||
* customCharacterSet: Define your own character set.
|
||||
*/
|
||||
/*'ascii-options' => array(
|
||||
/*'ascii-options' => [
|
||||
"characterSet" => 'two',
|
||||
"scale" => 14,
|
||||
"luminanceStrategy" => 3,
|
||||
"customCharacterSet" => null,
|
||||
);
|
||||
},*/
|
||||
],*/
|
||||
];
|
||||
|
@@ -10,6 +10,7 @@
|
||||
* @link https://github.com/mosbth/cimage
|
||||
*
|
||||
*/
|
||||
define("CIMAGE_BUNDLE", true);
|
||||
|
||||
|
||||
/**
|
||||
|
970
webroot/imgd.php
970
webroot/imgd.php
File diff suppressed because it is too large
Load Diff
91
webroot/imgf.php
Normal file
91
webroot/imgf.php
Normal 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
1
webroot/imgf_config.php
Symbolic link
@@ -0,0 +1 @@
|
||||
img_config.php
|
970
webroot/imgp.php
970
webroot/imgp.php
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user