$avg ? $hist[$j] : 0; } $score = \array_sum($hist); if ($bestScore < $score) { $bestScore = $score; $bestDegree = $i; } } $im = \imagerotate($im, $bestDegree, 1); if ($im === false) { return; } if (\strripos($outPath, 'png') !== false) { \imagepng($im, $outPath); } elseif (\strripos($outPath, 'jpg') !== false || \strripos($outPath, 'jpeg') !== false) { \imagejpeg($im, $outPath); } elseif (\strripos($outPath, 'webp') !== false) { \imagewebp($im, $outPath); } else { \imagegif($im, $outPath); } \imagedestroy($im); } /** * Rotate the pixel matrix by a certain degree * * @param array $pixel Pixel matrix (0 index = y, 1 index = x) * @param array $dim Matrix dimension (0 index = y, 1 index = x) * @param int $deg Degree to rotate * * @return array * * @since 1.0.0 */ public static function rotatePixelMatrix(array $pixel, array $dim, int $deg) : array { $rad = \deg2rad($deg); $sin = \sin(-$rad); $cos = \cos(-$rad); $rotated = [[]]; $cXArr = []; for ($j = 0; $j < $dim[1]; ++$j) { $cXArr[] = $j - $dim[1] / 2.0; // center } for ($i = 0; $i < $dim[0]; ++$i) { $cY = $i - $dim[0] / 2.0; // center foreach ($cXArr as $j => $cX) { $x = $cos * $cX + $sin * $cY + $dim[1] / 2.0; $y = -$sin * $cX + $cos * $cY + $dim[0] / 2.0; $rotated[$i][$j] = self::getNearestValue($pixel, $dim, $x, $y); } } return $rotated; } /** * Find the closes pixel based on floating points * * @param array $pixel Pixel matrix (0 index = y, 1 index = x) * @param array $dim Matrix dimension (0 index = y, 1 index = x) * @param float $x X coordinate * @param float $y Y coordinate * * @return int * * @since 1.0.0 */ private static function getNearestValue(array $pixel, array $dim, float $x, float $y) : int { $xLow = ($x < 0) ? 0 : (($x > ($dim[1] - 1)) ? ($dim[1] - 1) : (int) $x); $xHigh = ($xLow === $dim[1] - 1) ? $xLow : ($xLow + 1); $yLow = ($y < 0) ? 0 : (($y > ($dim[0] - 1)) ? ($dim[0] - 1) : (int) $y); $yHigh = ($yLow === $dim[0] - 1) ? $yLow : ($yLow + 1); $points = [ [$xLow, $yLow], [$xLow, $yHigh], [$xHigh, $yLow], [$xHigh, $yHigh], ]; $minDistance = \PHP_FLOAT_MAX; $minValue = 0; foreach ($points as $point) { $distance = ($point[0] - $x) * ($point[0] - $x) + ($point[1] - $y) * ($point[1] - $y); if ($distance < $minDistance) { $minDistance = $distance; $minValue = $point[0] >= 0 && $point[0] < $dim[0] && $point[1] >= 0 && $point[1] < $dim[1] ? $pixel[$point[1]][$point[0]] : 0; } } return $minValue; } }