mirror of
https://github.com/mosbth/cimage.git
synced 2025-04-22 09:54:07 +02:00
Added support for custom convolutions. Fix #49.
This commit is contained in:
parent
832edc9d26
commit
3c04a2dd0f
185
CImage.php
185
CImage.php
@ -188,14 +188,30 @@ class CImage
|
||||
|
||||
|
||||
/**
|
||||
* Array with details on how to do image convolution.
|
||||
* String with details on how to do image convolution. String
|
||||
* should map a key in the $convolvs array or be a string of
|
||||
* 11 float values separated by comma. The first nine builds
|
||||
* up the matrix, then divisor and last offset.
|
||||
*/
|
||||
private $convolve;
|
||||
private $convolveString = null; // Original argument, if existing
|
||||
|
||||
|
||||
/**
|
||||
* Properties (clean up these)
|
||||
* Custom convolution expressions, matrix 3x3, divisor and offset.
|
||||
*/
|
||||
private $convolves = array(
|
||||
'lighten' => '0,0,0, 0,12,0, 0,0,0, 9, 0',
|
||||
'darken' => '0,0,0, 0,6,0, 0,0,0, 9, 0',
|
||||
'sharpen' => '-1,-1,-1, -1,16,-1, -1,-1,-1, 8, 0',
|
||||
'emboss' => '1,1,-1, 1,3,-1, 1,-1,-1, 3, 0',
|
||||
'blur' => '1,1,1, 1,15,1, 1,1,1, 23, 0',
|
||||
'gblur' => '1,2,1, 2,4,2, 1,2,1, 16, 0',
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Properties
|
||||
* @todo Clean up these and check if and how they are used)
|
||||
*/
|
||||
private $offset;
|
||||
|
||||
@ -361,7 +377,7 @@ class CImage
|
||||
'sharpen' => null,
|
||||
'emboss' => null,
|
||||
'blur' => null,
|
||||
'convolve' => null,
|
||||
'convolve' => null,
|
||||
'rotateAfter' => null,
|
||||
'autoRotate' => false,
|
||||
|
||||
@ -417,34 +433,6 @@ class CImage
|
||||
}
|
||||
}
|
||||
|
||||
// Convert convolve settings from string to array
|
||||
if (isset($args['convolve']) && !is_array($args['convolve'])) {
|
||||
$part = explode(',', $args['convolve']);
|
||||
$this->convolveString = $args['convolve'];
|
||||
|
||||
if (count($part) != 11) {
|
||||
throw new Exception(
|
||||
'Missmatch in argument convolve. Expected comma-separated string with 11 float values.'
|
||||
);
|
||||
}
|
||||
|
||||
array_walk($part, function ($item, $key) {
|
||||
if (!is_numeric($item)) {
|
||||
throw new Exception("Argument convole should be float but is not.");
|
||||
}
|
||||
});
|
||||
|
||||
$args['convolve'] = array(
|
||||
'matrix' => array(
|
||||
array($part[0], $part[1], $part[2]),
|
||||
array($part[3], $part[4], $part[5]),
|
||||
array($part[6], $part[7], $part[8]),
|
||||
),
|
||||
'div' => $part[9],
|
||||
'offset' => $part[10],
|
||||
);
|
||||
}
|
||||
|
||||
// Merge default arguments with incoming and set properties.
|
||||
//$args = array_merge_recursive($defaults, $args);
|
||||
$args = array_merge($defaults, $args);
|
||||
@ -897,7 +885,7 @@ class CImage
|
||||
|
||||
$convolve = null;
|
||||
if ($this->convolve) {
|
||||
$convolve = 'convolve' . str_replace(',', '', $this->convolveString);
|
||||
$convolve = 'convolve' . preg_replace('/[^a-zA-Z0-9]/', '', $this->convolve);
|
||||
}
|
||||
|
||||
$subdir = str_replace('/', '-', dirname($this->imageSrc));
|
||||
@ -1292,14 +1280,14 @@ class CImage
|
||||
|
||||
// Custom convolution
|
||||
if ($this->convolve) {
|
||||
$this->log("Convolve: " . $this->convolveString);
|
||||
//$this->log("Convolve: " . $this->convolve);
|
||||
$this->imageConvolution();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rotate image using angle.
|
||||
@ -1395,70 +1383,100 @@ class CImage
|
||||
|
||||
|
||||
/**
|
||||
* Sharpen image as http://php.net/manual/en/ref.image.php#56144
|
||||
* http://loriweb.pair.com/8udf-sharpen.html
|
||||
* Sharpen image using image convolution.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sharpenImage()
|
||||
{
|
||||
$matrix = array(
|
||||
array(-1,-1,-1,),
|
||||
array(-1,16,-1,),
|
||||
array(-1,-1,-1,),
|
||||
);
|
||||
|
||||
$divisor = 8;
|
||||
$offset = 0;
|
||||
|
||||
imageconvolution($this->image, $matrix, $divisor, $offset);
|
||||
|
||||
$this->imageConvolution('sharpen');
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Emboss image as http://loriweb.pair.com/8udf-emboss.html
|
||||
* Emboss image using image convolution.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function embossImage()
|
||||
{
|
||||
$matrix = array(
|
||||
array( 1, 1,-1,),
|
||||
array( 1, 3,-1,),
|
||||
array( 1,-1,-1,),
|
||||
);
|
||||
|
||||
$divisor = 3;
|
||||
$offset = 0;
|
||||
|
||||
imageconvolution($this->image, $matrix, $divisor, $offset);
|
||||
|
||||
$this->imageConvolution('emboss');
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Blur image as http://loriweb.pair.com/8udf-basics.html
|
||||
* Blur image using image convolution.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function blurImage()
|
||||
{
|
||||
$matrix = array(
|
||||
array( 1, 1, 1,),
|
||||
array( 1,15, 1,),
|
||||
array( 1, 1, 1,),
|
||||
$this->imageConvolution('blur');
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create convolve expression and return arguments for image convolution.
|
||||
*
|
||||
* @param string $expression constant string which evaluates to a list of
|
||||
* 11 numbers separated by komma or such a list.
|
||||
*
|
||||
* @return array as $matrix (3x3), $divisor and $offset
|
||||
*/
|
||||
public function createConvolveArguments($expression)
|
||||
{
|
||||
// Check of matching constant
|
||||
if (isset($this->convolves[$expression])) {
|
||||
$expression = $this->convolves[$expression];
|
||||
}
|
||||
|
||||
$part = explode(',', $expression);
|
||||
$this->log("Creating convolution expressen: $expression");
|
||||
|
||||
// Expect list of 11 numbers, split by , and build up arguments
|
||||
if (count($part) != 11) {
|
||||
throw new Exception(
|
||||
"Missmatch in argument convolve. Expected comma-separated string with
|
||||
11 float values. Got $expression."
|
||||
);
|
||||
}
|
||||
|
||||
array_walk($part, function ($item, $key) {
|
||||
if (!is_numeric($item)) {
|
||||
throw new Exception("Argument to convolve expression should be float but is not.");
|
||||
}
|
||||
});
|
||||
|
||||
return array(
|
||||
array(
|
||||
array($part[0], $part[1], $part[2]),
|
||||
array($part[3], $part[4], $part[5]),
|
||||
array($part[6], $part[7], $part[8]),
|
||||
),
|
||||
$part[9],
|
||||
$part[10],
|
||||
);
|
||||
|
||||
$divisor = 23;
|
||||
$offset = 0;
|
||||
|
||||
imageconvolution($this->image, $matrix, $divisor, $offset);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add custom expressions (or overwrite existing) for image convolution.
|
||||
*
|
||||
* @param array $options Key value array with strings to be converted
|
||||
* to convolution expressions.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addConvolveExpressions($options)
|
||||
{
|
||||
$this->convolves = array_merge($this->convolves, $options);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -1467,22 +1485,25 @@ class CImage
|
||||
/**
|
||||
* Image convolution.
|
||||
*
|
||||
* @param array $matrix A 3x3 matrix: an array of three arrays of three floats.
|
||||
* @param float $div The divisor of the result of the convolution, used for normalization.
|
||||
* @param float $offset Color offset.
|
||||
* @param string $options A string with 11 float separated by comma.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function imageConvolution($matrix = null, $div = null, $offset = null)
|
||||
public function imageConvolution($options = null)
|
||||
{
|
||||
if ($matrix == null && $this->convolve) {
|
||||
$matrix = $this->convolve['matrix'];
|
||||
$div = $this->convolve['div'];
|
||||
$offset = $this->convolve['offset'];
|
||||
}
|
||||
// Use incoming options or use $this.
|
||||
$options = $options ? $options : $this->convolve;
|
||||
|
||||
imageconvolution($this->image, $matrix, $div, $offset);
|
||||
|
||||
// Treat incoming as string, split by +
|
||||
$this->log("Convolution with '$options'");
|
||||
$options = explode(":", $options);
|
||||
|
||||
// Check each option if it matches constant value
|
||||
foreach($options as $option) {
|
||||
list($matrix, $divisor, $offset) = $this->createConvolveArguments($option);
|
||||
imageconvolution($this->image, $matrix, $divisor, $offset);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,7 @@ Revision history
|
||||
|
||||
v0.5.x (latest)
|
||||
|
||||
* 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.
|
||||
|
@ -465,19 +465,35 @@ verbose("json = $outputFormat");
|
||||
|
||||
/**
|
||||
* dpr - change to get larger image to easier support larger dpr, such as retina.
|
||||
*/
|
||||
*/
|
||||
$dpr = get(array('ppi', 'dpr', 'device-pixel-ratio'), 1);
|
||||
|
||||
verbose("dpr = $dpr");
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create the class for the image.
|
||||
*/
|
||||
require $config['cimage_class'];
|
||||
|
||||
$img = new CImage();
|
||||
$img->setVerbose($verbose);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* convolve - image convolution as in http://php.net/manual/en/function.imageconvolution.php
|
||||
*/
|
||||
$convolve = get('convolve', null);
|
||||
|
||||
verbose("convolve = $convolve");
|
||||
// Check if the convolve is matching an existing constant
|
||||
if ($convolve && isset($config['convolution_constant'])) {
|
||||
$img->addConvolveExpressions($config['convolution_constant']);
|
||||
verbose("convolve = " . print_r($config['convolution_constant'], 1));
|
||||
}
|
||||
|
||||
verbose("convolve = " . print_r($convolve, 1));
|
||||
|
||||
|
||||
|
||||
@ -502,14 +518,10 @@ EOD;
|
||||
|
||||
|
||||
/**
|
||||
* Create and output the image
|
||||
* Load, process and output the image
|
||||
*/
|
||||
require $config['cimage_class'];
|
||||
|
||||
$img = new CImage();
|
||||
|
||||
$img->setVerbose($verbose)
|
||||
->log("Incoming arguments: " . print_r(verbose(), 1))
|
||||
$img->log("Incoming arguments: " . print_r(verbose(), 1))
|
||||
->setSource($srcImage, $config['image_path'])
|
||||
->setOptions(
|
||||
array(
|
||||
|
@ -11,14 +11,16 @@ return array(
|
||||
* Paths, where are all the stuff I should use?
|
||||
* Append ending slash on directories.
|
||||
*/
|
||||
'cimage_class' => __DIR__.'/../CImage.php',
|
||||
'image_path' => __DIR__.'/img/',
|
||||
'cache_path' => __DIR__.'/../cache/',
|
||||
'cimage_class' => __DIR__ . '/../CImage.php',
|
||||
'image_path' => __DIR__ . '/img/',
|
||||
'cache_path' => __DIR__ . '/../cache/',
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check that the imagefile is a file below 'image_path' using realpath().
|
||||
* Security constraint to avoid reaching images outside image_path.
|
||||
* This means that symbolic links to images outside the image_path will fail.
|
||||
*/
|
||||
'image_path_constraint' => true,
|
||||
|
||||
@ -32,7 +34,7 @@ return array(
|
||||
|
||||
|
||||
/**
|
||||
* Set default timezone, it defaults to UTC if not specified otherwise.
|
||||
* Set default timezone, it defaults to UTC if not specified.
|
||||
*
|
||||
*/
|
||||
//'default_timezone' => 'UTC',
|
||||
@ -40,7 +42,9 @@ return array(
|
||||
|
||||
|
||||
/**
|
||||
* Max image dimensions,
|
||||
* Max image dimensions, larger dimensions results in 404.
|
||||
* This is basically a security constraint to avoid using resources on creating
|
||||
* large (unwanted) images.
|
||||
*
|
||||
*/
|
||||
'max_width' => 2000,
|
||||
@ -65,9 +69,33 @@ return array(
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create custom convolution expressions, matrix 3x3, divisor and
|
||||
* offset.
|
||||
*/
|
||||
'convolution_constant' => array(
|
||||
'edge' => '-1,-1,-1, -1,8,-1, -1,-1,-1, 9, 0',
|
||||
'edge-alt' => '0,1,0, 1,-4,1, 0,1,0, 1, 0',
|
||||
'draw' => '0,-1,0, -1,5,-1, 0,-1,0, 0, 0',
|
||||
'sharpen-alt' => '0,-1,0, -1,5,-1, 0,-1,0, 1, 0',
|
||||
'emboss-alt' => '-2,-1,0, -1,1,1, 0,1,2, 1, 0',
|
||||
'mean' => '1,1,1, 1,1,1, 1,1,1, 9, 0',
|
||||
'motion' => '1,0,0, 0,1,0, 0,0,1, 3, 0',
|
||||
),
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Predefined size constants.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
* Useful when your site changes its layout or if you have a grid to fit images into.
|
||||
*
|
||||
* Example:
|
||||
* &width=w1 // results in width=613
|
||||
* &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
|
||||
*/
|
||||
'size_constant' => function () {
|
||||
|
||||
@ -115,8 +143,10 @@ return array(
|
||||
'error_reporting' => function () {
|
||||
error_reporting(-1); // Report all type of errors
|
||||
ini_set('display_errors', 1); // Display all errors
|
||||
ini_set('output_buffering', 0); // Do not buffer outputs, write directly
|
||||
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.");
|
||||
}
|
||||
},
|
||||
);
|
||||
|
38
webroot/test/test_issue49.php
Normal file
38
webroot/test/test_issue49.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
// Include config for all testcases
|
||||
include __DIR__ . "/config.php";
|
||||
|
||||
|
||||
|
||||
// The title of the test case
|
||||
$title = "Testing issue 49 - flexible convolution";
|
||||
|
||||
|
||||
|
||||
// Provide a short description of the testcase.
|
||||
$description = "Creating shortcuts to custom convolutions by using configurable list of constant convolutions.";
|
||||
|
||||
|
||||
|
||||
// Use these images in the test
|
||||
$images = array(
|
||||
'kodim08.png',
|
||||
);
|
||||
|
||||
|
||||
|
||||
// For each image, apply these testcases
|
||||
$testcase = array(
|
||||
'&nc&width=400&convolve=lighten',
|
||||
'&nc&width=400&convolve=darken',
|
||||
'&nc&width=400&convolve=sharpen',
|
||||
'&nc&width=400&convolve=emboss',
|
||||
'&nc&width=400&convolve=blur',
|
||||
'&nc&width=400&convolve=blur:blur',
|
||||
'&nc&width=400&convolve=blur:blur:blur:blur',
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Apply testcases and present results
|
||||
include __DIR__ . "/template.php";
|
Loading…
x
Reference in New Issue
Block a user