Skip to content

Commit

Permalink
Merge branch 'develop' into feature/font-system
Browse files Browse the repository at this point in the history
  • Loading branch information
olivervogel committed Jan 12, 2025
2 parents 001942a + f0307ce commit 76869c6
Show file tree
Hide file tree
Showing 28 changed files with 837 additions and 92 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"homepage": "https://image.intervention.io/",
"keywords": [
"image",
"vips"
"vips",
"libvips"
],
"license": "MIT",
"authors": [
Expand Down
22 changes: 11 additions & 11 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,35 +82,35 @@ the features that have already been implemented.
| Image::scaleDown() ||
| Image::cover() ||
| Image::coverDown() ||
| Image::pad() | |
| Image::pad() | |
| Image::contain() ||
| Image::crop() ||
| Image::resizeCanvas() | |
| Image::resizeCanvasRelative() | |
| Image::trim() | 🪲 |
| Image::place() | 🪲 |
| Image::resizeCanvas() | |
| Image::resizeCanvasRelative() | |
| Image::trim() | |
| Image::place() | |
| Image::brightness() ||
| Image::contrast() ||
| Image::gamma() ||
| Image::colorize() ||
| Image::greyscale() ||
| Image::flip() ||
| Image::flop() ||
| Image::rotate() | 🪲 |
| Image::rotate() | |
| Image::orient() ||
| Image::blur() ||
| Image::sharpen() ||
| Image::invert() ||
| Image::pixelate() | 🪲 |
| Image::pixelate() | |
| Image::reduceColors() ||
| Image::text() ||
| Image::fill() ||
| Image::drawPixel() | |
| Image::drawPixel() | |
| Image::drawEllipse() ||
| Image::drawCircle() ||
| Image::drawLine() | |
| Image::drawPolygon() | |
| Image::drawBezier() | |
| Image::drawLine() | |
| Image::drawPolygon() | |
| Image::drawBezier() | |
| Image::resolution() ||
| Image::setResolution() ||
| Image::exif() ||
Expand Down
2 changes: 1 addition & 1 deletion src/Analyzers/PixelColorAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ protected function colorAt(ColorspaceInterface $colorspace, VipsImage $vipsImage
return $this->driver()
->colorProcessor($colorspace)
->nativeToColor(array_map(
fn ($value): int => (int) min($value, 255),
fn(int|float $value): int => (int) min($value, 255),
$vipsImage->getpoint($x, $y)
));
}
Expand Down
2 changes: 1 addition & 1 deletion src/ColorProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function __construct(protected ColorspaceInterface $colorspace)
*/
public function colorToNative(ColorInterface $color)
{
return array_map(fn($value) => $value * 255, $color->normalize());
return array_map(fn(float $value) => $value * 255, $color->normalize());
}

/**
Expand Down
11 changes: 1 addition & 10 deletions src/Modifiers/ContainModifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@

namespace Intervention\Image\Drivers\Vips\Modifiers;

use Intervention\Image\Colors\Rgb\Channels\Alpha;
use Intervention\Image\Colors\Rgb\Channels\Blue;
use Intervention\Image\Colors\Rgb\Channels\Green;
use Intervention\Image\Colors\Rgb\Channels\Red;
use Intervention\Image\Drivers\Vips\Core;
use Intervention\Image\Drivers\Vips\Traits\PositionToGravity;
use Intervention\Image\Exceptions\ColorException;
Expand Down Expand Up @@ -73,12 +69,7 @@ private function contain(FrameInterface $frame, SizeInterface $resize, ColorInte
$resize->height(),
[
'extend' => Extend::BACKGROUND,
'background' => [
$bgColor->channel(Red::class)->value(),
$bgColor->channel(Green::class)->value(),
$bgColor->channel(Blue::class)->value(),
$bgColor->channel(Alpha::class)->value(),
],
'background' => $bgColor->toArray(),
]
)
);
Expand Down
60 changes: 41 additions & 19 deletions src/Modifiers/CropModifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use Intervention\Image\Colors\Rgb\Channels\Blue;
use Intervention\Image\Colors\Rgb\Channels\Green;
use Intervention\Image\Colors\Rgb\Channels\Red;
use Intervention\Image\Drivers\Vips\Core;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SizeInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
Expand Down Expand Up @@ -48,27 +50,14 @@ public function apply(ImageInterface $image): ImageInterface
)
);
} else {
$offset_x = $crop->pivot()->x() + $this->offset_x;
$offset_y = $crop->pivot()->y() + $this->offset_y;

$targetWidth = min($crop->width(), $originalSize->width());
$targetHeight = min($crop->height(), $originalSize->height());

$targetWidth = $targetWidth > $originalSize->width() ? $targetWidth + $offset_x : $targetWidth;
$targetHeight = $targetHeight > $originalSize->height() ? $targetHeight + $offset_y : $targetHeight;

$cropped = $image->core()->native()->crop(
max($offset_x, 0),
max($offset_y, 0),
$targetWidth,
$targetHeight
);

if ($crop->width() > $originalSize->width() || $cropped->height < $crop->height()) {
$cropped = $background->insert($cropped, max($offset_x * -1, 0), max($offset_y * -1, 0));
$frames = [];
foreach ($image as $frame) {
$frames[] = $frame->setNative($this->cropFrame($frame, $crop, $originalSize, $background));
}

$image->core()->setNative($cropped);
$image->core()->setNative(
Core::replaceFrames($image->core()->native(), $frames)
);
}

return $image;
Expand Down Expand Up @@ -116,4 +105,37 @@ private function getInterestingPositions(): array
Interesting::ALL,
]);
}

private function cropFrame(
FrameInterface $frame,
SizeInterface $crop,
SizeInterface $originalSize,
VipsImage $background
): VipsImage {
$offset_x = $crop->pivot()->x() + $this->offset_x;
$offset_y = $crop->pivot()->y() + $this->offset_y;

$targetWidth = min($crop->width(), $originalSize->width());
$targetHeight = min($crop->height(), $originalSize->height());

$targetWidth = $targetWidth > $originalSize->width() ? $targetWidth + $offset_x : $targetWidth;
$targetHeight = $targetHeight > $originalSize->height() ? $targetHeight + $offset_y : $targetHeight;

$cropped = $frame->native()->crop(
max($offset_x, 0),
max($offset_y, 0),
$targetWidth,
$targetHeight
);

if ($crop->width() > $originalSize->width() || $cropped->height < $crop->height()) {
$cropped = $background->insert(
$cropped,
max($offset_x * -1, 0),
max($offset_y * -1, 0)
);
}

return $cropped;
}
}
60 changes: 60 additions & 0 deletions src/Modifiers/DrawBezierModifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Drivers\Vips\Modifiers;

use Intervention\Image\Drivers\Vips\Core;
use Intervention\Image\Drivers\Vips\Driver;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\DrawBezierModifier as GenericDrawBezierModifier;
use Jcupitt\Vips\BlendMode;
use Jcupitt\Vips\Exception as VipsException;

class DrawBezierModifier extends GenericDrawBezierModifier implements SpecializedInterface
{
/**
* {@inheritdoc}
*
* @see ModifierInterface::apply()
* @throws VipsException|RuntimeException|\RuntimeException
*/
public function apply(ImageInterface $image): ImageInterface
{
$chunks = array_chunk($this->drawable->toArray(), 2);
$points = join(' ', array_map(function (array $coordinates, int $key) use ($chunks): string {
return match ($key) {
0 => 'M' . join(' ', $coordinates),
1 => count($chunks) === 3 ? 'Q' . join(' ', $coordinates) : 'C' . join(' ', $coordinates),
default => join(' ', $coordinates),
};
}, $chunks, array_keys($chunks)));

$polygon = Driver::createShape(
'path',
[
'd' => $points,
'fill' => $this->backgroundColor()->toString(),
'stroke' => $this->borderColor()->toString(),
'stroke-width' => $this->drawable->borderSize(),
],
$image->width(),
$image->height(),
);

$frames = [];
foreach ($image as $frame) {
$frames[] = $frame->setNative(
$frame->native()->composite($polygon->core()->native(), [BlendMode::OVER])
);
}

$image->core()->setNative(
Core::replaceFrames($image->core()->native(), $frames)
);

return $image;
}
}
53 changes: 53 additions & 0 deletions src/Modifiers/DrawLineModifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Drivers\Vips\Modifiers;

