Login   Register  
PHP Classes
elePHPant
Icontem

File: batchresize.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Chris Jeffries  >  Value Seek  >  batchresize.php  >  Download  
File: batchresize.php
Role: Example script
Content type: text/plain
Description: Example code using ValueSeek to resize image files. Command line utility, not web page script
Class: Value Seek
Seek for optimal values with binary search
Author: By
Last change:
Date: 1 year ago
Size: 7,339 bytes
 

Contents

Class file image Download
<?php
/**
 * Seek the input value that generates the required output value for a given function and context
 *
 * Given a supplied (callback) function, finds out what input value to the function is required to generate the specified
 * result value for a given set of conditions. For example, what value of the quality parameter is needed to 
 * achieve a specified file size for a given image. The binary chop search method is used to minimise the
 * number of attempts. This method requires a comparison between the required value and the most recent achieved value.
 * This comparison is also carried out in a callback function so that the comparison is under user control.
 *
 * @property callback string The name of a function which maps the independent variable to the dependent variable
 * @property comparator string The name of a function which compares the result of callback to the sought value
 * @property maxattempts integer Max number of times to iterate. Default 30
 * @property boundLower integer the minimum value of the independent variable. Default 0
 * @property boundUpper integer the maximum value of the independent variable. Default 99
 * @property searchvalue mixed this value will be passed to comparator for comparison with the result of callback function
 * @property items mixed cargo for the callback function. Invariate value(s)
 * @property-read status integer how the search was completed. Values 1-4
 * @ property-read statusmsg string how the search was completed.
 * @ property-read outputvalue mixed contains the final result from callback
 * @method mixed search returns outputvalue, documented above
 *
*/
class ValueSeeker
{    private $callback;        //The function which transforms the input value into the output value - default: pick element from array
    
private $comparator;    //used for tests of $searchvalue against outputvalue of callback function - default: simple comparison a gt/lt/= b
    
private $maxattempts;    //maximum number of times the search is iterated before giving up - default 30
    
private $boundLower;    //lowest input value to the callback function - default 0
    
private $boundUpper;    //highest input value to the callback function - default 99
    
private $searchvalue;    //The output value to be aimed for
    
private $items;            //parametric data for the callback function
    
private $status;
    private 
$statusmsg;
    private 
$inputvalue;    //used to probe output values of callback. value range between $boundUpper and $boundLower
    
private $outputvalue;    //hold the result of the callback function

/**
 * Function to compare two result values
 * 
 * This is a simple comparison between two integers or strings. It is the default
 * callback function for comparator. It will normally be overridden by a more complex
 * comparison. 
 * 
 * @param mixed a the value of the searchvalue property
 * @param mixed b the return value after calling the callback function defined in the callback property
 * @return integer -1: a is less, +1: b is less; 0: they are the same
 *
*/
    
private function compare($a$b)
    {    
//default function for comparator
        
if ($a == $b) return 0;
        if (
$a $b) return 1;
        return -
1;
    }

/**
 * Function to map an independent variable to a dependent variable
 * 
 * This is a sample function. It assumes that the property 'items' contains a number
 * indexed array. This sample callback function transforms the index of the array to
 * the value of that indexed item.
 *
*/
    
private function arrayselect($array$index)
    {    
//default function for callback
        
return $array[$index];
    }

    function 
__construct()
    {
        
$this->callback 'arrayselect';
        
$this->comparator 'compare';
        
$this->maxattempts 30;
        
$this->boundLower 0;
        
$this->boundUpper 99;
    }

    public function 
__set ($var$value)
    {
        switch (
$var)
        {
        case 
'searchvalue':
            
$this->searchvalue $value;
            break;

        case 
'items':
            
$this->items $value;
            break;

        case 
'callback':
            if(!
function_exists($value)) throw new Exception("$var function '$value()' does not exist",4);
            
$this->callback $value;
            break;

        case 
'comparator':
            if(!
function_exists($value))  throw new Exception("$var function '$value()' does not exist",5);
            
$this->comparator $value;
            break;

        case 
'maxAttempts':
            if(!
is_integer($value))     throw new Exception("maxattempts is not an integer",2);
            if( 
$maxattempts )         throw new Exception("maxattempts must be at least 1"3);
            
$this->maxattempts $value;    
            break;

        case 
'boundLower':
            if(!
is_integer($value))     throw new Exception("lower bound of range is not an integer",2);
            
$this->boundLower $value;
            break;

        case 
'boundUpper':
            if(!
is_integer($value))     throw new Exception("upper bound of range is not an integer",2);
            
$this->boundUpper $value;
            break;

        default:
            throw new 
Exception("Attempt to set non-existent property:$var\n\r",10);
        }
    }
    public function 
__get($var)
    {
        switch (
$var)
        {
            case 
'searchvalue':     return $this->searchvalue;     break;
            case 
'items':             return $this->items;         break;
            case 
'maxattempts':     return $this->maxattempts;     break;
            case 
'boundLower':         return $this->boundLower;     break;
            case 
'boundUpper':         return $this->boundUpper;     break;
            case 
'comparator':         return $this->comparator;     break;
            case 
'callback':         return $this->callback;     break;
            case 
'outputvalue':     return $this->outputvalue;     break;
            case 
'status':             return $this->status;         break;
            case 
'statusmsg':         return $this->statusmsg;     break;
            default:                 throw new 
Exception("Attempt to get non-existent property:$var\n\r",11);
        }
    }

    function 
search()
    {
        if(
$this->boundUpper $this->boundLower)          throw new Exception("range invalid:lower bound > upper bound",1);

        
$boundUpper $this->boundUpper;
        
$boundLower $this->boundLower;

        
$inputValue round(($boundUpper $boundLower) / 20);
        
$attempts     0;
        
$comparison 0;

        while( 
$attempts $this->maxattempts )
        {
            
$this->outputvalue call_user_func($this->callback$this->items$inputValue);
            
$comparison call_user_func($this->comparator$this->searchvalue$this->outputvalue );

            if ( 
$comparison 
            {
                
$boundLower $inputValue;
                
$inputValue round(($boundUpper $inputValue) / 20);
                if(
$inputValue == $boundLower
                {
                        if(
$boundLower == $this->boundLower)
                        {
                            
$this->statusmsg "Hit lower bound";
                            
$this->status 3;
                        }
                        else
                        {
                            
$this->statusmsg "Found nearest input value(-)";
                            
$this->status 2;
                        }
                    return 
$inputValue;//gone as low as we can
                
}
            }
            else
            {
                if ( 
$comparison )
                {
                    
$boundUpper $inputValue;
                    
$inputValue round(($boundLower $inputValue) / 20);
                    if( 
$inputValue == $boundUpper 
                    {
                        if(
$boundUpper == $this->boundUpper)
                        {
                            
$this->statusmsg "Hit upper bound";
                            
$this->status 4;
                        }
                        else
                        {
                            
$this->statusmsg "Found nearest input value(-)";
                            
$this->status 2;
                        }
                        return 
$inputValue 1;//gone as high as we can
                    
}
                }
                else
                {
                    
$this->statusmsg "Reached target value";
                    
$this->status 1;
                    return 
$inputValue;
                }
            }
            
$attempts++;
        }
        
$this->statusmsg "Performed maximum no of attempts";
        
$this->status 4;
        return 
$inputValue//bombed out on attempts limit
    
}
}
?>