Skip to content

Instantly share code, notes, and snippets.

@licson
Last active February 5, 2016 16:59
Show Gist options
  • Select an option

  • Save licson/ed8299bb48ff8b17e3e6 to your computer and use it in GitHub Desktop.

Select an option

Save licson/ed8299bb48ff8b17e3e6 to your computer and use it in GitHub Desktop.
FXAA in PHP
<?php
class FXAA {
const FXAA_REDUCE_MIN = 0.0078125;
const FXAA_REDUCE_MUL = 0.125;
const FXAA_SPAN_MAX = 8;
static $w = 0;
static $h = 0;
private static function add($a, $b){
return array($a[0] + $b[0], $a[1] + $b[1], $a[2] + $b[2]);
}
private static function dot($a, $b){
return $a[0] * $b[0] + $a[1] * $b[1] + $a[2] * $b[2];
}
private static function texture2D($img, $pos){
if(($pos[0] >= self::$w || $pos[0] < 0) || ($pos[1] >= self::$h || $pos[1] < 0)){
return array(0, 0, 0, 0);
}
$x = floor($pos[0]);
$y = floor($pos[1]);
$rx = $pos[0] - $x - 0.5;
$ry = $pos[1] - $y - 0.5;
$ax = abs($rx);
$ay = abs($ry);
$dx = $rx < 0 ? -1 : 1;
$dy = $ry < 0 ? -1 : 1;
$c = imagecolorat($img, $x, $y);
$cx = imagecolorat($img, $x + $dx, $y);
$cy = imagecolorat($img, $x, $y + $dy);
$cxy = imagecolorat($img, $x + $dx, $y + $dy);
$ca = ($c >> 24) & 255;
$cr = ($c >> 16) & 255;
$cg = ($c >> 8) & 255;
$cb = $c & 255;
$cxa = ($cx >> 24) & 255;
$cxr = ($cx >> 16) & 255;
$cxg = ($cx >> 8) & 255;
$cxb = $cx & 255;
$cya = ($cy >> 24) & 255;
$cyr = ($cy >> 16) & 255;
$cyg = ($cy >> 8) & 255;
$cyb = $cy & 255;
$cxya = ($cxy >> 24) & 255;
$cxyr = ($cxy >> 16) & 255;
$cxyg = ($cxy >> 8) & 255;
$cxyb = $cxy & 255;
$cf1 = array(
(1 - $ax) * $cr + $ax * $cxr,
(1 - $ax) * $cg + $ax * $cxg,
(1 - $ax) * $cb + $ax * $cxb,
(1 - $ax) * $ca + $ax * $cxa
);
$cf2 = array(
(1 - $ax) * $cyr + $ax * $cxyr,
(1 - $ax) * $cyg + $ax * $cxyg,
(1 - $ax) * $cyb + $ax * $cxyb,
(1 - $ax) * $cya + $ax * $cxya
);
return array(
(1 - $ay) * $cf1[0] + $ay * $cf2[0],
(1 - $ay) * $cf1[1] + $ay * $cf2[1],
(1 - $ay) * $cf1[2] + $ay * $cf2[2],
(1 - $ay) * $cf1[3] + $ay * $cf2[3]
);
}
public static function process(&$img){
self::$w = imagesx($img);
self::$h = imagesy($img);
$output = imagecreatetruecolor(self::$w, self::$h);
for($x = 0; $x < imagesx($img); $x++){
for($y = 0; $y < imagesy($img); $y++){
$rgbNW = self::texture2D($img,array($x - 1, $y - 1));
$rgbNE = self::texture2D($img,array($x + 1, $y - 1));
$rgbSW = self::texture2D($img,array($x - 1, $y + 1));
$rgbSE = self::texture2D($img,array($x + 1, $y + 1));
$rgbaM = $rgbM = self::texture2D($img,array($x, $y));
$opacity = array_pop($rgbM);
$luma = array(76, 149, 29);
$lumaNW = self::dot($rgbNW, $luma);
$lumaNE = self::dot($rgbNE, $luma);
$lumaSW = self::dot($rgbSW, $luma);
$lumaSE = self::dot($rgbSE, $luma);
$lumaM = self::dot($rgbM, $luma);
$lumaMin = min($lumaM, min(min($lumaNW, $lumaNE ), min($lumaSW, $lumaSE)));
$lumaMax = max($lumaM, max(max($lumaNW, $lumaNE), max($lumaSW, $lumaSE)));
$dir = array(
-(($lumaNW + $lumaNE) - ($lumaSW + $lumaSE)),
(($lumaNW + $lumaSW) - ($lumaNE + $lumaSE))
);
$dirReduce = max(($lumaNW + $lumaNE + $lumaSW + $lumaSE ) * ( 0.25 * self::FXAA_REDUCE_MUL ), self::FXAA_REDUCE_MIN);
$rcpDirMin = 1 / (min(abs($dir[0]), abs($dir[1])) + $dirReduce);
$dir[0] = min(self::FXAA_SPAN_MAX, max(-self::FXAA_SPAN_MAX, $dir[0] * $rcpDirMin));
$dir[1] = min(self::FXAA_SPAN_MAX, max(-self::FXAA_SPAN_MAX, $dir[1] * $rcpDirMin));
$rgbA = self::add(
self::texture2D($img, array($x + $dir[0] * (1 / 3 - 0.5), $y + $dir[1] * (1 / 3 - 0.5))),
self::texture2D($img, array($x + $dir[0] * (2 / 3 - 0.5), $y + $dir[1] * (1 / 3 - 0.5)))
);
$rgbA[0] *= 0.5;
$rgbA[1] *= 0.5;
$rgbA[2] *= 0.5;
$rgbB = self::add(
self::texture2D($img, array($x + $dir[0] * -0.5, $y + $dir[1] * -0.5)),
self::texture2D($img, array($x + $dir[0] * 0.5, $y + $dir[1] * 0.5))
);
$rgbB[0] = $rgbB[0] * 0.25 + $rgbA[0] * 0.5;
$rgbB[1] = $rgbB[1] * 0.25 + $rgbA[1] * 0.5;
$rgbB[2] = $rgbB[2] * 0.25 + $rgbA[2] * 0.5;
$lumaB = self::dot($rgbB, $luma);
if(($lumaB < $lumaMin) || ($lumaB > $lumaMax)){
imagesetpixel($output, $x, $y, imagecolorallocatealpha($img, $rgbA[0], $rgbA[1], $rgbA[2], $opacity));
}
else {
imagesetpixel($output, $x, $y, imagecolorallocatealpha($img, $rgbB[0], $rgbB[1], $rgbB[2], $opacity));
}
}
}
$img = $output;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment