ValueSeeker class

When is it useful

This class is useful when you want to achieve a given result and there is a parameter you can adjust to achieve it, but you do not know without trial and error what value to set it to.

The result must be measurable by a number which describes the characteristic you want to test. For example, if you are choosing the least compression that will achieve a given file size, you would measure the length of the compressed result.

There can only be one control parameter, and it must be numeric. The program has been tested for numbers in the range 10-99, but other ranges ought to work too. For example, it could be the quality parameter used to specify JPEG compression.

How it works

The seeker uses a b-tree algorithm to seek the closest value, so the average execution time varies as the logarithm of the range, rather than in direct proportion.

After the search is complete, the following properties are set

  1. How the search ended – e.g. maximum attempts reached

  2. The output of the final execution of your callback function – eg the compressed image string if you were trying to optimise a JPEG compression

  3. The value of the input variable that achieved this result

There are some flexibilities, and some limitations to this class.

Flexibilities

You can specify any function you like as a callback function to this class. The function will be tested with varying input values in order to find the closest output value. However, you must wrap the functon in your own function so that it accepts and returns appropriate values

You also specify how the comparison is done by supplying a comparator callback function. For example, your function may return an object and your test is for just one property of the object. This is a callback function similar to the sort of callback function used by uasort().

You specify the max and min values of the input variable (default 10-99)

You specify the maximum number of attempts before giving up (default 30)

You provide the cargo needed for your callback function (e.g. a GD resource for an image)

You provide the search value that will be passed to your comparator callback function

Limitations

There can only be one varying input value. The measured result must always move in the same direction as the input value (eg increasing JPEG quality will result in an increasing file size)

The input variable is always rounded to the nearest integer, so if you want fine control, use a larger range. e.g. multiply the range by 1000 (0-9999) and then divide it to suitable value in your wrapper function.

Example

One example use is provided – batchresize.php.

It's purpose is to provide a batch resizing facility for image files. For example to prepare web ready versions of all your high-res digital photos.

This program is meant to be invoked from the command line, not through a web page. Who wants to upload all their high res pics up to a web page for squashing, after all.

The parameters are

The directory to output to. This will be created if it does not exist. However the program has not been tested for, and probably will not work to create a directory within a directory which also does not exist. The program has not been tested where the output directory is the same as the input directory. The likely behaviour is that the original files will be overwritten. Beware!

The target file size in bytes

A list of files to be processed, or (in a bash shell at least) a file pattern which will get expanded into a list of files by the OS command shell. The files must all be of type mime/jpeg, mime/png or mime/gif. The program will halt if it encounters a file not of one of these types.

The program provides relatively verbose output. One line per file processed. There is no option to change this output.

Structure of example

The use of ValueSeeker is wrapped in the function getJPEGbysize. This function creates a ValueSeeker object ($x) and sets the various properties (including two callback functions.

Finally it asks the object to seek for a result. On completion of the seek, it retrieves the reuqired data (the JPEG string) and passes it back to the main routine.

The two callback functions are:

callback(): turns a GD resource into a JPEG string (by catching the output buffer). It returns an object containing the jpeg string and the length of the string in bytes.

comparator(): receives the target file size and the object returned by the callback. It returns -1 if the string is smaller than required, +1 if it is bigger than required, and 0 if it is just right.

There is also a function to create a GD resource from a jpeg, png or gif file. This GD resource is provided to the main callbackfunction via the ValueSeeker object.

After checking out the supplied parameters, the main routine steps through the list of files supplied in the command line. It attempts to create a GD resource from the file then asks ValueSeeker to create a jpeg string of the specified size.

It writes the jpeg string to a file with the same name as the source file into the directory specified in the command line.