libvips / php-vips-ext

Low-level libvips binding for PHP
MIT License
101 stars 11 forks source link

The fastest way to convert from vips to imagick? #16

Closed chregu closed 7 years ago

chregu commented 7 years ago

Question: Anyone knows what could be the fastest way from a vips resource to an imagick resource (retaining the image, of course) and maybe vice versa. I sometimes need to convert (for example for saving gif) from one to the other. I basically currently do:

$image = new \Imagick();
$imagick->readImageBlob($vips->pngsave_buffer(['interlace' => false]));

Any better recommended way?

jcupitt commented 7 years ago

Hello Christian, PNG is very slow, unfortunately, uncompressed TIFF would be a lot quicker.

Best of all would be simply passing a pointer to large array of uncompressed bytes (this is what pyvips does when interchanging images with numpy and PIL), but that would need additions to php-vips-ext.

Does imagick support creating an image from a memory array?

kleisauke commented 7 years ago

Imagick::exportImagePixels / Imagick::importImagePixels and https://github.com/jcupitt/php-vips-ext/pull/13 might be relevant here.

jcupitt commented 7 years ago

Oh dear Kleis, sorry, I'd forgotten about #13. Let's merge now since we're doing a new version. I'll have a look.

chregu commented 7 years ago

Ah, cool, great. No need to png/tiffsave anymore, will test soon

But regarding tiffsave, I have something I can't explain. Simple case:

$v = \Jcupitt\Vips\Image::newFromFile("animated.gif");
$v = $v->premultiply();
$v = $v->resize(0.5);
$v = $v->unpremultiply();
$v->pngsave("foo.png");
$v->tiffsave("foo.tiff");

The png looks like expected, but the tiff is totally wrong, looks like a black and white image (even without resize). Does it need something more?

Input:

animated

Output (converted to a png outside of vips, since github doesn't support tiff):

foo tiff

jcupitt commented 7 years ago

Hello, premultiply / unpremultiply use float format, so you are saving as a float TIFF (12 bytes per pixel). Float TIFF usually uses 0 - 1 for black - white, rather than 0 - 255, so your 0 - 255 float TIFFs look white.

After unpremultiply, I would use cast() to put image image back to the original band format, something like:

$original_format = $image->format;
$image = $image->premultiply()->resize(0.5)->unpremultiply();
$image = $image->cast($original_format);

Processing as float is obviously slower than byte or short, so I would only premultiply if necessary, and cast back as soon as possible after.

chregu commented 7 years ago

Thanks, that works. And with #13 in the works, I think we can close this issue again.