Как вырезать область вне полигона?

Я хотел бы сделать прозрачным что-либо за пределами предопределенного многоугольника в PHP. Предположим, у вас есть форма вашей головы, тогда все остальное изображения должно быть зажато. Заранее большое спасибо! Чтобы понять, вот какой код я работаю:

$dat = dirname(__FILE__)."/foto_".time().".png"; $img = imagecreatefrompng("foto.png"); $points = array(93,36,147,1,255,-5,294,37,332,114,327,189,315,249,303,291,290,327,260,360,205,404,165,407,131,376,86,325,62,236,61,155,66,96,77,57,87,45); $schwarz = ImageColorAllocate ($img, 0, 0, 0); imagefilledpolygon($img, $points, count($points)/2, $schwarz); imagepng($img, $dat); 

Исходное изображение можно найти здесь и результат здесь . Все, кроме черной области, должно быть отброшено.

    Я знаю, что немного поздно, но я искал по всему Интернету решение этой проблемы и не мог найти решение «все-в-одном». Многие из сообщений, которые я нашел, включали редактирование изображения на пиксельной основе, которое я не слишком любил делать. После сборки нескольких образцов из нескольких сайтов, вот что я придумал:

    resizeCropPolygonImage ()

     function resizeCropPolygonImage($source, $dest = null, $newWidth = null, $newHeight = null, $startX = 0, $startY = 0, $points = array(), $numCoords = 2) { // Added in $numCoords in case we want to do 3D image processing in the future // (currently we do not process anything other than 2D coordinates) $points = array(100,115, 124,65, 192,65, 216,115, 192,165, 124,165); $numPoints = count($points) / $numCoords; // If there are not enough points to draw a polygon, then we can't perform any actions if ($numPoints < 3) { return; } // Get the original image's info list($width, $height, $file_type) = getimagesize($source); /******* Here I am using a custom function to resize the image ********* ******* keeping the aspect ratio. ********* ******* You'll have to add in your own re-sizing logic ********* // Resize the source (using dummy vars because we don't want our // start x & y to be overwritten) scaleDimensions($width, $height, $newWidth, $newHeight, $dummyX = null, $dummyY = null); For simplicity sake, I'll just set the width and height to the new width and height *************************************************************************/ $width = $newWidth; $height = $newHeight; switch ($file_type) { case 1: $srcImage = imagecreatefromgif($source); if (function_exists(ImageGIF)) { $imgType = "gif"; } else { $imgType = "jpeg"; } break; case 2: $srcImage = imagecreatefromjpeg($source); $imgType = "jpeg"; break; case 3: $srcImage = imagecreatefrompng($source); $imgType = "png"; break; default: return; } // Setup the merge image from the source image with scaling $mergeImage = ImageCreateTrueColor($width, $height); imagecopyresampled($mergeImage, $srcImage, 0, 0, 0, 0, $width, $height, imagesx($srcImage), imagesy($srcImage)); /******** This is probably the part that you're most interested in *******/ // Create the image we will use for the mask of the polygon shape and // fill it with an uncommon color $maskPolygon = imagecreatetruecolor($width, $height); $borderColor = imagecolorallocate($maskPolygon, 1, 254, 255); imagefill($maskPolygon, 0, 0, $borderColor); // Add the transparent polygon mask $transparency = imagecolortransparent($maskPolygon, imagecolorallocate($maskPolygon, 255, 1, 254)); imagesavealpha($maskPolygon, true); imagefilledpolygon($maskPolygon, $points, $numPoints, $transparency); // Apply the mask imagesavealpha($mergeImage, true); imagecopymerge($mergeImage, $maskPolygon, 0, 0, 0, 0, $width, $height, 100); /******* Here I am using a custom function to get the outer ********* ******* perimeter of the polygon. I'll add this one in below ********/ // Crop down to just the polygon area $polygonPerimeter = getPolygonCropCorners($points, $numCoords); $polygonX = $polygonPerimeter[0]['min']; $polygonY = $polygonPerimeter[1]['min']; $polygonWidth = $polygonPerimeter[0]['max'] - $polygonPerimeter[0]['min']; $polygonHeight = $polygonPerimeter[1]['max'] - $polygonPerimeter[1]['min']; // Create the final image $destImage = ImageCreateTrueColor($polygonWidth, $polygonHeight); imagesavealpha($destImage, true); imagealphablending($destImage, true); imagecopy($destImage, $mergeImage, 0, 0, $polygonX, $polygonY, $polygonWidth, $polygonHeight); // Make the the border transparent (we're assuming there's a 2px buffer on all sides) $borderRGB = imagecolorsforindex($destImage, $borderColor); $borderTransparency = imagecolorallocatealpha($destImage, $borderRGB['red'], $borderRGB['green'], $borderRGB['blue'], 127); imagesavealpha($destImage, true); imagealphablending($destImage, true); imagefill($destImage, 0, 0, $borderTransparency); if (!$dest) { // If no dest was given, then return to browser header('Content-Type: image/png'); imagepng($destImage); } else { // Output image will always be png $dest .= '.png'; // Save to destination imagepng($destImage, $dest); } // Destroy remaining images imagedestroy($maskPolygon); imagedestroy($srcImage); imagedestroy($destImage); // Only return a value if we were given a destination file if ($dest) { return $dest; } } 

    getPolygonCropCorners ()

     function getPolygonCropCorners($points, $numCoords) { $perimeter = array(); for ( $i = 0; $i < count($points); $i++ ) { $axisIndex = $i % $numCoords; if (count($perimeter) < $axisIndex) { $perimeter[] = array(); } $min = isset($perimeter[$axisIndex]['min']) ? $perimeter[$axisIndex]['min'] : $points[$i]; $max = isset($perimeter[$axisIndex]['max']) ? $perimeter[$axisIndex]['max'] : $points[$i]; // Adding an extra pixel of buffer $perimeter[$axisIndex]['min'] = min($min, $points[$i] - 2); $perimeter[$axisIndex]['max'] = max($max, $points[$i] + 2); } return $perimeter; } 

    Используя эту функцию, я могу повернуть это изображение

    Крупные жирафы

    в этот

    Маленькие жирафы

    Возможно, это не совсем полно, но я думаю, что это, безусловно, хорошая отправная точка.


    РЕДАКТИРОВАТЬ

    • 09/19/2014 – Добавлена ​​прозрачность на границе

    Вы можете использовать ImageArtist, который является оболочкой GD, созданной мной, чтобы сделать манипуляции с изображениями безумно легкими.

    см. код обрезки многоугольника, вам просто нужно передать координаты в процентах или в виде значений пикселей

     $pentagon = new PolygonShape("./morning.jpeg"); $pentagon->scale(60); $pentagon->push(new Node(50,0, Node::$PERCENTAGE_METRICS)); $pentagon->push(new Node(75,50, Node::$PERCENTAGE_METRICS)); $pentagon->push(new Node(62.5,100, Node::$PERCENTAGE_METRICS)); $pentagon->push(new Node(37.5,100, Node::$PERCENTAGE_METRICS)); $pentagon->push(new Node(25,50, Node::$PERCENTAGE_METRICS)); $pentagon->build(); //this will build the polygon $triangle->save("./finalImage.png",IMAGETYPE_PNG); //see the documentation for many other methods available. 

    Это конечный результат введите описание изображения здесь