Why there is imageCreateFrom* if there is imageCreateFromString? - php

I really can't understand why GD has different function for loading images such like:
imagecreatefromjpeg()
imagecreatefrompng()
imagecreatefromgif()
While there is a single function if the image is string?
imagecreatefromstring()
Indeed it's much better to read the image into the string and pass it to the function, something like:
$imgBlob = file_get_contents($imagePath);
imagecreatefromstring($imageBlob);
unset($imgBlob); //> Free memory, but I am not interested in memory consumpation
? Or I am missing something ? This could led to potential confusion for new users
Maybe they just forgot to create a function imageCreateFromFile()?
Ps. Of course I am not interested about memory consumation using the file_get_contents method

imagecreatefromstring() runs a switch against the passed image type, checks if your system has support for that image type, and then actually runs the correct imagecreatefrom* function.
You can check out the source code to see this: https://github.com/php/php-src/blob/master/ext/gd/gd.c?source=cc (line 2280 for the function, line 2301 where it switches on the image type and calls the correct function).
So, the imagecreatefromstring() function is really just a helper wrapper. You'll get a very slight benefit from not running _php_image_type (line 2217) if you call the actual image type function.

imagecreatefromjpeg()
imagecreatefrompng()
imagecreatefromgif()
create image resource from a file - you pass file path as parameter and that's the only acceptable input.
imagecreatefromstring()
creates image resource from string, not file - it could be virtually anything, you can even type in a content. For example you can use
imagecreatefromstring(base64_decode('R0lGODlhAQABAJAAAP8AAAAAACH5BAUQAAAALAAAAAABAAEAAAICBAEAOw=='));
to get 1x1 pixel transparent gif (useful for tracking gifs)
Granted, you could pass everything through imagecreatefromstring, but it would not be memory efficient - handling large images takes a lot of memory and with low memory limit that makes a huge difference.

Related

Can PHP filesize() method be spoofed with image metadata?

The php filesize() method is used to determine the size of a file in bytes. One example would be to determine the size of an image file. If the method gets its data from an images metadata, is it possible this could be spoofed by modifying the image metadata somehow, or does the method actually calculate file size based on the true contents of the image file?
<?php filesize(); ?>
The function filesize
Returns the size of the file in bytes, or FALSE (and generates an error of level E_WARNING) in case of an error.
http://php.net/manual/en/function.filesize.php
It does not in any way try to interpret image metadata.

Passing image resource to Imagick class on initialization

Would it be possible somehow to pass image resource to Imagick class on initialization instead of passing the file name? For example:
$imageResource = imagecreatefromjpeg('test.jpg');
$imagegickObj = new Imagick($imageResource);
Because I have a class that manipulates images with GD library. And I need some functionality from Imagick class as well. So it would be great that the image once opened
could be passed as a resource even to Imagagick class on init.
Your help would be appreciated.
Short version, no. The resource is just the underlying program data structure that GD uses to store the image while it is memory. There is no way to pass this directly to Imagick to have it open it as an image.
Theoretically you could output it is as a PNG using the imagepng() function, capture it with an output buffer, and then feed it to Imagick, however this would be a bit silly. You'd almost certainly be better off by just writing it to a temp PNG* file and then re-reading it. Or converting your current library to use Imagick everywhere.
*Don't use JPEG for this - you will lose image quality as it is a lossy format.

separating image tag from image resizing

I currently have a function in PHP called img(), that takes at least two arguments, as such:
print img("foo.jpg", 100);
That would return something like this:
<img src='/cache/foo_XXXXX.jpg' width='100' height='76' />
So, the function takes the arguments, resize the original file and save it as a cached file on the server and return the image tag. Obviously, if the cached version already exists, it just returns it and saves the processing for the next time.
Now, this works perfectly in 99 cases out of 100, but for some sites there are pages which are quite image-heavy, and since the cached versions of the image is expired after X number of days, the img() functions needs to recreate 50+ high resolution images to small thumbnails, and loading such a page takes several seconds and that's not acceptable.
So my idea is to separate this. So doing this:
print img("foo.jpg", 100);
would return this:
<img src='img.php?ARGUMENTS' width='?' height='?' />
Which means that the img() function doesn't actually handle the file at all, but rather output HTML that tells the browser to get the image from a PHP script rather than a static image file on the server.
Now, the "ARGUMENT" part would of course contain all the information that img.php needs to deal with the file in the same way that img() has dealt with it - perhaps a serialized string version of all the arguments to the function?
But the problem is the width/height values of the image tag! Since processing is moved outside the scope of the current script, it has no idea how large the resulting image would be, right? I obviously can't wait for img.php to complete and return it. I am using imagemagick for the processing (so the second argument can be 100, "50%", "<40" and whatnot) and perhaps there is a way to "dryrun" it with imagemagick - i.e. having imagemagick return the resulting size of a specific file using a specific command?
How would you solve this?
You have the list of all images somewhere in database, right? You can add the fields for width and height and calculate scaled width and height while generating HTML. You could also add thumbnails width and height into database as well.

