How can I make these images load faster? I have a loop that displays a profiles pictures and the photos take 1 to 2.5 seconds to load. Not one after another but pretty much all at once. I tried re-sizing with PHP but that didn't really change anything. I am not sure how I can pre-load these images with such a loop. What can I do to increase load performance?
PHP
$query = "SELECT `photoid` FROM `site`.`photos` WHERE `profileid`='$profileid'";
try{
$getphotos = $connect->prepare($query);
$getphotos->execute();
while ($array = $getphotos->fetch(PDO::FETCH_ASSOC)){
echo '<div id="photo"><img src="photoprocess.php?photo='.$array['photoid'].'"></div>';
}
} catch (PDOException $e) {
echo $e->getMessage();
}
CSS
#photo img {
max-width:100%;
max-height:100%;
}
photoprocess.php
$photoid = $_GET['photo'];
$query = "SELECT `ext` FROM `site`.`photos` WHERE `photoid`='$photoid'";
try{
$getphotos = $connect->prepare($query);
$getphotos->execute();
$array = $getphotos->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo $e->getMessage();
}
$ext = $array['ext'];
$image = imagecreatefromjpeg('userphotos/'.$photoid.''.$ext.'');
$imagearray = imagejpeg($image, null);
header('Content-type: image/jpeg');
echo $imagearray;
I also have extension checks as "if statements" but those can't be slowing it down this much.
This part
$image = imagecreatefromjpeg('userphotos/'.$photoid.''.$ext.'');
$imagearray = imagejpeg($image, null);
shouldn't be necessary* and is going to be heavy on the server. You're loading (decoding) and saving (re-encoding) the image for no apparent reason.
Use something like fpasshtru():
$name = 'userphotos/'.$photoid.''.$ext.'';
$fp = fopen($name, 'rb');
header('Content-type: image/jpeg');
fpassthru($fp);
Or just link directly to the image. Unless you do some security checks or something, or the images are stored outside the web root, there is no need to go through PHP at all here.
* = unless you have a very specific use case like removing EXIF data from the stored images. In which case you should use some form of caching.
Currently, you are loading image data from disk into an image buffer, which is validated by PHP. After that, you re-encode the image data to a jpg image buffer again and output it.
This is useless. You can just load an thruput the file (read about fpassthru). This is also much more memory efficient, since the image doesn't need to be entrely loaded in memory entirely at once.
That will be way, way faster, but it can be faster still, because I think you can use just .htaccess to redirect an url with an image id to the actual image. You don't even need PHP for that.
Related
i am trying to learn how to cache an image that is created in PHP, this current piece of PHP wil cache text to a file, but i want to get it to cache an image called 'my_barcode.png' to the cache folder, any help would be greatly appreciated.
<?php
$h = opendir('data/');
$chace = 'cache/test.cache.php';
if(file_exists($chace))
{
include($chace);
}
else
{
$result = NULL;
while (($file = readdir($h)) !=false)
{
$result .= $file. '<br />';
}
closedir($h);
echo $result;
$fs = fopen($chace, 'w+');
fwrite($fs, $result);
fclose($fs);
}
?>
If the purpose is to serve cached files, PHP should create them when not existing but the http server (such as Apache) should be serving the static files if they exist. Implementing cache the way you did takes too many resources as PHP is still called.
I want to rotate an uploaded and retrieved image from one location. Yes i am almost done. But the problem is, due to header("content-type: image/jpeg") the page redirected to another/or image format. I want to display it in same page as original image in. Here my code..
$imgnames="upload/".$_SESSION["img"];
header("content-type: image/jpeg");
$source=imagecreatefromjpeg($imgnames);
$rotate=imagerotate($source,$degree,0);
imagejpeg($rotate);
i also did with css property.
echo "<img src='$imgnames' style='image-orientation:".$degree."deg;' />";
But anyway my task is to done only with php. Please guide me, or give any reference you have
thanks advance.
<?php
// Okay, so in your upload page
$imgName = "upload/".$_SESSION["img"];
$source=imagecreatefromjpeg($imgName);
$rotate=imagerotate($source, $degree,0);
// you generate a PHP uniqid,
$uniqid = uniqid();
// and use it to store the image
$rotImage = "upload/".$uniqid.".jpg";
// using imagejpeg to save to a file;
imagejpeg($rotate, $rotImage, $quality = 75);
// then just output a html containing ` <img src="UniqueId.000.jpg" />`
// and another img tag with the other file.
print <<<IMAGES
<img src="$imgName" />
<img src="$rotName" />
IMAGES;
// The browser will do the rest.
?>
UPDATE
Actually, while uniqid() usually works, we want to use uniqid() to create a file. That's a specialized usage for which there exists a better function, tempnam().
Yet, tempnam() does not allow a custom extension to be specified, and many browsers would balk at downloading a JPEG file called "foo" instead of "foo.jpg".
To be more sure that there will not be two identical unique names we can use
$uniqid = uniqid('', true);
adding the "true" parameter to have a longer name with more entropy.
Otherwise we need a more flexible function that will check if a unique name already exists and, if so, generate another: instead of
$uniqid = uniqid();
$rotImage = "upload/".$uniqid.".jpg";
we use
$rotImage = uniqueFile("upload/*.jpg");
where uniqueFile() is
function uniqueFile($template, $more = false) {
for ($retries = 0; $retries < 3; $retries++) {
$testfile = preg_replace_callback(
'#\\*#', // replace asterisks
function() use($more) {
return uniqid('', $more); // with unique strings
},
$template // throughout the template
);
if (file_exists($testfile)) {
continue;
}
// We don't want to return a filename if it has few chances of being usable
if (!is_writeable($dir = dirname($testfile))) {
trigger_error("Cannot create unique files in {$dir}", E_USER_ERROR);
}
return $testfile;
}
// If it doesn't work after three retries, something is seriously broken.
trigger_error("Cannot create unique file {$template}", E_USER_ERROR);
}
You need to generate the image separately - something like <img src="path/to/image.php?id=123">. Trying to use it as a variable like that isn't going to work.
In my project I have a code for downloading images from a server. In php code I have:
if (is_dir($dir)){ //check if is directory
$files = scandir($dir); //list files
$i=-1;
$result = array();
foreach($files as $file){
$file = $dir.$file; //complete dir of file
if(is_file($file)){ //if it's a file
$i++;
$fileo = #fopen($file,"rb"); //open and write it on $result[$i]
if ($fileo) {
$result[$i] = "";
while(!feof($fileo)) {
$result[$i] .= fread($fileo, 1024*8);
flush();
if (connection_status()!=0) {
#fclose($fileo);
die();
}
}
$result[$i] = utf8_encode($result[$i]); //This prevents null returning on jsonencode
#fclose($fileo);
}
}
}
}else{
echo json_encode(array('Error'));
}
echo json_encode($result); //returns images as an array of strings, each one with all code of an image.
And in java I have an httpost method with asynctask. The problem of this is that I need to wait until all images are downloaded. I have thought that maybe I can download an image with a number and if the number is 0 for example recall to the server to download the next image but I think that maybe is a waste of time calling again the server and listing files again. Is there a better way so I can download image per image instead of all at the same time without calling N times to the sever?
I've had the same problem that you are having, and my solution was the next:
1º Download all data you need
2º Download to the computer the image web direction
3º Execute an asynctask per Image to download it and update your Activity while is needed
Maybe i'm not so exact and i would need some more details to give a better solution.
Having big time problems in displaying an image out of my mysql database
I'm storing it in a longblob type
when the image is displayed i get a broken image icon
here is code for storing image
if(isset($_FILES['image']) && $_FILES['image']['size'] > 0 && isset($_POST['photoName']))
{
//temporary file name
// Temporary file name stored on the server
$tmpName = $_FILES['image']['tmp_name'];
$imageType = $_FILES['image']['type'];
// Read the file
$fp = fopen($tmpName, 'r');
$data = fread($fp, filesize($tmpName));
$data = addslashes($data);
fclose($fp);
$sql="INSERT INTO photos (photoName, caption, photoData, photoType, userName)
VALUES
('$_POST[photoName]','$_POST[caption]','$tmpName','$imageType', '$currentUser')";
//For debugging purposes
if(!mysqli_query($con,$sql))
{
die('Error: ' . mysqli_error($con));
}
else
{
echo "Your Image has been Added";
}
}
then printing the image
if(isset($_POST['usersImage'])){
//code to show images
$user = $_POST['usersImage'];
$sql = "SELECT * FROM `photos` WHERE userName = '$user'";
$result = mysqli_query($con,$sql);
while($row = mysqli_fetch_array($result))
{
switch ($row['photoType']) {
case 'image/jpeg':
echo "<tr>";
echo '<img src="data:image/jpeg;base64,'. base64_encode($row['photoData'])."\"></td>";
echo "</tr>";
//echo '<img src="image>' .$row['photoData']. '.jpeg'.'</p>';
//echo '<p id="caption">'.$row['caption'].' </p>';
break;
}
}
}
as you can see my latest attempt was to use base64 encoding to print out the image
my previous try was the commented out code
When you display the image it has to be from its own request. src="" should contain a url to a script that will deliver the content with the correct MIME header image/jpeg.
<?php
$photo_bin = //binary data from query here;
header("Content-Type: image/jpeg"); // or whatever the correct content type is.
echo $photo_bin;
Quick example^ of a php script that can be requested by the browser from an img tag.
Validation is important. You are opening yourself up to so many security issues.
Never use $_POST / $_GET inside a sql statement. Escape them, better yet, use PDO statements. Validate that the image is actually an image, at this point, you could be entering any type of file into your table.
As you're finding, it's also far more difficult to store images in a database than on the filesystem. Usually, there are far more arguments to store the image on the filesystem than inside a table.
Having a quick look down your insertion code, I'm not quite sure why you're adding slashes to the binary data. remove the call to addslahes, and try that.
I want a PHP to be able to send 1 of 3 images, depending on a $_GET[] parameter. I have the images as three separate PNGs right now, and would like the PHP script to have those embedded in it, then return the specified image. So, I want one PHP script instead of 3 images. Is this possible? I don't need to create special images on the fly, just print out one of those. Thanks!
If your images are in files, use PHP's readfile() function, and send a content-type header before outputting it:
<?php
$imagePaths = array(
'1' => 'file1.png',
'2' => 'file2.png',
'3' => 'file3.png',
);
$type = $_GET['img'];
if ( isset($imagePaths[$type]) ) {
$imagePath = $imagePaths[$type];
header('Content-Type: image/png');
readfile($imagePath);
} else {
header('HTTP/1.1 404 File Not Found');
echo 'File not found.';
}
?>
EDIT:
You could also embed your images in the script by encoding them e.g. as Base64, then embed them as strings in PHP, then decode it there with base64_decode to deliver them:
<?php
$imageData = array(
'1' => '...', // Base64-encoded data as string
...
);
$type = $_GET['img'];
if ( isset($imageData[$type]) ) {
header('Content-Type: image/png');
echo base64_decode($imageData[$type]);
} else {
header('HTTP/1.1 404 File Not Found');
echo 'File not found.';
}
?>
You could also use PHP to encode the image on the command line. Just execute this PHP script in the command line (php script.php image1.png image2.png image3.png > output.php) and save its output, and incorporate it into your script:
<?php
$imageData = array();
foreach ($argv as $index => $imagePath)
$imageData[(string)($index + 1)] = base64_encode(file_get_contents($imagePath));
echo '$imageData = '.var_export($imageData, true).';';
?>
I have not tested the following, but it should work. Use this script to get PHP code that will contain the image data.
To get the image:
$image = base64_encode(file_get_contents("image.png"));
// The string $image now contains your image data.
Get this (potentially big) string in your code where you want the image, for each image. Print it and copy it then paste it. Import it as a text file over the web. That's up to you.
Then, to print the image (only the image as if the PHP script were the image), do:
header("content-type: image/png");
print base64_decode($image);
Of course, you would put each image data in an array or something like that.
Let me know if it works.
Yes, it's possible.
Do this:
Write a php script deciding which image to output.
Set the appropriate headers with header() function (I.e. Content-type)
Open the file, read it and send it to the output stream.
Remember that you will probably lose any benefits from browser's cache with this approach...
A fast but not really secure nor elegant way to do it...
<?php
switch($_GET['type']){
case "1":
$image = "image1.png";
break;
case "2":
$image = "image2.png";
break;
case "3":
$image = "image3.png";
break;
}
header('Content-Type: image/png');
readfile($image);
?>
the moral of the story: use header() and readfile() =D