No, ono linearni dct se toho mnoho zjednodusilo. Treba nemusim pocitat sumacos, tam to vychazi 16 pro nultou pozici a 10 a nejake desetinky pro ostatni. Desetinky jsem zanedbal, vysledna chyba se nepatrne zvysila.
Hlavne jsem to mohl testnout na 3000 px. (snad to bude cele, odmazaval jsem komenty kodu...)
<?php
ini_set('max_execution_time', 10000); //10000s
//set_time_limit(10000);
//ini_set('memory_limit', '256M');
function microtime_float() //pp 17.3.2014
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
$time = array();
$time[] = microtime_float();
function printNonZero(&$arr)
{
$stat = array();
$v = 16;
for ($i=0;$i<$v;$i++)
{
$stat[$i] = 0;
}
$i = 0;
foreach ($arr as $key=>$value)
{
if ($value!=0) {echo "[$key] => $value\n"; $i++;}
$x = abs($value);
if ($x<$v) {$stat[$x]++;}
}
if ($i!=0) {echo "Sum $i\n";}
ksort($stat);
echo "Sum abs<$v "; print_r($stat); echo "\n";
}
// input
$file = "img/1299576.jpg";
list($width, $height, $type, $attr) = getimagesize($file);
$img = ImageCreateFromJpeg($file);
imagefilter($img, IMG_FILTER_GRAYSCALE);
$time[] = microtime_float();
// prepare tables
$maxM = 16;
$maxM = 256;
//$maxM = 1024;
//$maxM = 1920-300; //1920x1200 - 300x600
//$maxM = 3000;
$cosA = array();
$cosB = array();
$qcA = array();
$qcB = array();
$c0 = pow(1/$maxM,0.5);
$c1 = pow(2/$maxM,0.5);
$cosM = M_PI / ($maxM * 2);
$qcB = null;
$time[] = microtime_float();
// read input
$x = 300;
$y = 600;
$inp = array();
for ($i=0;$i<$maxM;$i++)
{
$x++;
if ($x>=1920) {$x=0; $y++; if ($y>960) break;}
$inp[$i] = imagecolorat($img, $x, $y) & 0xFF; //$r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF;
// $inp[$i] = rand(0,256);
}
$time[] = microtime_float();
// transform 1D
$out = array();
$cosSuma = array();
for ($i=0;$i<$maxM;$i++)
{
$c = $i==0 ? $c0 : $c1;
$j = 0;
$cosSuma[$i] = ($i==0 ? 16 : 10) / abs(cos($cosM * (2*$j+1)*$i));
$out[$i] = 0;
for ($j=0;$j<$maxM;$j++)
{
$out[$i] += $inp[$j] * cos($cosM * (2*$j+1)*$i);
}
$out[$i] = round($out[$i] * ($c / $cosSuma[$i]));
}
$time[] = microtime_float();
// transform 1D back
$inp2 = array();
$stat_diff = array();
$stat_inp=0;
$stat_out=0;
$stat_err=0;
for ($i=0;$i<$maxM;$i++)
{
$inp2[$i] = 0;
for ($j=0;$j<$maxM;$j++)
{
$c = $j==0 ? $c0 : $c1;
$inp2[$i] += $out[$j] * cos($cosM * (2*$i+1)*$j) * $c * $cosSuma[$j];
}
$inp2[$i] = round($inp2[$i]);
// $inp2[$i] = $inp2[$i] <= 255 ? ($inp2[$i] >= 0 ? $inp2[$i] : 0) : 255;
$stat_inp += $inp[$i]>0 ? $inp[$i] : -$inp[$i];
$stat_out += $out[$i]>0 ? $out[$i] : -$out[$i];
$x = $inp[$i] - $inp2[$i];
$stat_err += $x>0 ? $x : -$x;
}
$time[] = microtime_float();
// print
echo '<table><tr>';
if ($maxM<=16)
{
echo '<td>INP';
echo '<pre>'; print_r($inp); echo '</pre>';
echo '<td>OUT';
echo '<pre>'; print_r($out); echo '</pre>';
echo '<td>INP2';
echo '<pre>'; print_r($inp2); echo '</pre>';
echo '<td>stat_diff';
echo '<pre>'; print_r($stat_diff); echo '</pre>';
}
else
{
echo '<td>OUT';
echo '<pre>'; printNonZero($out); echo '</pre>';
}
echo '</tr></table>';
echo "err = $stat_err / ".($maxM*256)." (".($stat_err/($maxM*256)*100)." %) ... abs(D) / (max*256)<br>";
echo "inp = $stat_inp | out = $stat_out ... suma(value)<br>";
echo "errinp = $stat_err / $stat_inp = ".($stat_err/$stat_inp*100)." % (A / B)";
//output
imagedestroy($img);
$time[] = microtime_float();
$t = array();
$t[] = round($time[count($time)-1]-$time[0],3);
for ($i=1;$i<count($time);$i++)
{
$t[] = round($time[$i]-$time[$i-1],3);
}
$t = implode(" | ",$t);
echo '<hr>Cas zpracovani '.$t.' s';
?>