I have a .php file that's supposed to load an image for display in an img tag(i.e., <img src="the_file.php?which=0"/>). It looks like this:
<?php
ob_clean();
header("Content-type: image/png");
include_once("util.php");
//Do a simple calculation to get $name from (int)$_GET["which"];
$im = imagecreatefrompng("protected_directory/".$name.".png");
imagepng($im,NULL,0,NULL);
imagedestroy($im);
ob_end_flush();
?>
It works correctly, but the image loads substantially slower than just loading it directly(i.e. <img src="protected_directory/the_name.png"/>, where "the_name" was calculated the same way as in the PHP file, but I can't just do this because the protected_directory isn't world readable).
My question is, why is this suddenly so much slower? It's not a large image, but nor is it terribly small.
If you're just displaying an existing file, use readfile() to output it to the browser. There's no need to go through all the overhead of creating an editable GD object for this.
imagepng is known to be slow, if you need to output images with a PHP script, use code like this:
$filename = md5(time() . mk_rand());
imagepng($im, $filename);
echo file_get_contents($filename);
As another answer, I figured out that you can use the third parameter to compress the image (PNG uses zlib). Setting it to 9 works about as well as the other solutions.
Related
This seems like a SUPER easy question for people who knows PHP but I can't figure out how to make this work (probably because I know VERY little about PHP). Most question related to this asks how to output an image to either browser or disk, but I wanna do both. See example below:
<?php
header('Content-type: image/png');
$filename = "my_written_image.png";
$png_image = imagecreatefrompng('some_fancy_image.png');
imagepng($png_image, $filename);
imagepng($png_image);
?>
This won't work. The image won't show in the browser, but it will work if I remove this line: imagepng($png_image, $filename);
I'm guessing one can only "output" one thing using imagepng but how will I accomplish the above?
You should use the following code:
<?php
header('Content-type: image/png');
$filename = "my_written_image.png";
$png_image = imagecreatefrompng('some_fancy_image.png');
file_put_contents($filename, $image);
imagepng($png_image, $filename);
?>
My server is not turned on so I can't test the code but I think this should work.
Okay it seems my original solution actually did work. The problem was I was using (in my real code): if(readfile("myfile.png")) and this will return false if it's not found, but it will also throw an error if #readfile() is not used (note the #). The docs said:
an error message is printed
I didn't think this would cause the whole thing to fail. Sorry for my stupidness.
Trying to see what actions can be performed with a PHP script that is being called via an image src like so:
<img src="http://example.com/script.php" />
Now, I have tried to include the PHP header() function in script.php:
<?php
header("Location: http://example.com");
I have also tried to echo an image url expecting the img to display it, which it didn't:
<?php
echo 'http://example.com/image.png';
Are there any ways of doing such things with a PHP script that is being called in the img src attribute?
Are there any ways of doing such things with a PHP script that is being called in the img src attribute?
No. A resource that is used as a src for an img tag needs to output image data, nothing else.
There are some exceptions, eg. a header("location: ....") redirect, but the redirect needs to point to another valid image resource, not a web site as you show in your example.
Check out the readfile() as a way to output your image file from your script.php
readfile($file);
Read more about it here in the manual:
http://php.net/manual/en/function.readfile.php
where Example #1 gives an idea of how to set up the headers.
The manual also states that:
readfile() will not present any memory issues, even when sending large
files, on its own.
and
A URL can be used as a filename with this function
ps: This was the way Wordpress Multisite used to open user uploaded (e.g. images) files.
Your script.php should return the output of an image with the correct headers. For instance:
<img src="/html/img/script.php" />
// Script.php
$file = "tiger.jpeg";
$type = "image/jpeg";
header("Content-Type: $type");
header("Content-Length: " . filesize($file));
readfile($file);
You should keep in mind that the src tag should directly point to an image file. However, it is possible to use PHP to create an image, for exmaple by using the GD library:
http://php.net/manual/en/book.image.php
So using:
<img src="http://example.com/script.php" />
is possible, as long as script.php really outputs an image file, for example by using the example as described here:
http://www.php.net/manual/en/image.examples-png.php
I used this kind of processing in the past to overlay texts on JPG images for a broker website (e.g. new, sold, for rent, etc.).
Are there any ways of doing such things with a PHP script that is being called in the img src attribute?
Yes, but the PHP Script has to output image data only, as stated in various other answers.
With that being said, just read the image and output it to the stream with readfile
header('Content-Type: image/png');
readfile($file);
exit();
I know I might be a couple years late to really help you, but the accepted answer just isn't true (anymore).
I am simply trying to return an PNG image through PHP, but I have a problem with the transparency not showing right. (Basically one PHP file will be capable of returning any of my images.)
I use simple code to return the image:
<?php
$im = imagecreatefrompng("images/fakehairsalon.png");
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>
The original image looks like this:
And the one returned via PHP (and that piece of code) looks like this:
Is there anything I can do to prevent this and make the image come through normal?
As explained in a user comment, you must do this:
<?php
$im = imagecreatefrompng("borrame.png");
header('Content-Type: image/png');
imagealphablending($im, true); // setting alpha blending on
imagesavealpha($im, true); // save alphablending setting (important)
imagepng($im);
imagedestroy($im);
?>
Update: This answer was assuming that your code is an except from a bigger script you are using to do on-the-fly image manipulation.
If you don't want to change the original file, this is a plain waste of memory and CPU cycles. You can use file system functions to read it as a regular file, such as readfile().
It's also worth noting that using PHP to deliver a file only makes sense if you want to do something else as well, such as:
Restricting access to the file
Keeping a counter
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!
I'm building a basic analytics service, based in theory off of how Google Analytics works, but instead of requesting an actual image, I'm routing the image request to a script that accepts the data and then outputs an image. Since browsers will be requesting this image on every load, every millisecond counts.
I'm looking for the most efficient way for a file to output a gif file from a PHP script. So far, I've established 3 main methods.
Is there a more efficient way for me output a 1x1 GIF file from within a PHP script? If not, which of these is the most efficient and scalable?
Three Identified Methods
PHP image building libraries
$im = imagecreatetruecolor(1, 1);
imagefilledrectangle($im, 0, 0, 0, 0, 0xFb6b6F);
header('Content-Type: image/gif');
imagegif($im);
imagedestroy($im);
file_get_contents the image off of the server and output it
$im = file_get_contents('raw.gif');
header('Content-Type: image/gif');
echo $im;
base64_decode the image
header('Content-Type: image/gif');
echo base64_decode("R0lGODdhAQABAIAAAPxqbAAAACwAAAAAAQABAAACAkQBADs=");
(My gut was that base64 would be fastest, but I have no idea how resource intensive that function is; and that file_get_contents would likely scale less well, since it adds another file-system action.)
For reference, the GIF I'm using is here: http://i.stack.imgur.com/LQ1CR.gif
EDIT
So, the reason I'm serving this image is that my analytics library builds a query string and attaches it to this image request. Rather than parse logs, I'm routing the request to a PHP script which processes the data and responds with an image,so that the end user's browser doesn't hang or throw an error. My question is, how do I best serve that image within the confines of a script?
maybe
header('Content-Type: image/gif');
//equivalent to readfile('pixel.gif')
echo "\x47\x49\x46\x38\x37\x61\x1\x0\x1\x0\x80\x0\x0\xfc\x6a\x6c\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
That will output a binary string identical to the binary file contents of a 1x1 transparent gif. I'm claiming this as efficient based on the grounds that it doesn't do any slow IO such as reading a file, nor do I call any functions.
If you want to make your own version of the above hex string, perhaps so that you can change the color, you can use this to generate the php code for the echo statement.
printf('echo "%s";', preg_replace_callback('/./s', function ($matches) {
return '\x' . dechex(ord($matches[0]));
}, file_get_contents('https://upload.wikimedia.org/wikipedia/en/d/d0/Clear.gif')));
header('Content-Type: image/gif');
header("Content-Length: " . filesize("image.gif"));
$f = fopen('image.gif', 'rb');
fpassthru($f);
fclose($f);
Probably would be fastest for image from disk, but (especially if you're using bytecode caching) for a small images known in advance the base64 way will be the fastest I think. Sending Content-Length might be a good idea too, for the small image the browser would in most cases not wait for anything after receiving the bytes so while your server would take as much time, use experience will be sightly better.
Another way would be to let Apache/lighttpd/nginx serve the image, log the access and the parse it offline.
With Laravel:
$pixel = "\x47\x49\x46\x38\x39\x61\x1\x0\x1\x0\x80\x0\x0\xff\xff\xff\x0\x0\x0\x21\xf9\x4\x1\x0\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
return response($pixel,200,[
'Content-Type' => 'image/gif',
'Content-Length' => strlen($pixel),
]);
If anyone wants that for some reason.
Alternatively, if you don't like long(ish) hex strings in your code:
base64_decode('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw')
Instead of dynamically generating/outputting an image, why not just redirect to a static image?
<?php
// process query param stuff
header('Location: pixel.gif');
exit();
?>