Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c03ebedc93 | ||
|
c9d41ceca2 | ||
|
218bd9491a | ||
|
d8a65ae409 | ||
|
c59f44f366 | ||
|
688cd5c000 | ||
|
60c76653b3 | ||
|
47e5cb2327 | ||
|
04fd68cb2b | ||
|
664fd6a3be | ||
|
fedbf9e381 | ||
|
28b107e64f | ||
|
ce63730cb6 | ||
|
0482744f89 | ||
|
0998f2819e |
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Cache files #
|
||||
######################
|
||||
cache/_*
|
||||
|
908
CImage.php
113
README.md
@@ -4,73 +4,113 @@ Image conversion on the fly using PHP
|
||||
About
|
||||
-------------------------------------
|
||||
|
||||
The `CImage.php` is a PHP class that can resize and crop images on the fly and output
|
||||
them to, for example to a webpage. The class preserves a cache of the generated images
|
||||
and responds with HTTP 304 (not modified) if the image has not changed.
|
||||
`CImage` is a PHP class which enables scaling, cropping, filtering effects and processing of images using PHP GD. The script `img.php` uses `CImage` to enable server-side image processing together with caching and optimization of the processed images.
|
||||
|
||||
The file `img.php` uses `CImage.php` to resize images. It is a usecase on how to use
|
||||
the class. `img.php` is useful for webpages which want to dynamically resize the images.
|
||||
Server-side image processing is a useful tool for any web developer, `img.php` has an easy to use interface and its quite powerful when you integrate it with your website. This is a most useful tool for any web developer who has a need to create and process images for a website.
|
||||
|
||||
The file `test.php` has testcases that show the results of `img.php` with different
|
||||
settings.
|
||||
This is free software and open source.
|
||||
|
||||
Start by reviewing the `test.php`, then have a look at `img.php` and finally go through
|
||||
`CImage.php`.
|
||||
|
||||
CImage lives at github: https://github.com/mosbth/cimage
|
||||
|
||||
You can try out a live example at: http://dbwebb.se/kod-exempel/cimage/
|
||||
Read more on http://dbwebb.se/opensource/cimage
|
||||
|
||||
Enjoy!
|
||||
|
||||
Mikael Roos (me@mikaelroos.se)
|
||||
|
||||
|
||||
Installation
|
||||
License
|
||||
-------------------------------------
|
||||
|
||||
1. Clone from github: `git://github.com/mosbth/cimage.git`
|
||||
License according to MIT.
|
||||
|
||||
2. Make the cache directory writable by the webserver.
|
||||
|
||||
<pre><code>
|
||||
|
||||
Installation and get going
|
||||
-------------------------------------
|
||||
|
||||
**Latest stable version is v0.4 released 2013-10-08.**
|
||||
|
||||
```bash
|
||||
git clone git://github.com/mosbth/cimage.git
|
||||
cd cimage
|
||||
git checkout v0.4
|
||||
```
|
||||
|
||||
Make the cache-directory writable by the webserver.
|
||||
|
||||
```bash
|
||||
chmod 777 cache
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
3. Point your browser to `test.php`.
|
||||
Try it out by pointing your browser to the test file `test.php`.
|
||||
|
||||
4. Review the settings in `img.php` and try it out.
|
||||
Review the settings in `img.php`.
|
||||
|
||||
5. Advanced usage. Put `img.php` in your `/img`-directory. Create a `.htaccess` in your
|
||||
web root folder containing the following line:
|
||||
|
||||
<pre><code>
|
||||
RewriteEngine on
|
||||
RewriteRule ^image/(.*)$ img/img.php?src=$1 [QSA,NC,L]
|
||||
</code></pre>
|
||||
|
||||
Now you can access and resize your images through `/image/someimage.jpg?w=80`. Very handy.
|
||||
Usage
|
||||
-------------------------------------
|
||||
|
||||
| Parameter | Explained |
|
||||
|----------------|----------------------------------------------|
|
||||
| `src` | `src=img.png` choses the source image to use. |
|
||||
| `h, height` | `h=200` sets the width to be to max 200px. `h=25%` sets the height to 25% of its original height. |
|
||||
| `w, width` | `w=200` sets the height to be max 200px. `w=100%` sets the width to 100% of its original width. |
|
||||
| `ar, aspect-ratio` | Use this as aspect ratio. Use together with either height or width or alone to base calculations on original image dimensions. This setting is used to calculate the resulting dimension for the image. `w=160&aspect-ratio=1.6` results in a width of 100px. |
|
||||
| `s, scale` | Scale the image to a size proportional to a percentage of its original size, `scale=25` makes a image 25% of its original size and `size=200` doubles up the image size. Scale is applied before all processing and has no impact of the final width and height. |
|
||||
| `nr, no-ratio, stretch` | Do *not* keep aspect ratio when resizing 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` & `w` to make the image fit into dimensions, and crop out the rest of the image. |
|
||||
| `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 which part of the image you want to process. Its an alternative to use `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. |
|
||||
| `q, quality` | Quality affects lossy compression and file size for JPEG images by setting the quality between 1-100, default is 60. Quality has no effect on PNG or GIF. |
|
||||
| `d, deflate` | For PNG images it defines the compression algorithm, values can be 1-9, default is defined by PHP GD. Quality has no effect on JPEG or GIF. |
|
||||
| `sharpen` | Appy a filter that sharpens the image. |
|
||||
| `emboss` | Appy a filter with an emboss effect. |
|
||||
| `blur` | Appy a filter with a blur effect. |
|
||||
| `f, filter` | Apply filter to image, `f=colorize,0,255,0,0` makes image more green. Supports all filters as defined in [PHP GD `imagefilter()`](http://php.net/manual/en/function.imagefilter.php). |
|
||||
| `f0, f1-f9` | Same as `filter`, just add more filters. Applied in order `f`, `f0-f9`. |
|
||||
| `p, palette` | Create a palette version of the image with up to 256 colors. |
|
||||
| `sa, save-as` | Save resulting image as JPEG, PNG or GIF, for example `?src=river.png&save-as=gif`. |
|
||||
| `nc, no-cache` | Do not use the cached version, do all image processing and save a new image to cache. |
|
||||
| `so, skip-original`| Skip using the original image, always process image, create and use a cached version of the original image. |
|
||||
| `v, verbose` | Do verbose output and print out a log what happens. Good for debugging, analyzing what happens or analyzing the image being processed. |
|
||||
|
||||
Combine the parameters to get the desired behavior and resulting image. For example, take the original image, resize it, apply a sharpen effect, save the image as JPEG and use quality 30.
|
||||
|
||||
`img.php?src=kodim13.png&w=600&sharpen&save-as=jpg&q=30`
|
||||
|
||||
|
||||
|
||||
Revision history
|
||||
-------------------------------------
|
||||
|
||||
ToDo.
|
||||
v0.4 (2013-10-08)
|
||||
|
||||
* Improved support for pre-defined sizes.
|
||||
* crop-to-fit, add parameter for offset x and y to enable to define which area is the
|
||||
center of the image from which the crop is done.
|
||||
* Show how to integrate with WordPress, shortcodes.
|
||||
* 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.
|
||||
* Clean up code in `CImage.php`.
|
||||
* 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`
|
||||
* Readding `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.
|
||||
* Pre-defined sizes can be configured for width in `img.php`.
|
||||
* 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)
|
||||
|
||||
@@ -80,6 +120,7 @@ v0.2 (2012-05-09)
|
||||
* Added quality-setting.
|
||||
* Added testcases for above.
|
||||
|
||||
|
||||
v0.1.1 (2012-04-27)
|
||||
|
||||
* Corrected calculation where both width and height were set.
|
||||
@@ -87,7 +128,9 @@ v0.1.1 (2012-04-27)
|
||||
|
||||
v0.1 (2012-04-25)
|
||||
|
||||
* Initial release after rewriting some older code I had lying around.
|
||||
* Initial release after rewriting some older code doing the same, but not that good and flexible.
|
||||
|
||||
<pre>
|
||||
.
|
||||
..: Copyright 2012 by Mikael Roos (me@mikaelroos.se)
|
||||
..: Copyright 2012-2013 by Mikael Roos (me@mikaelroos.se)
|
||||
</pre>
|
||||
|
192
img.php
@@ -10,31 +10,109 @@
|
||||
error_reporting(-1);
|
||||
set_time_limit(20);
|
||||
|
||||
// Append ending slash
|
||||
$cimageClassFile = __DIR__ .'/CImage.php';
|
||||
$pathToImages = __DIR__.'/img/';
|
||||
$pathToCache = __DIR__.'/cache/';
|
||||
$maxWidth = $maxHeight = 2000;
|
||||
// Do some sanity checks
|
||||
function errorPage($msg) {
|
||||
header("Status: 404 Not Found");
|
||||
die('404: ' . $msg);
|
||||
}
|
||||
|
||||
// Set areas to map constant to value, easier to use with width or height
|
||||
$area = array(
|
||||
// Custom exception handler
|
||||
function myExceptionHandler($exception) {
|
||||
errorPage("<p><b>img.php: Uncaught exception:</b> <p>" . $exception->getMessage() . "</p><pre>" . $exception->getTraceAsString(), "</pre>");
|
||||
}
|
||||
set_exception_handler('myExceptionHandler');
|
||||
|
||||
|
||||
// Use preprocessing of images
|
||||
#define('PNG_FILTER', '/usr/local/bin/optipng -q');
|
||||
#define('PNG_DEFLATE', '/usr/local/bin/pngout -q');
|
||||
#define('JPEG_OPTIMIZE', '/usr/local/bin/jpegtran -copy none -optimize');
|
||||
|
||||
|
||||
// Append ending slash
|
||||
$cimageClassFile = __DIR__.'/CImage.php'; // Where is the class file
|
||||
$pathToImages = __DIR__.'/img/'; // Where are the image base directory
|
||||
$pathToCache = __DIR__.'/cache/'; // Where is the cache directory
|
||||
$gridColumnWidth = 30;
|
||||
$gridGutterWidth = 10;
|
||||
$gridColumns = 24;
|
||||
// settings for do not largen smaller images
|
||||
|
||||
// settings for max image dimensions
|
||||
$maxWidth = $maxHeight = 2000;
|
||||
$maxScale = 400;
|
||||
|
||||
// Set sizes to map constant to value, easier to use with width or height
|
||||
$sizes = array(
|
||||
'w1' => 613,
|
||||
'w2' => 630,
|
||||
);
|
||||
|
||||
// Get input from querystring
|
||||
$srcImage = isset($_GET['src']) ? $_GET['src'] : null;
|
||||
$newWidth = isset($_GET['width']) ? $_GET['width'] : (isset($_GET['w']) ? $_GET['w'] : null);
|
||||
$newHeight = isset($_GET['height']) ? $_GET['height'] : (isset($_GET['h']) ? $_GET['h'] : null);
|
||||
$keepRatio = isset($_GET['no-ratio']) ? false : true;
|
||||
$cropToFit = isset($_GET['crop-to-fit']) ? true : false;
|
||||
$crop = isset($_GET['crop']) ? $_GET['crop'] : (isset($_GET['c']) ? $_GET['c'] : null);
|
||||
$quality = isset($_GET['quality']) ? $_GET['quality'] : (isset($_GET['q']) ? $_GET['q'] : 100);
|
||||
// Predefine some common aspect ratios
|
||||
$aspectRatios = 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 area
|
||||
if(isset($area[$newWidth])) {
|
||||
$newWidth = $area[$newWidth];
|
||||
|
||||
|
||||
// Add column width to $area, useful for use as predefined size for width (or height).
|
||||
for($i = 1; $i <= $gridColumns; $i++) {
|
||||
$sizes['c' . $i] = ($gridColumnWidth + $gridGutterWidth) * $i - $gridGutterWidth;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Get input from querystring
|
||||
$srcImage = isset($_GET['src']) ? $_GET['src'] : null;
|
||||
$newWidth = isset($_GET['width']) ? $_GET['width'] : (isset($_GET['w']) ? $_GET['w'] : null);
|
||||
$newHeight = isset($_GET['height']) ? $_GET['height'] : (isset($_GET['h']) ? $_GET['h'] : null);
|
||||
$aspectRatio = isset($_GET['aspect-ratio']) ? $_GET['aspect-ratio'] : (isset($_GET['ar']) ? $_GET['ar'] : null);
|
||||
$scale = isset($_GET['scale']) ? $_GET['scale'] : (isset($_GET['s']) ? $_GET['s'] : null);
|
||||
$area = isset($_GET['area']) ? $_GET['area'] : (isset($_GET['a']) ? $_GET['a'] : null);
|
||||
$crop = isset($_GET['crop']) ? $_GET['crop'] : (isset($_GET['c']) ? $_GET['c'] : null);
|
||||
$quality = isset($_GET['quality']) ? $_GET['quality'] : (isset($_GET['q']) ? $_GET['q'] : null);
|
||||
$deflate = isset($_GET['deflate']) ? $_GET['deflate'] : (isset($_GET['d']) ? $_GET['d'] : null);
|
||||
$saveAs = isset($_GET['save-as']) ? $_GET['save-as'] : (isset($_GET['sa']) ? $_GET['sa'] : null);
|
||||
$sharpen = isset($_GET['sharpen']) ? true : null;
|
||||
$emboss = isset($_GET['emboss']) ? true : null;
|
||||
$blur = isset($_GET['blur']) ? true : null;
|
||||
$palette = isset($_GET['palette']) || isset($_GET['p']) ? true : false;
|
||||
$verbose = isset($_GET['verbose']) || isset($_GET['v']) ? true : false;
|
||||
$useCache = isset($_GET['no-cache']) || isset($_GET['nc']) ? false : true;
|
||||
$useOriginal = isset($_GET['skip-original']) || isset($_GET['so']) ? false : true;
|
||||
$keepRatio = isset($_GET['no-ratio']) ? false : (isset($_GET['nr']) ? false : (isset($_GET['stretch']) ? false : true ));
|
||||
$cropToFit = isset($_GET['crop-to-fit']) ? true : (isset($_GET['cf']) ? true : false);
|
||||
|
||||
|
||||
|
||||
// Check to replace predefined size
|
||||
if(isset($sizes[$newWidth])) {
|
||||
$newWidth = $sizes[$newWidth];
|
||||
}
|
||||
if(isset($sizes[$newHeight])) {
|
||||
$newHeight = $sizes[$newHeight];
|
||||
}
|
||||
|
||||
// Check to replace predefined aspect ratio
|
||||
$negateAspectRatio = ($aspectRatio[0] == '!') ? true : false;
|
||||
$aspectRatio = $negateAspectRatio ? substr($aspectRatio, 1) : $aspectRatio;
|
||||
|
||||
if(isset($aspectRatios[$aspectRatio])) {
|
||||
$aspectRatio = $aspectRatios[$aspectRatio];
|
||||
}
|
||||
|
||||
if($negateAspectRatio) {
|
||||
$aspectRatio = 1 / $aspectRatio;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add all filters to an array
|
||||
$filters = array();
|
||||
$filter = isset($_GET['filter']) ? $_GET['filter'] : (isset($_GET['f']) ? $_GET['f'] : null);
|
||||
@@ -44,24 +122,74 @@ for($i=0; $i<10;$i++) {
|
||||
if($filter) { $filters[] = $filter; }
|
||||
}
|
||||
|
||||
// Do some sanity checks
|
||||
function errorPage($msg) {
|
||||
header("Status: 404 Not Found");
|
||||
die('404: ' . $msg);
|
||||
}
|
||||
|
||||
// Santize and check domain for incoming parameters. (Move to CImage)
|
||||
isset($srcImage) or errorPage('Must set src-attribute.');
|
||||
preg_match('#^[a-z0-9A-Z-/_\.]+$#', $srcImage) or errorPage('Filename contains invalid characters.');
|
||||
is_file($pathToImages . '/' . $srcImage) or errorPage('Imagefile does not exists.');
|
||||
is_writable($pathToCache) or errorPage('Cache-directory does not exists or is not writable.');
|
||||
is_null($newWidth) or ($newWidth > 10 && $newWidth <= $maxWidth) or errorPage('Width out of range.');
|
||||
is_null($newHeight) or ($newHeight > 10 && $newHeight <= $maxHeight) or errorPage('Hight out of range.');
|
||||
$quality >= 0 and $quality <= 100 or errorPage('Quality out of range');
|
||||
is_null($quality) or ($quality > 0 and $quality <= 100) or errorPage('Quality out of range');
|
||||
is_null($deflate) or ($defalte > 0 and $deflate <= 9) or errorPage('Deflate out of range');
|
||||
is_null($scale) or ($scale >= 0 and $quality <= 400) or errorPage('Scale out of range');
|
||||
is_null($aspectRatio) or is_numeric($aspectRatio) or errorPage('Aspect ratio out of range');
|
||||
|
||||
// Create the image object
|
||||
// width
|
||||
if($newWidth[strlen($newWidth)-1] == '%') {
|
||||
is_numeric(substr($newWidth, 0, -1)) or errorPage('Width % out of range.');
|
||||
}
|
||||
else {
|
||||
is_null($newWidth) or ($newWidth > 10 && $newWidth <= $maxWidth) or errorPage('Width out of range.');
|
||||
}
|
||||
|
||||
// height
|
||||
if($newHeight[strlen($newHeight)-1] == '%') {
|
||||
is_numeric(substr($newHeight, 0, -1)) or errorPage('Height % out of range.');
|
||||
}
|
||||
else {
|
||||
is_null($newHeight) or ($newHeight > 10 && $newHeight <= $maxHeight) or errorPage('Hight out of range.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Display image if vebose mode
|
||||
if($verbose) {
|
||||
$query = array();
|
||||
parse_str($_SERVER['QUERY_STRING'], $query);
|
||||
unset($query['verbose']);
|
||||
unset($query['v']);
|
||||
unset($query['nocache']);
|
||||
$url1 = '?' . http_build_query($query);
|
||||
echo <<<EOD
|
||||
<a href=$url1><code>$url1</code></a><br>
|
||||
<img src='{$url1}' />
|
||||
|
||||
EOD;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create and output the image
|
||||
require($cimageClassFile);
|
||||
$img = new CImage($srcImage, $pathToImages, $pathToCache);
|
||||
$img->ResizeAndOutput(array('newWidth'=>$newWidth, 'newHeight'=>$newHeight, 'keepRatio'=>$keepRatio,
|
||||
'cropToFit'=>$cropToFit, 'quality'=>$quality,
|
||||
'crop'=>$crop, 'filters'=>$filters,
|
||||
));
|
||||
$img->ResizeAndOutput(array(
|
||||
'newWidth' => $newWidth,
|
||||
'newHeight' => $newHeight,
|
||||
'aspectRatio' => $aspectRatio,
|
||||
'keepRatio' => $keepRatio,
|
||||
'cropToFit' => $cropToFit,
|
||||
'scale' => $scale,
|
||||
'area' => $area,
|
||||
'quality' => $quality,
|
||||
'deflate' => $deflate,
|
||||
'crop' => $crop,
|
||||
'filters' => $filters,
|
||||
'verbose' => $verbose,
|
||||
'useCache' => $useCache,
|
||||
'useOriginal' => $useOriginal,
|
||||
'saveAs' => $saveAs,
|
||||
'sharpen' => $sharpen,
|
||||
'emboss' => $emboss,
|
||||
'blur' => $blur,
|
||||
'palette' => $palette,
|
||||
));
|
||||
|
||||
|
BIN
img/ball24.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
img/ball8.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
img/car.png
Normal file
After Width: | Height: | Size: 245 KiB |
BIN
img/kodim04.png
Normal file
After Width: | Height: | Size: 622 KiB |
BIN
img/kodim07.png
Normal file
After Width: | Height: | Size: 544 KiB |
BIN
img/kodim08.png
Normal file
After Width: | Height: | Size: 770 KiB |
BIN
img/kodim13.png
Normal file
After Width: | Height: | Size: 803 KiB |
BIN
img/kodim22.png
Normal file
After Width: | Height: | Size: 684 KiB |
BIN
img/kodim23.png
Normal file
After Width: | Height: | Size: 544 KiB |
BIN
img/kodim24.png
Normal file
After Width: | Height: | Size: 681 KiB |
BIN
img/round24.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
img/round8.png
Normal file
After Width: | Height: | Size: 6.2 KiB |