ama-team/php-projection-framework

View on GitHub
src/Conversion/Processor/FXAA/EdgeDistanceCalculator.php

Summary

Maintainability
A
3 hrs
Test Coverage
<?php

namespace AmaTeam\Image\Projection\Conversion\Processor\FXAA;

use AmaTeam\Image\Projection\Image\Utility\Luma;

class EdgeDistanceCalculator
{
    /**
     * @param Edge $edge
     * @param bool $inverse
     * @return int
     *
     * @SuppressWarnings(PHPMD.ElseExpression)
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public static function calculate(Edge $edge, $inverse = false)
    {
        $width = $edge->image->getWidth();
        $height = $edge->image->getHeight();
        $offset = $inverse ? -1 : 1;
        if ($edge->horizontal) {
            $xOffset = $offset;
            $yOffset = 0;
            $xSampleOffset = 0;
            $ySampleOffset = $edge->inward ? -1 : 1;
        } else {
            $xOffset = 0;
            $yOffset = $offset;
            $xSampleOffset = $edge->inward ? -1 : 1;
            $ySampleOffset = 0;
        }
        $distance = 1;
        $averageLuma = $edge->averageLuma;
        for ($i = 0; $i < 10; $i++) {
            $edgeX = $edge->x + $distance * $xOffset;
            $edgeY = $edge->y + $distance * $yOffset;
            if ($edgeX < 0 || $edgeX >= $width || $edgeY < 0 || $edgeY >= $height) {
                break;
            }
            $sampleX = $edgeX + $xSampleOffset;
            $sampleY = $edgeY + $ySampleOffset;
            if ($sampleX < 0 || $sampleX >= $width || $sampleY < 0 || $sampleY >= $height) {
                break;
            }
            $edgeColor = $edge->image->getColorAt($edgeX, $edgeY);
            $sampleColor = $edge->image->getColorAt($sampleX, $sampleY);
            $edgeLuma = Luma::compute($edgeColor);
            $sampleLuma = Luma::compute($sampleColor);
            $luma = ($edgeLuma + $sampleLuma) / 2;
            if (abs($averageLuma - $luma) >= $edge->threshold) {
                break;
            }
            $multiplier = (int) ($distance / 4);
            $distance += 1 + $multiplier * $multiplier;
        }
        return $distance;
    }

    public static function apply(Edge $edge)
    {
        $edge->forwardDistance = self::calculate($edge, false);
        $edge->backwardDistance = self::calculate($edge, true);
    }
}