mirror of
https://github.com/Intervention/image.git
synced 2025-08-20 04:31:24 +02:00
Merge branch 'develop' into feature/config
This commit is contained in:
7
.github/workflows/run-tests.yml
vendored
7
.github/workflows/run-tests.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php: [ '8.1', '8.2', '8.3' ]
|
php: [ '8.1', '8.2', '8.3' ]
|
||||||
imagemagick: [ '6.9.12-55', '7.1.0-40' ]
|
imagemagick: [ '6.9.12-55', '7.1.1-32' ]
|
||||||
imagick: [ '3.7.0' ]
|
imagick: [ '3.7.0' ]
|
||||||
stability: [ prefer-stable ]
|
stability: [ prefer-stable ]
|
||||||
|
|
||||||
@@ -89,7 +89,10 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction
|
run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction
|
||||||
|
|
||||||
- name: Which Imagick Version
|
- name: GD Version
|
||||||
|
run: php -r 'var_dump(gd_info());'
|
||||||
|
|
||||||
|
- name: Imagick Version
|
||||||
run: php -r 'var_dump(Imagick::getVersion());'
|
run: php -r 'var_dump(Imagick::getVersion());'
|
||||||
|
|
||||||
- name: Supported Imagick Formats
|
- name: Supported Imagick Formats
|
||||||
|
@@ -26,10 +26,10 @@ class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterfa
|
|||||||
// be handled by the standard GD decoder.
|
// be handled by the standard GD decoder.
|
||||||
'image/gif' => $this->decodeGif($input),
|
'image/gif' => $this->decodeGif($input),
|
||||||
default => parent::decode(match ($mediaType) {
|
default => parent::decode(match ($mediaType) {
|
||||||
'image/jpeg', 'image/jpg', 'image/pjpeg' => imagecreatefromjpeg($input),
|
'image/jpeg', 'image/jpg', 'image/pjpeg' => @imagecreatefromjpeg($input),
|
||||||
'image/webp', 'image/x-webp' => imagecreatefromwebp($input),
|
'image/webp', 'image/x-webp' => @imagecreatefromwebp($input),
|
||||||
'image/png', 'image/x-png' => imagecreatefrompng($input),
|
'image/png', 'image/x-png' => @imagecreatefrompng($input),
|
||||||
'image/avif', 'image/x-avif' => imagecreatefromavif($input),
|
'image/avif', 'image/x-avif' => @imagecreatefromavif($input),
|
||||||
'image/bmp',
|
'image/bmp',
|
||||||
'image/ms-bmp',
|
'image/ms-bmp',
|
||||||
'image/x-bitmap',
|
'image/x-bitmap',
|
||||||
@@ -37,7 +37,7 @@ class FilePathImageDecoder extends NativeObjectDecoder implements DecoderInterfa
|
|||||||
'image/x-ms-bmp',
|
'image/x-ms-bmp',
|
||||||
'image/x-win-bitmap',
|
'image/x-win-bitmap',
|
||||||
'image/x-windows-bmp',
|
'image/x-windows-bmp',
|
||||||
'image/x-xbitmap' => imagecreatefrombmp($input),
|
'image/x-xbitmap' => @imagecreatefrombmp($input),
|
||||||
default => throw new DecoderException('Unable to decode input'),
|
default => throw new DecoderException('Unable to decode input'),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@@ -19,6 +19,7 @@ class DrawLineModifier extends GenericDrawLineModifier implements SpecializedInt
|
|||||||
{
|
{
|
||||||
$drawing = new ImagickDraw();
|
$drawing = new ImagickDraw();
|
||||||
$drawing->setStrokeWidth($this->drawable->width());
|
$drawing->setStrokeWidth($this->drawable->width());
|
||||||
|
$drawing->setFillOpacity(0);
|
||||||
$drawing->setStrokeColor(
|
$drawing->setStrokeColor(
|
||||||
$this->driver()->colorProcessor($image->colorspace())->colorToNative(
|
$this->driver()->colorProcessor($image->colorspace())->colorToNative(
|
||||||
$this->backgroundColor()
|
$this->backgroundColor()
|
||||||
|
@@ -11,7 +11,10 @@ use Intervention\Image\Interfaces\SizeInterface;
|
|||||||
class RectangleResizer
|
class RectangleResizer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* @param null|int $width
|
||||||
|
* @param null|int $height
|
||||||
* @throws GeometryException
|
* @throws GeometryException
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected ?int $width = null,
|
protected ?int $width = null,
|
||||||
@@ -31,35 +34,62 @@ class RectangleResizer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Static factory method to create resizer with given target size
|
||||||
|
*
|
||||||
|
* @param mixed $arguments
|
||||||
* @throws GeometryException
|
* @throws GeometryException
|
||||||
|
* @return RectangleResizer
|
||||||
*/
|
*/
|
||||||
public static function to(mixed ...$arguments): self
|
public static function to(mixed ...$arguments): self
|
||||||
{
|
{
|
||||||
return new self(...$arguments);
|
return new self(...$arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if resize has target width
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected function hasTargetWidth(): bool
|
protected function hasTargetWidth(): bool
|
||||||
{
|
{
|
||||||
return is_integer($this->width);
|
return is_integer($this->width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return target width of resizer if available
|
||||||
|
*
|
||||||
|
* @return null|int
|
||||||
|
*/
|
||||||
protected function getTargetWidth(): ?int
|
protected function getTargetWidth(): ?int
|
||||||
{
|
{
|
||||||
return $this->hasTargetWidth() ? $this->width : null;
|
return $this->hasTargetWidth() ? $this->width : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if resize has target height
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
protected function hasTargetHeight(): bool
|
protected function hasTargetHeight(): bool
|
||||||
{
|
{
|
||||||
return is_integer($this->height);
|
return is_integer($this->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return target width of resizer if available
|
||||||
|
*
|
||||||
|
* @return null|int
|
||||||
|
*/
|
||||||
protected function getTargetHeight(): ?int
|
protected function getTargetHeight(): ?int
|
||||||
{
|
{
|
||||||
return $this->hasTargetHeight() ? $this->height : null;
|
return $this->hasTargetHeight() ? $this->height : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Return target size object
|
||||||
|
*
|
||||||
* @throws GeometryException
|
* @throws GeometryException
|
||||||
|
* @return SizeInterface
|
||||||
*/
|
*/
|
||||||
protected function getTargetSize(): SizeInterface
|
protected function getTargetSize(): SizeInterface
|
||||||
{
|
{
|
||||||
@@ -70,6 +100,12 @@ class RectangleResizer
|
|||||||
return new Rectangle($this->width, $this->height);
|
return new Rectangle($this->width, $this->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set target width of resizer
|
||||||
|
*
|
||||||
|
* @param int $width
|
||||||
|
* @return RectangleResizer
|
||||||
|
*/
|
||||||
public function toWidth(int $width): self
|
public function toWidth(int $width): self
|
||||||
{
|
{
|
||||||
$this->width = $width;
|
$this->width = $width;
|
||||||
@@ -77,6 +113,12 @@ class RectangleResizer
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set target height of resizer
|
||||||
|
*
|
||||||
|
* @param int $height
|
||||||
|
* @return RectangleResizer
|
||||||
|
*/
|
||||||
public function toHeight(int $height): self
|
public function toHeight(int $height): self
|
||||||
{
|
{
|
||||||
$this->height = $height;
|
$this->height = $height;
|
||||||
@@ -84,6 +126,12 @@ class RectangleResizer
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set target size to given size object
|
||||||
|
*
|
||||||
|
* @param SizeInterface $size
|
||||||
|
* @return RectangleResizer
|
||||||
|
*/
|
||||||
public function toSize(SizeInterface $size): self
|
public function toSize(SizeInterface $size): self
|
||||||
{
|
{
|
||||||
$this->width = $size->width();
|
$this->width = $size->width();
|
||||||
@@ -92,6 +140,12 @@ class RectangleResizer
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get proportinal width
|
||||||
|
*
|
||||||
|
* @param SizeInterface $size
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
protected function getProportionalWidth(SizeInterface $size): int
|
protected function getProportionalWidth(SizeInterface $size): int
|
||||||
{
|
{
|
||||||
if (!$this->hasTargetHeight()) {
|
if (!$this->hasTargetHeight()) {
|
||||||
@@ -101,6 +155,12 @@ class RectangleResizer
|
|||||||
return max([1, (int) round($this->height * $size->aspectRatio())]);
|
return max([1, (int) round($this->height * $size->aspectRatio())]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get proportinal height
|
||||||
|
*
|
||||||
|
* @param SizeInterface $size
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
protected function getProportionalHeight(SizeInterface $size): int
|
protected function getProportionalHeight(SizeInterface $size): int
|
||||||
{
|
{
|
||||||
if (!$this->hasTargetWidth()) {
|
if (!$this->hasTargetWidth()) {
|
||||||
@@ -110,6 +170,12 @@ class RectangleResizer
|
|||||||
return max([1, (int) round($this->width / $size->aspectRatio())]);
|
return max([1, (int) round($this->width / $size->aspectRatio())]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize given size to target size of the resizer
|
||||||
|
*
|
||||||
|
* @param SizeInterface $size
|
||||||
|
* @return SizeInterface
|
||||||
|
*/
|
||||||
public function resize(SizeInterface $size): SizeInterface
|
public function resize(SizeInterface $size): SizeInterface
|
||||||
{
|
{
|
||||||
$resized = new Rectangle($size->width(), $size->height());
|
$resized = new Rectangle($size->width(), $size->height());
|
||||||
@@ -125,6 +191,12 @@ class RectangleResizer
|
|||||||
return $resized;
|
return $resized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize given size to target size of the resizer but do not exceed original size
|
||||||
|
*
|
||||||
|
* @param SizeInterface $size
|
||||||
|
* @return SizeInterface
|
||||||
|
*/
|
||||||
public function resizeDown(SizeInterface $size): SizeInterface
|
public function resizeDown(SizeInterface $size): SizeInterface
|
||||||
{
|
{
|
||||||
$resized = new Rectangle($size->width(), $size->height());
|
$resized = new Rectangle($size->width(), $size->height());
|
||||||
@@ -144,6 +216,12 @@ class RectangleResizer
|
|||||||
return $resized;
|
return $resized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize given size to target size proportinally
|
||||||
|
*
|
||||||
|
* @param SizeInterface $size
|
||||||
|
* @return SizeInterface
|
||||||
|
*/
|
||||||
public function scale(SizeInterface $size): SizeInterface
|
public function scale(SizeInterface $size): SizeInterface
|
||||||
{
|
{
|
||||||
$resized = new Rectangle($size->width(), $size->height());
|
$resized = new Rectangle($size->width(), $size->height());
|
||||||
@@ -168,6 +246,12 @@ class RectangleResizer
|
|||||||
return $resized;
|
return $resized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize given size to target size proportinally but do not exceed original size
|
||||||
|
*
|
||||||
|
* @param SizeInterface $size
|
||||||
|
* @return SizeInterface
|
||||||
|
*/
|
||||||
public function scaleDown(SizeInterface $size): SizeInterface
|
public function scaleDown(SizeInterface $size): SizeInterface
|
||||||
{
|
{
|
||||||
$resized = new Rectangle($size->width(), $size->height());
|
$resized = new Rectangle($size->width(), $size->height());
|
||||||
|
@@ -86,8 +86,8 @@ class Line implements IteratorAggregate, Countable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count segments of line
|
* Count segments (individual words including punctuation marks) of line
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function count(): int
|
public function count(): int
|
||||||
@@ -95,6 +95,16 @@ class Line implements IteratorAggregate, Countable
|
|||||||
return count($this->segments);
|
return count($this->segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count characters of line
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function length(): int
|
||||||
|
{
|
||||||
|
return mb_strlen((string) $this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast line to string
|
* Cast line to string
|
||||||
*
|
*
|
||||||
|
@@ -62,10 +62,10 @@ class TextBlock extends Collection
|
|||||||
{
|
{
|
||||||
$lines = $this->lines();
|
$lines = $this->lines();
|
||||||
usort($lines, function (Line $a, Line $b) {
|
usort($lines, function (Line $a, Line $b) {
|
||||||
if (mb_strlen((string) $a) === mb_strlen((string) $b)) {
|
if ($a->length() === $b->length()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return mb_strlen((string) $a) > mb_strlen((string) $b) ? -1 : 1;
|
return $a->length() > $b->length() ? -1 : 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
return $lines[0];
|
return $lines[0];
|
||||||
|
@@ -25,4 +25,14 @@ final class DrawLineModifierTest extends ImagickTestCase
|
|||||||
$image->modify(new DrawLineModifier($line));
|
$image->modify(new DrawLineModifier($line));
|
||||||
$this->assertEquals('b53517', $image->pickColor(0, 0)->toHex());
|
$this->assertEquals('b53517', $image->pickColor(0, 0)->toHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testApplyTransparent(): void
|
||||||
|
{
|
||||||
|
$image = $this->createTestImage(10, 10)->fill('ff5500');
|
||||||
|
$this->assertColor(255, 85, 0, 255, $image->pickColor(5, 5));
|
||||||
|
$line = new Line(new Point(0, 5), new Point(10, 5), 4);
|
||||||
|
$line->setBackgroundColor('fff4');
|
||||||
|
$image->modify(new DrawLineModifier($line));
|
||||||
|
$this->assertColor(255, 136, 77, 255, $image->pickColor(5, 5));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,21 @@ final class LineTest extends BaseTestCase
|
|||||||
$this->assertEquals(2, $line->count());
|
$this->assertEquals(2, $line->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testLength(): void
|
||||||
|
{
|
||||||
|
$line = new Line();
|
||||||
|
$this->assertEquals(0, $line->length());
|
||||||
|
|
||||||
|
$line = new Line("foo");
|
||||||
|
$this->assertEquals(3, $line->length());
|
||||||
|
|
||||||
|
$line = new Line("foo bar.");
|
||||||
|
$this->assertEquals(8, $line->length());
|
||||||
|
|
||||||
|
$line = new Line("🫷🙂🫸");
|
||||||
|
$this->assertEquals(3, $line->length());
|
||||||
|
}
|
||||||
|
|
||||||
public function testAdd(): void
|
public function testAdd(): void
|
||||||
{
|
{
|
||||||
$line = new Line();
|
$line = new Line();
|
||||||
|
Reference in New Issue
Block a user