2016-12-26 2 views
1

Мне нужно знать, как можно маскировать любое квадратное изображение с помощью Imagick. Вот код, который я до сих пор, но изображение просто не получить маскироваться должным образом:Изображения маски с созданным изображением Imagick

Получить изображение

$srcFile = 'filename.png'; 
$image = new Imagick($srcFile); 

Crop изображение на площади

$d = $image->getImageGeometry(); 
$src_width = $d['width']; 
$src_height = $d['height']; 
$thumbSize = min(max($src_width, $src_height), abs($thumbSize));   
if ($src_width < $src_height) { 
    $image->cropImage($src_width, $src_width, 0, (($src_height - $src_width)/2)); 
} else { 
    $image->cropImage($src_height, $src_height, (($src_width - $src_height)/2), 0); 
} 

Изменить размер изображения

$image->thumbnailImage($thumbSize, $thumbSize, 1); 

Crop/Маска изображения с формой Безье

$image->compositeImage(bezier($thumbSize, $thumbSize), Imagick::COMPOSITE_COPYOPACITY, 0, 0); 

Функция Безье создает форму вида:

bezier mask shape

function bezier($width, $height) { 
    $fillColor = "#000"; 
    $draw = new ImagickDraw(); 

Заполните немаскированную часть с черным цветом

$fillColor = new ImagickPixel($fillColor); 
    $draw->setFillColor($fillColor); 
    $smoothPointsSet = [ 
     [ 
      ['x' => 0.0 * $width, 'y' => 0.5 * $width], 
      ['x' => 0.0 * $width, 'y' => 0.905 * $width], 
      ['x' => 0.095 * $width, 'y' => 1.0 * $width], 
      ['x' => 0.5 * $width, 'y' => 1.0 * $width] 
     ], [ 
      ['x' => 0.5 * $width, 'y' => 1.0 * $width], 
      ['x' => 0.905 * $width, 'y' => 1.0 * $width], 
      ['x' => 1.0 * $width, 'y' => 0.905 * $width], 
      ['x' => 1.0 * $width, 'y' => 0.5 * $width] 
     ], [ 
      ['x' => 1.0 * $width, 'y' => 0.5 * $width], 
      ['x' => 1.0 * $width, 'y' => 0.095 * $width], 
      ['x' => 0.905 * $width, 'y' => 0.0 * $width], 
      ['x' => 0.5 * $width, 'y' => 0.0 * $width] 
     ], [ 
      ['x' => 0.5 * $width, 'y' => 0.0 * $width], 
      ['x' => 0.095 * $width, 'y' => 0.0 * $width], 
      ['x' => 0.0 * $width, 'y' => 0.095 * $width], 
      ['x' => 0.0 * $width, 'y' => 0.5 * $width] 
     ] 
    ]; 

    foreach ($smoothPointsSet as $points) { 
     $draw->bezier($points); 
    } 

Безье точек не заполняют квадрат в середине, так заполнить его вручную

$points = [ 
     ['x' => $width * 0.5, 'y' => 0.0], 
     ['x' => 0.0, 'y' => $height * 0.5], 
     ['x' => $width * 0.5, 'y' => $height], 
     ['x' => $width, 'y' => $height * 0.5] 
    ]; 
    $draw->polygon($points); 

Скопируйте ящик изображение в новый прозрачный Imagick изображение

$imagick = new Imagick(); 
    $imagick->newImage($width, $width, "none"); 

Здесь я экспериментировал с различными свойствами. Я не получил удовлетворительного результата - изображение почти всегда не маскируется.

#$imagick->setImageAlphaChannel(Imagick::ALPHACHANNEL_SHAPE); 
    #$imagick->setImageFormat("png"); 

    $imagick->drawImage($draw); 

    #$imagick->setImageMatte(false); 

    return $imagick; 
} 

Я был бы очень рад, если бы я мог знать, где проблема и как ее исправить. Я нашел различные ответы на SO, которые не работали для меня:

Используйте $dude->setImageMatte(1); Using a transparent PNG as a clip mask

Используйте $base->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA); How to use Imagick to merge and mask images?

К сожалению, я не смог решить эту проблему.

ответ

0

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

$mask = bezier($thumbSize, $thumbSize); 

// Copy opacity mask 
if ($image->getImageMatte()) { 
    $image->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA); 
} else { 
    $image->compositeImage($mask, Imagick::COMPOSITE_COPYOPACITY, 0, 0); 
} 

$image->setImageBackgroundColor(new ImagickPixel('white')); 
#$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_DEACTIVATE); 
$image = $image->flattenImages(); 

В функции Безье:

$imagick = new Imagick(); 
$imagick->newImage($width, $width, "none"); 
$imagick->setImageBackgroundColor(new ImagickPixel('transparent')); 
#$imagick->setImageAlphaChannel(Imagick::ALPHACHANNEL_SHAPE); 
$imagick->setImageFormat("png"); 

//Render the draw commands in the ImagickDraw object 
//into the image. 
$imagick->drawImage($draw); 
$imagick->negateImage(FALSE); 


return $imagick; 
+0

Это стоит идея отправить в список рассылки ImageMagick, или ударить свой IRC канал, или независимо от способа их непосредственного контакта заключается в том, чтобы сообщить им, что магия изображения, по-видимому, не предупреждает пользователей, когда они сохраняют изображения в формате, который не поддерживает используемые функции. Сохранение изображения с альфа-каналом в растровом изображении, поскольку JPEG должен иметь хотя бы предупреждение о консоли, которое позволило бы вам сразу обнаружить и устранить проблему. –

+0

", чтобы сообщить им, что магия изображения, по-видимому, не предупреждает пользователей, когда они сохраняют изображения в формате« Это, вероятно, по дизайну. Философия, стоящая за C api, которую предоставляет ImageMagick, заключается в том, чтобы делать то, что пользователь говорит ей, исходя из предположения, что они знают, что они делают. Сохранение изображения с прозрачностью, поскольку Jpeg - это обычная вещь (иногда), поэтому она просто делает это, а не сомневается в том, что пользователь намеревался. – Danack

Смежные вопросы