Php GD imagecopy后的空白区域被黑色填充,但仅在某些情况下

Php GD imagecopy后的空白区域被黑色填充,但仅在某些情况下,php,gd,Php,Gd,我遇到一个问题,我允许用户调整容器中图像的大小,然后需要创建一个与容器大小相同的结果图像,但图像会根据用户的选择进行缩放和调整 例如,假设容器为400 x 200,用户希望能够放入600 x 100的徽标,他们可能希望缩小徽标,使其适合,并在顶部和底部留出空间。我需要能够保存为一个图像是400x200与适当的差距,在顶部和底部 但我发现,如果图像内容(本例中的徽标)超出容器的顶部和右侧,则一切正常,或者如果图像内容没有超出其中一个,则一切正常,但如果图像内容超出其中一个,而不是另一个,则我会得到

我遇到一个问题,我允许用户调整容器中图像的大小,然后需要创建一个与容器大小相同的结果图像,但图像会根据用户的选择进行缩放和调整

例如,假设容器为400 x 200,用户希望能够放入600 x 100的徽标,他们可能希望缩小徽标,使其适合,并在顶部和底部留出空间。我需要能够保存为一个图像是400x200与适当的差距,在顶部和底部

但我发现,如果图像内容(本例中的徽标)超出容器的顶部和右侧,则一切正常,或者如果图像内容没有超出其中一个,则一切正常,但如果图像内容超出其中一个,而不是另一个,则我会得到黑色填充-或类似的内容-参见下面的示例

下面是一些结果示例,这是我正在使用的代码

$cropped =  wp_imagecreatetruecolor( $frame_w, $frame_h);
    $backgroundColor = imagecolorallocatealpha($cropped, 0, 0, 0, 127);
    //imageantialias( $cropped, true );
    //if $img_y or $img_x are negative we need to apply the value to $img_x and $img_y
    //if $img_y or $img_x are positive we need to apply the value to $dest_x and $dest_y
    $dest_x = strstr($img_x,'-') ? 0 : abs($img_x);//if neg is true = 0 else offset inside
    $dest_y = strstr($img_y,'-') ? 0 : abs($img_y);
    $img_x = strstr($img_x,'-') ? abs($img_x) : 0;//if neg is true offset outside else 0
    $img_y = strstr($img_y,'-') ? abs($img_y) : 0;
    $img_w = $img_w > $frame_w ? $frame_w : $img_w;
    $img_h = $img_h > $frame_h ? $frame_h : $img_h;
    imagecopy( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $img_w, $img_h);
    //imagecopymerge( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $img_w, $img_h,100);
    //imagecopyresampled( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $frame_w, $frame_h, $img_w, $img_h );
    imagefill($cropped, 0, 0, $backgroundColor);//putting this after the copy makes any black borders transparent again unless $resized does not extend beyond both dimensions
例子

图像不超出顶部或右侧(精细)

图像超出底部但不正确(不正确)

图像超出了两者(精细)

图像超出右侧,但不在底部(不精细)

图像超出两者(精细)

我一直在努力解决这个问题,并尝试了imagesavealpha、imagecopymerged、imagecolorallocatealpha、imagealphablending等我能想到的所有可能的组合,但似乎没有什么能解决这个问题


这是GD的缺陷/限制吗?或者有人能来救我

我不知道这是否对你有帮助,但我今天早些时候对此有异议。盒子扩大了,但区域是黑色的。以下是我的代码(修复了它):



我想这只会发生在其他格式的PNG检查中

我不确定这是否是一个实际的答案,因为它基本上是“使用ImageMagick”,但不管怎样,对于那些ImageMagick是一个选项的人,下面的代码可能会帮助他们实现与我在上面尝试的相同的事情。。。基本上,ImageMagick似乎远远优于GD,旋转图像周围没有边框,透明度没有问题,没有不想要的黑色填充,放大时更清晰地调整大小

