Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/vendor/
/.transformers-cache/
/examples/focus-crop/
/.vscode/
.phpunit.result.cache
.idea
.DS_Store
.DS_Store
12 changes: 9 additions & 3 deletions Dockerfile-php-8.1
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
FROM composer:2.0 AS step0
FROM composer:2 AS step0

WORKDIR /src/

COPY composer.lock /src/
COPY composer.json /src/

RUN composer update --ignore-platform-reqs --optimize-autoloader \
--no-plugins --no-scripts --prefer-dist
RUN composer install --ignore-platform-reqs --optimize-autoloader \
--no-scripts --prefer-dist

FROM appwrite/utopia-base:php-8.1-0.1.1 AS final

LABEL maintainer="team@appwrite.io"

RUN apk add --no-cache libffi \
&& apk add --no-cache --virtual .build-deps $PHPIZE_DEPS libffi-dev \
&& docker-php-ext-install ffi \
&& apk del .build-deps \
&& printf 'ffi.enable=true\n' > /usr/local/etc/php/conf.d/ffi-enable.ini

WORKDIR /code

COPY --from=step0 /src/vendor /code/vendor
Expand Down
12 changes: 9 additions & 3 deletions Dockerfile-php-8.2
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
FROM composer:2.0 AS step0
FROM composer:2 AS step0

WORKDIR /src/

COPY composer.lock /src/
COPY composer.json /src/

RUN composer update --ignore-platform-reqs --optimize-autoloader \
--no-plugins --no-scripts --prefer-dist
RUN composer install --ignore-platform-reqs --optimize-autoloader \
--no-scripts --prefer-dist

FROM appwrite/utopia-base:php-8.2-0.1.1 AS final

LABEL maintainer="team@appwrite.io"

RUN apk add --no-cache libffi \
&& apk add --no-cache --virtual .build-deps $PHPIZE_DEPS libffi-dev \
&& docker-php-ext-install ffi \
&& apk del .build-deps \
&& printf 'ffi.enable=true\n' > /usr/local/etc/php/conf.d/ffi-enable.ini

WORKDIR /code

COPY --from=step0 /src/vendor /code/vendor
Expand Down
12 changes: 9 additions & 3 deletions Dockerfile-php-8.3
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
FROM composer:2.0 AS step0
FROM composer:2 AS step0

WORKDIR /src/

COPY composer.lock /src/
COPY composer.json /src/

RUN composer update --ignore-platform-reqs --optimize-autoloader \
--no-plugins --no-scripts --prefer-dist
RUN composer install --ignore-platform-reqs --optimize-autoloader \
--no-scripts --prefer-dist

FROM appwrite/utopia-base:php-8.3-0.1.1 AS final

LABEL maintainer="team@appwrite.io"

RUN apk add --no-cache libffi \
&& apk add --no-cache --virtual .build-deps $PHPIZE_DEPS libffi-dev \
&& docker-php-ext-install ffi \
&& apk del .build-deps \
&& printf 'ffi.enable=true\n' > /usr/local/etc/php/conf.d/ffi-enable.ini

WORKDIR /code

COPY --from=step0 /src/vendor /code/vendor
Expand Down
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ use Utopia\Image\Image;
//crop image
$image = new Image(\file_get_contents('image.jpg'));
$target = 'image_100x100.jpg';
$image->crop(100, 100, Image::GRAVITY_NORTHWEST);
$image->crop(100, 100, Image::GRAVITY_TOP_LEFT);
$image->save($target, 'jpg', 100);

//crop around subjects described with natural language
$image = new Image(\file_get_contents('image.jpg'));
$image->crop(400, 300, focus: 'person holding a phone');
$image->save('focused.jpg', 'jpg', 100);

$image = new Image(\file_get_contents('image.jpg'));
$target = 'image_border.jpg';
$image->setBorder(2, "#ff0000"); //add border 2 px, red
Expand All @@ -41,9 +46,38 @@ $image->save($target, 'png', 100);

```

### Focus Cropping

The optional `focus` argument uses zero-shot object detection to position the crop around matching subjects:

```php
$image->crop(400, 300, focus: 'person');
$image->crop(400, 300, focus: 'red car');
```

When multiple subjects match, the crop keeps all of them when possible and otherwise prioritizes the strongest detections. If nothing matches, the supplied gravity is used as a fallback:

```php
$image->crop(400, 300, Image::GRAVITY_TOP, focus: 'red car');
```

Focus cropping requires PHP FFI. The platform-specific inference runtime is installed through Composer, which requires allowing its reviewed installer plugin:

```bash
composer config allow-plugins.codewithkyrian/platform-package-installer true
```

The prebuilt Linux inference runtime targets glibc. Alpine and other musl-based images require a musl-compatible ONNX Runtime build.

The quantized model is cached on first use. Production deployments should download it during the build instead of during an image request:

```bash
./vendor/bin/transformers download Xenova/owlvit-base-patch32 zero-shot-object-detection
```

## System Requirements

Utopia Image requires PHP 8.0 or later. We recommend using the latest PHP version whenever possible.
Utopia Image requires PHP 8.1 or later with the Imagick, GD, and FFI extensions. We recommend using the latest PHP version whenever possible.

## Copyright and license

Expand Down
14 changes: 12 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@
"scripts": {
"lint": "./vendor/bin/pint --test",
"format": "./vendor/bin/pint",
"check": "./vendor/bin/phpstan analyse --level max src tests",
"check": "./vendor/bin/phpstan analyse --level max src tests --memory-limit=512M",
"test": "phpunit"
},
"require": {
"php": ">=8.1",
"ext-ffi": "*",
"ext-imagick": "*",
"ext-gd": "*"
"ext-gd": "*",
"codewithkyrian/transformers": "^0.6.2",
"symfony/console": "^6.4",
"symfony/string": "^6.4",
"symfony/yaml": "^6.4"
},
"require-dev": {
"phpunit/phpunit": "10.5.*",
Expand All @@ -26,5 +31,10 @@
"suggest": {
"ext-imagick": "Imagick extension is required for Imagick adapter"
},
"config": {
"allow-plugins": {
"codewithkyrian/platform-package-installer": true
}
},
"minimum-stability": "dev"
}
Loading
Loading