mirror of
https://github.com/mosbth/cimage.git
synced 2025-08-29 18:39:53 +02:00
Compare commits
29 Commits
v0.6.1
...
v0.7.0-rc.
Author | SHA1 | Date | |
---|---|---|---|
|
c2b037af0d | ||
|
889dba1ddb | ||
|
0baea7c346 | ||
|
ab4e8a6fae | ||
|
641d67d7a0 | ||
|
aa009510be | ||
|
9348141e65 | ||
|
800dcbc248 | ||
|
7b18030580 | ||
|
e5738c02b1 | ||
|
6478915f3c | ||
|
ba58ce80c0 | ||
|
d4d645a00e | ||
|
011148b0e8 | ||
|
eb0fc69036 | ||
|
c012cb2537 | ||
|
16a7a3dad5 | ||
|
bc4e04c3cb | ||
|
3452ea1908 | ||
|
5e08e5ed80 | ||
|
4fae208c4c | ||
|
f87dc2967f | ||
|
c35587c7e2 | ||
|
81e70b7acd | ||
|
8e9a3b68f0 | ||
|
61afe445f1 | ||
|
be98ae8979 | ||
|
f9704a4fbc | ||
|
cae7a49d21 |
240
CHttpGet.php
Normal file
240
CHttpGet.php
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Get a image from a remote server using HTTP GET and If-Modified-Since.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CHttpGet
|
||||||
|
{
|
||||||
|
private $request = array();
|
||||||
|
private $response = array();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->request['header'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the url for the request.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUrl($url)
|
||||||
|
{
|
||||||
|
$this->request['url'] = $url;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set custom header field for the request.
|
||||||
|
*
|
||||||
|
* @param string $field
|
||||||
|
* @param string $value
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setHeader($field, $value)
|
||||||
|
{
|
||||||
|
$this->request['header'][] = "$field: $value";
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set header fields for the request.
|
||||||
|
*
|
||||||
|
* @param string $field
|
||||||
|
* @param string $value
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function parseHeader()
|
||||||
|
{
|
||||||
|
$header = explode("\r\n", rtrim($this->response['headerRaw'], "\r\n"));
|
||||||
|
$output = array();
|
||||||
|
|
||||||
|
if ('HTTP' === substr($header[0], 0, 4)) {
|
||||||
|
list($output['version'], $output['status']) = explode(' ', $header[0]);
|
||||||
|
unset($header[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($header as $entry) {
|
||||||
|
$pos = strpos($entry, ':');
|
||||||
|
$output[trim(substr($entry, 0, $pos))] = trim(substr($entry, $pos + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response['header'] = $output;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the request.
|
||||||
|
*
|
||||||
|
* @param boolean $debug set to true to dump headers.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function doGet($debug = false)
|
||||||
|
{
|
||||||
|
$options = array(
|
||||||
|
CURLOPT_URL => $this->request['url'],
|
||||||
|
CURLOPT_HEADER => 1,
|
||||||
|
CURLOPT_HTTPHEADER => $this->request['header'],
|
||||||
|
CURLOPT_AUTOREFERER => true,
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLINFO_HEADER_OUT => $debug,
|
||||||
|
CURLOPT_CONNECTTIMEOUT => 5,
|
||||||
|
CURLOPT_TIMEOUT => 5,
|
||||||
|
);
|
||||||
|
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt_array($ch, $options);
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
|
||||||
|
if (!$response) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||||
|
$this->response['headerRaw'] = substr($response, 0, $headerSize);
|
||||||
|
$this->response['body'] = substr($response, $headerSize);
|
||||||
|
|
||||||
|
$this->parseHeader();
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
$info = curl_getinfo($ch);
|
||||||
|
echo "Request header<br><pre>", var_dump($info['request_header']), "</pre>";
|
||||||
|
echo "Response header (raw)<br><pre>", var_dump($this->response['headerRaw']), "</pre>";
|
||||||
|
echo "Response header (parsed)<br><pre>", var_dump($this->response['header']), "</pre>";
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get HTTP code of response.
|
||||||
|
*
|
||||||
|
* @return integer as HTTP status code or null if not available.
|
||||||
|
*/
|
||||||
|
public function getStatus()
|
||||||
|
{
|
||||||
|
return isset($this->response['header']['status'])
|
||||||
|
? (int) $this->response['header']['status']
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file modification time of response.
|
||||||
|
*
|
||||||
|
* @return int as timestamp.
|
||||||
|
*/
|
||||||
|
public function getLastModified()
|
||||||
|
{
|
||||||
|
return isset($this->response['header']['Last-Modified'])
|
||||||
|
? strtotime($this->response['header']['Last-Modified'])
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get content type.
|
||||||
|
*
|
||||||
|
* @return string as the content type or null if not existing or invalid.
|
||||||
|
*/
|
||||||
|
public function getContentType()
|
||||||
|
{
|
||||||
|
$type = isset($this->response['header']['Content-Type'])
|
||||||
|
? $this->response['header']['Content-Type']
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return preg_match('#[a-z]+/[a-z]+#', $type)
|
||||||
|
? $type
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file modification time of response.
|
||||||
|
*
|
||||||
|
* @param mixed $default as default value (int seconds) if date is
|
||||||
|
* missing in response header.
|
||||||
|
*
|
||||||
|
* @return int as timestamp or $default if Date is missing in
|
||||||
|
* response header.
|
||||||
|
*/
|
||||||
|
public function getDate($default = false)
|
||||||
|
{
|
||||||
|
return isset($this->response['header']['Date'])
|
||||||
|
? strtotime($this->response['header']['Date'])
|
||||||
|
: $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get max age of cachable item.
|
||||||
|
*
|
||||||
|
* @param mixed $default as default value if date is missing in response
|
||||||
|
* header.
|
||||||
|
*
|
||||||
|
* @return int as timestamp or false if not available.
|
||||||
|
*/
|
||||||
|
public function getMaxAge($default = false)
|
||||||
|
{
|
||||||
|
$cacheControl = isset($this->response['header']['Cache-Control'])
|
||||||
|
? $this->response['header']['Cache-Control']
|
||||||
|
: null;
|
||||||
|
|
||||||
|
$maxAge = null;
|
||||||
|
if ($cacheControl) {
|
||||||
|
// max-age=2592000
|
||||||
|
$part = explode('=', $cacheControl);
|
||||||
|
$maxAge = ($part[0] == "max-age")
|
||||||
|
? (int) $part[1]
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($maxAge) {
|
||||||
|
return $maxAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
$expire = isset($this->response['header']['Expires'])
|
||||||
|
? strtotime($this->response['header']['Expires'])
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return $expire ? $expire : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get body of response.
|
||||||
|
*
|
||||||
|
* @return string as body.
|
||||||
|
*/
|
||||||
|
public function getBody()
|
||||||
|
{
|
||||||
|
return $this->response['body'];
|
||||||
|
}
|
||||||
|
}
|
422
CImage.php
422
CImage.php
@@ -2,9 +2,9 @@
|
|||||||
/**
|
/**
|
||||||
* Resize and crop images on the fly, store generated images in a cache.
|
* Resize and crop images on the fly, store generated images in a cache.
|
||||||
*
|
*
|
||||||
* @author Mikael Roos mos@dbwebb.se
|
* @author Mikael Roos mos@dbwebb.se
|
||||||
* @example http://dbwebb.se/opensource/cimage
|
* @example http://dbwebb.se/opensource/cimage
|
||||||
* @link https://github.com/mosbth/cimage
|
* @link https://github.com/mosbth/cimage
|
||||||
*/
|
*/
|
||||||
class CImage
|
class CImage
|
||||||
{
|
{
|
||||||
@@ -17,7 +17,7 @@ class CImage
|
|||||||
const PNG_RGB_PALETTE = 3;
|
const PNG_RGB_PALETTE = 3;
|
||||||
const PNG_GREYSCALE_ALPHA = 4;
|
const PNG_GREYSCALE_ALPHA = 4;
|
||||||
const PNG_RGB_ALPHA = 6;
|
const PNG_RGB_ALPHA = 6;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,7 +224,7 @@ class CImage
|
|||||||
private $newHeight;
|
private $newHeight;
|
||||||
private $newHeightOrig; // Save original value
|
private $newHeightOrig; // Save original value
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change target height & width when different dpr, dpr 2 means double image dimensions.
|
* Change target height & width when different dpr, dpr 2 means double image dimensions.
|
||||||
*/
|
*/
|
||||||
@@ -250,13 +250,13 @@ class CImage
|
|||||||
* String with details on how to do image convolution. String
|
* String with details on how to do image convolution. String
|
||||||
* should map a key in the $convolvs array or be a string of
|
* should map a key in the $convolvs array or be a string of
|
||||||
* 11 float values separated by comma. The first nine builds
|
* 11 float values separated by comma. The first nine builds
|
||||||
* up the matrix, then divisor and last offset.
|
* up the matrix, then divisor and last offset.
|
||||||
*/
|
*/
|
||||||
private $convolve;
|
private $convolve;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom convolution expressions, matrix 3x3, divisor and offset.
|
* Custom convolution expressions, matrix 3x3, divisor and offset.
|
||||||
*/
|
*/
|
||||||
private $convolves = array(
|
private $convolves = array(
|
||||||
'lighten' => '0,0,0, 0,12,0, 0,0,0, 9, 0',
|
'lighten' => '0,0,0, 0,12,0, 0,0,0, 9, 0',
|
||||||
@@ -276,30 +276,51 @@ class CImage
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resize strategy to fill extra area with background color.
|
* Resize strategy to fill extra area with background color.
|
||||||
* True or false.
|
* True or false.
|
||||||
*/
|
*/
|
||||||
private $fillToFit;
|
private $fillToFit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used with option area to set which parts of the image to use.
|
* Used with option area to set which parts of the image to use.
|
||||||
*/
|
*/
|
||||||
private $offset;
|
private $offset;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate target dimension for image when using fill-to-fit resize strategy.
|
* Calculate target dimension for image when using fill-to-fit resize strategy.
|
||||||
*/
|
*/
|
||||||
private $fillWidth;
|
private $fillWidth;
|
||||||
private $fillHeight;
|
private $fillHeight;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow remote file download, default is to disallow remote file download.
|
||||||
|
*/
|
||||||
|
private $allowRemote = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pattern to recognize a remote file.
|
||||||
|
*/
|
||||||
|
//private $remotePattern = '#^[http|https]://#';
|
||||||
|
private $remotePattern = '#^https?://#';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the cache if true, set to false to ignore the cached file.
|
||||||
|
*/
|
||||||
|
private $useCache = true;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties, the class is mutable and the method setOptions()
|
* Properties, the class is mutable and the method setOptions()
|
||||||
* decides (partly) what properties are created.
|
* decides (partly) what properties are created.
|
||||||
*
|
*
|
||||||
* @todo Clean up these and check if and how they are used
|
* @todo Clean up these and check if and how they are used
|
||||||
*/
|
*/
|
||||||
@@ -313,7 +334,6 @@ class CImage
|
|||||||
public $filters;
|
public $filters;
|
||||||
private $type; // Calculated from source image
|
private $type; // Calculated from source image
|
||||||
private $attr; // Calculated from source image
|
private $attr; // Calculated from source image
|
||||||
private $useCache; // Use the cache if true, set to false to ignore the cached file.
|
|
||||||
private $useOriginal; // Use original image if possible
|
private $useOriginal; // Use original image if possible
|
||||||
|
|
||||||
|
|
||||||
@@ -338,7 +358,8 @@ class CImage
|
|||||||
/**
|
/**
|
||||||
* Set verbose mode.
|
* Set verbose mode.
|
||||||
*
|
*
|
||||||
* @param boolean $mode true or false to enable and disable versbose mode, default is true.
|
* @param boolean $mode true or false to enable and disable verbose mode,
|
||||||
|
* default is true.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@@ -347,8 +368,81 @@ class CImage
|
|||||||
$this->verbose = $mode;
|
$this->verbose = $mode;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set save folder, base folder for saving cache files.
|
||||||
|
*
|
||||||
|
* @todo clean up how $this->saveFolder is used in other methods.
|
||||||
|
*
|
||||||
|
* @param string $path where to store cached files.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setSaveFolder($path)
|
||||||
|
{
|
||||||
|
$this->saveFolder = $path;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use cache or not.
|
||||||
|
*
|
||||||
|
* @todo clean up how $this->noCache is used in other methods.
|
||||||
|
*
|
||||||
|
* @param string $use true or false to use cache.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function useCache($use = true)
|
||||||
|
{
|
||||||
|
$this->useCache = $use;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow or disallow remote image download.
|
||||||
|
*
|
||||||
|
* @param boolean $allow true or false to enable and disable.
|
||||||
|
* @param string $pattern to use to detect if its a remote file.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setRemoteDownload($allow, $pattern = null)
|
||||||
|
{
|
||||||
|
$this->allowRemote = $allow;
|
||||||
|
$this->remotePattern = $pattern ? $pattern : $this->remotePattern;
|
||||||
|
|
||||||
|
$this->log("Set remote download to: "
|
||||||
|
. ($this->allowRemote ? "true" : "false")
|
||||||
|
. " using pattern "
|
||||||
|
. $this->remotePattern);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the image resource is a remote file or not.
|
||||||
|
*
|
||||||
|
* @param string $src check if src is remote.
|
||||||
|
*
|
||||||
|
* @return boolean true if $src is a remote file, else false.
|
||||||
|
*/
|
||||||
|
public function isRemoteSource($src)
|
||||||
|
{
|
||||||
|
$remote = preg_match($this->remotePattern, $src);
|
||||||
|
$this->log("Detected remote image: " . ($remote ? "true" : "false"));
|
||||||
|
return $remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if file extension is valid as a file extension.
|
* Check if file extension is valid as a file extension.
|
||||||
@@ -366,9 +460,46 @@ class CImage
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download a remote image and return path to its local copy.
|
||||||
|
*
|
||||||
|
* @param string $src remote path to image.
|
||||||
|
*
|
||||||
|
* @return string as path to downloaded remote source.
|
||||||
|
*/
|
||||||
|
public function downloadRemoteSource($src)
|
||||||
|
{
|
||||||
|
$remote = new CRemoteImage();
|
||||||
|
$cache = $this->saveFolder . "/remote/";
|
||||||
|
|
||||||
|
if (!is_dir($cache)) {
|
||||||
|
if (!is_writable($this->saveFolder)) {
|
||||||
|
throw new Exception("Can not create remote cache, cachefolder not writable.");
|
||||||
|
}
|
||||||
|
mkdir($cache);
|
||||||
|
$this->log("The remote cache does not exists, creating it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_writable($cache)) {
|
||||||
|
$this->log("The remote cache is not writable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$remote->setCache($cache);
|
||||||
|
$remote->useCache($this->useCache);
|
||||||
|
$src = $remote->download($src);
|
||||||
|
|
||||||
|
$this->log("Remote HTTP status: " . $remote->getStatus());
|
||||||
|
$this->log("Remote item has local cached file: $src");
|
||||||
|
$this->log("Remote details on cache:" . print_r($remote->getDetails(), true));
|
||||||
|
|
||||||
|
return $src;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set src file.
|
* Set src file.
|
||||||
*
|
*
|
||||||
@@ -381,7 +512,14 @@ class CImage
|
|||||||
{
|
{
|
||||||
if (!isset($src)) {
|
if (!isset($src)) {
|
||||||
return $this;
|
return $this;
|
||||||
} else if (!isset($dir)) {
|
}
|
||||||
|
|
||||||
|
if ($this->allowRemote && $this->isRemoteSource($src)) {
|
||||||
|
$src = $this->downloadRemoteSource($src);
|
||||||
|
$dir = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($dir)) {
|
||||||
$dir = dirname($src);
|
$dir = dirname($src);
|
||||||
$src = basename($src);
|
$src = basename($src);
|
||||||
}
|
}
|
||||||
@@ -391,14 +529,14 @@ class CImage
|
|||||||
$this->pathToImage = $this->imageFolder . '/' . $this->imageSrc;
|
$this->pathToImage = $this->imageFolder . '/' . $this->imageSrc;
|
||||||
$this->fileExtension = strtolower(pathinfo($this->pathToImage, PATHINFO_EXTENSION));
|
$this->fileExtension = strtolower(pathinfo($this->pathToImage, PATHINFO_EXTENSION));
|
||||||
//$this->extension = $this->fileExtension;
|
//$this->extension = $this->fileExtension;
|
||||||
|
|
||||||
$this->checkFileExtension($this->fileExtension);
|
$this->checkFileExtension($this->fileExtension);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set target file.
|
* Set target file.
|
||||||
*
|
*
|
||||||
@@ -424,12 +562,12 @@ class CImage
|
|||||||
// Sanitize filename
|
// Sanitize filename
|
||||||
$this->cacheFileName = preg_replace('/^a-zA-Z0-9\.-_/', '', $this->cacheFileName);
|
$this->cacheFileName = preg_replace('/^a-zA-Z0-9\.-_/', '', $this->cacheFileName);
|
||||||
$this->log("The cache file name is: " . $this->cacheFileName);
|
$this->log("The cache file name is: " . $this->cacheFileName);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set options to use when processing image.
|
* Set options to use when processing image.
|
||||||
*
|
*
|
||||||
@@ -517,7 +655,7 @@ class CImage
|
|||||||
$filter["arg{$i}"] = $parts[$i];
|
$filter["arg{$i}"] = $parts[$i];
|
||||||
} else {
|
} else {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
'Missing arg to filter, review how many arguments are needed at
|
'Missing arg to filter, review how many arguments are needed at
|
||||||
http://php.net/manual/en/function.imagefilter.php'
|
http://php.net/manual/en/function.imagefilter.php'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -553,7 +691,7 @@ class CImage
|
|||||||
* @param string $name the name of the filter.
|
* @param string $name the name of the filter.
|
||||||
*
|
*
|
||||||
* @return array with filter settings
|
* @return array with filter settings
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function mapFilter($name)
|
private function mapFilter($name)
|
||||||
{
|
{
|
||||||
@@ -578,8 +716,8 @@ class CImage
|
|||||||
throw new Exception('No such filter.');
|
throw new Exception('No such filter.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load image details from original image file.
|
* Load image details from original image file.
|
||||||
@@ -612,8 +750,8 @@ class CImage
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
@@ -746,12 +884,12 @@ class CImage
|
|||||||
|
|
||||||
// Crop-to-fit and both new width and height are set.
|
// Crop-to-fit and both new width and height are set.
|
||||||
if (($this->cropToFit || $this->fillToFit) && isset($this->newWidth) && isset($this->newHeight)) {
|
if (($this->cropToFit || $this->fillToFit) && isset($this->newWidth) && isset($this->newHeight)) {
|
||||||
|
|
||||||
// Use newWidth and newHeigh as width/height, image should fit in box.
|
// Use newWidth and newHeigh as width/height, image should fit in box.
|
||||||
$this->log("Use newWidth and newHeigh as width/height, image should fit in box.");
|
$this->log("Use newWidth and newHeigh as width/height, image should fit in box.");
|
||||||
|
|
||||||
} elseif (isset($this->newWidth) && isset($this->newHeight)) {
|
} elseif (isset($this->newWidth) && isset($this->newHeight)) {
|
||||||
|
|
||||||
// Both new width and height are set.
|
// Both new width and height are set.
|
||||||
// Use newWidth and newHeigh as max width/height, image should not be larger.
|
// Use newWidth and newHeigh as max width/height, image should not be larger.
|
||||||
$ratioWidth = $width / $this->newWidth;
|
$ratioWidth = $width / $this->newWidth;
|
||||||
@@ -760,23 +898,23 @@ class CImage
|
|||||||
$this->newWidth = round($width / $ratio);
|
$this->newWidth = round($width / $ratio);
|
||||||
$this->newHeight = round($height / $ratio);
|
$this->newHeight = round($height / $ratio);
|
||||||
$this->log("New width and height was set.");
|
$this->log("New width and height was set.");
|
||||||
|
|
||||||
} elseif (isset($this->newWidth)) {
|
} elseif (isset($this->newWidth)) {
|
||||||
|
|
||||||
// Use new width as max-width
|
// Use new width as max-width
|
||||||
$factor = (float)$this->newWidth / (float)$width;
|
$factor = (float)$this->newWidth / (float)$width;
|
||||||
$this->newHeight = round($factor * $height);
|
$this->newHeight = round($factor * $height);
|
||||||
$this->log("New width was set.");
|
$this->log("New width was set.");
|
||||||
|
|
||||||
} elseif (isset($this->newHeight)) {
|
} elseif (isset($this->newHeight)) {
|
||||||
|
|
||||||
// Use new height as max-hight
|
// Use new height as max-hight
|
||||||
$factor = (float)$this->newHeight / (float)$height;
|
$factor = (float)$this->newHeight / (float)$height;
|
||||||
$this->newWidth = round($factor * $width);
|
$this->newWidth = round($factor * $width);
|
||||||
$this->log("New height was set.");
|
$this->log("New height was set.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get image dimensions for pre-resize image.
|
// Get image dimensions for pre-resize image.
|
||||||
if ($this->cropToFit || $this->fillToFit) {
|
if ($this->cropToFit || $this->fillToFit) {
|
||||||
|
|
||||||
@@ -785,7 +923,7 @@ class CImage
|
|||||||
$ratioHeight = $height / $this->newHeight;
|
$ratioHeight = $height / $this->newHeight;
|
||||||
|
|
||||||
if ($this->cropToFit) {
|
if ($this->cropToFit) {
|
||||||
|
|
||||||
// Use newWidth and newHeigh as defined width/height,
|
// Use newWidth and newHeigh as defined width/height,
|
||||||
// image should fit the area.
|
// image should fit the area.
|
||||||
$this->log("Crop to fit.");
|
$this->log("Crop to fit.");
|
||||||
@@ -793,9 +931,9 @@ class CImage
|
|||||||
$this->cropWidth = round($width / $ratio);
|
$this->cropWidth = round($width / $ratio);
|
||||||
$this->cropHeight = round($height / $ratio);
|
$this->cropHeight = round($height / $ratio);
|
||||||
$this->log("Crop width, height, ratio: $this->cropWidth x $this->cropHeight ($ratio).");
|
$this->log("Crop width, height, ratio: $this->cropWidth x $this->cropHeight ($ratio).");
|
||||||
|
|
||||||
} else if ($this->fillToFit) {
|
} else if ($this->fillToFit) {
|
||||||
|
|
||||||
// Use newWidth and newHeigh as defined width/height,
|
// Use newWidth and newHeigh as defined width/height,
|
||||||
// image should fit the area.
|
// image should fit the area.
|
||||||
$this->log("Fill to fit.");
|
$this->log("Fill to fit.");
|
||||||
@@ -834,7 +972,7 @@ class CImage
|
|||||||
/**
|
/**
|
||||||
* Re-calculate image dimensions when original image dimension has changed.
|
* Re-calculate image dimensions when original image dimension has changed.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function reCalculateDimensions()
|
public function reCalculateDimensions()
|
||||||
{
|
{
|
||||||
@@ -857,7 +995,7 @@ class CImage
|
|||||||
*
|
*
|
||||||
* @param string $saveas extension to save image as
|
* @param string $saveas extension to save image as
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setSaveAsExtension($saveAs = null)
|
public function setSaveAsExtension($saveAs = null)
|
||||||
{
|
{
|
||||||
@@ -879,7 +1017,7 @@ class CImage
|
|||||||
* Set JPEG quality to use when saving image
|
* Set JPEG quality to use when saving image
|
||||||
*
|
*
|
||||||
* @param int $quality as the quality to set.
|
* @param int $quality as the quality to set.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setJpegQuality($quality = null)
|
public function setJpegQuality($quality = null)
|
||||||
@@ -906,7 +1044,7 @@ class CImage
|
|||||||
* Set PNG compressen algorithm to use when saving image
|
* Set PNG compressen algorithm to use when saving image
|
||||||
*
|
*
|
||||||
* @param int $compress as the algorithm to use.
|
* @param int $compress as the algorithm to use.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setPngCompression($compress = null)
|
public function setPngCompression($compress = null)
|
||||||
@@ -967,7 +1105,7 @@ class CImage
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate filename to save file in cache.
|
* Generate filename to save file in cache.
|
||||||
@@ -1000,7 +1138,7 @@ class CImage
|
|||||||
$crop = $this->crop
|
$crop = $this->crop
|
||||||
? '_c' . $this->crop['width'] . '-' . $this->crop['height'] . '-' . $this->crop['start_x'] . '-' . $this->crop['start_y']
|
? '_c' . $this->crop['width'] . '-' . $this->crop['height'] . '-' . $this->crop['start_x'] . '-' . $this->crop['start_y']
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
$filters = null;
|
$filters = null;
|
||||||
if (isset($this->filters)) {
|
if (isset($this->filters)) {
|
||||||
foreach ($this->filters as $filter) {
|
foreach ($this->filters as $filter) {
|
||||||
@@ -1017,7 +1155,7 @@ class CImage
|
|||||||
$emboss = $this->emboss ? 'e' : null;
|
$emboss = $this->emboss ? 'e' : null;
|
||||||
$blur = $this->blur ? 'b' : null;
|
$blur = $this->blur ? 'b' : null;
|
||||||
$palette = $this->palette ? 'p' : null;
|
$palette = $this->palette ? 'p' : null;
|
||||||
|
|
||||||
$autoRotate = $this->autoRotate ? 'ar' : null;
|
$autoRotate = $this->autoRotate ? 'ar' : null;
|
||||||
|
|
||||||
$this->extension = isset($this->extension)
|
$this->extension = isset($this->extension)
|
||||||
@@ -1058,7 +1196,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Use cached version of image, if possible.
|
* Use cached version of image, if possible.
|
||||||
*
|
*
|
||||||
* @param boolean $useCache is default true, set to false to avoid using cached object.
|
* @param boolean $useCache is default true, set to false to avoid using cached object.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
@@ -1068,7 +1206,7 @@ class CImage
|
|||||||
if ($useCache && is_readable($this->cacheFileName)) {
|
if ($useCache && is_readable($this->cacheFileName)) {
|
||||||
$fileTime = filemtime($this->pathToImage);
|
$fileTime = filemtime($this->pathToImage);
|
||||||
$cacheTime = filemtime($this->cacheFileName);
|
$cacheTime = filemtime($this->cacheFileName);
|
||||||
|
|
||||||
if ($fileTime <= $cacheTime) {
|
if ($fileTime <= $cacheTime) {
|
||||||
if ($this->useCache) {
|
if ($this->useCache) {
|
||||||
if ($this->verbose) {
|
if ($this->verbose) {
|
||||||
@@ -1090,7 +1228,7 @@ class CImage
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error message when failing to load somehow corrupt image.
|
* Error message when failing to load somehow corrupt image.
|
||||||
*
|
*
|
||||||
@@ -1107,11 +1245,11 @@ class CImage
|
|||||||
case 'jpeg':
|
case 'jpeg':
|
||||||
$this->image = imagecreatefromjpeg($this->pathToImage);
|
$this->image = imagecreatefromjpeg($this->pathToImage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'gif':
|
case 'gif':
|
||||||
$this->image = imagecreatefromgif($this->pathToImage);
|
$this->image = imagecreatefromgif($this->pathToImage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'png':
|
case 'png':
|
||||||
$this->image = imagecreatefrompng($this->pathToImage);
|
$this->image = imagecreatefrompng($this->pathToImage);
|
||||||
break;
|
break;
|
||||||
@@ -1145,19 +1283,19 @@ class CImage
|
|||||||
$this->image = @imagecreatefromjpeg($this->pathToImage);
|
$this->image = @imagecreatefromjpeg($this->pathToImage);
|
||||||
$this->image or $this->failedToLoad();
|
$this->image or $this->failedToLoad();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'gif':
|
case 'gif':
|
||||||
$this->image = @imagecreatefromgif($this->pathToImage);
|
$this->image = @imagecreatefromgif($this->pathToImage);
|
||||||
$this->image or $this->failedToLoad();
|
$this->image or $this->failedToLoad();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'png':
|
case 'png':
|
||||||
$this->image = @imagecreatefrompng($this->pathToImage);
|
$this->image = @imagecreatefrompng($this->pathToImage);
|
||||||
$this->image or $this->failedToLoad();
|
$this->image or $this->failedToLoad();
|
||||||
|
|
||||||
$type = $this->getPngType();
|
$type = $this->getPngType();
|
||||||
$hasFewColors = imagecolorstotal($this->image);
|
$hasFewColors = imagecolorstotal($this->image);
|
||||||
|
|
||||||
if ($type == self::PNG_RGB_PALETTE || ($hasFewColors > 0 && $hasFewColors <= 256)) {
|
if ($type == self::PNG_RGB_PALETTE || ($hasFewColors > 0 && $hasFewColors <= 256)) {
|
||||||
if ($this->verbose) {
|
if ($this->verbose) {
|
||||||
$this->log("Handle this image as a palette image.");
|
$this->log("Handle this image as a palette image.");
|
||||||
@@ -1175,6 +1313,8 @@ class CImage
|
|||||||
$this->log("imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
|
$this->log("imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
|
||||||
$this->log("imagecolorstotal() : " . imagecolorstotal($this->image));
|
$this->log("imagecolorstotal() : " . imagecolorstotal($this->image));
|
||||||
$this->log("Number of colors in image = " . $this->colorsTotal($this->image));
|
$this->log("Number of colors in image = " . $this->colorsTotal($this->image));
|
||||||
|
$index = imagecolortransparent($this->image);
|
||||||
|
$this->log("Detected transparent color = " . ($index > 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@@ -1193,7 +1333,7 @@ class CImage
|
|||||||
$pngType = ord(file_get_contents($this->pathToImage, false, null, 25, 1));
|
$pngType = ord(file_get_contents($this->pathToImage, false, null, 25, 1));
|
||||||
|
|
||||||
switch ($pngType) {
|
switch ($pngType) {
|
||||||
|
|
||||||
case self::PNG_GREYSCALE:
|
case self::PNG_GREYSCALE:
|
||||||
$this->log("PNG is type 0, Greyscale.");
|
$this->log("PNG is type 0, Greyscale.");
|
||||||
break;
|
break;
|
||||||
@@ -1209,7 +1349,7 @@ class CImage
|
|||||||
case self::PNG_GREYSCALE_ALPHA:
|
case self::PNG_GREYSCALE_ALPHA:
|
||||||
$this->Log("PNG is type 4, Greyscale with alpha channel");
|
$this->Log("PNG is type 4, Greyscale with alpha channel");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case self::PNG_RGB_ALPHA:
|
case self::PNG_RGB_ALPHA:
|
||||||
$this->Log("PNG is type 6, RGB with alpha channel (PNG 32-bit)");
|
$this->Log("PNG is type 6, RGB with alpha channel (PNG 32-bit)");
|
||||||
break;
|
break;
|
||||||
@@ -1223,12 +1363,12 @@ class CImage
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate number of colors in an image.
|
* Calculate number of colors in an image.
|
||||||
*
|
*
|
||||||
* @param resource $im the image.
|
* @param resource $im the image.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
private function colorsTotal($im)
|
private function colorsTotal($im)
|
||||||
{
|
{
|
||||||
@@ -1304,7 +1444,7 @@ class CImage
|
|||||||
|
|
||||||
// Only use a specified area of the image, $this->offset is defining the area to use
|
// Only use a specified area of the image, $this->offset is defining the area to use
|
||||||
if (isset($this->offset)) {
|
if (isset($this->offset)) {
|
||||||
|
|
||||||
$this->log("Offset for area to use, cropping it width={$this->offset['width']}, height={$this->offset['height']}, start_x={$this->offset['left']}, start_y={$this->offset['top']}");
|
$this->log("Offset for area to use, cropping it width={$this->offset['width']}, height={$this->offset['height']}, start_x={$this->offset['left']}, start_y={$this->offset['top']}");
|
||||||
$img = $this->CreateImageKeepTransparency($this->offset['width'], $this->offset['height']);
|
$img = $this->CreateImageKeepTransparency($this->offset['width'], $this->offset['height']);
|
||||||
imagecopy($img, $this->image, 0, 0, $this->offset['left'], $this->offset['top'], $this->offset['width'], $this->offset['height']);
|
imagecopy($img, $this->image, 0, 0, $this->offset['left'], $this->offset['top'], $this->offset['width'], $this->offset['height']);
|
||||||
@@ -1312,7 +1452,7 @@ class CImage
|
|||||||
$this->width = $this->offset['width'];
|
$this->width = $this->offset['width'];
|
||||||
$this->height = $this->offset['height'];
|
$this->height = $this->offset['height'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->crop) {
|
if ($this->crop) {
|
||||||
|
|
||||||
// Do as crop, take only part of image
|
// Do as crop, take only part of image
|
||||||
@@ -1329,15 +1469,15 @@ class CImage
|
|||||||
// likely to be more readable code.
|
// likely to be more readable code.
|
||||||
// The code is more or leass equal in below crop-to-fit, fill-to-fit and stretch
|
// The code is more or leass equal in below crop-to-fit, fill-to-fit and stretch
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->cropToFit) {
|
if ($this->cropToFit) {
|
||||||
|
|
||||||
// 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));
|
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
|
||||||
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
|
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
|
||||||
|
|
||||||
@@ -1347,7 +1487,7 @@ class CImage
|
|||||||
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->newHeight > $this->height) {
|
if ($this->newHeight > $this->height) {
|
||||||
$posY = round(($this->newHeight - $this->height) / 2);
|
$posY = round(($this->newHeight - $this->height) / 2);
|
||||||
}
|
}
|
||||||
@@ -1366,9 +1506,9 @@ class CImage
|
|||||||
$this->image = $imageResized;
|
$this->image = $imageResized;
|
||||||
$this->width = $this->newWidth;
|
$this->width = $this->newWidth;
|
||||||
$this->height = $this->newHeight;
|
$this->height = $this->newHeight;
|
||||||
|
|
||||||
} else if ($this->fillToFit) {
|
} else if ($this->fillToFit) {
|
||||||
|
|
||||||
// Resize by fill to fit
|
// Resize by fill to fit
|
||||||
$this->log("Resizing using strategy - Fill to fit");
|
$this->log("Resizing using strategy - Fill to fit");
|
||||||
|
|
||||||
@@ -1388,13 +1528,13 @@ 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->fillWidth - $this->width) / 2);
|
||||||
$posY = round(($this->fillHeight - $this->height) / 2);
|
$posY = round(($this->fillHeight - $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->fillWidth, $this->fillHeight);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
|
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
|
||||||
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
|
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
|
||||||
@@ -1405,9 +1545,9 @@ class CImage
|
|||||||
$this->image = $imageResized;
|
$this->image = $imageResized;
|
||||||
$this->width = $this->newWidth;
|
$this->width = $this->newWidth;
|
||||||
$this->height = $this->newHeight;
|
$this->height = $this->newHeight;
|
||||||
|
|
||||||
} else if (!($this->newWidth == $this->width && $this->newHeight == $this->height)) {
|
} else if (!($this->newWidth == $this->width && $this->newHeight == $this->height)) {
|
||||||
|
|
||||||
// Resize it
|
// Resize it
|
||||||
$this->log("Resizing, new height and/or width");
|
$this->log("Resizing, new height and/or width");
|
||||||
|
|
||||||
@@ -1473,24 +1613,24 @@ class CImage
|
|||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
if (isset($this->filters) && is_array($this->filters)) {
|
if (isset($this->filters) && is_array($this->filters)) {
|
||||||
|
|
||||||
foreach ($this->filters as $filter) {
|
foreach ($this->filters as $filter) {
|
||||||
$this->log("Applying filter {$filter['type']}.");
|
$this->log("Applying filter {$filter['type']}.");
|
||||||
|
|
||||||
switch ($filter['argc']) {
|
switch ($filter['argc']) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
imagefilter($this->image, $filter['type']);
|
imagefilter($this->image, $filter['type']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
imagefilter($this->image, $filter['type'], $filter['arg1']);
|
imagefilter($this->image, $filter['type'], $filter['arg1']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2']);
|
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2'], $filter['arg3']);
|
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2'], $filter['arg3']);
|
||||||
break;
|
break;
|
||||||
@@ -1535,11 +1675,11 @@ class CImage
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate image using angle.
|
* Rotate image using angle.
|
||||||
*
|
*
|
||||||
* @param float $angle to rotate image.
|
* @param float $angle to rotate image.
|
||||||
* @param int $anglebgColor to fill image with if needed.
|
* @param int $anglebgColor to fill image with if needed.
|
||||||
*
|
*
|
||||||
@@ -1551,7 +1691,7 @@ class CImage
|
|||||||
|
|
||||||
$color = $this->getBackgroundColor();
|
$color = $this->getBackgroundColor();
|
||||||
$this->image = imagerotate($this->image, $angle, $color);
|
$this->image = imagerotate($this->image, $angle, $color);
|
||||||
|
|
||||||
$this->width = imagesx($this->image);
|
$this->width = imagesx($this->image);
|
||||||
$this->height = imagesy($this->image);
|
$this->height = imagesy($this->image);
|
||||||
|
|
||||||
@@ -1564,7 +1704,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate image using information in EXIF.
|
* Rotate image using information in EXIF.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function rotateExif()
|
public function rotateExif()
|
||||||
@@ -1599,7 +1739,7 @@ class CImage
|
|||||||
} else {
|
} else {
|
||||||
$this->log("Autorotate ignored, no orientation in EXIF.");
|
$this->log("Autorotate ignored, no orientation in EXIF.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1633,7 +1773,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sharpen image using image convolution.
|
* Sharpen image using image convolution.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function sharpenImage()
|
public function sharpenImage()
|
||||||
@@ -1646,7 +1786,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Emboss image using image convolution.
|
* Emboss image using image convolution.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function embossImage()
|
public function embossImage()
|
||||||
@@ -1659,7 +1799,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Blur image using image convolution.
|
* Blur image using image convolution.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function blurImage()
|
public function blurImage()
|
||||||
@@ -1672,7 +1812,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create convolve expression and return arguments for image convolution.
|
* Create convolve expression and return arguments for image convolution.
|
||||||
*
|
*
|
||||||
* @param string $expression constant string which evaluates to a list of
|
* @param string $expression constant string which evaluates to a list of
|
||||||
* 11 numbers separated by komma or such a list.
|
* 11 numbers separated by komma or such a list.
|
||||||
*
|
*
|
||||||
@@ -1691,17 +1831,17 @@ class CImage
|
|||||||
// Expect list of 11 numbers, split by , and build up arguments
|
// Expect list of 11 numbers, split by , and build up arguments
|
||||||
if (count($part) != 11) {
|
if (count($part) != 11) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Missmatch in argument convolve. Expected comma-separated string with
|
"Missmatch in argument convolve. Expected comma-separated string with
|
||||||
11 float values. Got $expression."
|
11 float values. Got $expression."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_walk($part, function ($item, $key) {
|
array_walk($part, function ($item, $key) {
|
||||||
if (!is_numeric($item)) {
|
if (!is_numeric($item)) {
|
||||||
throw new Exception("Argument to convolve expression should be float but is not.");
|
throw new Exception("Argument to convolve expression should be float but is not.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array(
|
array(
|
||||||
array($part[0], $part[1], $part[2]),
|
array($part[0], $part[1], $part[2]),
|
||||||
@@ -1717,7 +1857,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add custom expressions (or overwrite existing) for image convolution.
|
* Add custom expressions (or overwrite existing) for image convolution.
|
||||||
*
|
*
|
||||||
* @param array $options Key value array with strings to be converted
|
* @param array $options Key value array with strings to be converted
|
||||||
* to convolution expressions.
|
* to convolution expressions.
|
||||||
*
|
*
|
||||||
@@ -1733,7 +1873,7 @@ class CImage
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Image convolution.
|
* Image convolution.
|
||||||
*
|
*
|
||||||
* @param string $options A string with 11 float separated by comma.
|
* @param string $options A string with 11 float separated by comma.
|
||||||
*
|
*
|
||||||
* @return $this
|
* @return $this
|
||||||
@@ -1752,7 +1892,7 @@ class CImage
|
|||||||
list($matrix, $divisor, $offset) = $this->createConvolveArguments($option);
|
list($matrix, $divisor, $offset) = $this->createConvolveArguments($option);
|
||||||
imageconvolution($this->image, $matrix, $divisor, $offset);
|
imageconvolution($this->image, $matrix, $divisor, $offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1842,7 +1982,7 @@ class CImage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a image and keep transparency for png and gifs.
|
* Create a image and keep transparency for png and gifs.
|
||||||
@@ -1859,7 +1999,17 @@ class CImage
|
|||||||
imagealphablending($img, false);
|
imagealphablending($img, false);
|
||||||
imagesavealpha($img, true);
|
imagesavealpha($img, true);
|
||||||
|
|
||||||
if ($this->bgColorDefault) {
|
$index = imagecolortransparent($this->image);
|
||||||
|
if ($index != -1) {
|
||||||
|
|
||||||
|
imagealphablending($img, true);
|
||||||
|
$transparent = imagecolorsforindex($this->image, $index);
|
||||||
|
$color = imagecolorallocatealpha($img, $transparent['red'], $transparent['green'], $transparent['blue'], $transparent['alpha']);
|
||||||
|
imagefill($img, 0, 0, $color);
|
||||||
|
$index = imagecolortransparent($img, $color);
|
||||||
|
$this->Log("Detected transparent color = " . implode(", ", $transparent) . " at index = $index");
|
||||||
|
|
||||||
|
} elseif ($this->bgColorDefault) {
|
||||||
|
|
||||||
$color = $this->getBackgroundColor($img);
|
$color = $this->getBackgroundColor($img);
|
||||||
imagefill($img, 0, 0, $color);
|
imagefill($img, 0, 0, $color);
|
||||||
@@ -1869,10 +2019,10 @@ class CImage
|
|||||||
return $img;
|
return $img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set optimizing and post-processing options.
|
* Set optimizing and post-processing options.
|
||||||
*
|
*
|
||||||
* @param array $options with config for postprocessing with external tools.
|
* @param array $options with config for postprocessing with external tools.
|
||||||
*
|
*
|
||||||
@@ -1897,7 +2047,7 @@ class CImage
|
|||||||
} else {
|
} else {
|
||||||
$this->pngDeflateCmd = null;
|
$this->pngDeflateCmd = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1921,12 +2071,12 @@ class CImage
|
|||||||
or $this->raiseError('Target directory is not writable.');
|
or $this->raiseError('Target directory is not writable.');
|
||||||
|
|
||||||
switch(strtolower($this->extension)) {
|
switch(strtolower($this->extension)) {
|
||||||
|
|
||||||
case 'jpeg':
|
case 'jpeg':
|
||||||
case 'jpg':
|
case 'jpg':
|
||||||
$this->Log("Saving image as JPEG to cache using quality = {$this->quality}.");
|
$this->Log("Saving image as JPEG to cache using quality = {$this->quality}.");
|
||||||
imagejpeg($this->image, $this->cacheFileName, $this->quality);
|
imagejpeg($this->image, $this->cacheFileName, $this->quality);
|
||||||
|
|
||||||
// Use JPEG optimize if defined
|
// Use JPEG optimize if defined
|
||||||
if ($this->jpegOptimizeCmd) {
|
if ($this->jpegOptimizeCmd) {
|
||||||
if ($this->verbose) {
|
if ($this->verbose) {
|
||||||
@@ -1942,10 +2092,8 @@ class CImage
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'gif':
|
case 'gif':
|
||||||
if ($this->saveFolder) {
|
$this->Log("Saving image as GIF to cache.");
|
||||||
$this->Log("Saving image as GIF to cache.");
|
imagegif($this->image, $this->cacheFileName);
|
||||||
imagegif($this->image, $this->cacheFileName);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'png':
|
case 'png':
|
||||||
@@ -1955,7 +2103,7 @@ class CImage
|
|||||||
imagealphablending($this->image, false);
|
imagealphablending($this->image, false);
|
||||||
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 filter PNG, if defined
|
// Use external program to filter PNG, if defined
|
||||||
if ($this->pngFilterCmd) {
|
if ($this->pngFilterCmd) {
|
||||||
if ($this->verbose) {
|
if ($this->verbose) {
|
||||||
@@ -1994,6 +2142,42 @@ class CImage
|
|||||||
$this->log("imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
|
$this->log("imageistruecolor() : " . (imageistruecolor($this->image) ? 'true' : 'false'));
|
||||||
$this->log("imagecolorstotal() : " . imagecolorstotal($this->image));
|
$this->log("imagecolorstotal() : " . imagecolorstotal($this->image));
|
||||||
$this->log("Number of colors in image = " . $this->ColorsTotal($this->image));
|
$this->log("Number of colors in image = " . $this->ColorsTotal($this->image));
|
||||||
|
$index = imagecolortransparent($this->image);
|
||||||
|
$this->log("Detected transparent color = " . ($index > 0 ? implode(", ", imagecolorsforindex($this->image, $index)) : "NONE") . " at index = $index");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a hard link, as an alias, to the cached file.
|
||||||
|
*
|
||||||
|
* @param string $alias where to store the link,
|
||||||
|
* filename without extension.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function linkToCacheFile($alias)
|
||||||
|
{
|
||||||
|
if ($alias === null) {
|
||||||
|
$this->log("Ignore creating alias.");
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
$alias = $alias . "." . $this->extension;
|
||||||
|
|
||||||
|
if (is_readable($alias)) {
|
||||||
|
unlink($alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = link($this->cacheFileName, $alias);
|
||||||
|
|
||||||
|
if ($res) {
|
||||||
|
$this->log("Created an alias as: $alias");
|
||||||
|
} else {
|
||||||
|
$this->log("Failed to create the alias: $alias");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@@ -2039,17 +2223,17 @@ class CImage
|
|||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
$this->verboseOutput();
|
$this->verboseOutput();
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
header("HTTP/1.0 304 Not Modified");
|
header("HTTP/1.0 304 Not Modified");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ($this->verbose) {
|
if ($this->verbose) {
|
||||||
$this->log("Last modified: " . $gmdate . " GMT");
|
$this->log("Last modified: " . $gmdate . " GMT");
|
||||||
$this->verboseOutput();
|
$this->verboseOutput();
|
||||||
@@ -2064,7 +2248,7 @@ class CImage
|
|||||||
header('Content-type: ' . $mime);
|
header('Content-type: ' . $mime);
|
||||||
readfile($file);
|
readfile($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2108,7 +2292,7 @@ class CImage
|
|||||||
if (defined("JSON_PRETTY_PRINT") && defined("JSON_UNESCAPED_SLASHES")) {
|
if (defined("JSON_PRETTY_PRINT") && defined("JSON_UNESCAPED_SLASHES")) {
|
||||||
$options = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES;
|
$options = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES;
|
||||||
}
|
}
|
||||||
|
|
||||||
return json_encode($details, $options);
|
return json_encode($details, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2129,9 +2313,9 @@ class CImage
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do verbose output and print out the log and the actual images.
|
* Do verbose output and print out the log and the actual images.
|
||||||
*
|
*
|
||||||
@@ -2146,7 +2330,7 @@ class CImage
|
|||||||
|
|
||||||
$included = get_included_files();
|
$included = get_included_files();
|
||||||
$this->log("Included files: " . count($included));
|
$this->log("Included files: " . count($included));
|
||||||
|
|
||||||
foreach ($this->log as $val) {
|
foreach ($this->log as $val) {
|
||||||
if (is_array($val)) {
|
if (is_array($val)) {
|
||||||
foreach ($val as $val1) {
|
foreach ($val as $val1) {
|
||||||
@@ -2175,7 +2359,7 @@ EOD;
|
|||||||
*
|
*
|
||||||
* @param string $message the error message to display.
|
* @param string $message the error message to display.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function raiseError($message)
|
private function raiseError($message)
|
||||||
|
351
CRemoteImage.php
Normal file
351
CRemoteImage.php
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Get a image from a remote server using HTTP GET and If-Modified-Since.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CRemoteImage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Path to cache files.
|
||||||
|
*/
|
||||||
|
private $saveFolder = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use cache or not.
|
||||||
|
*/
|
||||||
|
private $useCache = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP object to aid in download file.
|
||||||
|
*/
|
||||||
|
private $http;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status of the HTTP request.
|
||||||
|
*/
|
||||||
|
private $status;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defalt age for cached items 60*60*24*7.
|
||||||
|
*/
|
||||||
|
private $defaultMaxAge = 604800;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Url of downloaded item.
|
||||||
|
*/
|
||||||
|
private $url;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base name of cache file for downloaded item.
|
||||||
|
*/
|
||||||
|
private $fileName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filename for json-file with details of cached item.
|
||||||
|
*/
|
||||||
|
private $fileJson;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filename for image-file.
|
||||||
|
*/
|
||||||
|
private $fileImage;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache details loaded from file.
|
||||||
|
*/
|
||||||
|
private $cache;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get status of last HTTP request.
|
||||||
|
*
|
||||||
|
* @return int as status
|
||||||
|
*/
|
||||||
|
public function getStatus()
|
||||||
|
{
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get JSON details for cache item.
|
||||||
|
*
|
||||||
|
* @return array with json details on cache.
|
||||||
|
*/
|
||||||
|
public function getDetails()
|
||||||
|
{
|
||||||
|
return $this->cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the path to the cache directory.
|
||||||
|
*
|
||||||
|
* @param boolean $use true to use the cache and false to ignore cache.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCache($path)
|
||||||
|
{
|
||||||
|
$this->saveFolder = $path;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if cache is writable or throw exception.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws Exception if cahce folder is not writable.
|
||||||
|
*/
|
||||||
|
public function isCacheWritable()
|
||||||
|
{
|
||||||
|
if (!is_writable($this->saveFolder)) {
|
||||||
|
throw new Exception("Cache folder is not writable for downloaded files.");
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decide if the cache should be used or not before trying to download
|
||||||
|
* a remote file.
|
||||||
|
*
|
||||||
|
* @param boolean $use true to use the cache and false to ignore cache.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function useCache($use = true)
|
||||||
|
{
|
||||||
|
$this->useCache = $use;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate a content type to a file extension.
|
||||||
|
*
|
||||||
|
* @param string $type a valid content type.
|
||||||
|
*
|
||||||
|
* @return string as file extension or false if no match.
|
||||||
|
*/
|
||||||
|
function contentTypeToFileExtension($type) {
|
||||||
|
$extension = array(
|
||||||
|
'image/jpeg' => 'jpg',
|
||||||
|
'image/png' => 'png',
|
||||||
|
'image/gif' => 'gif',
|
||||||
|
);
|
||||||
|
|
||||||
|
return isset($extension[$type])
|
||||||
|
? $extension[$type]
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set header fields.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
function setHeaderFields() {
|
||||||
|
$this->http->setHeader("User-Agent", "CImage/0.6 (PHP/". phpversion() . " cURL)");
|
||||||
|
$this->http->setHeader("Accept", "image/jpeg,image/png,image/gif");
|
||||||
|
|
||||||
|
if ($this->useCache) {
|
||||||
|
$this->http->setHeader("Cache-Control", "max-age=0");
|
||||||
|
} else {
|
||||||
|
$this->http->setHeader("Cache-Control", "no-cache");
|
||||||
|
$this->http->setHeader("Pragma", "no-cache");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save downloaded resource to cache.
|
||||||
|
*
|
||||||
|
* @return string as path to saved file or false if not saved.
|
||||||
|
*/
|
||||||
|
function save() {
|
||||||
|
|
||||||
|
$this->cache = array();
|
||||||
|
$date = $this->http->getDate(time());
|
||||||
|
$maxAge = $this->http->getMaxAge($this->defaultMaxAge);
|
||||||
|
$lastModified = $this->http->getLastModified();
|
||||||
|
$type = $this->http->getContentType();
|
||||||
|
$extension = $this->contentTypeToFileExtension($type);
|
||||||
|
|
||||||
|
$this->cache['Date'] = gmdate("D, d M Y H:i:s T", $date);
|
||||||
|
$this->cache['Max-Age'] = $maxAge;
|
||||||
|
$this->cache['Content-Type'] = $type;
|
||||||
|
$this->cache['File-Extension'] = $extension;
|
||||||
|
|
||||||
|
if ($lastModified) {
|
||||||
|
$this->cache['Last-Modified'] = gmdate("D, d M Y H:i:s T", $lastModified);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($extension) {
|
||||||
|
|
||||||
|
$this->fileImage = $this->fileName . "." . $extension;
|
||||||
|
|
||||||
|
// Save only if body is a valid image
|
||||||
|
$body = $this->http->getBody();
|
||||||
|
$img = imagecreatefromstring($body);
|
||||||
|
|
||||||
|
if ($img !== false) {
|
||||||
|
file_put_contents($this->fileImage, $body);
|
||||||
|
file_put_contents($this->fileJson, json_encode($this->cache));
|
||||||
|
return $this->fileImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Got a 304 and updates cache with new age.
|
||||||
|
*
|
||||||
|
* @return string as path to cached file.
|
||||||
|
*/
|
||||||
|
function updateCacheDetails() {
|
||||||
|
|
||||||
|
$date = $this->http->getDate(time());
|
||||||
|
$maxAge = $this->http->getMaxAge($this->defaultMaxAge);
|
||||||
|
$lastModified = $this->http->getLastModified();
|
||||||
|
|
||||||
|
$this->cache['Date'] = gmdate("D, d M Y H:i:s T", $date);
|
||||||
|
$this->cache['Max-Age'] = $maxAge;
|
||||||
|
|
||||||
|
if ($lastModified) {
|
||||||
|
$this->cache['Last-Modified'] = gmdate("D, d M Y H:i:s T", $lastModified);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($this->fileJson, json_encode($this->cache));
|
||||||
|
return $this->fileImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download a remote file and keep a cache of downloaded files.
|
||||||
|
*
|
||||||
|
* @param string $url a remote url.
|
||||||
|
*
|
||||||
|
* @return string as path to downloaded file or false if failed.
|
||||||
|
*/
|
||||||
|
function download($url) {
|
||||||
|
|
||||||
|
$this->http = new CHttpGet();
|
||||||
|
$this->url = $url;
|
||||||
|
|
||||||
|
// First check if the cache is valid and can be used
|
||||||
|
$this->loadCacheDetails();
|
||||||
|
|
||||||
|
if ($this->useCache) {
|
||||||
|
$src = $this->getCachedSource();
|
||||||
|
if ($src) {
|
||||||
|
$this->status = 1;
|
||||||
|
return $src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a HTTP request to download item
|
||||||
|
$this->setHeaderFields();
|
||||||
|
$this->http->setUrl($this->url);
|
||||||
|
$this->http->doGet();
|
||||||
|
|
||||||
|
$this->status = $this->http->getStatus();
|
||||||
|
if ($this->status === 200) {
|
||||||
|
$this->isCacheWritable();
|
||||||
|
return $this->save();
|
||||||
|
} else if ($this->status === 304) {
|
||||||
|
$this->isCacheWritable();
|
||||||
|
return $this->updateCacheDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the cached image file if the cache is valid.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function loadCacheDetails()
|
||||||
|
{
|
||||||
|
$cacheFile = str_replace(array("/", ":", "#", ".", "?"), "-", $this->url);
|
||||||
|
$this->fileName = $this->saveFolder . $cacheFile;
|
||||||
|
$this->fileJson = $this->fileName . ".json";
|
||||||
|
if (is_readable($this->fileJson)) {
|
||||||
|
$this->cache = json_decode(file_get_contents($this->fileJson), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the cached image file if the cache is valid.
|
||||||
|
*
|
||||||
|
* @return string as the path ot the image file or false if no cache.
|
||||||
|
*/
|
||||||
|
public function getCachedSource()
|
||||||
|
{
|
||||||
|
$this->fileImage = $this->fileName . "." . $this->cache['File-Extension'];
|
||||||
|
$imageExists = is_readable($this->fileImage);
|
||||||
|
|
||||||
|
// Is cache valid?
|
||||||
|
$date = strtotime($this->cache['Date']);
|
||||||
|
$maxAge = $this->cache['Max-Age'];
|
||||||
|
$now = time();
|
||||||
|
if ($imageExists && $date + $maxAge > $now) {
|
||||||
|
return $this->fileImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare for a 304 if available
|
||||||
|
if ($imageExists && isset($this->cache['Last-Modified'])) {
|
||||||
|
$this->http->setHeader("If-Modified-Since", $this->cache['Last-Modified']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
218
README.md
218
README.md
@@ -12,20 +12,20 @@ This software is free and open source, licensed according MIT.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Use case
|
Use case
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
You got an image from your friend who took it with the iPhone and you want to put it up on your website.
|
You got an image from your friend who took it with the iPhone and you want to put it up on your website.
|
||||||
|
|
||||||
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=issue36/me-270.jpg&w=300" alt="">
|
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=issue36/me-270.jpg&w=300" alt="">
|
||||||
|
|
||||||
The original image is looking like this one, scaled down to a width of 300 pixels.
|
The original image is looking like this one, scaled down to a width of 300 pixels.
|
||||||
|
|
||||||
So, you need to rotate it and crop off some parts to make it intresting.
|
So, you need to rotate it and crop off some parts to make it intresting.
|
||||||
|
|
||||||
To show it off, I'll autorotate the image based on its EXIF-information, I will crop it to a thumbnail of 100x100 pixels and add a filter to make it greyscale finishing up with a sharpen effect. Just for the show I'll rotate the image 25 degrees - do not ask me why.
|
To show it off, I'll autorotate the image based on its EXIF-information, I will crop it to a thumbnail of 100x100 pixels and add a filter to make it greyscale finishing up with a sharpen effect. Just for the show I'll rotate the image 25 degrees - do not ask me why.
|
||||||
|
|
||||||
Lets call this *the URL-Photoshopper*. This is how the magic looks like.
|
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`<br>`&convolve=sharpen-alt`
|
`img.php?src=issue36/me-270.jpg&w=100&h=100&cf&aro&rb=-25&a=8,30,30,38&f=grayscale`<br>`&convolve=sharpen-alt`
|
||||||
|
|
||||||
@@ -38,14 +38,14 @@ For myself, I use `img.php` to put up all images on my website, it gives me the
|
|||||||
Requirements
|
Requirements
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
`CImage` and `img.php` supports GIF (with transparency), JPEG and PNG (8bit transparent, 24bit semi transparent) images. It requires PHP 5.3 and PHP GD. You optionally need the EXIF extension to support auto-rotation of JPEG-images.
|
`CImage` and `img.php` supports GIF (with transparency), JPEG and PNG (8bit transparent, 24bit semi transparent) images. It requires PHP 5.3 and PHP GD. You optionally need the EXIF extension to support auto-rotation of JPEG-images.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
I prefer cloning like this. Do switch to the latest stable version.
|
I prefer cloning like this. Do switch to the latest stable version.
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ chmod 777 cache
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Get going quickly
|
Get going quickly
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -76,7 +76,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&w=w2&a=40,0,50,0" alt=''>
|
<img src="http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim04.png&w=w2&a=40,0,50,0" alt=''>
|
||||||
|
|
||||||
@@ -84,15 +84,15 @@ Try it yourself by opening up an image in your browser. Start with `webroot/img.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
###What does "processing the image" involves?
|
###What does "processing the image" involves?
|
||||||
|
|
||||||
Add `&verbose` to the link to get a verbose output of what is happens during image processing. This is useful for developers or those who seek a deeper understanding on how it all works.
|
Add `&verbose` to the link to get a verbose output of what is happens during image processing. This is useful for developers or those who seek a deeper understanding on how it all works.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###Check your system
|
###Check your system
|
||||||
|
|
||||||
Open up `webroot/check_system.php` if you need to troubleshoot or if you are uncertain if your system has the right extensions loaded.
|
Open up `webroot/check_system.php` if you need to troubleshoot or if you are uncertain if your system has the right extensions loaded.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -106,13 +106,13 @@ The programatic flow, just to get you oriented in the environment, is.
|
|||||||
2. `img.php` reads configuration details from `img_config.php`.
|
2. `img.php` reads configuration details from `img_config.php`.
|
||||||
3. `img.php` reads and processes incoming `$_GET` arguments to prepare using `CImage`.
|
3. `img.php` reads and processes incoming `$_GET` arguments to prepare using `CImage`.
|
||||||
4. `img.php` uses `CImage`.
|
4. `img.php` uses `CImage`.
|
||||||
5. `CImage` processes and outputs the image according to how its used.
|
5. `CImage` processes and outputs the image according to how its used.
|
||||||
|
|
||||||
Read on to learn more on how to use `img.php`.
|
Read on to learn more on how to use `img.php`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Basic usage
|
Basic usage
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -127,11 +127,11 @@ It looks like this.
|
|||||||
|
|
||||||
<img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=w1&save-as=jpg alt="">
|
<img src=http://dbwebb.se/kod-exempel/cimage/webroot/img.php?src=kodim13.png&w=w1&save-as=jpg alt="">
|
||||||
|
|
||||||
All images are stored in a directory structure and you access them as `?src=dir1/dir2/image.png`.
|
All images are stored in a directory structure and you access them as `?src=dir1/dir2/image.png`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###Resize using constraints on width and height
|
###Resize using constraints on width and height
|
||||||
|
|
||||||
Create a thumbnail of the image by applying constraints on width and height, or one of them.
|
Create a thumbnail of the image by applying constraints on width and height, or one of them.
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ Think of the constraints as a imaginary box where the image should fit. With `wi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
###Resize to fit a certain dimension
|
###Resize to fit a certain dimension
|
||||||
|
|
||||||
Creating a thumbnail with a certain dimension of width and height, usually involves stretching or cropping the image to fit in the selected dimensions. Here is how you create a image that has the exact dimensions of 300x150 pixels, by either *stretching*, *cropping* or *fill to fit*.
|
Creating a thumbnail with a certain dimension of width and height, usually involves stretching or cropping the image to fit in the selected dimensions. Here is how you create a image that has the exact dimensions of 300x150 pixels, by either *stretching*, *cropping* or *fill to fit*.
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ Fill to fit is useful when you have some image that must fit in a certain dimens
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
###List of parameters
|
###List of parameters
|
||||||
|
|
||||||
`img.php` supports a lot of parameters. Combine the parameters to get the desired behavior and resulting image. For example, take the original image, resize it using width, aspect-ratio and crop-to-fit, apply a sharpen effect, save the image as JPEG using quality 30.
|
`img.php` supports a lot of parameters. Combine the parameters to get the desired behavior and resulting image. For example, take the original image, resize it using width, aspect-ratio and crop-to-fit, apply a sharpen effect, save the image as JPEG using quality 30.
|
||||||
|
|
||||||
@@ -173,14 +173,14 @@ Fill to fit is useful when you have some image that must fit in a certain dimens
|
|||||||
|-----------------------------------------------------------|
|
|-----------------------------------------------------------|
|
||||||
| <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=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=''> |
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
||||||
####Mandatory options and debugging
|
####Mandatory options and debugging
|
||||||
|
|
||||||
Option `src` is the only mandatory option. The other in this section is useful for debugging or deciding what version of the target image is used.
|
Option `src` is the only mandatory option. The other in this section is useful for debugging or deciding what version of the target image is used.
|
||||||
|
|
||||||
| Parameter | Explained |
|
| Parameter | Explained |
|
||||||
|----------------|----------------------------------------------|
|
|----------------|----------------------------------------------|
|
||||||
| `src` | Source image to use, mandatory. `src=img.png` or with subdirectory `src=dir/img.png`. |
|
| `src` | Source image to use, mandatory. `src=img.png` or with subdirectory `src=dir/img.png`. |
|
||||||
| `nc, no-cache` | Do not use the cached version, do all image processing and save a new image to cache. |
|
| `nc, no-cache` | Do not use the cached version, do all image processing and save a new image to cache. |
|
||||||
@@ -190,11 +190,11 @@ Option `src` is the only mandatory option. The other in this section is useful f
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
####Options for deciding width and height of target image
|
####Options for deciding width and height of target image
|
||||||
|
|
||||||
These options are all affecting the final dimensions, width and height, of the resulting image.
|
These options are all affecting the final dimensions, width and height, of the resulting image.
|
||||||
|
|
||||||
| Parameter | Explained |
|
| Parameter | Explained |
|
||||||
|----------------|----------------------------------------------|
|
|----------------|----------------------------------------------|
|
||||||
| `h, height` | `h=200` sets the width to be to max 200px. `h=25%` sets the height to max 25% of its original height. |
|
| `h, height` | `h=200` sets the width to be to max 200px. `h=25%` sets the height to max 25% of its original height. |
|
||||||
| `w, width` | `w=200` sets the height to be max 200px. `w=100%` sets the width to max 100% of its original width. |
|
| `w, width` | `w=200` sets the height to be max 200px. `w=100%` sets the width to max 100% of its original width. |
|
||||||
@@ -203,11 +203,11 @@ These options are all affecting the final dimensions, width and height, of the r
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
####Options for resize strategy
|
####Options for resize strategy
|
||||||
|
|
||||||
These options affect strategy to use when resizing an image into a target image that has both width and height set.
|
These options affect strategy to use when resizing an image into a target image that has both width and height set.
|
||||||
|
|
||||||
| Parameter | Explained |
|
| Parameter | Explained |
|
||||||
|----------------|----------------------------------------------|
|
|----------------|----------------------------------------------|
|
||||||
| `nr, no-ratio, stretch` | Do *not* keep aspect ratio when resizing and using both width & height constraints. Results in stretching the image, if needed, to fit in the resulting box. |
|
| `nr, no-ratio, stretch` | Do *not* keep aspect ratio when resizing and using both width & height constraints. Results in stretching the image, if needed, to fit in the resulting box. |
|
||||||
| `cf, crop-to-fit` | Set together with both `h` and `w` to make the image fit into dimensions, and crop out the rest of the image. |
|
| `cf, crop-to-fit` | Set together with both `h` and `w` to make the image fit into dimensions, and crop out the rest of the image. |
|
||||||
@@ -216,32 +216,32 @@ These options affect strategy to use when resizing an image into a target image
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
####Options for cropping part of image
|
####Options for cropping part of image
|
||||||
|
|
||||||
These options enable to decide what part of image to crop out.
|
These options enable to decide what part of image to crop out.
|
||||||
|
|
||||||
| Parameter | Explained |
|
| Parameter | Explained |
|
||||||
|----------------|----------------------------------------------|
|
|----------------|----------------------------------------------|
|
||||||
| `a, area` | Define the area of the image to work with. Set `area=10,10,10,10` (top,right,bottom,left) to crop out the 10% of the outermost area. It works like an offset to define the part of the image you want to process. Its an alternative of using `crop`. |
|
| `a, area` | Define the area of the image to work with. Set `area=10,10,10,10` (top,right,bottom,left) to crop out the 10% of the outermost area. It works like an offset to define the part of the image you want to process. Its an alternative of using `crop`. |
|
||||||
| `c, crop` | Crops an area from the original image, set width, height, start_x and start_y to define the area to crop, for example `crop=100,100,10,10` (`crop=width,height,start_x,start_y`). Left top corner is 0, 0. You can use `left`, `right` or `center` when setting start_x. You may use `top`, `bottom` or `center` when setting start_y. |
|
| `c, crop` | Crops an area from the original image, set width, height, start_x and start_y to define the area to crop, for example `crop=100,100,10,10` (`crop=width,height,start_x,start_y`). Left top corner is 0, 0. You can use `left`, `right` or `center` when setting start_x. You may use `top`, `bottom` or `center` when setting start_y. |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####General processing options
|
####General processing options
|
||||||
|
|
||||||
These options are general options affecting processing.
|
These options are general options affecting processing.
|
||||||
|
|
||||||
| Parameter | Explained |
|
| Parameter | Explained |
|
||||||
|----------------|----------------------------------------------|
|
|----------------|----------------------------------------------|
|
||||||
| `bgc, bg-color` | Set the backgroundcolor to use (if its needed). Use six hex digits as `bgc=00ff00` and 8 digits when using the alpha channel, as this `bgc=00ff007f`. The alpha value can be between 00 and 7f. |
|
| `bgc, bg-color` | Set the backgroundcolor to use (if its needed). Use six hex digits as `bgc=00ff00` and 8 digits when using the alpha channel, as this `bgc=00ff007f`. The alpha value can be between 00 and 7f. |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####Processing of image before resizing
|
####Processing of image before resizing
|
||||||
|
|
||||||
This option are executed *before* the image is resized.
|
This option are executed *before* the image is resized.
|
||||||
|
|
||||||
| Parameter | Explained |
|
| Parameter | Explained |
|
||||||
|----------------|----------------------------------------------|
|
|----------------|----------------------------------------------|
|
||||||
| `s, scale` | Scale the image to a size proportional to a percentage of its original size, `scale=25` makes an image 25% of its original size and `size=200` doubles up the image size. Scale is applied before resizing and has no impact of the target width and height. |
|
| `s, scale` | Scale the image to a size proportional to a percentage of its original size, `scale=25` makes an image 25% of its original size and `size=200` doubles up the image size. Scale is applied before resizing and has no impact of the target width and height. |
|
||||||
| `rb, rotate-before` | Rotate the image before its processed, send the angle as parameter `rb=45`. |
|
| `rb, rotate-before` | Rotate the image before its processed, send the angle as parameter `rb=45`. |
|
||||||
@@ -249,7 +249,7 @@ This option are executed *before* the image is resized.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
####Processing of image after resizing
|
####Processing of image after resizing
|
||||||
|
|
||||||
These options are executed *after* the image is resized.
|
These options are executed *after* the image is resized.
|
||||||
|
|
||||||
@@ -267,7 +267,7 @@ These options are executed *after* the image is resized.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
Read full documentation at:
|
Read full documentation at:
|
||||||
@@ -275,155 +275,7 @@ http://dbwebb.se/opensource/cimage
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Revision history
|
```
|
||||||
-------------------------------------
|
.
|
||||||
|
..: Copyright 2012-2015 by Mikael Roos (me@mikaelroos.se)
|
||||||
|
```
|
||||||
v0.6.1 (2015-01-08)
|
|
||||||
|
|
||||||
* Adding compare-page for comparing images. Issue #20.
|
|
||||||
* Added option `no-upscale, nu` as resizing strategy to decline upscaling of smaller images. Fix #61.
|
|
||||||
* Minor change in `CImage::resize()`, crop now does imagecopy without resamling.
|
|
||||||
* Correcting internal details for save-as and response json which indicated wrong colors. Fix #62.
|
|
||||||
* Fixed fill-to-fit that failed when using aspect-ratio. Fix #52.
|
|
||||||
* JSON returns correct values for resulting image. Fix #58.
|
|
||||||
* Corrected behaviour for skip-original. Fix #60.
|
|
||||||
|
|
||||||
|
|
||||||
v0.6 (2014-12-06)
|
|
||||||
|
|
||||||
* Rewrote and added documentation.
|
|
||||||
* Moved conolution expressesion from `img_config.php` to `CImage`.
|
|
||||||
* Minor cleaning of properties in `CImage`. Fix #23.
|
|
||||||
* Adding `webroot/htaccess` to show off how friendly urls can be created for `img.php`. Fix #45.
|
|
||||||
* Added option `fill-to-fit, ff`. Fix #38.
|
|
||||||
* Added option `shortcut, sc` to enable configuration of complex expressions. Fix #2.
|
|
||||||
* Added support for custom convolutions. Fix #49.
|
|
||||||
* Restructured testprograms. Fix #41.
|
|
||||||
* Corrected json on PHP 5.3. Fix #42.
|
|
||||||
* Improving template for tests in `webroot/tests` when testing out #40.
|
|
||||||
* Adding testcase for #40.
|
|
||||||
* Adding option `convolve` taking comma-separated list of 11 float-values, wraps and exposes `imageconvoluttion()`. #4
|
|
||||||
* Adding option `dpr, device-pixel-ratio` which defaults to 1. Set to 2 to get a twice as large image. Useful for Retina displays. Basically a shortcut to enlarge the image.
|
|
||||||
* Adding utility `cache.bash` to ease gathering stats on cache usage. #21
|
|
||||||
* Cache-directory can now be readonly and serve all cached files, still failing when need to save files. #5
|
|
||||||
* Cache now uses same file extension as original image #37.
|
|
||||||
* Can output image as json format using `json` #11.
|
|
||||||
|
|
||||||
|
|
||||||
v0.5.3 (2014-11-21)
|
|
||||||
|
|
||||||
* Support filenames of uppercase JPEG, JPG, PNG and GIF, as proposed in #37.
|
|
||||||
* Changing `CImage::output()` as proposed in #37.
|
|
||||||
* Adding security check that image filename is always below the path `image_path` as specified in `img_config.php` #37.
|
|
||||||
* Adding configuration item in `img_config.php` for setting valid characters in image filename.
|
|
||||||
* Moving `webroot/test*` into directory `webroot/test`.
|
|
||||||
* `webroot/check_system.php` now outputs if extension for exif is loaded.
|
|
||||||
* Broke API when `initDimensions()` split into two methods, new `initDimensions()` and `loadImageDetails()`.
|
|
||||||
* Added `autoRotate, aro` to auto rotate image based on EXIF information.
|
|
||||||
* Added `bgColor, bgc` to use as backgroundcolor when needing a filler color, for example rotate 45.
|
|
||||||
* Added `rotateBefore, rb` to rotate image a certain angle before processing.
|
|
||||||
* Added `rotateAfter, ra` to rotate image a certain angle after processing.
|
|
||||||
* Cleaned up code formatting, removed trailing spaces.
|
|
||||||
* Removed @ from opening images, better to display correct warning when failing #34, but put it back again.
|
|
||||||
* Setting gd.jpeg_ignore_warning to true as default #34.
|
|
||||||
* `webroot/check_system.php` now outputs version of PHP and GD.
|
|
||||||
* #32 correctly send 404 header when serving an error message.
|
|
||||||
* Trying to verify issue #29, but can not.
|
|
||||||
* Adding structure for testprograms together with, use `webroot/test_issue29.php` as sample.
|
|
||||||
* Improving code formatting.
|
|
||||||
* Moving parts of verbose output from img.php to CImage.php.
|
|
||||||
|
|
||||||
|
|
||||||
v0.5.2 (2014-04-01)
|
|
||||||
|
|
||||||
* Correcting issue #26 providing error message when not using postprocessing.
|
|
||||||
* Correcting issue #27 warning of default timezone.
|
|
||||||
* Removed default $config options in `img.php`, was not used, all configuration should be in `img_config.php`.
|
|
||||||
* Verified known bug - sharpen acts as blur in PHP 5.5.9 and 5.5.10 #28
|
|
||||||
|
|
||||||
|
|
||||||
v0.5.1 (2014-02-12)
|
|
||||||
|
|
||||||
* Display image in README-file.
|
|
||||||
* Create an empty `cache` directory as part of repo.
|
|
||||||
|
|
||||||
|
|
||||||
v0.5 (2014-02-12)
|
|
||||||
|
|
||||||
* Change constant name `CImage::PNG_QUALITY_DEFAULT` to `CImage::PNG_COMPRESSION_DEFAULT`.
|
|
||||||
* Split JPEG quality and PNG compression, `CImage->quality` and `CImage->compression`
|
|
||||||
* Changed `img.php` parameter name `d, deflate` to `co, compress`.
|
|
||||||
* Separating configuration issues from `img.php` to `img_config.php`.
|
|
||||||
* Format code according to PSR-2.
|
|
||||||
* Disabled post-processing JPEG and PNG as default.
|
|
||||||
* This version is supporting PHP 5.3, later versions will require 5.5 or later.
|
|
||||||
* Using GitHub issue tracking for feature requests and planning.
|
|
||||||
* Rewrote [the manual](http://dbwebb.se/opensource/cimage).
|
|
||||||
* Created directory `webroot` and moved some files there.
|
|
||||||
|
|
||||||
|
|
||||||
v0.4.1 (2014-01-27)
|
|
||||||
|
|
||||||
* Changed => to == on Modified-Since.
|
|
||||||
* Always send Last-Modified-Header.
|
|
||||||
* Added `htmlentities()` to verbose output.
|
|
||||||
* Fixed support for jpeg, not only jpg.
|
|
||||||
* Fixed crop whole image by setting crop=0,0,0,0
|
|
||||||
* Use negative values for crop width & height to base calulation on original width/height and withdraw selected amount.
|
|
||||||
* Correcting jpeg when setting quality.
|
|
||||||
* Removed obsolete reference to `$newName` in `CImage::__construct()` (issue 1).
|
|
||||||
|
|
||||||
|
|
||||||
v0.4 (2013-10-08)
|
|
||||||
|
|
||||||
* Improved support for pre-defined sizes.
|
|
||||||
* Adding grid column size as predefined size, c1-c24 for a 24 column grid. Configure in `img.php`.
|
|
||||||
* Corrected error on naming cache-files using subdir.
|
|
||||||
* Corrected calculation error on width & height for crop-to-fit.
|
|
||||||
* Adding effects for sharpen, emboss and blur through imageconvolution using matrixes.
|
|
||||||
* crop-to-fit, add parameter for offset x and y to enable to define which area is the, implemented as area.
|
|
||||||
* Support for resizing opaque images.
|
|
||||||
* Center of the image from which the crop is done. Improved usage of area to crop.
|
|
||||||
* Added support for % in width & height.
|
|
||||||
* Added aspect-ratio.
|
|
||||||
* Added scale.
|
|
||||||
* Quality for PNG images is now knows as deflate.
|
|
||||||
* Added palette to create images with max 256 colors.
|
|
||||||
* Added usage of all parameters to README.md
|
|
||||||
* Added documentation here http://dbwebb.se/opensource/cimage
|
|
||||||
* Adding `.gitignore`
|
|
||||||
* Re-adding `cache` directory
|
|
||||||
|
|
||||||
|
|
||||||
v0.3 (2012-10-02)
|
|
||||||
|
|
||||||
* Added crop. Can crop a area (`width`, `height`, `start_x`, `start_y`) from the original
|
|
||||||
image.
|
|
||||||
* Corrected to make the 304 Not Modified header work.
|
|
||||||
* Predefined sizes can be configured for width in `img.php`.
|
|
||||||
* Corrected to make crop work with width or height in combination with crop-to-fit.
|
|
||||||
|
|
||||||
|
|
||||||
v0.2 (2012-05-09)
|
|
||||||
|
|
||||||
* Implemented filters as in http://php.net/manual/en/function.imagefilter.php
|
|
||||||
* Changed `crop` to `crop_to_fit`, works the same way.
|
|
||||||
* Changed arguments and sends them in array.
|
|
||||||
* Added quality-setting.
|
|
||||||
* Added testcases for above.
|
|
||||||
|
|
||||||
|
|
||||||
v0.1.1 (2012-04-27)
|
|
||||||
|
|
||||||
* Corrected calculation where both width and height were set.
|
|
||||||
|
|
||||||
|
|
||||||
v0.1 (2012-04-25)
|
|
||||||
|
|
||||||
* Initial release after rewriting some older code doing the same, but not that good and flexible.
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
.
|
|
||||||
..: Copyright 2012-2014 by Mikael Roos (me@mikaelroos.se)
|
|
||||||
</pre>
|
|
||||||
|
185
REVISION.md
Normal file
185
REVISION.md
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
Revision history
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
|
||||||
|
v0.7.0-rc.1 (2015-02-10)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Always use password, setting in img_config.php, fix #78.
|
||||||
|
* Resize gif keeping transparency #81.
|
||||||
|
* Now returns statuscode 500 when something fails #55.
|
||||||
|
* Three different modes: strict, production, development #44.
|
||||||
|
* Three files for all-in-one `imgs.php`, `imgp.php`, `imgd.php` #73.
|
||||||
|
* Change name of script all-in-one to `webroot/imgs.php` #73.
|
||||||
|
* Combine all code into one singel script, `webroot/img_single.php` #73.
|
||||||
|
* Disallow hotlinking/leeching by configuration #46.
|
||||||
|
* Alias-name is without extension #47.
|
||||||
|
* Option `alias` now requires `password` to work #47.
|
||||||
|
* Support for option `password, pwd` to protect usage of `alias` and remote download.
|
||||||
|
* Added support for option `alias` that creates a link to a cached version of the image #47.
|
||||||
|
* Create cache directory for remote download if it does not exists.
|
||||||
|
* Cleaned up `img_config.php` and introduced default values for almost all options #72.
|
||||||
|
|
||||||
|
|
||||||
|
v0.6.2 (2015-01-14)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Added support for download of remote images #43.
|
||||||
|
* Added autoloader.
|
||||||
|
|
||||||
|
|
||||||
|
v0.6.1 (2015-01-08)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Adding compare-page for comparing images. Issue #20.
|
||||||
|
* Added option `no-upscale, nu` as resizing strategy to decline upscaling of smaller images. Fix #61.
|
||||||
|
* Minor change in `CImage::resize()`, crop now does imagecopy without resamling.
|
||||||
|
* Correcting internal details for save-as and response json which indicated wrong colors. Fix #62.
|
||||||
|
* Fixed fill-to-fit that failed when using aspect-ratio. Fix #52.
|
||||||
|
* JSON returns correct values for resulting image. Fix #58.
|
||||||
|
* Corrected behaviour for skip-original. Fix #60.
|
||||||
|
|
||||||
|
|
||||||
|
v0.6 (2014-12-06)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Rewrote and added documentation.
|
||||||
|
* Moved conolution expressesion from `img_config.php` to `CImage`.
|
||||||
|
* Minor cleaning of properties in `CImage`. Fix #23.
|
||||||
|
* Adding `webroot/htaccess` to show off how friendly urls can be created for `img.php`. Fix #45.
|
||||||
|
* Added option `fill-to-fit, ff`. Fix #38.
|
||||||
|
* Added option `shortcut, sc` to enable configuration of complex expressions. Fix #2.
|
||||||
|
* Added support for custom convolutions. Fix #49.
|
||||||
|
* Restructured testprograms. Fix #41.
|
||||||
|
* Corrected json on PHP 5.3. Fix #42.
|
||||||
|
* Improving template for tests in `webroot/tests` when testing out #40.
|
||||||
|
* Adding testcase for #40.
|
||||||
|
* Adding option `convolve` taking comma-separated list of 11 float-values, wraps and exposes `imageconvoluttion()`. #4
|
||||||
|
* Adding option `dpr, device-pixel-ratio` which defaults to 1. Set to 2 to get a twice as large image. Useful for Retina displays. Basically a shortcut to enlarge the image.
|
||||||
|
* Adding utility `cache.bash` to ease gathering stats on cache usage. #21
|
||||||
|
* Cache-directory can now be readonly and serve all cached files, still failing when need to save files. #5
|
||||||
|
* Cache now uses same file extension as original image #37.
|
||||||
|
* Can output image as json format using `json` #11.
|
||||||
|
|
||||||
|
|
||||||
|
v0.5.3 (2014-11-21)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Support filenames of uppercase JPEG, JPG, PNG and GIF, as proposed in #37.
|
||||||
|
* Changing `CImage::output()` as proposed in #37.
|
||||||
|
* Adding security check that image filename is always below the path `image_path` as specified in `img_config.php` #37.
|
||||||
|
* Adding configuration item in `img_config.php` for setting valid characters in image filename.
|
||||||
|
* Moving `webroot/test*` into directory `webroot/test`.
|
||||||
|
* `webroot/check_system.php` now outputs if extension for exif is loaded.
|
||||||
|
* Broke API when `initDimensions()` split into two methods, new `initDimensions()` and `loadImageDetails()`.
|
||||||
|
* Added `autoRotate, aro` to auto rotate image based on EXIF information.
|
||||||
|
* Added `bgColor, bgc` to use as backgroundcolor when needing a filler color, for example rotate 45.
|
||||||
|
* Added `rotateBefore, rb` to rotate image a certain angle before processing.
|
||||||
|
* Added `rotateAfter, ra` to rotate image a certain angle after processing.
|
||||||
|
* Cleaned up code formatting, removed trailing spaces.
|
||||||
|
* Removed @ from opening images, better to display correct warning when failing #34, but put it back again.
|
||||||
|
* Setting gd.jpeg_ignore_warning to true as default #34.
|
||||||
|
* `webroot/check_system.php` now outputs version of PHP and GD.
|
||||||
|
* #32 correctly send 404 header when serving an error message.
|
||||||
|
* Trying to verify issue #29, but can not.
|
||||||
|
* Adding structure for testprograms together with, use `webroot/test_issue29.php` as sample.
|
||||||
|
* Improving code formatting.
|
||||||
|
* Moving parts of verbose output from img.php to CImage.php.
|
||||||
|
|
||||||
|
|
||||||
|
v0.5.2 (2014-04-01)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Correcting issue #26 providing error message when not using postprocessing.
|
||||||
|
* Correcting issue #27 warning of default timezone.
|
||||||
|
* Removed default $config options in `img.php`, was not used, all configuration should be in `img_config.php`.
|
||||||
|
* Verified known bug - sharpen acts as blur in PHP 5.5.9 and 5.5.10 #28
|
||||||
|
|
||||||
|
|
||||||
|
v0.5.1 (2014-02-12)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Display image in README-file.
|
||||||
|
* Create an empty `cache` directory as part of repo.
|
||||||
|
|
||||||
|
|
||||||
|
v0.5 (2014-02-12)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Change constant name `CImage::PNG_QUALITY_DEFAULT` to `CImage::PNG_COMPRESSION_DEFAULT`.
|
||||||
|
* Split JPEG quality and PNG compression, `CImage->quality` and `CImage->compression`
|
||||||
|
* Changed `img.php` parameter name `d, deflate` to `co, compress`.
|
||||||
|
* Separating configuration issues from `img.php` to `img_config.php`.
|
||||||
|
* Format code according to PSR-2.
|
||||||
|
* Disabled post-processing JPEG and PNG as default.
|
||||||
|
* This version is supporting PHP 5.3, later versions will require 5.5 or later.
|
||||||
|
* Using GitHub issue tracking for feature requests and planning.
|
||||||
|
* Rewrote [the manual](http://dbwebb.se/opensource/cimage).
|
||||||
|
* Created directory `webroot` and moved some files there.
|
||||||
|
|
||||||
|
|
||||||
|
v0.4.1 (2014-01-27)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Changed => to == on Modified-Since.
|
||||||
|
* Always send Last-Modified-Header.
|
||||||
|
* Added `htmlentities()` to verbose output.
|
||||||
|
* Fixed support for jpeg, not only jpg.
|
||||||
|
* Fixed crop whole image by setting crop=0,0,0,0
|
||||||
|
* Use negative values for crop width & height to base calulation on original width/height and withdraw selected amount.
|
||||||
|
* Correcting jpeg when setting quality.
|
||||||
|
* Removed obsolete reference to `$newName` in `CImage::__construct()` (issue 1).
|
||||||
|
|
||||||
|
|
||||||
|
v0.4 (2013-10-08)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Improved support for pre-defined sizes.
|
||||||
|
* Adding grid column size as predefined size, c1-c24 for a 24 column grid. Configure in `img.php`.
|
||||||
|
* Corrected error on naming cache-files using subdir.
|
||||||
|
* Corrected calculation error on width & height for crop-to-fit.
|
||||||
|
* Adding effects for sharpen, emboss and blur through imageconvolution using matrixes.
|
||||||
|
* crop-to-fit, add parameter for offset x and y to enable to define which area is the, implemented as area.
|
||||||
|
* Support for resizing opaque images.
|
||||||
|
* Center of the image from which the crop is done. Improved usage of area to crop.
|
||||||
|
* Added support for % in width & height.
|
||||||
|
* Added aspect-ratio.
|
||||||
|
* Added scale.
|
||||||
|
* Quality for PNG images is now knows as deflate.
|
||||||
|
* Added palette to create images with max 256 colors.
|
||||||
|
* Added usage of all parameters to README.md
|
||||||
|
* Added documentation here http://dbwebb.se/opensource/cimage
|
||||||
|
* Adding `.gitignore`
|
||||||
|
* Re-adding `cache` directory
|
||||||
|
|
||||||
|
|
||||||
|
v0.3 (2012-10-02)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Added crop. Can crop a area (`width`, `height`, `start_x`, `start_y`) from the original
|
||||||
|
image.
|
||||||
|
* Corrected to make the 304 Not Modified header work.
|
||||||
|
* Predefined sizes can be configured for width in `img.php`.
|
||||||
|
* Corrected to make crop work with width or height in combination with crop-to-fit.
|
||||||
|
|
||||||
|
|
||||||
|
v0.2 (2012-05-09)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Implemented filters as in http://php.net/manual/en/function.imagefilter.php
|
||||||
|
* Changed `crop` to `crop_to_fit`, works the same way.
|
||||||
|
* Changed arguments and sends them in array.
|
||||||
|
* Added quality-setting.
|
||||||
|
* Added testcases for above.
|
||||||
|
|
||||||
|
|
||||||
|
v0.1.1 (2012-04-27)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Corrected calculation where both width and height were set.
|
||||||
|
|
||||||
|
|
||||||
|
v0.1 (2012-04-25)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* Initial release after rewriting some older code doing the same, but not that good and flexible.
|
23
autoload.php
Normal file
23
autoload.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Autoloader for CImage and related class files.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//include __DIR__ . "/../CHttpGet.php";
|
||||||
|
//include __DIR__ . "/../CRemoteImage.php";
|
||||||
|
//include __DIR__ . "/../CImage.php";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autoloader for classes.
|
||||||
|
*
|
||||||
|
* @param string $class the fully-qualified class name.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
spl_autoload_register(function ($class) {
|
||||||
|
//$path = CIMAGE_SOURCE_PATH . "/{$class}.php";
|
||||||
|
$path = __DIR__ . "/{$class}.php";
|
||||||
|
if(is_file($path)) {
|
||||||
|
require($path);
|
||||||
|
}
|
||||||
|
});
|
74
create-img-single.bash
Executable file
74
create-img-single.bash
Executable file
@@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Paths and settings
|
||||||
|
#
|
||||||
|
TARGET_D="webroot/imgd.php"
|
||||||
|
TARGET_P="webroot/imgp.php"
|
||||||
|
TARGET_S="webroot/imgs.php"
|
||||||
|
NEWLINES="\n\n\n"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Specify the utilities used
|
||||||
|
#
|
||||||
|
ECHO="printf"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Main, start by checking basic usage
|
||||||
|
#
|
||||||
|
if [ $# -gt 0 ]
|
||||||
|
then
|
||||||
|
$ECHO "Usage: $0\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Print out details on cache-directory
|
||||||
|
#
|
||||||
|
$ECHO "Creating '$TARGET_D', '$TARGET_P' and '$TARGET_S' by combining the following files:"
|
||||||
|
$ECHO "\n"
|
||||||
|
$ECHO "\n webroot/img_header.php"
|
||||||
|
$ECHO "\n CHttpGet.php"
|
||||||
|
$ECHO "\n CRemoteImage.php"
|
||||||
|
$ECHO "\n CImage.php"
|
||||||
|
$ECHO "\n webroot/img.php"
|
||||||
|
$ECHO "\n"
|
||||||
|
$ECHO "\n'$TARGET_D' is for development mode."
|
||||||
|
$ECHO "\n'$TARGET_P' is for production mode (default mode)."
|
||||||
|
$ECHO "\n'$TARGET_S' is for strict mode."
|
||||||
|
$ECHO "\n"
|
||||||
|
|
||||||
|
$ECHO "\nPress enter to continue. "
|
||||||
|
read answer
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Create the $TARGET_? files
|
||||||
|
#
|
||||||
|
cat webroot/img_header.php > $TARGET_P
|
||||||
|
cat webroot/img_header.php | sed "s|//'mode' => 'production',|'mode' => 'development',|" > $TARGET_D
|
||||||
|
cat webroot/img_header.php | sed "s|//'mode' => 'production',|'mode' => 'development',|" > $TARGET_S
|
||||||
|
|
||||||
|
$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
|
||||||
|
|
||||||
|
tail -n +2 CRemoteImage.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 CImage.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
|
||||||
|
|
||||||
|
$ECHO "\nDone."
|
||||||
|
$ECHO "\n"
|
||||||
|
$ECHO "\n"
|
376
webroot/img.php
376
webroot/img.php
@@ -1,9 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Resize images on the fly using CImage, configuration is made in file named.
|
* Resize and crop images on the fly, store generated images in a cache.
|
||||||
|
*
|
||||||
|
* @author Mikael Roos mos@dbwebb.se
|
||||||
|
* @example http://dbwebb.se/opensource/cimage
|
||||||
|
* @link https://github.com/mosbth/cimage
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
$version = "v0.7.0-rc.1 (2015-02-10)";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,8 +21,16 @@
|
|||||||
*/
|
*/
|
||||||
function errorPage($msg)
|
function errorPage($msg)
|
||||||
{
|
{
|
||||||
header("HTTP/1.0 404 Not Found");
|
global $mode;
|
||||||
die('img.php say 404: ' . $msg);
|
|
||||||
|
header("HTTP/1.0 500 Internal Server Error");
|
||||||
|
|
||||||
|
if ($mode == 'development') {
|
||||||
|
die("[img.php] $msg");
|
||||||
|
} else {
|
||||||
|
error_log("[img.php] $msg");
|
||||||
|
die("HTTP/1.0 500 Internal Server Error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,6 +84,24 @@ function getDefined($key, $defined, $undefined)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Log when verbose mode, when used without argument it returns the result.
|
||||||
*
|
*
|
||||||
@@ -96,20 +128,78 @@ function verbose($msg = null)
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get configuration options from file.
|
* Get configuration options from file, if the file exists, else use $config
|
||||||
|
* if its defined or create an empty $config.
|
||||||
*/
|
*/
|
||||||
$configFile = __DIR__.'/'.basename(__FILE__, '.php').'_config.php';
|
$configFile = __DIR__.'/'.basename(__FILE__, '.php').'_config.php';
|
||||||
$config = require $configFile;
|
|
||||||
|
|
||||||
call_user_func($config['error_reporting']);
|
if (is_file($configFile)) {
|
||||||
|
$config = require $configFile;
|
||||||
|
} else if (!isset($config)) {
|
||||||
|
$config = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verbose, v - do a verbose dump of what happens
|
||||||
|
*/
|
||||||
|
$verbose = getDefined(array('verbose', 'v'), true, false);
|
||||||
|
verbose("img.php version = $version");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set mode as strict, production or development.
|
||||||
|
* Default is production environment.
|
||||||
|
*/
|
||||||
|
$mode = getConfig('mode', 'production');
|
||||||
|
|
||||||
|
// Settings for any mode
|
||||||
|
set_time_limit(20);
|
||||||
|
ini_set('gd.jpeg_ignore_warning', 1);
|
||||||
|
|
||||||
|
if (!extension_loaded('gd')) {
|
||||||
|
errorPage("Extension gd is nod loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specific settings for each mode
|
||||||
|
if ($mode == 'strict') {
|
||||||
|
|
||||||
|
error_reporting(0);
|
||||||
|
ini_set('display_errors', 0);
|
||||||
|
ini_set('log_errors', 1);
|
||||||
|
$verbose = false;
|
||||||
|
|
||||||
|
} else if ($mode == 'production') {
|
||||||
|
|
||||||
|
error_reporting(-1);
|
||||||
|
ini_set('display_errors', 0);
|
||||||
|
ini_set('log_errors', 1);
|
||||||
|
$verbose = false;
|
||||||
|
|
||||||
|
} else if ($mode == 'development') {
|
||||||
|
|
||||||
|
error_reporting(-1);
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
ini_set('log_errors', 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
errorPage("Unknown mode: $mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose("mode = $mode");
|
||||||
|
verbose("error log = " . ini_get('error_log'));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set default timezone if not set or if its set in the config-file.
|
* Set default timezone if not set or if its set in the config-file.
|
||||||
*/
|
*/
|
||||||
if (isset($config['default_timezone'])) {
|
$defaultTimezone = getConfig('default_timezone', null);
|
||||||
date_default_timezone_set($config['default_timezone']);
|
|
||||||
|
if ($defaultTimezone) {
|
||||||
|
date_default_timezone_set($defaultTimezone);
|
||||||
} else if (!ini_get('default_timezone')) {
|
} else if (!ini_get('default_timezone')) {
|
||||||
date_default_timezone_set('UTC');
|
date_default_timezone_set('UTC');
|
||||||
}
|
}
|
||||||
@@ -117,36 +207,128 @@ if (isset($config['default_timezone'])) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* verbose, v - do a verbose dump of what happens
|
* Check if passwords are configured, used and match.
|
||||||
|
* Options decide themself if they require passwords to be used.
|
||||||
*/
|
*/
|
||||||
$verbose = getDefined(array('verbose', 'v'), true, false);
|
$pwdConfig = getConfig('password', false);
|
||||||
|
$pwdAlways = getConfig('password_always', false);
|
||||||
|
$pwd = get(array('password', 'pwd'), null);
|
||||||
|
|
||||||
|
// Check if passwords match, if configured to use passwords
|
||||||
|
$passwordMatch = null;
|
||||||
|
if ($pwdAlways) {
|
||||||
|
|
||||||
|
$passwordMatch = ($pwdConfig === $pwd);
|
||||||
|
if (!$passwordMatch) {
|
||||||
|
errorPage("Password required and does not match or exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif ($pwdConfig && $pwd) {
|
||||||
|
|
||||||
|
$passwordMatch = ($pwdConfig === $pwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose("password match = $passwordMatch");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent hotlinking, leeching, of images by controlling who access them
|
||||||
|
* from where.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$allowHotlinking = getConfig('allow_hotlinking', true);
|
||||||
|
$hotlinkingWhitelist = getConfig('hotlinking_whitelist', array());
|
||||||
|
|
||||||
|
$serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : null;
|
||||||
|
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
|
||||||
|
$refererHost = parse_url($referer, PHP_URL_HOST);
|
||||||
|
|
||||||
|
if (!$allowHotlinking) {
|
||||||
|
if ($passwordMatch) {
|
||||||
|
; // Always allow when password match
|
||||||
|
} else if ($passwordMatch === false) {
|
||||||
|
errorPage("Hotlinking/leeching not allowed when password missmatch.");
|
||||||
|
} else if (!$referer) {
|
||||||
|
errorPage("Hotlinking/leeching not allowed and referer is missing.");
|
||||||
|
} else if (strcmp($serverName, $refererHost) == 0) {
|
||||||
|
; // Allow when serverName matches refererHost
|
||||||
|
} else if (!empty($hotlinkingWhitelist)) {
|
||||||
|
|
||||||
|
$allowedByWhitelist = false;
|
||||||
|
foreach ($hotlinkingWhitelist as $val) {
|
||||||
|
if (preg_match($val, $refererHost)) {
|
||||||
|
$allowedByWhitelist = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$allowedByWhitelist) {
|
||||||
|
errorPage("Hotlinking/leeching not allowed by whitelist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
errorPage("Hotlinking/leeching not allowed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose("allow_hotlinking = $allowHotlinking");
|
||||||
|
verbose("referer = $referer");
|
||||||
|
verbose("referer host = $refererHost");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the source files.
|
||||||
|
*/
|
||||||
|
$autoloader = getConfig('autoloader', false);
|
||||||
|
$cimageClass = getConfig('cimage_class', false);
|
||||||
|
|
||||||
|
if ($autoloader) {
|
||||||
|
require $autoloader;
|
||||||
|
} else if ($cimageClass) {
|
||||||
|
require $cimageClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the class for the image.
|
* Create the class for the image.
|
||||||
*/
|
*/
|
||||||
require $config['cimage_class'];
|
|
||||||
|
|
||||||
$img = new CImage();
|
$img = new CImage();
|
||||||
$img->setVerbose($verbose);
|
$img->setVerbose($verbose);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow or disallow remote download of images from other servers.
|
||||||
|
* Passwords apply if used.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$allowRemote = getConfig('remote_allow', false);
|
||||||
|
|
||||||
|
if ($allowRemote && $passwordMatch !== false) {
|
||||||
|
$pattern = getConfig('remote_pattern', null);
|
||||||
|
$img->setRemoteDownload($allowRemote, $pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shortcut, sc - extend arguments with a constant value, defined
|
* shortcut, sc - extend arguments with a constant value, defined
|
||||||
* in config-file.
|
* in config-file.
|
||||||
*/
|
*/
|
||||||
$shortcut = get(array('shortcut', 'sc'), null);
|
$shortcut = get(array('shortcut', 'sc'), null);
|
||||||
|
$shortcutConfig = getConfig('shortcut', array(
|
||||||
|
'sepia' => "&f=grayscale&f0=brightness,-10&f1=contrast,-20&f2=colorize,120,60,0,0&sharpen",
|
||||||
|
));
|
||||||
|
|
||||||
verbose("shortcut = $shortcut");
|
verbose("shortcut = $shortcut");
|
||||||
|
|
||||||
if (isset($shortcut)
|
if (isset($shortcut)
|
||||||
&& isset($config['shortcut'])
|
&& isset($shortcutConfig[$shortcut])) {
|
||||||
&& isset($config['shortcut'][$shortcut])) {
|
|
||||||
|
parse_str($shortcutConfig[$shortcut], $get);
|
||||||
parse_str($config['shortcut'][$shortcut], $get);
|
verbose("shortcut-constant = {$shortcutConfig[$shortcut]}");
|
||||||
verbose("shortcut-constant = {$config['shortcut'][$shortcut]}");
|
|
||||||
$_GET = array_merge($_GET, $get);
|
$_GET = array_merge($_GET, $get);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,43 +340,76 @@ if (isset($shortcut)
|
|||||||
$srcImage = get('src')
|
$srcImage = get('src')
|
||||||
or errorPage('Must set src-attribute.');
|
or errorPage('Must set src-attribute.');
|
||||||
|
|
||||||
|
|
||||||
// Check for valid/invalid characters
|
// Check for valid/invalid characters
|
||||||
preg_match($config['valid_filename'], $srcImage)
|
$imagePath = getConfig('image_path', __DIR__ . '/img/');
|
||||||
|
$imagePathConstraint = getConfig('image_path_constraint', true);
|
||||||
|
$validFilename = getConfig('valid_filename', '#^[a-z0-9A-Z-/_\.:]+$#');
|
||||||
|
|
||||||
|
preg_match($validFilename, $srcImage)
|
||||||
or errorPage('Filename contains invalid characters.');
|
or errorPage('Filename contains invalid characters.');
|
||||||
|
|
||||||
|
if ($allowRemote && $img->isRemoteSource($srcImage)) {
|
||||||
|
|
||||||
// Check that the image is a file below the directory 'image_path'.
|
// If source is a remote file, ignore local file checks.
|
||||||
if ($config['image_path_constraint']) {
|
|
||||||
|
} else if ($imagePathConstraint) {
|
||||||
$pathToImage = realpath($config['image_path'] . $srcImage);
|
|
||||||
$imageDir = realpath($config['image_path']);
|
// Check that the image is a file below the directory 'image_path'.
|
||||||
|
$pathToImage = realpath($imagePath . $srcImage);
|
||||||
|
$imageDir = realpath($imagePath);
|
||||||
|
|
||||||
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.'
|
||||||
);
|
);
|
||||||
|
|
||||||
substr_compare($imageDir, $pathToImage, 0, strlen($imageDir)) == 0
|
substr_compare($imageDir, $pathToImage, 0, strlen($imageDir)) == 0
|
||||||
or errorPage(
|
or errorPage(
|
||||||
'Security constraint: Source image is not below the directory "image_path"
|
'Security constraint: Source image is not below the directory "image_path"
|
||||||
as specified in the config file img_config.php.'
|
as specified in the config file img_config.php.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
verbose("src = $srcImage");
|
verbose("src = $srcImage");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage size constants from config file, use constants to replace values
|
||||||
|
* for width and height.
|
||||||
|
*/
|
||||||
|
$sizeConstant = getConfig('size_constant', function () {
|
||||||
|
|
||||||
|
// Set sizes to map constant to value, easier to use with width or height
|
||||||
|
$sizes = array(
|
||||||
|
'w1' => 613,
|
||||||
|
'w2' => 630,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add grid column width, useful for use as predefined size for width (or height).
|
||||||
|
$gridColumnWidth = 30;
|
||||||
|
$gridGutterWidth = 10;
|
||||||
|
$gridColumns = 24;
|
||||||
|
|
||||||
|
for ($i = 1; $i <= $gridColumns; $i++) {
|
||||||
|
$sizes['c' . $i] = ($gridColumnWidth + $gridGutterWidth) * $i - $gridGutterWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sizes;
|
||||||
|
});
|
||||||
|
|
||||||
|
$sizes = call_user_func($sizeConstant);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* width, w - set target width, affecting the resulting image width, height and resize options
|
* width, w - set target width, affecting the resulting image width, height and resize options
|
||||||
*/
|
*/
|
||||||
$newWidth = get(array('width', 'w'));
|
$newWidth = get(array('width', 'w'));
|
||||||
|
$maxWidth = getConfig('max_width', 2000);
|
||||||
|
|
||||||
// Check to replace predefined size
|
// Check to replace predefined size
|
||||||
$sizes = call_user_func($config['size_constant']);
|
|
||||||
if (isset($sizes[$newWidth])) {
|
if (isset($sizes[$newWidth])) {
|
||||||
$newWidth = $sizes[$newWidth];
|
$newWidth = $sizes[$newWidth];
|
||||||
}
|
}
|
||||||
@@ -205,7 +420,7 @@ if ($newWidth[strlen($newWidth)-1] == '%') {
|
|||||||
or errorPage('Width % not numeric.');
|
or errorPage('Width % not numeric.');
|
||||||
} else {
|
} else {
|
||||||
is_null($newWidth)
|
is_null($newWidth)
|
||||||
or ($newWidth > 10 && $newWidth <= $config['max_width'])
|
or ($newWidth > 10 && $newWidth <= $maxWidth)
|
||||||
or errorPage('Width out of range.');
|
or errorPage('Width out of range.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,6 +432,7 @@ verbose("new width = $newWidth");
|
|||||||
* height, h - set target height, affecting the resulting image width, height and resize options
|
* height, h - set target height, affecting the resulting image width, height and resize options
|
||||||
*/
|
*/
|
||||||
$newHeight = get(array('height', 'h'));
|
$newHeight = get(array('height', 'h'));
|
||||||
|
$maxHeight = getConfig('max_height', 2000);
|
||||||
|
|
||||||
// Check to replace predefined size
|
// Check to replace predefined size
|
||||||
if (isset($sizes[$newHeight])) {
|
if (isset($sizes[$newHeight])) {
|
||||||
@@ -229,7 +445,7 @@ if ($newHeight[strlen($newHeight)-1] == '%') {
|
|||||||
or errorPage('Height % out of range.');
|
or errorPage('Height % out of range.');
|
||||||
} else {
|
} else {
|
||||||
is_null($newHeight)
|
is_null($newHeight)
|
||||||
or ($newHeight > 10 && $newHeight <= $config['max_height'])
|
or ($newHeight > 10 && $newHeight <= $maxHeight)
|
||||||
or errorPage('Hight out of range.');
|
or errorPage('Hight out of range.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,10 +456,21 @@ verbose("new height = $newHeight");
|
|||||||
/**
|
/**
|
||||||
* aspect-ratio, ar - affecting the resulting image width, height and resize options
|
* aspect-ratio, ar - affecting the resulting image width, height and resize options
|
||||||
*/
|
*/
|
||||||
$aspectRatio = get(array('aspect-ratio', 'ar'));
|
$aspectRatio = get(array('aspect-ratio', 'ar'));
|
||||||
|
$aspectRatioConstant = getConfig('aspect_ratio_constant', function () {
|
||||||
|
return array(
|
||||||
|
'3:1' => 3/1,
|
||||||
|
'3:2' => 3/2,
|
||||||
|
'4:3' => 4/3,
|
||||||
|
'8:5' => 8/5,
|
||||||
|
'16:10' => 16/10,
|
||||||
|
'16:9' => 16/9,
|
||||||
|
'golden' => 1.618,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// Check to replace predefined aspect ratio
|
// Check to replace predefined aspect ratio
|
||||||
$aspectRatios = call_user_func($config['aspect_ratio_constant']);
|
$aspectRatios = call_user_func($aspectRatioConstant);
|
||||||
$negateAspectRatio = ($aspectRatio[0] == '!') ? true : false;
|
$negateAspectRatio = ($aspectRatio[0] == '!') ? true : false;
|
||||||
$aspectRatio = $negateAspectRatio ? substr($aspectRatio, 1) : $aspectRatio;
|
$aspectRatio = $negateAspectRatio ? substr($aspectRatio, 1) : $aspectRatio;
|
||||||
|
|
||||||
@@ -275,9 +502,11 @@ verbose("crop to fit = $cropToFit");
|
|||||||
/**
|
/**
|
||||||
* Set default background color from config file.
|
* Set default background color from config file.
|
||||||
*/
|
*/
|
||||||
if (isset($config['background_color'])) {
|
$backgroundColor = getConfig('background_color', null);
|
||||||
$img->setDefaultBackgroundColor($config['background_color']);
|
|
||||||
verbose("Using default background_color = {$config['background_color']}");
|
if ($backgroundColor) {
|
||||||
|
$img->setDefaultBackgroundColor($backgroundColor);
|
||||||
|
verbose("Using default background_color = $backgroundColor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -374,7 +603,7 @@ verbose("quality = $quality");
|
|||||||
*/
|
*/
|
||||||
$compress = get(array('compress', 'co'));
|
$compress = get(array('compress', 'co'));
|
||||||
|
|
||||||
|
|
||||||
is_null($compress)
|
is_null($compress)
|
||||||
or ($compress > 0 and $compress <= 9)
|
or ($compress > 0 and $compress <= 9)
|
||||||
or errorPage('Compress out of range');
|
or errorPage('Compress out of range');
|
||||||
@@ -518,11 +747,12 @@ verbose("dpr = $dpr");
|
|||||||
* convolve - image convolution as in http://php.net/manual/en/function.imageconvolution.php
|
* convolve - image convolution as in http://php.net/manual/en/function.imageconvolution.php
|
||||||
*/
|
*/
|
||||||
$convolve = get('convolve', null);
|
$convolve = get('convolve', null);
|
||||||
|
$convolutionConstant = getConfig('convolution_constant', array());
|
||||||
|
|
||||||
// Check if the convolve is matching an existing constant
|
// Check if the convolve is matching an existing constant
|
||||||
if ($convolve && isset($config['convolution_constant'])) {
|
if ($convolve && isset($convolutionConstant)) {
|
||||||
$img->addConvolveExpressions($config['convolution_constant']);
|
$img->addConvolveExpressions($convolutionConstant);
|
||||||
verbose("convolve constant = " . print_r($config['convolution_constant'], 1));
|
verbose("convolve constant = " . print_r($convolutionConstant, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose("convolve = " . print_r($convolve, 1));
|
verbose("convolve = " . print_r($convolve, 1));
|
||||||
@@ -538,6 +768,50 @@ verbose("upscale = $upscale");
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get details for post processing
|
||||||
|
*/
|
||||||
|
$postProcessing = getConfig('postprocessing', array(
|
||||||
|
'png_filter' => false,
|
||||||
|
'png_filter_cmd' => '/usr/local/bin/optipng -q',
|
||||||
|
|
||||||
|
'png_deflate' => false,
|
||||||
|
'png_deflate_cmd' => '/usr/local/bin/pngout -q',
|
||||||
|
|
||||||
|
'jpeg_optimize' => false,
|
||||||
|
'jpeg_optimize_cmd' => '/usr/local/bin/jpegtran -copy none -optimize',
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* alias - Save resulting image to another alias name.
|
||||||
|
* Password always apply, must be defined.
|
||||||
|
*/
|
||||||
|
$alias = get('alias', null);
|
||||||
|
$aliasPath = getConfig('alias_path', null);
|
||||||
|
$validAliasname = getConfig('valid_aliasname', '#^[a-z0-9A-Z-_]+$#');
|
||||||
|
$aliasTarget = null;
|
||||||
|
|
||||||
|
if ($alias && $aliasPath && $passwordMatch) {
|
||||||
|
|
||||||
|
$aliasTarget = $aliasPath . $alias;
|
||||||
|
$useCache = false;
|
||||||
|
|
||||||
|
is_writable($aliasPath)
|
||||||
|
or errorPage("Directory for alias is not writable.");
|
||||||
|
|
||||||
|
preg_match($validAliasname, $alias)
|
||||||
|
or errorPage('Filename for alias contains invalid characters. Do not add extension.');
|
||||||
|
|
||||||
|
} else if ($alias) {
|
||||||
|
errorPage('Alias is not enabled in the config file or password not matching.');
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose("alias = $alias");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display image if verbose mode
|
* Display image if verbose mode
|
||||||
*/
|
*/
|
||||||
@@ -570,11 +844,20 @@ EOD;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cachepath from config.
|
||||||
|
*/
|
||||||
|
$cachePath = getConfig('cache_path', __DIR__ . '/../cache/');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load, process and output the image
|
* Load, process and output the image
|
||||||
*/
|
*/
|
||||||
$img->log("Incoming arguments: " . print_r(verbose(), 1))
|
$img->log("Incoming arguments: " . print_r(verbose(), 1))
|
||||||
->setSource($srcImage, $config['image_path'])
|
->setSaveFolder($cachePath)
|
||||||
|
->useCache($useCache)
|
||||||
|
->setSource($srcImage, $imagePath)
|
||||||
->setOptions(
|
->setOptions(
|
||||||
array(
|
array(
|
||||||
// Options for calculate dimensions
|
// Options for calculate dimensions
|
||||||
@@ -591,7 +874,7 @@ $img->log("Incoming arguments: " . print_r(verbose(), 1))
|
|||||||
// Pre-processing, before resizing is done
|
// Pre-processing, before resizing is done
|
||||||
'scale' => $scale,
|
'scale' => $scale,
|
||||||
'rotateBefore' => $rotateBefore,
|
'rotateBefore' => $rotateBefore,
|
||||||
'autoRotate' => $autoRotate,
|
'autoRotate' => $autoRotate,
|
||||||
|
|
||||||
// General processing options
|
// General processing options
|
||||||
'bgColor' => $bgColor,
|
'bgColor' => $bgColor,
|
||||||
@@ -617,12 +900,13 @@ $img->log("Incoming arguments: " . print_r(verbose(), 1))
|
|||||||
->setJpegQuality($quality)
|
->setJpegQuality($quality)
|
||||||
->setPngCompression($compress)
|
->setPngCompression($compress)
|
||||||
->useOriginalIfPossible($useOriginal)
|
->useOriginalIfPossible($useOriginal)
|
||||||
->generateFilename($config['cache_path'])
|
->generateFilename($cachePath)
|
||||||
->useCacheIfPossible($useCache)
|
->useCacheIfPossible($useCache)
|
||||||
->load()
|
->load()
|
||||||
->preResize()
|
->preResize()
|
||||||
->resize()
|
->resize()
|
||||||
->postResize()
|
->postResize()
|
||||||
->setPostProcessingOptions($config['postprocessing'])
|
->setPostProcessingOptions($postProcessing)
|
||||||
->save()
|
->save()
|
||||||
|
->linkToCacheFile($aliasTarget)
|
||||||
->output();
|
->output();
|
||||||
|
BIN
webroot/img/apple_trans.gif
Normal file
BIN
webroot/img/apple_trans.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.3 KiB |
BIN
webroot/img/circle_trans.png
Normal file
BIN
webroot/img/circle_trans.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
BIN
webroot/img/glider_anim.gif
Normal file
BIN
webroot/img/glider_anim.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
@@ -1,54 +1,123 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Configuration for img.php, name the config file the same as your img.php and
|
* Configuration for img.php, name the config file the same as your img.php and
|
||||||
* append _config. If you are testing out some in imgtest.php then label that
|
* append _config. If you are testing out some in imgtest.php then label that
|
||||||
* config-file imgtest_config.php.
|
* config-file imgtest_config.php.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
return array(
|
return array(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paths, where are all the stuff I should use?
|
* Set mode as 'strict', 'production' or 'development'.
|
||||||
* Append ending slash on directories.
|
*
|
||||||
|
* Default values:
|
||||||
|
* mode: 'production'
|
||||||
|
*/
|
||||||
|
'mode' => 'development',
|
||||||
|
//'mode' => 'production', // 'development', 'strict'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where are the sources for the classfiles.
|
||||||
|
*
|
||||||
|
* Default values:
|
||||||
|
* autoloader: null // used from v0.6.2
|
||||||
|
* cimage_class: null // used until v0.6.1
|
||||||
|
*/
|
||||||
|
'autoloader' => __DIR__ . '/../autoload.php',
|
||||||
|
//'cimage_class' => __DIR__ . '/../CImage.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/'
|
||||||
|
* alias_path: null
|
||||||
*/
|
*/
|
||||||
'cimage_class' => __DIR__ . '/../CImage.php',
|
|
||||||
'image_path' => __DIR__ . '/img/',
|
'image_path' => __DIR__ . '/img/',
|
||||||
'cache_path' => __DIR__ . '/../cache/',
|
'cache_path' => __DIR__ . '/../cache/',
|
||||||
|
//'alias_path' => __DIR__ . '/img/alias/',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Use password to protect from missusage, send &pwd=... or &password=..
|
||||||
|
* with the request to match the password or set to false to disable.
|
||||||
|
* Passwords are only used together with the options for remote download
|
||||||
|
* and aliasing.
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
* password: false // as in do not use password
|
||||||
|
* password_always: false // do not always require password,
|
||||||
|
*/
|
||||||
|
//'password' => false, // "secret-password",
|
||||||
|
//'password_always' => false, // always require password,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow or disallow downloading of remote files, images available on
|
||||||
|
* some remote server. Default is to disallow.
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
* remote_allow: false
|
||||||
|
* remote_pattern: null // use default values from CImage
|
||||||
|
*/
|
||||||
|
//'remote_allow' => true,
|
||||||
|
//'remote_pattern' => '#^https?://#',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A regexp for validating characters in the image or alias filename.
|
||||||
|
*
|
||||||
|
* Default value:
|
||||||
|
* valid_filename: '#^[a-z0-9A-Z-/_\.:]+$#'
|
||||||
|
* valid_aliasname: '#^[a-z0-9A-Z-_]+$#'
|
||||||
|
*/
|
||||||
|
//'valid_filename' => '#^[a-z0-9A-Z-/_\.:]+$#',
|
||||||
|
//'valid_aliasname' => '#^[a-z0-9A-Z-_]+$#',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
* 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:
|
||||||
|
* image_path_constraint: true
|
||||||
*/
|
*/
|
||||||
'image_path_constraint' => true,
|
//'image_path_constraint' => false,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A regexp for validating characters in the image filename.
|
* Set default timezone.
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
* default_timezone: ini_get('default_timezone') or 'UTC'
|
||||||
*/
|
*/
|
||||||
'valid_filename' => '#^[a-z0-9A-Z-/_\.]+$#',
|
//'default_timezone' => 'UTC',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set default timezone, it defaults to UTC if not specified.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
//'default_timezone' => 'UTC',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Max image dimensions, larger dimensions results in 404.
|
* Max image dimensions, larger dimensions results in 404.
|
||||||
* This is basically a security constraint to avoid using resources on creating
|
* This is basically a security constraint to avoid using resources on creating
|
||||||
* large (unwanted) images.
|
* large (unwanted) images.
|
||||||
*
|
*
|
||||||
|
* Default values.
|
||||||
|
* max_width: 2000
|
||||||
|
* max_height: 2000
|
||||||
*/
|
*/
|
||||||
'max_width' => 2000,
|
//'max_width' => 2000,
|
||||||
'max_height' => 2000,
|
//'max_height' => 2000,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -56,10 +125,12 @@ return array(
|
|||||||
* Set default background color for all images. Override it using
|
* Set default background color for all images. Override it using
|
||||||
* option bgColor.
|
* option bgColor.
|
||||||
* Colorvalue is 6 digit hex string between 000000-FFFFFF
|
* Colorvalue is 6 digit hex string between 000000-FFFFFF
|
||||||
* or 8 digit hex string if using the alpha channel where
|
* or 8 digit hex string if using the alpha channel where
|
||||||
* the alpha value is between 00 (opaqe) and 7F (transparent),
|
* the alpha value is between 00 (opaqe) and 7F (transparent),
|
||||||
* that is between 00000000-FFFFFF7F.
|
* that is between 00000000-FFFFFF7F.
|
||||||
*
|
*
|
||||||
|
* Default values.
|
||||||
|
* background_color: As specified by CImage
|
||||||
*/
|
*/
|
||||||
//'background_color' => "FFFFFF",
|
//'background_color' => "FFFFFF",
|
||||||
//'background_color' => "FFFFFF7F",
|
//'background_color' => "FFFFFF7F",
|
||||||
@@ -67,9 +138,21 @@ 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.
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
*
|
||||||
|
* png_filter: false
|
||||||
|
* png_filter_cmd: '/usr/local/bin/optipng -q'
|
||||||
|
*
|
||||||
|
* png_deflate: false
|
||||||
|
* png_deflate_cmd: '/usr/local/bin/pngout -q'
|
||||||
|
*
|
||||||
|
* jpeg_optimize: false
|
||||||
|
* jpeg_optimize_cmd: '/usr/local/bin/jpegtran -copy none -optimize'
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
'postprocessing' => array(
|
'postprocessing' => array(
|
||||||
'png_filter' => false,
|
'png_filter' => false,
|
||||||
'png_filter_cmd' => '/usr/local/bin/optipng -q',
|
'png_filter_cmd' => '/usr/local/bin/optipng -q',
|
||||||
@@ -80,41 +163,78 @@ return array(
|
|||||||
'jpeg_optimize' => false,
|
'jpeg_optimize' => false,
|
||||||
'jpeg_optimize_cmd' => '/usr/local/bin/jpegtran -copy none -optimize',
|
'jpeg_optimize_cmd' => '/usr/local/bin/jpegtran -copy none -optimize',
|
||||||
),
|
),
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create custom convolution expressions, matrix 3x3, divisor and
|
* Create custom convolution expressions, matrix 3x3, divisor and
|
||||||
* offset.
|
* offset.
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
* convolution_constant: array()
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
'convolution_constant' => array(
|
'convolution_constant' => array(
|
||||||
//'sharpen' => '-1,-1,-1, -1,16,-1, -1,-1,-1, 8, 0',
|
//'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',
|
//'sharpen-alt' => '0,-1,0, -1,5,-1, 0,-1,0, 1, 0',
|
||||||
),
|
),
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent leeching of images by controlling who can access them from where.
|
||||||
|
* Default it to allow hotlinking.
|
||||||
|
* Password apply when hotlinking is disallowed, use password to allow.
|
||||||
|
* The whitelist is an array of regexpes for allowed hostnames that can
|
||||||
|
* hotlink images.
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
* allow_hotlinking: true
|
||||||
|
* hotlinking_whitelist: array()
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
'allow_hotlinking' => false,
|
||||||
|
'hotlinking_whitelist' => array(
|
||||||
|
'#^localhost$#',
|
||||||
|
'#^dbwebb\.se$#',
|
||||||
|
),
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create custom shortcuts for more advanced expressions.
|
* Create custom shortcuts for more advanced expressions.
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
* shortcut: array(
|
||||||
|
* 'sepia' => "&f=grayscale&f0=brightness,-10&f1=contrast,-20&f2=colorize,120,60,0,0&sharpen",
|
||||||
|
* )
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
'shortcut' => array(
|
'shortcut' => array(
|
||||||
'sepia' => "&f=grayscale&f0=brightness,-10&f1=contrast,-20&f2=colorize,120,60,0,0&sharpen",
|
'sepia' => "&f=grayscale&f0=brightness,-10&f1=contrast,-20&f2=colorize,120,60,0,0&sharpen",
|
||||||
),
|
),*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Predefined size constants.
|
* Predefined size constants.
|
||||||
*
|
*
|
||||||
* These can be used together with &width or &height to create a constant value
|
* These can be used together with &width or &height to create a constant value
|
||||||
* for a width or height where can be changed in one place.
|
* for a width or height where can be changed in one place.
|
||||||
* Useful when your site changes its layout or if you have a grid to fit images into.
|
* Useful when your site changes its layout or if you have a grid to fit images into.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* &width=w1 // results in width=613
|
* &width=w1 // results in width=613
|
||||||
* &width=c2 // results in spanning two columns with a gutter, 30*2+10=70
|
* &width=c2 // results in spanning two columns with a gutter, 30*2+10=70
|
||||||
* &width=c24 // results in spanning whole grid 24*30+((24-1)*10)=950
|
* &width=c24 // results in spanning whole grid 24*30+((24-1)*10)=950
|
||||||
|
*
|
||||||
|
* Default values.
|
||||||
|
* size_constant: As specified by the function below.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
'size_constant' => function () {
|
'size_constant' => function () {
|
||||||
|
|
||||||
// Set sizes to map constant to value, easier to use with width or height
|
// Set sizes to map constant to value, easier to use with width or height
|
||||||
@@ -133,15 +253,17 @@ return array(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $sizes;
|
return $sizes;
|
||||||
},
|
},*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Predefined aspect ratios.
|
* Predefined aspect ratios.
|
||||||
*
|
*
|
||||||
|
* Default values.
|
||||||
|
* aspect_ratio_constant: As the function below.
|
||||||
*/
|
*/
|
||||||
'aspect_ratio_constant' => function () {
|
/*'aspect_ratio_constant' => function () {
|
||||||
return array(
|
return array(
|
||||||
'3:1' => 3/1,
|
'3:1' => 3/1,
|
||||||
'3:2' => 3/2,
|
'3:2' => 3/2,
|
||||||
@@ -151,20 +273,5 @@ return array(
|
|||||||
'16:9' => 16/9,
|
'16:9' => 16/9,
|
||||||
'golden' => 1.618,
|
'golden' => 1.618,
|
||||||
);
|
);
|
||||||
},
|
},*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set error reporting to match development or production environment
|
|
||||||
*/
|
|
||||||
'error_reporting' => function () {
|
|
||||||
error_reporting(-1); // Report all type of errors
|
|
||||||
ini_set('display_errors', 1); // Display all errors
|
|
||||||
set_time_limit(20);
|
|
||||||
ini_set('gd.jpeg_ignore_warning', 1); // Ignore warning of corrupt jpegs
|
|
||||||
if (!extension_loaded('gd')) {
|
|
||||||
throw new Exception("Extension gd is nod loaded.");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
35
webroot/img_header.php
Normal file
35
webroot/img_header.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Resize and crop images on the fly, store generated images in a cache.
|
||||||
|
*
|
||||||
|
* This version is a all-in-one version of img.php, it is not dependant an any other file
|
||||||
|
* so you can simply copy it to any place you want it.
|
||||||
|
*
|
||||||
|
* @author Mikael Roos mos@dbwebb.se
|
||||||
|
* @example http://dbwebb.se/opensource/cimage
|
||||||
|
* @link https://github.com/mosbth/cimage
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change configuration details in the array below or create a separate file
|
||||||
|
* where you store the configuration details.
|
||||||
|
*
|
||||||
|
* The configuration file should be named the same name as this file and then
|
||||||
|
* add '_config.php'. If this file is named 'img.php' then name the
|
||||||
|
* config file should be named 'img_config.php'.
|
||||||
|
*
|
||||||
|
* The settings below are only a few of the available ones. Check the file in
|
||||||
|
* webroot/img_config.php for a complete list of configuration options.
|
||||||
|
*/
|
||||||
|
$config = array(
|
||||||
|
|
||||||
|
//'mode' => 'production', // 'production', 'development', 'strict'
|
||||||
|
//'image_path' => __DIR__ . '/img/',
|
||||||
|
//'cache_path' => __DIR__ . '/../cache/',
|
||||||
|
//'alias_path' => __DIR__ . '/img/alias/',
|
||||||
|
//'remote_allow' => true,
|
||||||
|
//'password' => false, // "secret-password",
|
||||||
|
|
||||||
|
);
|
3906
webroot/imgd.php
Normal file
3906
webroot/imgd.php
Normal file
File diff suppressed because it is too large
Load Diff
3906
webroot/imgp.php
Normal file
3906
webroot/imgp.php
Normal file
File diff suppressed because it is too large
Load Diff
3906
webroot/imgs.php
Normal file
3906
webroot/imgs.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -17,11 +17,13 @@ $description = "The issue was to implement fill-to-fit, but it needs some flexib
|
|||||||
// Use these images in the test
|
// Use these images in the test
|
||||||
$images = array(
|
$images = array(
|
||||||
'kodim04.png',
|
'kodim04.png',
|
||||||
|
'apple_trans.gif',
|
||||||
|
'circle_trans.png',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// For each image, apply these testcases
|
// For each image, apply these testcases
|
||||||
$cache = "&nc"; // ""; // "&nc"
|
$cache = "&nc"; // ""; // "&nc"
|
||||||
$testcase = array(
|
$testcase = array(
|
||||||
"$cache&w=300&h=300&fill-to-fit",
|
"$cache&w=300&h=300&fill-to-fit",
|
||||||
|
Reference in New Issue
Block a user