-
Notifications
You must be signed in to change notification settings - Fork 11
Add new_from_memory / write_to_memory #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Work in progress!
Oh nice! I've almost got the JS binding working, I'll have a look this this when I'm done with that. |
OK, all done! I had to convert the |
zval *IM; | ||
VipsImage *image; | ||
size_t arr_len; | ||
uint8_t *arr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we expect larger values than 255
? If so, then this should be a regular int
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always bytes there, so it's fine.
vips.c
Outdated
RETURN_LONG(-1); | ||
} | ||
|
||
if ((format_value = vips_enum_from_nick("enum", VIPS_TYPE_BAND_FORMAT, format)) < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I change enum
(the domain) to php-vips
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good idea.
vips.c
Outdated
|
||
int i; | ||
for (i = 0; i < arr_len; i++) { | ||
add_next_index_long(return_value, arr[i]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A byte array will be horribly slow: you have to loop for each pixel.
I would use a binary string, I think. This is what the libvips bindings for python / ruby / javascript / lua etc. all do anyway.
vips.c
Outdated
@@ -1389,6 +1388,93 @@ PHP_FUNCTION(vips_image_copy_memory) | |||
} | |||
/* }}} */ | |||
|
|||
/* {{{ proto resource vips_image_write_to_memory(array data, integer width, integer height, integer bands, string format) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: that should be vips_image_new_from_memory, of course.
vips.c
Outdated
band_format = format_value; | ||
|
||
const int size = zend_hash_num_elements(ht); | ||
int arr[size]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be slow for large images, and perhaps break the stack. I think we should use binary strings to swap images back and forth. You can skip this expensive copy operation.
Hello, it all looks fine, I think there's just an issue with how we represent memory arrays. I think actual PHP arrays will be slow, and we should use binary strings. |
maybe once libvips/php-vips-ext#13 is done, we can use that
maybe once libvips/php-vips-ext#13 is done, we can use that
I've changed the PHP arrays to binary strings with commit 2032b9f. Let me know what you think. |
tests/037.phpt
Outdated
<?php if (!extension_loaded("vips")) print "skip"; ?> | ||
--FILE-- | ||
<?php | ||
$binary_str = pack("c*", ...array_fill(0, 200, 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I use "C*"
(unsigned char) here instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. Probably, yes.
To match the 0 to 255 range.
maybe once libvips/php-vips-ext#13 is done, we can use that
vips.c
Outdated
for (i = 0; i < arr_len; i++) { | ||
add_next_index_long(return_value, arr[i]); | ||
} | ||
RETVAL_STRINGL((char *)arr, arr_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RETVAL_STRINGL will take a copy of the string, so we need a g_free(arr);
afterwards to avoid a leak (I think).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 2880405.
maybe once libvips/php-vips-ext#13 is done, we can use that
\o/ |
Cool. But I can't figure out how to make imagick read it.
Complains about
No idea, what kind of header it needs, I randomly tried the two at
any pointers? Or is that not supposed to be used for this? (my imagick should be able to read vips images) |
RGBRGB You'd need to use an imagick thing that could wrap an image around a raw byte array. |
Got it working, but maybe not worth the trouble compared to just using tiffsave (but I should benchmark it ;))
(made $image->image public to make the example code easier ;)) |
Very nice! I pasted your code here: https://github.com/jcupitt/php-vips/blob/master/examples/vips-magick.php and it seems to work well! I'll see if I can get it working with some other image types (mono, RGBA, CMYK etc etc). Yes, it has to be 16 bit. IM represents everything internally as whatever your quantum is set to, and you can't change it except by recompiling the whole thing. It's one of the reasons IM is a bit sluggish. IM7 makes you use float (four bytes) everywhere, I think, so it's 2x slower again. |
I tried a benchmark: #!/usr/bin/env php
<?php
require __DIR__ . '/../vendor/autoload.php';
use Jcupitt\Vips;
/* Benchmark passing images from libvips into magick via either an uncompressed
* buffer or a formatted file.
*/
$image = Vips\Image::newFromFile($argv[1]);
// find the image average ... this will force the whole image into memory, so
// we don't time any of the loading
echo "image average: " . $image->avg() . "\n";
// time converting to IM via a memory buffer
$start = microtime(TRUE);
$x = $image->colourspace(Vips\Interpretation::RGB16);
$bin = $x->writeToMemory();
$imagick = new \Imagick();
$imagick->setSize($x->width, $x->height);
$imagick->setFormat("rgb");
$imagick->readImageBlob($bin, "rgb");
$end = microtime(TRUE);
echo "importing into imagick via a memory buffer: " . ($end - $start) . "s\n";
// time converting to IM via a TIFF-formatted memory buffer
$start = microtime(TRUE);
$bin = $x->writeToBuffer(".tif");
$imagick = new \Imagick();
$imagick->readImageBlob($bin);
$end = microtime(TRUE);
echo "importing into imagick via a tiff: " . ($end - $start) . "s\n";
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/ With a 10k x 10k RGB jpg I see:
So memory is maybe 30% faster. |
great, thanks for that. Will then maybe integrate it later |
maybe once libvips/php-vips-ext#13 is done, we can use that
maybe once libvips/php-vips-ext#13 is done, we can use that
maybe once libvips/php-vips-ext#13 is done, we can use that
maybe once libvips/php-vips-ext#13 is done, we can use that
maybe once libvips/php-vips-ext#13 is done, we can use that
maybe once libvips/php-vips-ext#13 is done, we can use that
Implementation of
new_from_memory
/write_to_memory
. It can wrap an image around a memory array and write an image to a memory array.However there seems to be something wrong with the passing thezval
array tovips_image_new_from_memory
because the image average returns random(?) values (vips_image_new_from_memory_copy
doesn't fix this). Therefore I'm not sure whether writing to memory works (how should I test this without doingnew_from_memory
first?).Next week I'll see if I can finish this. I've almost no experience in writing PHP extensions (and in general the C programming language) so my apologies if it takes longer.(I've selected the
Allow edits from maintainers
option that allows you to make commits on this branch)Edit:
All done! 🎉