use Intervention\Image\Drivers\Vips\Core;
use Intervention\Image\Drivers\Vips\Driver;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\DrawLineModifier as GenericDrawLineModifier;
use Jcupitt\Vips\BlendMode;
use Jcupitt\Vips\Exception as VipsException;

class DrawLineModifier extends GenericDrawLineModifier implements SpecializedInterface
{
/**
* {@inheritdoc}
*
* @see ModifierInterface::apply()
* @throws VipsException|RuntimeException|\RuntimeException
*/
public function apply(ImageInterface $image): ImageInterface
{
$ellipse = Driver::createShape(
'line',
[
'x1' => $this->drawable->start()->x(),
'y1' => $this->drawable->start()->y(),
'x2' => $this->drawable->end()->x(),
'y2' => $this->drawable->end()->y(),
'stroke' => $this->backgroundColor()->toString(),
'stroke-width' => $this->drawable->width(),
],
$image->width(),
$image->height(),
);

$frames = [];
foreach ($image as $frame) {
$frames[] = $frame->setNative(
$frame->native()->composite($ellipse->core()->native(), [BlendMode::OVER])
);
}

$image->core()->setNative(
Core::replaceFrames($image->core()->native(), $frames)
);

return $image;
}
}
63 changes: 63 additions & 0 deletions src/Modifiers/DrawPixelModifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace Intervention\Image\Drivers\Vips\Modifiers;

use Intervention\Image\Drivers\Vips\Core;
use Intervention\Image\Exceptions\AnimationException;
use Intervention\Image\Exceptions\ColorException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\DrawPixelModifier as GenericDrawPixelModifier;
use Jcupitt\Vips\BlendMode;
use Jcupitt\Vips\Image as VipsImage;
use Jcupitt\Vips\Exception as VipsException;

class DrawPixelModifier extends GenericDrawPixelModifier implements SpecializedInterface
{
/**
* {@inheritdoc}
*
* @throws VipsException|AnimationException|ColorException|RuntimeException
* @see Intervention\Image\Interfaces\ModifierInterface::apply()
*/
public function apply(ImageInterface $image): ImageInterface
{
// decode pixel color
$color = $this->driver()->colorProcessor($image->colorspace())->colorToNative(
$this->driver()->handleInput($this->color)
);

$pixel = VipsImage::black(1, 1)
->add($color[0]) // red
->cast($image->core()->native()->format)
->copy(['interpretation' => $image->core()->native()->interpretation])
->bandjoin([
$color[1], // green
$color[2], // blue
$color[3], // alpha
]);

$frames = [];
foreach ($image as $frame) {
$frames[] = $frame->setNative(
$frame->native()->composite2(
$pixel,
BlendMode::OVER,
[
'x' => $this->position->x(),
'y' => $this->position->y(),
],
)
);
}

$image->core()->setNative(
Core::replaceFrames($image->core()->native(), $frames)
);

return $image;
}
}
Loading

0 comments on commit 76869c6

Please sign in to comment.