Php GD добавляет черный фон вокруг обрезанного исходного изображения - PullRequest
0 голосов
/ 26 февраля 2019

Я создаю загрузчик, который может загружать изображения в формате jpg, giff и png.Затем преобразует их все слишком прозрачные PNG и затем обрезает изображение на основе параметров обрезки, отправленных со стороны клиента.Кадрирование может даже предоставлять отрицательные координаты оси, что означает, что изображение обрезается за пределы размеров изображения.

Чтобы обеспечить прозрачность всех поддерживаемых форматов, я сначала воссоздаю изображение в прозрачный png, и это работает хорошо.

//GET WIDTH AND HIEGHT OF UPLOADED JPG
list($imageWidth,$imageHeight)= getimagesize($originalDirectory.$file_name);
$image = imagecreatefromjpeg($originalDirectory.$file_name);

//CREATE NEW IMAGE BASED ON WIDTH AND HEIGHT OF SROUCE IMAGE
$bg = imagecreatetruecolor($imageWidth, $imageHeight);

//TRANSPARENCY SETTINGS FOR BOTH DESTINATION AND SOURCE IMAGES
$transparent2 = imagecolorallocatealpha($bg, 0, 0, 0, 127);
$transparent = imagecolorallocatealpha($image, 0,128,255,50); //ONLY TO ENSURE TRANSPARENCY IS WORKING

//SAVE TRANSPARENCY AMD FILL DESTINATION IMAGE
imagealphablending( $bg, false );
imagesavealpha($bg, true);
imagefill($bg, 0, 0, $transparent2);

//SAVE TRANSPARENCY AMD FILL SOURCE IMAGE
imagealphablending( $image, false );
imagesavealpha($image, true);
imagefill($image, 0, 0, $transparent); //ONLY TO ENSURE TRANSPARENCY IS WORKING

//CREATE AND SAVE AS PNG FILE WITH TRANSPARENCY
imagecopy($bg, $image, 0, 0, 0, 0, $imageWidth,$imageHeight);
header('Content-type: image/png');
imagepng($bg, $originalDirectory.$jpgFile);
imagedestroy($bg);

После создания нового png я использую его для обрезки только изображения в соответствии с параметрами, переданными из сценариев на стороне клиента.

//GET NEWLY CREATED PNG
$src = imagecreatefrompng($originalSRC);
// NOT SURE IF NECESSARY BUT HAS NO EFFECT ON FINAL RESULT REGGARDLESS OF ANY SETTINGS DONE
imagealphablending( $image, false );
imagesavealpha($image, true);

//DEFINE DESTINATION CROPPED FILE
$thumbHighFilename = $thumbHighDirectory.'test.png';

//CREATE NEW IMAGE BASED ON FINAL CROP SIZE
$tmp = imagecreatetruecolor($cropWidth, $cropHeight);

//ENSURE DESTINATION HAS TRANSPARENT BACKGROUND
$transparent2 = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
imagealphablending( $tmp, false );
imagesavealpha($tmp, true);
imagefill($tmp, 0, 0, $transparent2);

/* -------------------------------------------------
PROBLEM HERE
When I try to merge the two with the crop paramaters
send from client side. All transparencies work, except
where crop X and Y axis exceeds source image paramaters.
Currently 50px offset on destination image is to verify
transparency works.
The source coordinates are based on image not crop area.
Tried with both imagecopyresized & imagecopyresampled
-------------------------------------------------*/
imagecopyresized($tmp, $src, -50,-50, $xAxis,$yAxis,$cropWidth, $cropHeight, $pW, $pH);

//SAVE FINAL IMAGE
header('Content-type: image/png');
imagepng($tmp, $thumbHighFilename);
imagedestroy($tmp);

Здесь находится источники целевые изображения все еще имеют прозрачность;однако отрицательные координаты создают черный фон вокруг исходного изображения.Как я могу сделать это прозрачным?

Несмотря на то, что я много узнал о прозрачных пленках, ничто не было правильным решением.Например, imagefill впоследствии не будет работать, так как источник может использовать 100% черный по краям, а затем сделает это также прозрачным, чего не должно быть.

ПРИМЕР ОБРАБОТКИ СТОРОН КЛИЕНТА С ПОКАЗАНИЯМИ enter image description here

ТЕКУЩИЙ ЗАКЛЮЧИТЕЛЬНЫЙ РЕЗУЛЬТАТ ИЗОБРАЖЕНИЯ С ДОБАВЛЕННЫМИ УКАЗАНИЯМИ enter image description here

1 Ответ

0 голосов
/ 28 февраля 2019

Из того, что я смог найти, кажется, что нет никакого способа для GD imagecopyresized и imagecopyresamped наследовать заданные по умолчанию фоны изображений, которые он обрезает.Таким образом, он продолжает добавлять черный фон по умолчанию к исходному изображению.

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

Чтобы обойти проблему, я попросил своего разработчика интерфейса отправить мне больше параметров из обрезки.Ниже приведены все параметры, которые теперь передаются в php, и переменные в php, которые связаны с полученными параметрами:

  • $ xAxisCropper & $ yAxisCropper - Переменные получают X иКоординаты Y контейнера, а не обрезаемого изображения.
  • $ pW & $ pH - Определяет ширину и высоту рамки обрезки.
  • $ containerWidth& $ containerheight - Поскольку контейнер реагирует, получение высоты и ширины помогает понять, на какой размер рассчитаны координаты.
  • $ imResizeHeight & $ imResizeWidth - Поскольку изображения вВ контейнере всегда указывается, что он содержится в контейнере, важно было определить ширину и высоту, в которую CSS-изображение изменяет размеры изображения.Предоставление понимания того, что происходит с изображением в адаптивном контейнере.
  • $ originalWidth & $ originalHeight - Определяет исходный размер изображения и может быть передано в php или получено изИсходное изображение загружено на сервер.

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

