绘制超出图像边界的多边形

Draw polygon extending beyond image-border

注:


我想通过将带有多边形的背景图像和一些文本放在一起来创建自定义图形。

输入背景图像具有不同的尺寸和纵横比,但最终图形必须具有固定的 (2:1) 纵横比(它也必须具有预定义的尺寸,但调整大小图像是微不足道的,所以正确的纵横比是我唯一的目标)。


目前我是cropping-to-fit my input image to target aspect ratio (2:1) by performing max-center area cropping using imagecrop function. Thereafter I draw red polygon on it as shown below (ignore the texts drawn on red band) using imagefilledpolygon方法[下面的裁剪屏幕截图仅用于演示目的,实际上是通过imagecrop函数以编程方式完成的]

这是我绘制叠加层的函数(此函数在将图像裁剪为 2:1 纵横比完成后调用)

/**
 * adds overlay (colored band) on the image
 * for better output, overlay must be added before resizing
 */
public function withOverlay(): NotifAdsCreativeGenerator {
    // Prepare custom red-color Hex to RGB 
    list($r, $g, $b) = sscanf(self::OVERLAY_COLOR, "#%02x%02x%02x");
    $custom_red_color = imagecolorallocate($this->getCrrImage(), $r, $g, $b);
    // prepare coordinates for polygon
    $coords = [
        [0, 0],
        [(int) ($this->getCrrWidth() * self::OVERLAY_BEGIN_X_RATIO), 0],
        [(int) ($this->getCrrWidth() * self::OVERLAY_END_X_RATIO), $this->getCrrHeight()],
        [0, $this->getCrrHeight()]
    ];
    $flattened_coords = array_merge(...$coords);
    // draw polygon on image
    imagefilledpolygon($this->getCrrImage(), $flattened_coords, count($flattened_coords) / 2, $custom_red_color);
    return $this;
}

但我想要的是将图像裁剪为 ~ 1.28:1 纵横比(图形右侧没有红色带的大约比例),然后在图像外部绘制多边形(扩展)以获得最终图形具有相同的 2:1 纵横比,如下所示


我可以 crop image to my desired aspect ratio (1.28:1),但我想不出在图像边界外绘制多边形的方法(在此过程中有效地扩展了图像)。有没有办法使用 PHP-GD 库来做到这一点?

我只是缺乏理解(关于 PHP-GD 可用方法的工作),但解决方案非常简单

  • 使用imagecreatetruecolor 函数[=24= 创建所需尺寸(以及 2:1 目标纵横比)的 空 'canvas' 图像 ]
  • (在 cropping), copy the image on right side of canvas using imagecopy 方法之后(必须进行一些基本数学计算以确定图像必须放置在 canvas 上的偏移量)
  • 现在和以前一样,可以在canvas左边画红色多边形,得到最终图形

/**
 * adds overlay (colored band) on the image
 * for better output, overlay must be added before resizing
 *
 * This method tries to preserve maximum center region of input image by performing minCenterCrop(.) on it
 * before drawing an overlay that extends beyond left border of the cropped image
 *
 * (since this method incorporates call to 'withMinCenterCrop', calling that method before this is  not required
 * (and is redundant). For benefits of this method over 'withOverlay', read docstring comment of
 * 'withMinCenterCrop' method
 * @return NotifAdsCreativeGenerator
 */
public function withExtendedOverlay(): NotifAdsCreativeGenerator {
    // perform min center crop to the 1.28:1 aspect ratio (preserve max central portion of image)
    $this->withMinCenterCrop();

    // this $required_canvas_aspect_ratio calculates to 2.0 (2:1 aspect ratio)
    // calculate aspect ratio & dimensions of empty 'canvas' image
    // since canvas is wider than min center-cropped image (as space on the left will be occupied by red overlay)
    // therefore it's height is matched with cropped image and width is calculated
    $required_canvas_aspect_ratio = self::IMAGE_WIDTH / self::IMAGE_HEIGHT;
    // height of cropped image
    $canvas_height = $this->getCrrHeight();
    $canvas_width = $required_canvas_aspect_ratio * $canvas_height;
    // create a new 'canvas' (empty image) on which we will
    // 1. draw the existing input 'min-cropped' image on the right
    // 2. draw the red overlay on the left
    $canvas_image = imagecreatetruecolor($canvas_width, $canvas_height);

    // copy contents of image on right side of canvas
    imagecopy(
        $canvas_image,
        // cropped image
        $this->getCrrImage(),
        self::OVERLAY_BEGIN_X_RATIO * $canvas_width,
        0,
        0,
        0,
        // dimensions of cropped image
        $this->getCrrWidth(),
        $this->getCrrHeight()
    );

    // draw red band overlay on left side of canvas
    $this->crr_image = $canvas_image;
    return $this->withOverlay();
}