在GD图像复制后,空的空间变得充满黑色,但仅在某些情况下

I am experiencing an issue where I am allowing the user to resize images in a container and then need to create a resulting image that is the size of the container but with the image scaled and adjusted as per the users choices.

So for example say the container is 400 x 200 and the user wants to be able to put in a logo that is 600 x 100 they may wish to shrink the logo so it fits and leave space at the top and bottom. I need to be able to save that as an image that is 400x200 with the appropriate gaps at the top and bottom.

What I have found though is that if the image content (the logo in this example) extends beyond BOTH the top and the right of the container everything is fine OR if it DOESNT extend beyond either it is fine but if it extends beyond one and not the other then I get black fill- or something like that- see examples below...

Below are some examples of the results and this is the code I am using...

$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

Examples

Image does not extend beyond top or beyond right (fine) Image does not extend beyond top or beyond right (fine)

Image extends beyond bottom but not right (not fine) Image extends beyond bottom but not right (not fine)

Image extends beyond both (fine) Image extends beyond both (fine)

Image extends beyond right but not bottom (not fine) Image extends beyond right but not bottom (not fine)

Image Extends beyond neither (fine) Image Extends beyond neither (fine)

I have been literally tearing my hair out trying to fix this and tried every possible combination of imagesavealpha, imagecopymerged, imagecolorallocatealpha, imagealphablending etc I can think of but nothing seems to fix this...

So is this a bug/limitation of GD? Or can someone out there come to my rescue!

I don't know if this will help you, but I had an issue with this earlier today. The box expands but the area was black. Here's my code (which fixes it):

<?php
function createImage($text)
{
    // Adds an extra space to fill underline
    $text = " $text";
    // Adds one line at the end
    $text .= "
";
    // Wrap the text to fit the image
    $text = wordwrap($text, 40, "
");
    // Count new lines
    $newlines = substr_count($text, "
");
    // Count how long to expand
    if($newlines == 0)
    {
        $height = 30;
    }
    else
    {
        $height = 30*$newlines-$newlines*5;
    }

    putenv('GDFONTPATH=' . realpath('.'));
    header('Content-Type: image/png');
    // Adding underline
    $e = explode('<', $text);
    for($i=0;$i<count($e);$i++)
    {
        $e[$i] = implode('&#x0332;', str_split($e[$i]));
    }
    // Creating image
    $text = implode(' ', $e);
    $im = imagecreatetruecolor(315, $height);
    $white = imagecolorallocate($im, 255, 255, 255);
    $grey = imagecolorallocate($im, 128, 128, 128);
    $black = imagecolorallocate($im, 0, 0, 0);
    $purple = imagecolorallocate($im, 97, 26, 139);
    imagefilledrectangle($im, 0, 0, 399, $height, $white);
    $font = 'arialbd.ttf';

    imagettftext($im, 11, 0, 10, 20, $purple, $font, $text);
    imagepng($im);
    imagedestroy($im);
}

createImage("asbdasddsa");
?>

i think this will happen only for PNG check with other formats

I'm not sure if this is an actual answer since it is basically 'Use ImageMagick' but anyway for those for whom ImageMagick is an option the code below might help them achieve the same thing as I was trying to above... Basically ImageMagick seems far superior to GD, no borders around rotated images, no hassles with transparency, no onwanted black fill, clearer resizing if you are enlarging...

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

The above code produces The above code produces this...yay!