Get remote image with PHP and show it with GD - php

I have a code in my website to show remote Gravatar portraits or uploaded images. Uploaded is ok, but i can't get the gravatar images.
Cant use file_get_contents because it´s not allowed on my host.
Heres the start check for the file
if(file_exists($arUser['imagem'][0])){
$imgPath = $arUser['imagem'][0]; //Usar a imagem enviada
}elseif(!strlen($arUser['imagem'][0]) && checkRemoteFile('http://www.gravatar.com/avatar/'.md5($arUser['email'][0]).'fs=150')){
$imgPath = 'http://www.gravatar.com/avatar/'.md5($arUser['email'][0]).'fs=150';
}else
$imgPath = '../img/social_noavatar_150.jpg'; //Temporario
So this doesn´t work:
$imgData = getimagesize($imgPath);
$src = imagecreatefromwhatever($imgPath);
I know I should replace:
$imgPath = 'http://www.gravatar.com/avatar/'.md5($arUser['email'][0]).'fs=150';
with something like:
$imgPath = GetFileData('http://www.gravatar.com/avatar/'.md5($arUser['email'][0]).'fs=150');
or
*$imgPath = file_get_contents('http://www.gravatar.com/avatar/'.md5($arUser['email'][0]).'fs=150');*
Got error with both and I can´t create the image:
I´ve searched for the answer but the others didn't fited to me.
Sorry for my bad english. :(
Note:
function imagecreatefromwhatever($image){
$info = pathinfo($image);
$extension = strtolower($info['extension']);
switch($extension) {
case "jpg":
return imagecreatefromjpeg($image);
break;
case "jpeg":
return imagecreatefromjpeg($image);
break;
case "png":
return imagecreatefrompng($image);
break;
case "gif":
return imagecreatefromgif($image);
break;
default:
return imagecreatefromjpeg($image);
}
}

Well, if file_get_content is not available on your host, you might be out of luck. If this is a security feature on your host then you won't find a single function that allows you to get data from another server.
You might want to simply bypass the function and set your image src url to the gravatar one. Something like :
<img src="http://www.gravatar.com/avatar/<?=md5($arUser['email'][0]);?>&fs=150" width="150"/>
(Please double check the url, I added a & before the fs as it makes more sense, but I don't know how gravatar api url looks like)
This way it is the client browser that will make the request and not your server.

The easiest way I have found is to transfer the location:
if(checkRemoteFile('http://www.gravatar.com/avatar/'.md5($arUser['email'][0])))
header('Location: http://www.gravatar.com/avatar/'.md5($arUser['email'][0]).'fs='.$sizePic);

If your PHP security on your server prevents remote grabbing of files via file_get_contents(), then your next best option is a CURL call to get the file contents fed in perhaps.

If your host doesn't allow file_get_contents it's likely other methods will not work. From my experience the hosts will prevent any external socket connections from script. So check with the host first.
Assuming that is the issue, you could still echo out an tag with the src attribute to the same location you're trying to get in script.
<img src="<?php echo('http://www.gravatar.com/avatar/'.md5($arUser['email'][0]).'fs=150');?>" />
You could also use the same trick to put the url into a style if you don't want to use the tag.

Related

Show image from other domain without showing the domain name - PHP

I want to show an image on my website but not want to save in on my hosting.
I want to show it something like this:
<img src="https://example.com/img/pic.jpg">
or
<img src="https://example.com/img/image.php?img=pic.jpg">
Instead of:
<img src="https://example.org/img/pic.php">
I have tried using PHP file_get_contents() and CURL etc but none of that works.
This below codes have worked which convert image from URL to data:image but it takes too much time to load.
$url = 'https://otherdomain.com/img/'.$_GET['img'];
$allow = ['gif', 'jpg', 'png']; // allowed extensions
$img = file_get_contents($url);
$url_info = pathinfo($url);
// if allowed extension
if(in_array($url_info['extension'], $allow)) {
// Format the image to data:image : data:{mime};base64,{img_data_base64};
$re = 'data:image/'. $url_info['extension'] .';base64,'. base64_encode($img);
}
else $re = 'Invalid extension: '. $url_info['extension'];
header('Content-Type: application/json');
echo json_encode($src); // output $re data
I want proper URL format as I have mentioned above(https://example.com/img/image.php?img=pic.jpg) without saving image on my server.
NOTE: Here https://example.com is my domain but https://example.org is not.
Thanks
You can try this,
Your php page url - https://example.com/img.php?img=abc.png;
img.php code (You can change image path or url as per you)
think image url https://picsum.photos/id/666/536/354 as another domain https://example.org in your case
header('Content-Type: image/png');
readfile('https://picsum.photos/id/666/536/354');

What should I do to make specific images show for certain file extension types?

I'm trying to implement a php, mySQL Admin panel/dashboard which shows a small preview image of the file that has been uploaded, if the file is not a jpg, jpeg, png or gif then I would like to display a placeholder image.
So for example if the uploaded file is actually a jpg, the preview column in the table would show the image associated to the file name stored in the db (this I have working) but if it's a pdf then it should show a stock/filler/predefined image of my choosing.
I'm hoping to do this in php but have very limited knowledge in this area with this project being my first large php project.
I have tried to implement this functionality using a js/jquery switch but have had no such luck, Code for the last attempt included below:
$(document).ready(function() {
var fileName, fileExtension;
fileName = event.target.innerHTML;
fileExtension = fileName.replace(/^.*\./, '');
switch (fileExtension) {
case 'png': case 'jpeg': case 'jpg':
$('#tableImg').attr("src","<?php echo $row["fileName"]; ?>");
break;
case 'zip':
$('#tableImg').attr("src","images/pdf.png");
break;
case 'pdf':
$('#tableImg').attr("src","images/pdf.png");
break;
}
});
I am no longer using this method, it was just my last attempt to get it working.
The preview column is currently called in the php file like so;
<img id="tableImg" class="admin-thumb" src="<?php echo $row["fileName"]; ?>" alt="">
I know that my current methodology will only allow the files with jpg, png and other image related extensions to show but I can't figure out how to swap out the echo $row["filename"]
What I think I'm after, and please correct me if I'm wrong is either an if, else if, else or a php switch. I just have no idea how to make it work the way mentioned earlier.
To recap:
I need an assist making a preview column of a table show either the image associated to the file name/URL or if the file type is a zip, pdf or non image file it shows a placeholder image selected by me. I did have a screenshot to share but I don't have 10 rep to do so, yet.
Any help is appreciated and my thanks in advance.
Limur
SplFileInfo should provide the extention and then just use a switch statement to set the image you want to show.
$myfile=$row["fileName"];
$info = new SplFileInfo($myfile);
$ext = $info->getExtension();
switch ($ext) {
case 'zip':
$image='zip.png';
break;
case 'pdf':
$image='pdf.png';
break;
default:
$image=$myFile;
}
<img id="tableImg" class="admin-thumb" src="<?= $image ?>" alt="">

Understanding if a file is an image or a video from its content

I can not find a way to understand if a file is really a video or an image.
For example: I have a .jpg image renamed .mp4, if I open it via computer or browser I can not see anything because it is not really a video.
What I'm looking for is a way to understand if a video / image beyond the required extension is also really a video or an image, depending on the request.
In theory I would like a similar result:
$ImageOrVideo = pathinfo($_FILES["file"]["tmp_name"],PATHINFO_EXTENSION);
switch($ImageOrVideo){
case 'jpg': //check if a real image
case 'mp4': // check if a real video
default: exit('stop');
}
I had thought of some solutions, for example in the past I had used for the images getimagesize (), but now the php documentation says:
Caution This function expects filename to be a valid image file. If a
non-image file is supplied, it may be incorrectly detected as an image
and the function will return successfully, but the array may contain
nonsensical values.
Do not use getimagesize() to check that a given file is a valid image.
Use a purpose-built solution such as the Fileinfo extension instead.
$ImageOrVideo = $_FILES["file"]["tmp_name"];
switch(mime_content_type($ImageOrVideo)){
case 'image/jpeg':
// ........
break;
case 'video/mp4':
// ........
break;
default:
exit('stop');
}

ImageMagick and PHP to properly rotate an image

I am trying to use Imagick in my php code to properly orient images, so that I can strip the metadata from them and have them properly show up. I tried the methodology in this post:
Detect EXIF Orientation and Rotate Image using ImageMagick
But it is not working. Using the autorotate function in that post, this is what I am doing:
$working_image = new \Imagick();
$working_image->readImageBlob( $source_data);
$working_image->setImageFormat('jpeg');
autorotate($working_image);
... some resizing code:
$working_image->resizeImage( $width, $height, \Imagick::FILTER_CATROM, .7);
// get rid of metadata
$working_image->stripImage();
$working_image->writeImage( <unique filename> );
$working_image->getImageBlob();
... write out to data file to google
We're using Google's cloud stuff to store our files, hence the "getImageBlob" call.
Problem is that this doesn't seem to work. The resultant images are still oriented the same way they were, but now have no metadata, so the tag won't "fix" them.
What am I doing wrong here? I am using this version of the Imagick PHP object:
[versionNumber] => 1673
[versionString] => ImageMagick 6.8.9-9 Q16 x86_64 2015-01-05 http://www.imagemagick.org
In response to your answer:
Thanks for the clarifications. Looking at one of the specific images that I am having problems with, identify -verbose shows multiple places defining orientation:
Orientation: RightTop
exif:Orientation: 6
exif:thumbnail:Orientation: 6
And this is reflected in my call to Imagick::getImageOrientation in PHP, which returns the "6" value, which then causes my code to call functions like "Imagick::rotateImage("#000", 180);". The problem is that the image is unchanged by these calls. 8-(
The core problem is this: We get these images by the thousands every day from MLS's all over the country. We currently process them (resizing currently) via an automatic process. When they are displayed on our site, everything is currently fine, because the <img> tag seems to be happy to interpret the EXIF data and show the image in proper orientation. BUT... we want to start optimizing images, which means stripping the EXIF info out. So I need to figure out why Imagick->rotateImage() isn't working.
Ok, let's write a whole answer:)
What I meant with the link to ImageMagick's -auto-orient, was to point out, that this kind of auto-orientation depends on EXIF profile and "Orientation" setting. If it's missing or is wrong the auto-orientation will not work as expected. To check whether your images has the EXIF profile with Orientation in tact, you can use several ways:
PHP Imagick (check it with image before you call ->stripImage())
echo 'Orientation is: ', $working_image->getImageOrientation();
PHP (if you have local file)
$exif = exif_read_data('input.jpg');
echo 'Orientation is: ', isset($exif['Orientation']) ? $exif['Orientation'] : 'missing';
Online EXIF reader.
The values you get are described for example here or more about image auto-rotation topic and sample images are here
Or you can use programs like Gimp or Photoshop.
So you're doing nothing wrong, without EXIF this won't work. It's camera that is writing the tags into images, so there is no guarantee all your photos have it.
Perhaps offer image rotation for visitors in your website instead? There is now CSS3 transform: rotate(deg) property that makes it really easy, see....
We can get the current image orientation and can easily update to the original one with Imagick
public function fix_image_orientation()
{
$working_image = new \Imagick();
$working_image->readImageBlob($source_data);
$working_image->setImageFormat('jpeg');
$orientation = $working_image->getImageOrientation();
if (!empty($orientation)) {
switch ($orientation) {
case imagick::ORIENTATION_BOTTOMRIGHT:
$working_image->rotateimage("#000", 180);
break;
case imagick::ORIENTATION_RIGHTTOP:
$working_image->rotateimage("#000", 90);
break;
case imagick::ORIENTATION_LEFTBOTTOM:
$working_image->rotateimage("#000", -90);
break;
}
}
$working_image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
$working_image->writeImage( <unique filename> );
}
#Satendra Rawat posted a good, but incomplete answer. There is the GitHub repository https://github.com/ianare/exif-samples, where you can see 8 orientation examples. Only 3, 5 and 8 worked correctly.
So here is a update for all the orientations:
public function fix_image_orientation()
{
$working_image = new \Imagick();
$working_image->readImageBlob($source_data);
$working_image->setImageFormat('jpeg');
$orientation = $working_image->getImageOrientation();
if (!empty($orientation)) {
switch ($orientation) {
default:
case imagick::ORIENTATION_TOPLEFT:
break;
case imagick::ORIENTATION_TOPRIGHT:
$working_image->flipImage();
$working_image->rotateImage("#000", 180);
break;
case imagick::ORIENTATION_BOTTOMRIGHT:
$working_image->rotateImage("#000", 180);
break;
case imagick::ORIENTATION_BOTTOMLEFT:
$working_image->flipImage();
break;
case imagick::ORIENTATION_LEFTTOP:
$working_image->rotateImage("#000", -90);
$working_image->flipImage();
break;
case imagick::ORIENTATION_RIGHTTOP:
$working_image->rotateImage("#000", 90);
break;
case imagick::ORIENTATION_RIGHTBOTTOM:
$working_image->rotateImage("#000", 90);
$working_image->flipImage();
break;
case imagick::ORIENTATION_LEFTBOTTOM:
$working_image->rotateImage("#000", -90);
break;
}
}
$working_image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
$working_image->writeImage( <unique filename> );
}

ImageCreateFromString and getimagesize in PHP

Currently if a user POST/uploads a photo to my PHP script I start out with some code like this
getimagesize($_FILES['picture1']['tmp_name']);
I then do a LOT more stuff to it but I am trying to also be able to get a photo from a URL and process it with my other existing code if I can. SO I am wanting to know, I f I use something like this
$image = ImageCreateFromString(file_get_contents($url));
Would I be able to then run getimagesize() on my $image variable?
UPDATE
I just tried this...
$url = 'http://a0.twimg.com/a/1262802780/images/twitter_logo_header.png';
$image = imagecreatefromstring(file_get_contents($url));
$imageinfo = getimagesize($image);
print_r($imageinfo);
But it didnt work, gave this.
Warning: getimagesize(Resource id #4) [function.getimagesize]: failed to open stream: No such file or directory in
Any idea how I can do this or something similar to get the result I am after?
I suggest you follow this approach:
// if you need the image type
$type = exif_imagetype($url);
// if you need the image mime type
$type = image_type_to_mime_type(exif_imagetype($url));
// if you need the image extension associated with the mime type
$type = image_type_to_extension(exif_imagetype($url));
// if you don't care about the image type ignore all the above code
$image = ImageCreateFromString(file_get_contents($url));
echo ImageSX($image); // width
echo ImageSY($image); // height
Using exif_imagetype() is a lot faster than getimagesize(), the same goes for ImageSX() / ImageSY(), plus they don't return arrays and can also return the correct image dimension after the image has been resized or cropped for instance.
Also, using getimagesize() on URLs isn't good because it'll consume much more bandwidth than the alternative exif_imagetype(), from the PHP Manual:
When a correct signature is found, the
appropriate constant value will be
returned otherwise the return value is
FALSE. The return value is the same
value that getimagesize() returns in
index 2 but exif_imagetype() is much
faster.
That's because exif_imagetype() will only read the first few bytes of data.
If you've already got an image resource, you'd get the size using the imagesx and imagesy functions.
getimagesize can be used with HTTP.
Filename - It can reference a local file or (configuration permitting) a remote file using one of the supported streams.
Thus
$info = getimagesize($url);
$image = ImageCreateFromString(file_get_contents($url));
should be fine.
Not sure if this will help, but I ran into a similar issue and it turned out the firewall controlled by my host was blocking outgoing http connection from my server.
They changed the firewall settings. My code then worked.
BTW: I thought this might have been an issue when I tried file_get_contents() on a number of urls, none of which worked!

Categories