11

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?

Mark Lalor
  • 7,820
  • 18
  • 67
  • 106
  • No, firefox. Hmm, it works in IE... – Mark Lalor Sep 12 '10 at 13:54
  • 3
    Do you have a real need to use data: URIs? Because if you don't, it's better not to use them. They have an awful lot of downsides. IE < 8 doesn't support them at all, for example. – Pekka Sep 12 '10 at 13:57
  • *(related)* http://stackoverflow.com/questions/3385982/the-image-cannot-be-displayed-because-it-contains-errors/3386050#3386050 – Gordon Sep 12 '10 at 14:07

4 Answers4

18

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
  • 10,472
  • 6
  • 52
  • 68
11

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
  • 8,330
  • 11
  • 45
  • 78
1

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
  • 442,112
  • 142
  • 972
  • 1,088
0

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
  • 32,444
  • 17
  • 71
  • 86