首页 > 解决方案 > 如何在 PHP 中将图像全景到立方体

问题描述

如何将下面的 panaroma 图像转换为 php 中的立方体 iamges?

我使用了 imagick、js 代码和......但没有结果。

主图 在此处输入图像描述

请帮帮我谢谢

标签: php

解决方案


经过一番努力...

我得到了正确的结果

我的最终代码:

# get x,y,z coords from out image pixels coords
# i,j are pixel coords
# faceIdx is face number
# faceSize is edge length
function outImgToXYZ($i, $j, $faceIdx, $faceSize)
{
    $a = 2.0 * (float) $i / $faceSize;
    $b = 2.0 * (float) $j / $faceSize;

    switch ($faceIdx)
    {
        case 0: return [-1.0, 1.0 - $a, 3.0 - $b]; break; # back
        case 1: return [$a - 3.0, -1.0, 3.0 - $b]; break; # left
        case 2: return [1.0, $a - 5.0, 3.0 - $b]; break; # front
        case 3: return [7.0 - $a, 1.0, 3.0 - $b]; break; # right
        case 4: return [$b - 1.0, $a - 5.0, 1.0]; break; # top
        case 5: return [5.0 - $b, $a - 5.0, -1.0]; break; # bottom
    }

    return [0, 0, 0];
}

function clip($x, $min, $max)
{
    if ($x > $max) return $max;
    if ($x < $min) return $min;
    return $x;
}

# convert using an inverse transformation
function convertFace($imgIn, $imgInWidth, $imgInHeight, $imgOut, $imgOutWidth, $imgOutHeight)
{
    $pi = pi();
    $edge = $imgInWidth / 4;
    $face = 0;
    $face2 = 0;
    $rng = null;

    for($xOut = 0; $xOut <= $imgOutWidth; $xOut++)
    {
        $face = floor($xOut / $edge); // 0 - back, 1 - left 2 - front, 3 - right
        if ($face === 2) $rng = range(0, $edge * 3, 1);
        else $rng = range($edge, $edge * 2, 1);

        for($yOut =0; $yOut <= $imgOutHeight; $yOut++)
        {
            if ($yOut < $edge) $face2 = 4; // top
            else if ($yOut >= 2 * $edge) $face2 = 5; // bottom
            else $face2 = $face;

            list($x, $y, $z) = outImgToXYZ($xOut, $yOut, $face2, $edge);
            $theta = atan2($y, $x);
            $r = hypot($x, $y);
            $phi = atan2($z, $r);

            # source img coords
            $uf = 2.0 * $edge * ($theta + $pi) / $pi;
            $vf = 2.0 * $edge * ($pi / 2 - $phi) / $pi;

            # Use bilinear interpolation between the four surrounding pixels
            $ui = floor($uf); # coord of pixel to bottom left
            $vi = floor($vf);
            $u2 = $ui + 1; # coords of pixel to top right
            $v2 = $vi + 1;
            $mu = $uf - $ui; # fraction of way across pixel
            $nu = $vf - $vi;

            # Pixel values of four corners
            $a = imagecolorsforindex($imgIn, imagecolorat($imgIn, $ui % $imgInWidth, clip($vi, 0, $imgInHeight - 1)));
            $b = imagecolorsforindex($imgIn, imagecolorat($imgIn, $u2 % $imgInWidth, clip($vi, 0, $imgInHeight - 1)));
            $c = imagecolorsforindex($imgIn, imagecolorat($imgIn, $ui % $imgInWidth, clip($v2, 0, $imgInHeight - 1)));
            $d = imagecolorsforindex($imgIn, imagecolorat($imgIn, $u2 % $imgInWidth, clip($v2, 0, $imgInHeight - 1)));

            # interpolate
            list($r, $g, $b) =
                [
                    $a["red"] * (1 - $mu) * (1 - $nu) + $b["red"] * ($mu) * (1 - $nu) + $c["red"] * (1 - $mu) * $nu + $d["red"] * $mu * $nu,
                    $a["green"] * (1 - $mu) * (1 - $nu) + $b["green"] * ($mu) * (1 - $nu) + $c["green"] * (1 - $mu) * $nu + $d["green"] * $mu * $nu,
                    $a["blue"] * (1 - $mu) * (1 - $nu) + $b["blue"] * ($mu) * (1 - $nu) + $c["blue"] * (1 - $mu) * $nu + $d["blue"] * $mu * $nu
                ];
            imagesetpixel($imgOut, $xOut, $yOut, imagecolorallocate($imgOut, (int) round($r), (int) round($g), (int) round($b)));
        }
    }

    return $imgOut;
}

// start convert
$imgInPath = "./main.jpg";
$imgIn = imagecreatefromjpeg($imgInPath);
$imgInSize = getimagesize($imgInPath);
$imgInWidth = $imgInSize[0];
$imgInHeight = $imgInSize[1];
$imgOutWidthHeight = $imgInWidth / 4;
$imgOutFullWidth = $imgInWidth;
$imgOutFullHeight = $imgInWidth * 3 / 4;
$imgFormat = "jpg";

$imgOut = imagecreate($imgOutFullWidth, $imgOutFullHeight);
imagefill($imgOut, 0, 0, imagecolorallocate($imgOut, 0, 0, 0));
imagejpeg($imgOut, "./temp.jpg", 100);
$imgOut = imagecreatefromjpeg("./temp.jpg");
imagefill($imgOut, 0, 0, imagecolorallocate($imgOut, 0, 0, 0));
$imgOut = convertFace($imgIn, $imgInWidth, $imgInHeight, $imgOut, $imgOutFullWidth, $imgOutFullHeight);
imagejpeg($imgOut, "./temp.jpg", 100);
imagedestroy($imgOut);

$faceNames = [['', '', 'top', ''], ['left', 'front', 'right', 'back'], ['', '', 'bottom', '']];
for($i = 0; $i < 3; $i++)
{
    for($j = 0; $j < 4; $j++)
    {
        $faceName = $faceNames[$i][$j];
        if($faceName != "")
        {
            $im = imagecreatefromjpeg("temp.jpg");
            $im2 = imagecrop($im, ["x" => ($j * $imgOutWidthHeight), "y" => ($i * $imgOutWidthHeight), "width" => $imgOutWidthHeight, "height" => $imgOutWidthHeight]);
            if($im2 !== FALSE)
            {
                imagejpeg($im2, "main_$faceName.jpg", 100);
                imagedestroy($im2);
            }
            imagedestroy($im);
        }
    }
}

unlink("./temp.jpg");

推荐阅读