tags:

views:

40

answers:

4

In the PHP manual for base64_encode() I saw the following script for outputting an image.

<?php

$imgfile = "test.gif";

$handle = fopen($filename, "r");

$imgbinary = fread(fopen($imgfile, "r"), filesize($imgfile));

echo '<img src="data:image/gif;base64,' . base64_encode($imgbinary) . '" />';

?>

But how can you output an image dynamically created with GD?

I've tried this:

$im = imagecreatetruecolor(400, 400);

imagefilledrectangle($im, 0, 0, 200, 200, 0xFF0000);
imagefilledrectangle($im, 200, 0, 400, 200, 0x0000FF);
imagefilledrectangle($im, 0, 200, 200, 400, 0xFFFF00);
imagefilledrectangle($im, 200, 200, 400, 400, 0x00FF00);

echo '<img src="data:image/png;base64,'.base64_encode(imagepng($im)).'" />';

Why doesn't that work?

It seems to work in IE but not Firefox. How can I make it cross-browser?

+1  A: 

Most likely because the data: URI scheme is extremely limited and good to use unless there is absolutely no way around it.

In Internet Explorer, for example, this doesn't work at all until IE 8; and in there, there is a global 32 kilobyte limitation for data: URIs.

Pekka
So your saying do it another way?
Mark
@Mark what do you need data: URIs for in the first place?
Pekka
Captcha experiment. See http://stackoverflow.com/questions/3692969/captcha-encryption
Mark
I need to display it to the user without saving it
Mark
@Mark Why? To emphasize, what you are planning to do will not work at all in Internet Explorer 7. Can you really live with that?
Pekka
Im the author of the other question :P. But how can I do it so that the user can type what they see?
Mark
Is there simply a better way? What would that be
Mark
@Mark I'm still not entirely sure what the core issue is, but many Captcha solutions use the user's session to store data the user is not supposed to see.
Pekka
Would this be what I'm looking for http://www.articlesnatch.com/Article/How-To-Create-Captcha-With-Php/765335
Mark
@Mark maybe (I don't know the article), or something like it. Most CAPTCHA solutions use sessions to transfer their data back and forth.
Pekka
+4  A: 

Ok, sorry, I was thinking too fast :)

imagepng() will output raw data stream directly to the browser, so you must use ob_start() and other output buffering handles to obtain it.

Here you are:

ob_start();
imagepng($yourGdImageHandle);
$output = ob_get_contents();
ob_end_clean();

That is - you need to use $output variable for you base64_encode() function.

Tomasz Kowalczyk
Maybe, but isn't he doing exactly that already?
Pekka
@Tomasz good point! This is it. +1
Pekka
@Mark no, he is right. If it works in IE, then because the `img src` part gets ignored. The raw image will be output to the browser and `base64_encode` does never take place
Pekka
Why downvote? Id certaily DOES what I said - please read my edited comment.
Tomasz Kowalczyk
Please explain with `ob_start()`. How do you use it?
Mark
Ok, edited. If you are satisfied, please accept my answer, if no, ask for more :)
Tomasz Kowalczyk
It answers the question well
Mark
I am happy that you are happy then ;]
Tomasz Kowalczyk
A: 

You have to save your image as a PNG first, and then read from it to get its contents as a value.

http://www.php.net/manual/en/function.imagepng.php

imagepng() does not return the PNG file. It outputs it directly to the browser and then returns a boolean meaning success or failure.

(from php.net:) PHP internally works with a temporary file when sending the image to the browser, so you'll gain nothing by calling imagepng() twice.

Sebastián Grignoli
Well, I don't want to save as an image but...
Mark
You can enclose imagepng() between ob_start() and ob_get_contents(); ob_end_clean(); to get the image, but it uses a temporary file anyway.
Sebastián Grignoli
+2  A: 

Because imagepng outputs bool or image stream directly to output.
So, in order to get image data you should use output buffers like this:

ob_start();
imagepng($im);
$image = ob_get_contents();
ob_end_clean();
echo '<img src="data:image/png;base64,'.base64_encode($image).'" />';
Andrew