2012-03-06 2 views
3

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

$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); 

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

+1

пожалуйста попытаться сделать старт, и когда застрявший почтовый индекс. –

+0

Учитывая, что PHP не является графическим языком, вам нужно дать нам понять, как вы пытаетесь отобразить этот «многоугольник». Вы пытаетесь создать изображение? Если да, то какое расширение вы используете? Вы пытаетесь сделать это с помощью CSS? Пожалуйста, уточните, что именно вы ожидаете от конечного результата и где вы ожидаете его видимости. – DaveRandom

+0

Хорошо, чтобы прояснить следующий пример: http://www.chipwreck.de/blog/software/cwcrop/cwcrop-demo/. Теперь я не хочу, чтобы область света была обрезана, но затемненная. Кроме того, это не должен быть прямоугольник, а многоугольник. Затем результат должен быть объединен с другим изображением (я уже знаю, как это сделать). – Jan

ответ

3

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

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; 
} 

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

Large giraffes

в этот один

Small giraffes

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


EDIT

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

, если есть какая-либо белая область и отправьте точку на вашу функцию, есть некоторая несвязанная фотография. Пример: http://cdn.netmoda.com/items/1092799/cropped_0.jpg.png?i=4 –

+0

Извините, но я не совсем уверен, что вы имеете в виду. Какая часть изображения не сливается? У вас есть фотографии до и после? –

+0

Привет, спасибо за ваш комментарий. Я решил свою проблему, но есть проблема. Края обрезанного изображения настолько точены. Как я могу сделать их более мягкими? –

1

Вы можете использовать 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. 

Это окончательный результат enter image description here