I am using PHP to generate images and this works fine. I am having trouble displaying these images however:
My image generator is a PHP file that takes tons of parameters and loads of data to generate the image. Because of the excessive amounts that has to be passed to the generator, using the GET container does not work for me, so the data is sent via a POST request. The result of this request is the raw image data.
I am using
$result = post_request('http://myurl.com/graphx/generator.php', $data);
if($result['status'] == 'ok') {
echo "<img src=\"data:image/png;base64,".
base64_encode($result['content'])."\"/>\n";
}
to display my image. This works for very small images, but as they get bigger (300px*300px for example), the image is not displayed anymore (it seems to be cut somewhere).
Is my approach reasonable?
Is there any workaround for the size issue?
Update:
When I let the generator save the image to a file, the created file contains the image as I want it to be. Also, if convert my generator into a GET-generator, the following code works properly as well:
$data = http_build_query($data);
echo "<img src=\"http://myurl.com/graphx/get_generator.php?{$data}\"/>\n";
So it definitely seems to be a problem with either the POST request, or the conversion into the base64 format. I'm using the POST request as shown here.
I'd suggest having your page be structured like this:
main page:
<img src="imageproxy.php" />
imageproxy.php:
<?php
$result = post_request('http://myurl.com/graphx/generator.php', $data);
header('Content-type: image/png');
if($result['status'] == 'ok') {
echo $result['content']);
} else {
readfile('error_message_image.png');
}
instead of trying to work with data uris and length limits, just have your proxy script output the actual raw image data and treat it as an image in your client-side html.
According to http://en.wikipedia.org/wiki/Data_URI_scheme IE 8 (and presumably below if they support it) "limits data URIs to a maximum length of 32 KB". This could be what you are seeing if it only reads the first 32k of whatever you are sending it.
Why don't you base64 the parameters and put THAT in the GET request, and do a simple:
<img src="/path/to/php.php?p=eyJ0aGlzIjoiaXMiLCJhIjoiYmVhdXRpZnVsIiwic2V0Ijoib2YiLCJwYXJhbWV0ZXJzIjoiISEifQ==" />
Then on the php.php base64_decode($p) and return the image.
Even better on php.php, use X-Sendfile mod of apache (https://tn123.org/mod_xsendfile/) and perhaps cache the image as well locally so that you don't have to recreate it all the time
Edit:
I don't know exactly how many parameters we are talking about here. If you go and see What is the maximum length of a URL in different browsers? you will see that experience has shown that a URI is pretty much around 2000 characters.
So it depends if your base64 encoded string is less that that you are safe. Otherwise you could think of alternative ways of encoding. Perhaps yEnc or base85?
Even further you could do store a serialized object (containing the parameters needed) on a local storage (ie RDBMS), link it with an id and pass that id around. When php.php get's the id, looks it up on the storage retrieves the parameters creates the image and so on.
Related
I need to display an image that is generated by the server. It is generated based on parameters supplied via URL. Problem is, parameters can be very numerous and long and as we know there is a limit to GET request length.
Here is a simplified version of the code:
View:
<img alt="Preview" src="/preview/getPreview/?id=1&page=1&values=%7B%22object_82%22%3A%22Test%22%2C%22object_83%22%3A%22Test2%22%2C%22object_84%22%3A%22Test3%22%7D&size=676">
This is a very short list of parameters there will be much more. As you can see values is actually a JSON stringified array.
The controller part of the code is more or less like this (not sure if it's actually relevant to the question but still here it is):
function getPreview() {
$buffer = createImageFromData($id, $page, $values, false);
$img = new Imagick();
$img->setResolution(300, 300);
$img->readimageblob($buffer);
header("Content-type: image/jpeg");
header("Content-Length: $lenght");
header("Content-Disposition: inline; filename=preview.jpg");
echo $img;
}
So the question is - how to display server generated dynamic images without having to do the src='' part that will simply get too long for some images.
If you have a lot of information that you need to pass to the server. A get request is going to run out of space on older browsers fast: maximum length of HTTP GET request?
What you could do is using javascript, post the information to your server first before you show the image. If you would like to save the data to a database an return an ID that would be a good solution, you can then load the image with:
<img src="/preview/getPreview/?id=312">
If you do not want to save the data you could return a base64 encoded image directly, this isn't supported in < IE8 very well though. A response could look like:
<img src="data:image/gif;base64,R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="alt="Base64 encoded image" width="150" height="150"/>
I mentioned that you should post via javascript so the generation wouldn't have to reload the page. This however is something you do not have to do.
Also - If you are generating the same image over again. We have experienced large page loading times due to the image creation script - So would suggest to cache the image if you can.
Maybe if you update your question to specifically state what your intentions are and what images you are trying create, I could taylor this answer better.
I am using OAuth 1.0, I am getting the contacts just fine. Next I fetch an image using the link that is in the contact info. If the user has an image the request works and return a bunch of data. When I echo it I get something like this:
"" ÿÀ``"ÿÄÿÄ<!"12A#Qq‘BRa3‚’±Ñðbrƒ¡Â$%¢³ÿÄÿÄ#!1Q"AaqÿÚ?ôÌìç™pzõWoÂ~vïD±èÐvQNl/žåÐìMCÀƒÚüü¿ ÔLß÷&‹ðKš×aG¥=Ë È
Which I am assuming is the data for the image. Now that I have this, I cant figure out a way to display it.
here is an example of what I am doing:
$consumer = new OAuth($key,$secret);
$image = $consumer->fetch($theImageUrl);
return $image;
The request is working, theres no 400,401, or 404 errors.
I tried doing this already:
<img src="/art/transperantimage.png" style='background: #fff url(data:image/png;base64,<?=$image ?>) repeat-x bottom'/>
and I just ended up with more data jibberish.
I guess my question is how the heck to I display this data?
Per the documentation, this request returns the bytes of the image. So you have three options:
Write a PHP script that outputs those bytes (and only those bytes) directly to the client using the appropriate Content-Type header, which is what #Prowla has in mind. Then point to this script in your <img src="...">.
Write the bytes to a publicly-accessible file on your web server, and then put the URL of that file in your <img src="...">.
Use a data URI, which you seem to have attempted, but forgot that you need to Base64 encode the data first, e.g.:
<img src="data:image/jpeg;base64,<?php echo base64_encode( $image ); ?>" />
While #3 is looks the simplest, #2 is probably the best solution since the image likely doesn't change very often so there's no sense requesting it from the API every single time someone reloads your page. You can just write the image to a file if the file doesn't already exist, and then periodically (e.g. every day or week) check to see if there is a new image and if there is, overwrite the old one.
Before printing out the image set the header content type to something like (depending on the data type):
header('Content-Type: image/jpeg');
Am trying to create a video clip using .jpg images and ffmpeg, am creating .jpg images as below:
$str=$_REQUEST['data_array'];//gets the base64 encoded image data;
$count =$_REQUEST['count'];//gets number of images i've to create;
$edited_str=substr($str,23,strlen($str)-1);//
$edited_str=base64_decode($edited_str);
$f=fopen("Images/temp".$count.".jpg","w");//am creating temp.jpg file
fwrite($f,$edited_str);//placing my decoded data into file
fclose($f);
are the images am creating above different from normal .jpg images?
This line:
$edited_str=substr($str,23,strlen($str)-1);
makes it different. If this is the full base64 sting of the file, then this cuts it up and corrupts it. Maybe you are adding some stuff on the front.
If you are just removing stuff from the front that was added, then it should be the same as the original file that was encoded with base64.
If you want to get the information this way from another page, I suggest using $_POST as opposed to $_REQUEST for a number of reasons.
EDIT: I wouldn't say video manipulation in php is impossible. I think there is even a toolkit... here's one:
http://phpvideotoolkit.sourceforge.net/
which states:
It can perform video format conversion, extract video frames into separate image files, and assemble a video stream from a set of separate video images.
Haven't tested it, but plan to try it out one day.
EDIT2: On the php site, there were some issues that you could try, but to help more, there needs to be more information. Check with a file directly to make sure it's being sent and decrypted properly.
I haven't got to test any of these yet.
One piece of advice was for large files use:
$decodedstring=base64_decode(chunk_split($encodedstring));
Another was if you use javascript canvas.toDataURL() then you need to convert spaces back to pluses:
$encodedData = str_replace(' ','+',$encodedData);
$decocedData = base64_decode($encodedData);
http://php.net/manual/en/function.base64-decode.php
Ok, I'm hoping I can explain my situation rather than pasting lines and lines of code.
Currently, JSON sends positional info to my PHP file which in turn uses this data to generate an image, saves it and returns the filename via JSON back to browser. Javascript then refreshes the image on screen.
This all works fine at the moment, but I am wanting to optimise the process and look at the possibility of outputting the image file straight after it's created then save afterwards.
My ideal solution would be something like:
header('Content-Type: image/gif');
echo $this->canvas;
// Save user file
$this->canvas->writeImage( $this->userFile = 'user_img.gif' );
$this->canvas->destroy();
// encode everything and send to browser
echo json_encode(array('misc data back to the browser'));
(I still need to send data back to browser via JSON)
And in my HTML I would have the image laid out like this:
<img src='json-processing-script.php' />
But as usual nothing is ever that simple, so I'd like to hear if anyone can make any pointers.
In your example, the json would be added to the gif, messing up your image. If you want to return these two completely different things from your php script, you would have to encode the image, add it to the json and extract it in the javascript to get the source of your image.
See for example this question.
I am trying to display an image from a MySQL blob field. I have tried a few different things and none of them seem to work.
I have tried:
header("Content-type: $type"); img src = $blobData;
header("Content-type: $type"); echo($blobData);
<?php
header("Content-type: $type");
echo $blobData;
?>
This code looks perfectly OK. However, I heard a similar complain from another person and I was able to troubleshoot it by assuring that:
The php script does not output any extra character before or after sending the binary image data.
The php script is saved as a pure ASCII text file, not as a Unicode/UTF-8 encoded file. The Unicode/UTF-8 encoded PHP files might include a signature as the first bytes. These bytes will be invisible in your text editor but server will send these few extra bytes to the browser before the JPEG/GIF/PNG data. The browser will therefore find the wrong signature in the beginning of data. To workaround, create a blank text file in notepad, paste in the php code and save the file in ANSI encoding.
Another option you might consider (assuming you are on Apache):
Create an .htaccess file with a mod_rewrite for all image extensions (png, jpg, gif).
Have it redirect to a php script that looks up the image requested in the DB. If it is there, it echos out the header and BLOG. If it isn't there, it returns a standard 404.
This way you can have:
<img src="adorablepuppy.jpg" />
Which then gets redirected ala:
RewriteEngine on
RewriteRule \.(gif|jpg|png)$ imagelookup.php
This script does a query for the image, which (obviously) assumes that the requested image has a unique key that matches the filename in the URL:
$url = $_SERVER['REQUEST_URI'];
$url_parts = explode("/", $url);
$image_name = array_pop($url_parts);
Now you have just the image filename. Do the query (which I shall leave up to you, along with any validation methods and checks for real files at the address, etc.).
If it comes up with results:
header('Content-type: image/jpeg');
header('Content-Disposition: inline; filename="adorablepuppy.jpg"');
print($image_blog);
otherwise:
header("HTTP/1.0 404 Not Found");
FYI: I have no idea if this would be bad in terms of performance. But it would allow you to do what I think you want, which is output the image as though it were a flat image file on the server using a simple image element. I'm inclined to agree that BLOBs are not the best way to go, but this does avoid any cross-browser issues.
I believe that the issue that you are encountering is an issue with encoding. This resource claims that you can use the print function.
Just get the image from the database. And print it using the correct headers.
$image = mysql_fetch_array(...)
header("Content-type: image/jpeg"); // change it to the right extension
print $image['data'];
For performance reasons... this is not advisable. There are several reasons to put images in databases but the most common are:
a) keeping them indexed (duh!)
You can do this by storing the images flat on the server and just indexing the image filename.
b) keeping the image hidden/protected
Flickr and alike still store the images flat on the server and use a different approach. They generate a URL thats hard to find.
This link points to a protected image on my account. You can still access it once you know the correct URL. Try it!
farm2.static - a farm optimized for delivering static content
1399 - perhaps the server
862145282 - my username
bf83f25865_b - the image
In order to find all my secret images any user can hard hit Flickr with the above address and change the last part. But it would take ages and the user would probably be blocked for hammering the server with thousands of 404s.
That said there is little reason to store images on BLOBs.
Edit:Just a link pointing to someone that explained much better than I did why BLOB is not the way to go when storing images.