/**
* Calculate histograms for each color channel for the given image
*/
function GetImageHistogram($image_file, $options, $histograms)
{
    $histogram = null;
    $ext = strripos($image_file, '.jpg');
    if ($ext !== false) {
        $histogram_file = substr($image_file, 0, $ext) . '.hist';
    } else {
        $ext = strripos($image_file, '.png');
        if ($ext !== false) {
            $histogram_file = substr($image_file, 0, $ext) . '.hist';
        }
    }
    if (isset($histograms)) {
        // figure out the timestamp for the video frame in ms
        $ms = null;
        if (preg_match('/ms_(?P<ms>[0-9]+)\\.(png|jpg)/i', $image_file, $matches)) {
            $ms = intval($matches['ms']);
        } elseif (preg_match('/frame_(?P<ms>[0-9]+)\\.(png|jpg)/i', $image_file, $matches)) {
            $ms = intval($matches['ms']) * 100;
        }
        foreach ($histograms as &$hist) {
            if (isset($hist['histogram']) && isset($hist['time']) && $hist['time'] == $ms) {
                $histogram = $hist['histogram'];
                break;
            }
        }
    }
    // See if we have the old-style histograms (separate files)
    if (!isset($histogram) && !isset($options) && isset($histogram_file) && is_file($histogram_file)) {
        $histogram = json_decode(file_get_contents($histogram_file), true);
        if (!is_array($histogram) || !array_key_exists('r', $histogram) || !array_key_exists('g', $histogram) || !array_key_exists('b', $histogram) || count($histogram['r']) != 256 || count($histogram['g']) != 256 || count($histogram['b']) != 256) {
            unset($histogram);
        }
    }
    // generate a histogram from the image itself
    if (!isset($histogram)) {
        $im = imagecreatefromjpeg($image_file);
        if ($im !== false) {
            $width = imagesx($im);
            $height = imagesy($im);
            if ($width > 0 && $height > 0) {
                // default a resample to 1/4 in each direction which will significantly speed up processing with minimal impact to accuracy.
                // This is only for calculations done on the server.  Histograms from the client look at every pixel
                $resample = 8;
                if (isset($options) && array_key_exists('resample', $options)) {
                    $resample = $options['resample'];
                }
                if ($resample > 2) {
                    $oldWidth = $width;
                    $oldHeight = $height;
                    $width = intval($width * 2 / $resample);
                    $height = intval($height * 2 / $resample);
                    $tmp = imagecreatetruecolor($width, $height);
                    fastimagecopyresampled($tmp, $im, 0, 0, 0, 0, $width, $height, $oldWidth, $oldHeight, 3);
                    imagedestroy($im);
                    $im = $tmp;
                    unset($tmp);
                }
                $histogram = array();
                $histogram['r'] = array();
                $histogram['g'] = array();
                $histogram['b'] = array();
                $buckets = 256;
                if (isset($options) && array_key_exists('buckets', $options) && $options['buckets'] >= 1 && $options['buckets'] <= 256) {
                    $buckets = $options['buckets'];
                }
                for ($i = 0; $i < $buckets; $i++) {
                    $histogram['r'][$i] = 0;
                    $histogram['g'][$i] = 0;
                    $histogram['b'][$i] = 0;
                }
                for ($y = 0; $y < $height; $y++) {
                    for ($x = 0; $x < $width; $x++) {
                        $rgb = ImageColorAt($im, $x, $y);
                        $r = $rgb >> 16 & 0xff;
                        $g = $rgb >> 8 & 0xff;
                        $b = $rgb & 0xff;
                        // ignore white pixels
                        if ($r != 255 || $g != 255 || $b != 255) {
                            if (isset($options) && array_key_exists('colorSpace', $options) && $options['colorSpace'] != 'RGB') {
                                if ($options['colorSpace'] == 'HSV') {
                                    RGB_TO_HSV($r, $g, $b);
                                } elseif ($options['colorSpace'] == 'YUV') {
                                    RGB_TO_YUV($r, $g, $b);
                                }
                            }
                            $bucket = (int) (($r + 1.0) / 256.0 * $buckets) - 1;
                            $histogram['r'][$bucket]++;
                            $bucket = (int) (($g + 1.0) / 256.0 * $buckets) - 1;
                            $histogram['g'][$bucket]++;
                            $bucket = (int) (($b + 1.0) / 256.0 * $buckets) - 1;
                            $histogram['b'][$bucket]++;
                        }
                    }
                }
            }
            imagedestroy($im);
            unset($im);
        }
        if (!isset($options) && isset($histogram_file) && !is_file($histogram_file) && isset($histogram)) {
            file_put_contents($histogram_file, json_encode($histogram));
        }
    }
    return $histogram;
}
Example #2
0
/**
* Calculate a RGB histogram excluding white pixels
* 
* @param mixed $image_file
* @param mixed $ignoreWhite - bool - should white pixels be ignored
* @param mixed $colorSpace - string - RGB, HSV or YUV
*/
function Histogram($image_file, $ignoreWhite, $colorSpace = 'RGB')
{
    global $viewport;
    $histogram = null;
    $nowhite = $ignoreWhite ? '.nowhite' : '';
    $histogram_file = "{$image_file}{$nowhite}.{$colorSpace}.hist";
    if (is_file($histogram_file)) {
        $histogram = json_decode(file_get_contents($histogram_file));
    } else {
        $im = imagecreatefrompng($image_file);
        if ($im !== false) {
            $right = imagesx($im);
            $bottom = imagesy($im);
            $left = 0;
            $top = 0;
            if (isset($viewport)) {
                $left = $viewport['x'];
                $top = $viewport['y'];
                $right = $left + $viewport['width'];
                $bottom = $top + $viewport['height'];
            }
            $histogram = array(array(), array(), array());
            $buckets = 256;
            for ($i = 0; $i < $buckets; $i++) {
                $histogram[0][$i] = 0;
                $histogram[1][$i] = 0;
                $histogram[2][$i] = 0;
            }
            for ($y = $top; $y < $bottom; $y++) {
                for ($x = $left; $x < $right; $x++) {
                    $rgb = ImageColorAt($im, $x, $y);
                    $r = $rgb >> 16 & 0xff;
                    $g = $rgb >> 8 & 0xff;
                    $b = $rgb & 0xff;
                    // ignore white pixels
                    if (!$ignoreWhite || $r != 255 || $g != 255 || $b != 255) {
                        if ($colorSpace == 'HSV') {
                            RGB_TO_HSV($r, $g, $b);
                        } elseif ($colorSpace == 'YUV') {
                            RGB_TO_YUV($r, $g, $b);
                        }
                        $histogram[0][$r]++;
                        $histogram[1][$g]++;
                        $histogram[2][$b]++;
                    }
                }
            }
            imagedestroy($im);
            unset($im);
            file_put_contents($histogram_file, json_encode($histogram));
        }
    }
    return $histogram;
}