$img_x = -50; //left offset of the image within the frame
$img_y = 50; //top offset of the image within the frame
$img_w = 400; //width of the image to be put in the frame
$img_h = 200; // height of the image to be put in the frame
$angle = 45; //rotation to be applied to the image before it is put into the frame
$frame_w = 300; //width of the frame the image is going into
$frame_h = 300; //height of the frame the image is going into
$img_path = 'path/to/image/file.jpg';
$image = new Imagick( $img_path );
$size = $image->getImageGeometry();
$orig_w = $size['width']; $orig_h = $size['height'];
$image->scaleImage( $img_w, $img_h );
//rotate if necessary
if($angle)
    {
    $image->rotateImage( new ImagickPixel('none'), $angle );
    $size = $image->getImageGeometry();
    $img_w = $size['width']; $img_h = $size['height'];
    }
//composite into frame
//in imagemagick we create an image that is the size of the frame and make it transparent
$frame = new Imagick();
$frame->newImage($frame_w, $frame_h, new ImagickPixel("none"));
//then we composite the image itself into this with the respective offset values
$frame->compositeImage( $image, Imagick::COMPOSITE_DEFAULT, $img_x, $img_y );
//save it
$destfilename = "{$dir}/{$name}-{$img_suffix}.{$ext}";
$frame->writeImage($destfilename);
$frame->clear();
$frame->destroy();
$image->clear();
$image->destroy();

上面的代码生成了这个…耶

是的,不幸的是,我已经为输出图像指定了一种颜色,但它不是一直都正常工作-有时是正确的,有时不是-见上文。我需要它是透明的,因为我不知道背景页面的颜色会是什么-这似乎是阿尔法的问题…而且问题不在于高度本身上面的图像都是“正确”的高度和宽度(这是用户选择的),图像定位为用户选择的,只是有时候多余的空间会被黑色填满,当其他时候代码正确地输出透明的空白时…作为澄清,上面的图像从高度和内容的角度来看都是正确的-我知道它们看起来不正确,但我要做的是,它允许uer将图像内容定位到他们喜欢的任何位置。所以我对身高和内容的删减没有任何问题,这都没关系。问题很简单,在某些场景中,图像内容周围的空白空间被黑色填满,而它本应是透明的。旋转图像内容周围的1px边框让我非常不舒服。上面图片中的实际图像内容是以jpg开头的,但是我需要使用png作为输出,因为我需要未填充的区域是透明的。。。你知道imageMagick会更好吗?我的服务器上没有它,我已经询问了我的主机,但我正在等待他们是否会安装它。我想知道是否ImageMagick会解决这个问题之前,我通过移动服务器等麻烦。。。
$img_x = -50; //left offset of the image within the frame
$img_y = 50; //top offset of the image within the frame
$img_w = 400; //width of the image to be put in the frame
$img_h = 200; // height of the image to be put in the frame
$angle = 45; //rotation to be applied to the image before it is put into the frame
$frame_w = 300; //width of the frame the image is going into
$frame_h = 300; //height of the frame the image is going into
$img_path = 'path/to/image/file.jpg';
$image = new Imagick( $img_path );
$size = $image->getImageGeometry();
$orig_w = $size['width']; $orig_h = $size['height'];
$image->scaleImage( $img_w, $img_h );
//rotate if necessary
if($angle)
    {
    $image->rotateImage( new ImagickPixel('none'), $angle );
    $size = $image->getImageGeometry();
    $img_w = $size['width']; $img_h = $size['height'];
    }
//composite into frame
//in imagemagick we create an image that is the size of the frame and make it transparent
$frame = new Imagick();
$frame->newImage($frame_w, $frame_h, new ImagickPixel("none"));
//then we composite the image itself into this with the respective offset values
$frame->compositeImage( $image, Imagick::COMPOSITE_DEFAULT, $img_x, $img_y );
//save it
$destfilename = "{$dir}/{$name}-{$img_suffix}.{$ext}";
$frame->writeImage($destfilename);
$frame->clear();
$frame->destroy();
$image->clear();
$image->destroy();