rokka-io / imagine-vips Goto Github PK
View Code? Open in Web Editor NEWlibvips adapter for php imagine
Home Page: https://rokka.io
License: Other
libvips adapter for php imagine
Home Page: https://rokka.io
License: Other
Hello and congratulations on your release!
Re. layers, libvips can save multi-page TIFF images, and can load multi-page PDF, TIFF, and GIF. It can also load any multi-page format supported by libMagick.
It's certainly true that GIF save is not supported :(
Very cool package, thanks for releasing it. Locally, I can see a nice speedup using it over gd.
But I can't figure out how to deploy it to our production server, which is using dokku and the heroku buildpacks.
Installing platform packages...
remote:
remote: ! ERROR: Failed to install system packages!
remote: !
remote: ! Your platform requirements (for runtimes and extensions) could
remote: ! not be resolved to an installable set of dependencies, or a
remote: ! platform package repository was unreachable.
remote: !
remote: ! This usually means that you (or packages you are using) depend
remote: ! on a combination of PHP versions and/or extensions that are
remote: ! currently not available on Heroku.
remote: !
remote: ! The following is the full output from the installation attempt:
remote: !
remote: ! > Loading repositories with available runtimes and extensions
remote: ! > Updating dependencies
remote: ! > Your requirements could not be resolved to an installable set of packages.
remote: ! >
remote: ! > Problem 1
remote: ! > - composer.json/composer.lock requires ext-ffi * -> could not be found in any version, there may be a typo in the package name.
remote: ! > Problem 2
remote: ! > - Root composer.json requires jcupitt/vips v2.3.0 -> satisfiable by jcupitt/vips[v2.3.0].
remote: ! > - jcupitt/vips v2.3.0 requires ext-ffi * -> could not be found in any version, there may be a typo in the package name.
remote: ! >
remote: !
remote: ! For reference, the following runtimes are currently available:
remote: !
remote: ! PHP: 8.3.1, 8.3.0, 8.2.14, 8.2.13, 8.2.12, 8.2.11, 8.2.10,
remote: ! 8.2.9, 8.2.8, 8.2.7, 8.2.6, 8.2.5, 8.2.4, 8.2.3, 8.2.2,
remote: ! 8.2.1, 8.1.27, 8.1.26, 8.1.25, 8.1.24, 8.1.23, 8.1.22,
remote: ! 8.1.21, 8.1.20, 8.1.19, 8.1.18, 8.1.17, 8.1.16, 8.1.15,
remote: ! 8.1.14, 8.1.13, 8.1.12, 8.1.11, 8.1.10, 8.1.9, 8.1.8,
remote: ! 8.1.7, 8.1.6
Any suggestions or alteratives?
Thanks.
For the loaders VipsForeignLoadWebpFile
and VipsForeignLoadWebpBuffer
the n
-Option is not being applied so no animated webp can be loaded:
https://github.com/rokka-io/imagine-vips/blob/0.31.0/lib/Imagine/Vips/Imagine.php#L237
I think there should also be those two cases:
case 'VipsForeignLoadWebpFile':
case 'VipsForeignLoadWebpBuffer':
$options['n'] = -1; // not sure this should be enabled by default, to discuss
break;
When I add those lines, i can open animated webp images without any problems. Otherwise only the first frame will be loaded, so the animation will "get lost".
It is impossible to get the layers from a tif image (there is only one layer who contains the whole image) when using vips-dev version 8.14.2-rc2 on an alpine docker image as opposed to the latest version of imagick with image magick. I saw that it said in the readme that it should work 8.7.0, does that mean I have to downgrade my version of vips-dev?
Currently, with VIPS 8.9 empty array is returned.
imagine-vips/lib/Imagine/Vips/Image.php
Lines 427 to 442 in 5cd6490
Additionally, Layers::coalesce
return nothing instead of self.
And one more thing: there are public const
declarations. They were introduced in php 7.1, but php 7.0 is required.
Oh, Effects::modulate
returns inexistent RokkaImageInterface
.
For some reason, when loading gif from string my loader is VipsForeignLoadNsgifBuffer instead of VipsForeignLoadGifBuffer. The n option is not applied correctly.
The following addition fixes the issue (for now):
protected function getLoadOptions($loader, $loadOptions = [])
{
$options = [];
switch ($loader) {
case 'VipsForeignLoadJpegFile':
case 'VipsForeignLoadJpegBuffer':
$options['autorotate'] = true;
break;
case 'VipsForeignLoadHeifFile':
case 'VipsForeignLoadHeifBuffer':
$options['autorotate'] = true;
$options['n'] = -1; // not sure this should be enabled by default, to discuss
break;
case 'VipsForeignLoadGifFile':
case 'VipsForeignLoadGifBuffer':
case 'VipsForeignLoadNsgifBuffer':
$options['n'] = -1; // not sure this should be enabled by default, to discuss
break;
}
$options = array_merge($loadOptions, $options);
// FIXME: remove not allowed options
if (isset($options['shrink'])) {
switch ($loader) {
case 'VipsForeignLoadJpegFile':
case 'VipsForeignLoadJpegBuffer':
case 'VipsForeignLoadWebpFile':
case 'VipsForeignLoadWebpBuffer':
break;
default:
unset($options['shrink']);
}
}
return $options;
}
My current vips config is:
enable debug: no
enable deprecated library components: yes
enable modules: no
use fftw3 for FFT: no
accelerate loops with orc: yes
ICC profile support with lcms: yes (lcms2)
zlib: yes
text rendering with pangocairo: no
font file support with fontconfig:
RAD load/save: yes
Analyze7 load/save: yes
PPM load/save: yes
GIF load: yes
GIF save with cgif: yes
EXIF metadata support with libexif: yes
JPEG load/save with libjpeg: yes (pkg-config)
JXL load/save with libjxl: no (dynamic module: no)
JPEG2000 load/save with libopenjp2: no
PNG load with libspng: no
PNG load/save with libpng: yes (pkg-config libpng >= 1.2.9)
quantisation to 8 bit: yes
TIFF load/save with libtiff: no
image pyramid save: yes
HEIC/AVIF load/save with libheif: no (dynamic module: no)
WebP load/save with libwebp: yes
PDF load with PDFium: no
PDF load with poppler-glib: no (dynamic module: no)
SVG load with librsvg-2.0: yes
EXR load with OpenEXR: no
OpenSlide load: no (dynamic module: no)
Matlab load with matio: no
NIfTI load/save with niftiio: no
FITS load/save with cfitsio: no
Magick package: none (dynamic module: no)
Magick API version: none
load with libMagickCore: no
save with libMagickCore: no
Should I send a PR for this fix?
I would like to ask a question. Does font is still on "hold" for implementation?
Do you want to put text on the image? Please see this post if so libvips/php-vips#94
The “magicksave” link in the readme seems to be broken:
Line 59 in b66966d
It should probably link here I think: https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-magicksave
from here:
https://packages.debian.org/sid/all/icc-profiles-free/filelist
See also: libvips/nip2@5a66f0e
Imagine uses the standard quality
to set the png_compression_level
for pngs and uses quality
as fallback for all formats.
Now the Vips integration introduces png_quality
but doesn't fall back to quality
.
imagine-vips/lib/Imagine/Vips/Image.php
Line 55 in 86cff5a
So when using Imagine with various libraries one easily misses to set png_quality
which results in huge images that are much larger than their original when slightly scaled for example.
Setting png_quality
leads to a result which is slightly worse than what IMagick
can achieves.
So my question is whether the fallback shouldn't be introduced and what quality actually does? I didn't fully understand the consequence.
The final result f.e. should be in my opinion that IM scaled pngs with a quality of 90 should be nearly identical to the same png scaled with Vips and the same quality level.
It seems like the copy does not copy all the layers. This issue can be replicated by
The saved copy is just the first layer of the original gif image
To manipulate animated gifs I need to call for other adapters $image->layers()->coalesce(); function so all layers are the same size so I can crop something out of that gif, but when using the vips adapter i get the following error:
VipsOperation: Klasse »paste« nicht gefunden
VipsOperation: Class »paste« not found
PHP Version: 7.3.12
PHP Vips Version: 1.0.10
Vips Version: 8.8.4
Sadly I'm not familiar how to fix this.
generateImage
has:
// Make a 1x1 pixel with the red channel and cast it to provided format.
$pixel = VipsImage::black(1, 1)->add($red)->cast(BandFormat::UCHAR);
// Extend this 1x1 pixel to match the origin image dimensions.
$vips = $pixel->embed(0, 0, $width, $height, ['extend' => Extend::COPY]);
$vips = $vips->copy(['interpretation' => self::getInterpretation($color->getPalette())]);
// Bandwise join the rest of the channels including the alpha channel.
$vips = $vips->bandjoin([
$green,
$blue,
$alpha,
]);
You can make this a bit quicker. The add()
method can take an array, so you can skip the final bandjoin()
:
// Make a 1x1 pixel with the red channel and cast it to provided format.
$pixel = VipsImage::black(1, 1)->add([$red, $green, $blue, $alpha])->cast(BandFormat::UCHAR);
// Extend this 1x1 pixel to match the origin image dimensions.
$vips = $pixel->embed(0, 0, $width, $height, ['extend' => Extend::COPY]);
$vips = $vips->copy(['interpretation' => self::getInterpretation($color->getPalette())]);
As libvips doesn't support animated gifs, we maybe can fallback to gifsicle for this.
Example code for creating one from an existing animated gif
$im = new \Imagine\Vips\Imagine();
$ori = $im->open("animated.gif");
$i=0;
/**
* parse colors, loop for global options and disposal, delay from each frame with
* gifsicle --info first and use them later instead of hardcoding
*/
$options = "gifsicle -v --colors 256 --loop=forever -O3";
/** @var \Imagine\Vips\Image $merged */
foreach ($ori->layers() as $layer) {
//merge each layer into the merged image to not have ugly transparency effects when doing operations
if ($i > 0) {
$merged = $merged->paste($layer, new Point(0, 0));
} else {
$merged = $layer;
}
$frame = clone $merged;
// do the actual operation
$frame->effects()->negative();
$frame->save("anim$i.gif");
$options .= " --delay 4 anim$i.gif";
$i++;
}
$command = $options . " -o animated.new.gif \n";
echo $command;
// run the gifsicle command
echo `$command`;
We could of course also use imagick to do something similar instead of gifsicle, eg. the identify -verbose
command (also available in PHP imagick) gives you also all the "delay, loop" information one needs, see http://www.imagemagick.org/Usage/scripts/gif2anim for inspiration. And maybe better to rely on a php extension than a CLI. gifsicle of course makes the more optimized gifs, but that could be another step.
Hello,
Given a photo with exif-ifd0-Orientation: 6
. If I load the image like the code below, the thumbnail.jpg
file is rotated.
I would like to know if it's a mistake in the array_merge
arguments order in https://github.com/rokka-io/imagine-vips/blob/master/lib/Imagine/Vips/Imagine.php#L209?
Also, I would like to know if there is a reason to have automatic rotation enabled?
I spotted this issue while replacing Gd by Vips in the project I work on. Because when a picture is loaded with automatic rotation, the orientation related metadata is not reset leading to the Autorotate
transformation applying the rotation an other time.
<?php
use Imagine\Image\Box;
use Imagine\Vips\Imagine;
require __DIR__.'/vendor/autoload.php';
$imagine = new Imagine();
$image = $imagine->open(__DIR__.'/DSC_3513.JPG', ['autorotate' => false]);
$thumbnail = $image->thumbnail(new Box(300, 300));
$thumbnail->save(__DIR__.'/thumbnail.jpg');
See libvips/libvips#1346 for details and
$image = \Jcupitt\Vips\Image::newFromFile("foo.gif");
var_dump($image->get('delay'));
now returns an array with all the delays per frame
Sorry, if this question is answered and I just didn't see it: Is there a way to thumbnail / smartcrop an image?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.