working with image from imagecreatefromstring PHP

So i have an iphone app that that uploads an image to my webserver and i looked around and people seem to be doing something like
$data = file_get_contents($_FILES['file']['tmp_name']);
$image = imagecreatefromstring($data);
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
I looked at the php docs, but i still don't understand what the header() does; does it convert the image into whatever format i want?
And for the imagepng(), where is the image outputted to? memory? is that why i need the imagedestroy()?
and where would i put in
move_uploaded_file()
Thanks in advance!
This code is intended to return as output an image - you could use it as a valid src for an image tag. That is, you could do this:
<img src="thatfile.php?something=1" />
The headers tell the browser that the data the server is going to send is an image (a PNG image, specifically).
In your example code, the file never actually gets written anywhere: the data stays in memory until the script ends, then it is simply "forgotten". imagedestroy frees up the memory and is good practice, but it really isn't necessary since the memory will be garbage collected after the request ends. If you want to preserve the image in a file, you'd have to use one of the related functions such as imagepng: http://www.php.net/manual/en/function.imagepng.php. The only difference between writing the file or not in your example code is the lack of a second argument for imagepng - second argument would be the desired file path.
It would help to read through the docs on this entire subject to gain a firm grasp of how these functions work and what each does. There are plenty of demos on the doc pages that show this in action.
This particular example gets the image uploaded through POST from the $_FILES array and simply outputs it back to the browser. The header is there to inform the browser that the content following is a PNG image.
Since you create an image from a string, it doesn't have "an extension". It's just an image resource at this point. You can create an actual file from it using imagepng, imagejpeg or any of the other methods to save an image resource to a file. You decide the extension (and file name) at that stage yourself.
E.g.:
imagepng($image, 'path/to/file.png');
and where would i put in move_uploaded_file()?
You wouldn't, since you don't have an uploaded file, only a string.
Header is purely for the server to let the browser know "Oh hey this is a png image please render it so"
imagepng encodes it into the png format and "prints" to the output
imagedestroy frees the memory taken by the image resource.
If you need to force extension you can use mod_rewrite
Here's a sample couple lines from my .htaccess:
RewriteEngine on
RewriteRule images/000000/00FF00/newmyinfo.jpg images/newmyinfo.php?bgcolor=000000&color=00ff00 [L]
Hope this helps!

Estimate required memory for libGD operation

Before attempting to resize an image in PHP using libGD, I'd like to check if there's enough memory available to do the operation, because an "out of memory" completely kills the PHP process and can't be catched.
My idea was that I'd need 4 byte of memory for each pixel (RGBA) in the original and in the new image:
// check available memory
if(!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))){
return false;
}
Tests showed that this much more memory than the library really seem to use. Can anyone suggest a better method?
You should check this comment out, and also this one.
I imagine it must be possible to find out GD's peak memory usage by analyzing imagecopyresampled's source code, but this may be hard, require extended profiling, vary from version to version, and be generally unreliable.
Depending on your situation, a different approach comes to mind: When resizing an image, call another PHP script on the same server, but using http:
$file = urlencode("/path/to/file");
$result = file_get_contents("http://example.com/dir/canary.php?file=$file&width=1000&height=2000");
(sanitizing the file parameter, obviously)
If that script fails with an "out of memory" error, you'll know the image is too large.
If it successfully manages to resize the image, it could return the path to a temporary file containing the resize result. Things would go ahead normally from there.

Categories