in pdq/php/pdqhasher.php [622:754]
static function computeDCTAndQualityFromImage(
/*resource*/&$image,
/*bool*/ $show_timings,
/*bool*/ $dump
) {
$num_rows = imagesy($image);
$num_cols = imagesx($image);
if ($dump) {
echo "num_rows=$num_rows\n";
echo "num_cols=$num_cols\n";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// RGB to luma
$t1 = microtime(true);
$luma_matrix = self::imageToLumaMatrix($image, $num_rows, $num_cols);
$t2 = microtime(true);
if ($show_timings) {
printf("X010-LUMA %.6f\n", $t2-$t1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Downsample (blur and decimate)
$t1 = microtime(true);
$window_size_along_rows = self::computeJaroszFilterWindowSize($num_cols);
$window_size_along_cols = self::computeJaroszFilterWindowSize($num_rows);
self::jaroszFilter($luma_matrix, $num_rows, $num_cols, $window_size_along_rows, $window_size_along_cols);
$t2 = microtime(true);
if ($show_timings) {
printf("X020-JRSZ %.6f\n", $t2-$t1);
}
// Decimation per se. Target centers not corners.
$buffer_64x64 = array();
for ($i = 0; $i < 64; $i++) {
$row = array();
for ($j = 0; $j < 64; $j++) {
$row[$j] = 0;
}
$buffer_64x64[$i] = $row;
}
$t1 = microtime(true);
for ($i = 0; $i < 64; $i++) {
$ini = (int)((($i + 0.5) * $num_rows) / 64);
for ($j = 0; $j < 64; $j++) {
$inj = (int)((($j + 0.5) * $num_cols) / 64);
$buffer_64x64[$i][$j] = $luma_matrix[$ini][$inj];
}
}
$t2 = microtime(true);
if ($dump) {
echo "DOWNSAMPLE IMAGE:\n";
print_r($buffer_64x64);
}
if ($show_timings) {
printf("X030-DSMP %.6f\n", $t2-$t1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Quality metric. Reuse the 64x64 image-domain downsample
// since we already have it.
$t1 = microtime(true);
$quality = self::computeImageDomainQualityMetric($buffer_64x64);
$t2 = microtime(true);
if ($show_timings) {
printf("X040-QMTC %.6f\n", $t2-$t1);
}
if ($dump) {
echo "QUALITY:$quality\n";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$t1 = microtime(true);
$buffer_16x64 = array();
for ($i = 0; $i < 16; $i++) {
$row = array();
for ($j = 0; $j < 64; $j++) {
$row[$j] = 0;
}
$buffer_16x64[$i] = $row;
}
$buffer_16x16 = array();
for ($i = 0; $i < 16; $i++) {
$row = array();
for ($j = 0; $j < 16; $j++) {
$row[$j] = 0;
}
$buffer_16x16[$i] = $row;
}
$dct_16x64 = array();
for ($i = 0; $i < 16; $i++) {
$row = array();
for ($j = 0; $j < 64; $j++) {
$row[$j] = 0;
}
$dct_16x64[$i] = $row;
}
// See comments on dct64To16. Input is (0..63)x(0..63); output is
// (1..16)x(1..16) with the latter indexed as (0..15)x(0..15).
$matrix_scale_factor = sqrt(2.0 / 64.0);
$pi = 3.141592653589793;
for ($i = 0; $i < 16; $i++) {
for ($j = 0; $j < 64; $j++) {
$dct_16x64[$i][$j] = $matrix_scale_factor *
cos(($pi / 2 / 64.0) * ($i+1) * (2 * $j + 1));
}
}
$t2 = microtime(true);
if ($show_timings) {
printf("X050-DMTX %.6f\n", $t2-$t1);
}
if ($dump) {
echo "DCT MATRIX:\n";
print_r($dct_16x64);
}
// 2D DCT
$t1 = microtime(true);
self::computeDCT64To16($buffer_64x64, $buffer_16x64, $buffer_16x16, $dct_16x64);
$t2 = microtime(true);
if ($show_timings) {
printf("X060-CDCT %.6f\n", $t2-$t1);
}
if ($dump) {
echo "DCT OUTPUT:\n";
print_r($buffer_16x16);
}
return array($buffer_16x16, $quality);
}