diff --git a/docs/classes/DantSu/PHPImageEditor/Image.md b/docs/classes/DantSu/PHPImageEditor/Image.md index 1fa5b71..123797b 100644 --- a/docs/classes/DantSu/PHPImageEditor/Image.md +++ b/docs/classes/DantSu/PHPImageEditor/Image.md @@ -848,13 +848,14 @@ Write text on the image. |-----------|------|-------------| | `string` | **string** | Text to be added on the image | | `fontPath` | **string** | Path to the TTF file | -| `fontSize` | **int** | Font size | +| `fontSize` | **float** | Font size | | `color` | **string** | Hexadecimal string color | -| `posX` | **int|string** | Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | -| `posY` | **int|string** | Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | -| `anchorX` | **int|string** | Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | -| `anchorY` | **int|string** | Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | -| `rotation` | **int** | Counterclockwise text rotation in degrees | +| `posX` | **float|string** | Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | +| `posY` | **float|string** | Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | +| `anchorX` | **float|string** | Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | +| `anchorY` | **float|string** | Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | +| `rotation` | **float** | Counterclockwise text rotation in degrees | +| `letterSpacing` | **float** | add space between letters | #### Return Value: @@ -881,18 +882,19 @@ Write text on the image and get the bounding box of the text in the image. |-----------|------|-------------| | `string` | **string** | Text to be added on the image | | `fontPath` | **string** | Path to the TTF file | -| `fontSize` | **int** | Font size | +| `fontSize` | **float** | Font size | | `color` | **string** | Hexadecimal string color | -| `posX` | **int|string** | Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | -| `posY` | **int|string** | Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | -| `anchorX` | **int|string** | Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | -| `anchorY` | **int|string** | Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | -| `rotation` | **int** | Counterclockwise text rotation in degrees | +| `posX` | **float|string** | Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | +| `posY` | **float|string** | Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | +| `anchorX` | **float|string** | Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` | +| `anchorY` | **float|string** | Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` | +| `rotation` | **float** | Counterclockwise text rotation in degrees | +| `letterSpacing` | **float** | add space between letters | #### Return Value: - **array** : Pixels positions of the + **array** : Bounding box positions of the text diff --git a/src/Image.php b/src/Image.php index 09ac81e..4ef9b5a 100644 --- a/src/Image.php +++ b/src/Image.php @@ -318,7 +318,7 @@ public function curl(string $url, array $curlOptions = [], bool $failOnError = f $image = \curl_exec($curl); - if($failOnError && \curl_errno($curl)){ + if ($failOnError && \curl_errno($curl)) { throw new \Exception(\curl_error($curl)); } @@ -635,9 +635,9 @@ private static function formatColor(string $stringColor): string * Allocate a new color to the image. * * @param string $color Hexadecimal string color - * @return int Color id + * @return int|false Color id */ - private function colorAllocate(string $color): int + private function colorAllocate(string $color) { $color = static::formatColor($color); $red = \hexdec(\substr($color, 0, 2)); @@ -645,12 +645,12 @@ private function colorAllocate(string $color): int $blue = \hexdec(\substr($color, 4, 2)); $alpha = \floor(\hexdec(\substr($color, 6, 2)) / 2); - $newColor = \imagecolorexactalpha($this->image, $red, $green, $blue, $alpha); - if ($newColor === -1) { - $newColor = \imagecolorallocatealpha($this->image, $red, $green, $blue, $alpha); + $colorId = \imagecolorexactalpha($this->image, $red, $green, $blue, $alpha); + if ($colorId === -1) { + $colorId = \imagecolorallocatealpha($this->image, $red, $green, $blue, $alpha); } - return $newColor; + return $colorId; } @@ -801,18 +801,19 @@ public function grayscale(): Image * * @param string $string Text to be added on the image * @param string $fontPath Path to the TTF file - * @param int $fontSize Font size + * @param float $fontSize Font size * @param string $color Hexadecimal string color - * @param int|string $posX Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` - * @param int|string $posY Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` - * @param int|string $anchorX Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` - * @param int|string $anchorY Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` - * @param int $rotation Counterclockwise text rotation in degrees + * @param float|string $posX Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` + * @param float|string $posY Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` + * @param float|string $anchorX Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` + * @param float|string $anchorY Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` + * @param float $rotation Counterclockwise text rotation in degrees + * @param float $letterSpacing add space between letters * @return $this Fluent interface */ - public function writeText(string $string, string $fontPath, int $fontSize, string $color = '#ffffff', $posX = 0, $posY = 0, string $anchorX = Image::ALIGN_CENTER, string $anchorY = Image::ALIGN_MIDDLE, int $rotation = 0, int $letter_spacing = 0): Image + public function writeText(string $string, string $fontPath, float $fontSize, string $color = 'ffffff', $posX = 0, $posY = 0, $anchorX = Image::ALIGN_CENTER, $anchorY = Image::ALIGN_MIDDLE, float $rotation = 0, float $letterSpacing = 0): Image { - $this->writeTextAndGetBoundingBox($string, $fontPath, $fontSize, $color, $posX, $posY, $anchorX, $anchorY, $rotation, $letter_spacing); + $this->writeTextAndGetBoundingBox($string, $fontPath, $fontSize, $color, $posX, $posY, $anchorX, $anchorY, $rotation, $letterSpacing); return $this; } @@ -821,16 +822,17 @@ public function writeText(string $string, string $fontPath, int $fontSize, strin * * @param string $string Text to be added on the image * @param string $fontPath Path to the TTF file - * @param int $fontSize Font size + * @param float $fontSize Font size * @param string $color Hexadecimal string color - * @param int|string $posX Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` - * @param int|string $posY Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` - * @param int|string $anchorX Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` - * @param int|string $anchorY Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` - * @param int $rotation Counterclockwise text rotation in degrees - * @return array Pixels positions of the - */ - public function writeTextAndGetBoundingBox(string $string, string $fontPath, int $fontSize, string $color = '#ffffff', $posX = 0, $posY = 0, string $anchorX = Image::ALIGN_CENTER, string $anchorY = Image::ALIGN_MIDDLE, int $rotation = 0, int $letter_spacing = 0): array + * @param float|string $posX Left position in pixel. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` + * @param float|string $posY Top position in pixel. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` + * @param float|string $anchorX Horizontal anchor of the text. You can use `Image::ALIGN_LEFT`, `Image::ALIGN_CENTER`, `Image::ALIGN_RIGHT` + * @param float|string $anchorY Vertical anchor of the text. You can use `Image::ALIGN_TOP`, `Image::ALIGN_MIDDLE`, `Image::ALIGN_BOTTOM` + * @param float $rotation Counterclockwise text rotation in degrees + * @param float $letterSpacing add space between letters + * @return array Bounding box positions of the text + */ + public function writeTextAndGetBoundingBox(string $string, string $fontPath, float $fontSize, string $color = 'ffffff', $posX = 0, $posY = 0, $anchorX = Image::ALIGN_CENTER, $anchorY = Image::ALIGN_MIDDLE, float $rotation = 0, float $letterSpacing = 0): array { if (!$this->isImageDefined()) { return []; @@ -858,7 +860,7 @@ public function writeTextAndGetBoundingBox(string $string, string $fontPath, int ) { if ( ($newImg = \imagecreatetruecolor(1, 1)) === false || - ($posText = $this->imagettftextWithSpacing($newImg, $fontSize, $rotation, 0, 0, $color, $fontPath, $string, $letter_spacing)) === false + ($posText = $this->imagettftextWithSpacing($newImg, $fontSize, $rotation, 0, 0, $color, $fontPath, $string, $letterSpacing)) === false ) { return []; } @@ -884,6 +886,7 @@ public function writeTextAndGetBoundingBox(string $string, string $fontPath, int } $sizeWidth = $xMax - $xMin; + $sizeHeight = $yMax - $yMin; switch ($anchorX) { case static::ALIGN_LEFT : @@ -898,17 +901,18 @@ public function writeTextAndGetBoundingBox(string $string, string $fontPath, int } switch ($anchorY) { case static::ALIGN_TOP : - $posY = $posY + $fontSize; + $posY = $posY - $yMin; break; case static::ALIGN_MIDDLE : - $posY = $posY + $fontSize / 2; + $posY = $posY - $sizeHeight / 2 - $yMin; break; case static::ALIGN_BOTTOM : + $posY = $posY - $sizeHeight - $yMin; break; } } - $posText = $this->imagettftextWithSpacing($this->image, $fontSize, $rotation, $posX, $posY, $color, $fontPath, $string, $letter_spacing); + $posText = $this->imagettftextWithSpacing($this->image, $fontSize, $rotation, $posX, $posY, $color, $fontPath, $string, $letterSpacing); if ($posText === false) { return []; @@ -943,35 +947,52 @@ public function writeTextAndGetBoundingBox(string $string, string $fontPath, int /** * @param $image - * @param $size - * @param $angle - * @param $x - * @param $y - * @param $color - * @param $font - * @param $text - * @param int $spacing - * @return array - */ - private function imagettftextWithSpacing($image, float $size, float $angle, float $x, float $y, int $color, string $font, string $text, int $spacing = 0) + * @param float $size + * @param float $angle + * @param float $x + * @param float $y + * @param int $color + * @param string $font + * @param string $text + * @param float $spacing + * @return array|false + */ + private function imagettftextWithSpacing($image, float $size, float $angle, float $x, float $y, int $color, string $font, string $text, float $spacing = 0) { - if ($spacing == 0) - { + if ($spacing == 0) { return \imagettftext($image, $size, $angle, $x, $y, $color, $font, $text); - } - else - { - $temp_x = $x; - $temp_y = $y; - $posText = []; - for ($i = 0; $i < \mb_strlen($text); ++$i) - { - $posText = \imagettftext($image, $size, $angle, $temp_x, $temp_y, $color, $font, $text[$i]); + } else { + $length = \mb_strlen($text); + + if ($length == 0) { + return false; + } + + $letterPos = ['x' => $x, 'y' => $y]; + $textWidth = $spacing * ($length - 1); + $top = 0; + $bottom = 0; + + for ($i = 0; $i < $length; ++$i) { + \imagettftext($image, $size, $angle, $letterPos['x'], $letterPos['y'], $color, $font, $text[$i]); $bbox = \imagettfbbox($size, 0, $font, $text[$i]); - $temp_x += \cos(\deg2rad($angle)) * ($spacing + ($bbox[2] - $bbox[0])); - $temp_y -= \sin(\deg2rad($angle)) * ($spacing + ($bbox[2] - $bbox[0])); + $letterPos = Geometry2D::getDstXY($letterPos['x'], $letterPos['y'], $angle, $spacing + $bbox[2]); + + $textWidth += $bbox[2]; + if ($top > $bbox[5]) { + $top = $bbox[5]; + } + if ($bottom < $bbox[1]) { + $bottom = $bbox[1]; + } } - return $posText; + + $bottomLeft = Geometry2D::getDstXY($x, $y, $angle - 90, $bottom); + $bottomRight = Geometry2D::getDstXY($bottomLeft['x'], $bottomLeft['y'], $angle, $textWidth); + $topLeft = Geometry2D::getDstXY($x, $y, $angle + 90, \abs($top)); + $topRight = Geometry2D::getDstXY($topLeft['x'], $topLeft['y'], $angle, $textWidth); + + return [$bottomLeft['x'], $bottomLeft['y'], $bottomRight['x'], $bottomRight['y'], $topRight['x'], $topRight['y'], $topLeft['x'], $topLeft['y']]; } } @@ -1010,7 +1031,7 @@ public function drawRectangle(int $left, int $top, int $right, int $bottom, stri * @param string $color Hexadecimal string color * @return $this Fluent interface */ - public function drawPolygon(array $points, string $color = '#000000', $antialias = false): Image + public function drawPolygon(array $points, string $color = '000000', $antialias = false): Image { if (!$this->isImageDefined()) { return $this; @@ -1022,14 +1043,14 @@ public function drawPolygon(array $points, string $color = '#000000', $antialias return $this; } - if($antialias) { + if ($antialias) { \imageantialias($this->image, true); \imagepolygon($this->image, $points, \count($points) / 2, $color); } \imagefilledpolygon($this->image, $points, \count($points) / 2, $color); - if($antialias) { + if ($antialias) { \imageantialias($this->image, false); } @@ -1280,10 +1301,10 @@ private function getData(callable $imgFunction): string \ob_start(); $imgFunction(); - $image_data = \ob_get_contents(); + $imageData = \ob_get_contents(); \ob_end_clean(); - return $image_data; + return $imageData; } /** @@ -1293,7 +1314,9 @@ private function getData(callable $imgFunction): string */ public function getDataPNG(): string { - return $this->getData(function () {$this->displayPNG();}); + return $this->getData(function () { + $this->displayPNG(); + }); } /** @@ -1304,7 +1327,9 @@ public function getDataPNG(): string */ public function getDataJPG(int $quality = -1): string { - return $this->getData(function () use ($quality) {$this->displayJPG($quality);}); + return $this->getData(function () use ($quality) { + $this->displayJPG($quality); + }); } /** @@ -1314,7 +1339,9 @@ public function getDataJPG(int $quality = -1): string */ public function getDataGIF(): string { - return $this->getData(function () {$this->displayGIF();}); + return $this->getData(function () { + $this->displayGIF(); + }); } /** diff --git a/src/samples/sample6.php b/src/samples/sample6.php new file mode 100644 index 0000000..1f2e217 --- /dev/null +++ b/src/samples/sample6.php @@ -0,0 +1,24 @@ +writeTextAndGetBoundingBox('I got the power !', __DIR__ . '/resources/font.ttf', 40, '#FFFFFF', Image::ALIGN_RIGHT, Image::ALIGN_BOTTOM, Image::ALIGN_RIGHT, Image::ALIGN_BOTTOM, 0, 1); + +Image::newCanvas(500, 500) + ->drawPolygon( + [ + $bbox['top-left']['x'], $bbox['top-left']['y'], + $bbox['top-right']['x'], $bbox['top-right']['y'], + $bbox['bottom-right']['x'], $bbox['bottom-right']['y'], + $bbox['bottom-left']['x'], $bbox['bottom-left']['y'] + ], + '00000088' + ) + ->pasteOn($image1) + ->displayPNG();