2

I have a large string of base64 image data (about 200K). When I try to convert that data by outputting the decoded data with the correct header, the script dies, as if there isn't enough memory. I get no error in my Apache logs. The example code I have below works with small images. How can I decode a large image?

<?php
// function to display the image

function display_img($imgcode,$type) {  
     header('Content-type: image/'.$type);   
     header('Content-length: '.strlen($imgcode));   
     echo base64_decode($imgcode);  
}

$imgcode = file_get_contents("image.txt");  

// show the image directly  
display_img($imgcode,'jpg');

?>
zvineyard
  • 221
  • 3
  • 7

4 Answers4

1

Since base64-encoded data is cleanly separated every 4 bytes (i.e. 3 bytes of plaintext are encoded into 4 bytes of base64-encoded text), you could split your b64 string into multiples of 4 bytes, and process them separately:

while (not at end of string) {
   take next 4096 bytes // for example - 4096 is 2^12, therefore a multiple of 4
   // you could use much larger blocks, depends on your memory limits
   base64-decode them
   append the decoded result to a file, or a string, or send it to the output
}

If you have a valid base64 string, this will work identically to decoding it all at once.

Piskvor left the building
  • 91,498
  • 46
  • 177
  • 222
1

OK, here is a closer resolution. While this seems to decode the base64 data in smaller chunks, I still don't get an image in the browser. If I echo the data before I place a header, I get output. Again, this works with a small image but not a large one. Thoughts?

<?php
// function to display the image
function display_img($file,$type) {
    $src = fopen($file, 'r');
    $data = "";
    while(!feof($src)) {
        $data .= base64_decode(fread($src, 4096));
    }
    $length = strlen($data);
    header('Content-type: image/'.$type);
    header('Content-length: '.$length);
    echo $data;
}

// show the image directly
display_img('image.txt','jpg');
?>
zvineyard
  • 221
  • 3
  • 7
  • That looks okay. You may want to calculate the image length beforehand (IIRC `4 / 3 * $encoded_length`), and echo the decoded data as you receive it, instead of buffering into `$data`. – Piskvor left the building Mar 22 '11 at 16:12
  • Good point. I patched the script with the changes you recommend, but I still don't get an image. I can only think that my base64 string must be invalid. What do you think? – zvineyard Mar 22 '11 at 16:17
  • I'm getting my base64 data from the web with post. Does it need to be urlencoded? – zvineyard Mar 22 '11 at 16:30
  • Try to base64-decode it with a different method/language (see e.g. this: http://stackoverflow.com/questions/5242319/what-does-this-mean-image-pngbase64 ), it is possible that the source data is invalid. Also, base64 doesn't need urlencoding, as it is itself a mechanism against data mangling. – Piskvor left the building Mar 22 '11 at 16:31
0

Content-length must specify the actual (decoded) content length not the length of the base64 encoded data.

Though I'm not sure that fixing it would solve this problem...

Imi Borbas
  • 3,683
  • 1
  • 19
  • 16
-1

Save the base64 string to an image file using imagejpeg() or the correct function for the different formats, and then display the image with a simple <img> tag.