Для этого я начал с определения, масштабируется ли изображение в контейнере в контейнере.Если масштабированное изображение необходимо масштабировать до размера контейнера, при уменьшении необходимо увеличить контейнер, чтобы изображение поместилось в контейнере.Ниже приведен код, который в настоящее время определяет это и соответственно изменяет необходимые параметры:

    //IF CSS CONTAIN RESIZES HEIGHT EQUAL TO CROP CONTAINER HEIGHT
if($imResizeHeight == $containerheight){

    //IF IMAGE SIZE WAS INCREASED
    if($imResizeHeight>$originalHeight){
        //DEFINE NEW IMAGE SIZE TO SCALE TO CONTAINER
        $new_height = $imResizeHeight;
        $new_width = $originalWidth * ($new_height / $originalHeight);

        $scale = 'image'; //DEFINE WHAT IS BEING INCREASED

    //ESLSE INCREASE CONTAINER TO IMAGE HEIGHT DIMENSIONS
    }else{
        //RECALCULATE WIDTH & HEIGHT OF CONTAINER
        $newContainerWidth = $containerWidth * ($originalHeight / $containerheight);
        $newContainerheight = $originalHeight;

        $scale = 'container'; //DEFINE WHAT IS BEING INCREASED
    }

//IF CSS CONTAIN RESIZES WIDTH EQUAL TO CROP CONTAINER WIDTH
}elseif($imResizeWidth == $containerWidth) {
    //IF IMAGE SIZE WAS INCREASED
    if($imResizeWidth>$originalWidth){
        //DEFINE NEW IMAGE SIZE TO SCALE TO CONTAINER
        $new_width = $imResizeWidth;
        $new_height =  $originalHeight * ($new_width / $originalWidth);

        $scale = 'image'; //DEFINE WHAT IS BEING INCREASED

    //ESLSE INCREASE CONTAINER TO IMAGE WIDTH DIMENSIONS
    }else{
        //RECALCULATE WIDTH & HEIGHT OF CONTAINER
        $newContainerheight =  $containerheight * ($originalWidth / $containerWidth);
        $newContainerWidth = $originalWidth;

        $scale = 'container'; //DEFINE WHAT IS BEING INCREASED
    }
}

//IF IMAGE WAS INCREASED
if($scale=='image'){
    //SCALE IMAGE
    $src = imagescale ( $src , $new_width , $new_height, IMG_BILINEAR_FIXED);
    imagepng($src,$originalSRC,0);

    //ADD CHANGES TO VARIABLES USED IN CROP
    $pH = $pH * ($new_height / $originalHeight);
    $pW = max(0, round($pW * ($new_width / $originalWidth)));
    $originalWidth = $new_width;
    $originalHeight = $new_height;
    $newContainerWidth = $containerWidth;
    $newContainerheight = $containerheight;

//ELSE CONTAINER WAS INCREASED
}else {
    //RECALCULATE COORDINATES OF CONTAINER
    $yAxisCropper = max(0, round($yAxisCropper * ($newContainerheight / $containerheight)));
    $xAxisCropper = max(0, round($xAxisCropper * ($newContainerWidth / $containerWidth)));
}

После того, как параметры были переопределены в соответствии с масштабированием, я затем создаю прозрачный фон в соответствии с размером контейнера и добавляюизображение в центре.Таким образом, создайте правильную версию контейнера обрезки в виде изображения под кодом для создания нового изображения:

//CALCULATE CENTRE OF NEW CONTAINER
$centreX = max(0, round(($newContainerWidth-$originalWidth)/2));
$centreY = max(0, round(($newContainerheight-$originalHeight)/2));

//CREATE NEW IMAGE BASED ON WIDTH AND HEIGHT OF SROUCE IMAGE
$bg = imagecreatetruecolor($newContainerWidth, $newContainerheight);

//SAVE TRANSPARENCY AMD FILL DESTINATION IMAGE
$transparent = imagecolorallocatealpha($bg, 0,0,0,127);
imagealphablending( $bg, false);
imagesavealpha($bg, true);
imagefill($bg, 0, 0, $transparent);

//CREATE AND SAVE AS PNG FILE WITH TRANSPARENCY
imagecopy($bg, $src, $centreX, $centreY, 0, 0,  $originalWidth,$originalHeight);
header('Content-type: image/png');
imagepng($bg, $originalSRC, 0);
imagedestroy($bg);

Результат до настоящего времени: enter image description here

Только в этот момент я отправляю новое изображение для обрезки в соответствии с указанной шириной и высотой.Код ниже:

$src = imagecreatefrompng($originalSRC);

$thumbHighFilename = $thumbHighDirectory.$new_image;

$tmp = imagecreatetruecolor($cropWidth, $cropHeight);
$transparent2 = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
imagealphablending( $tmp, false );

imagesavealpha($tmp, true);
imagefill($tmp, 0, 0, $transparent2);

imagealphablending( $tmp, false );

imagesavealpha($tmp, true);
imagecopyresampled($tmp, $src, 0,0, $xAxisCropper,$yAxisCropper,$cropWidth, $cropHeight, $pW, $pH);

header('Content-type: image/png');
imagepng($tmp, $thumbHighFilename, 2);

Окончательный результат обрезан 400x300 enter image description here

Это был единственный способ, который мне удалось покарешить проблему.Возможно, код еще можно оптимизировать, но если у кого-то есть более оптимальное решение, поделитесь.

Я также хотел бы поблагодарить моего разработчика Salem за помощь в решении этой раздражающей проблемы.

...