PHP imagecreate() PNG from any commonly used file-format? - php

I currently have an image upload input that only accepts PNG, JPG/JPEG, GIF images.
If the file is valid, it then proceeds to create a thumbnail from the image using
imagecreatefrompng()
imagecopy()
imagejpg()
This works fine, but ONLY for png images, obviously.
What is the most logical and efficient way to use "imagecreatefrompng()" except using the proper file format that was submitted? All I can think of is if/else using multiple "imagecreatefrom__()" but that doesn't seem right.
Also, how can my outputted format always be PNG no matter what was submitted instead of the current imagejpg() I have now.

You will have to use a switch and determine the image type like so:
$extension = strtolower(strrchr($file, '.'));
switch ($extension) {
case '.jpg':
case '.jpeg':
$img = #imagecreatefromjpeg($file);
break;
case '.gif':
$img = #imagecreatefromgif($file);
break;
case '.png':
$img = #imagecreatefrompng($file);
break;
default:
$img = false;
break;
}
-EDIT- Didn't see the second part of your question, you just need to save it using imagepng to save it to a PNG, no need to do anything else.

Using imagecreatefromstring( file_get_contents( $filename)) would be the lazy option here.
And if you always want a png output, then just exchanging imagejpg for imagepng would do.

Related

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="">

PHP getimagesize() mixes up width and height

I use a PHP script that uploads an image, then gets the dimensions with PHP's getImageSize() and then does things to the image according to the pictures orientation (portrait or landscape).
However (PHP version 5.4.12) on some .jpg files it gets the height and width as they are, and in some (taken with an iPhone) it swaps them, thinking the portrait pictures are actually landscape.
It does not only happen on my local Wampserver, but also on a remote server (with a different PHP version).
Has anyone a clue how
1) to repair this or
2) find a way around the problem?
Some cameras include an orientation tag within the metadata section of the file itself. This is so the device itself can show it in the correct orientation every time regardless of the picture's orientation in its raw data.
It seems like Windows doesn't support reading this orientation tag and instead just reads the pixel data and displays it as-is.
A solution would be to either change the orientation tag in afflicted pictures' metadata on a per-image basis, OR
Use PHP's exif_read_data() function to read the orientation and orient your image accordingly like so:
<?php
$image = imagecreatefromstring(file_get_contents($_FILES['image_upload']['tmp_name']));
$exif = exif_read_data($_FILES['image_upload']['tmp_name']);
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$image = imagerotate($image,90,0);
break;
case 3:
$image = imagerotate($image,180,0);
break;
case 6:
$image = imagerotate($image,-90,0);
break;
}
}
// $image now contains a resource with the image oriented correctly
?>
References:
https://stackoverflow.com/a/10601175/1124793 (research as to why this is happening)
http://php.net/manual/en/function.exif-read-data.php#110894 (PHP Code)
Function getimagesize() changes width and height in photos that are landscape orientation (horizontal) .
You can use this code:
<?php
$img = "test.jpg";
$exif = exif_read_data($img);
if(empty($exif['Orientation'])) {
list($width, $height, $type, $attr) = getimagesize($img);
}else{
list($height, $width, $type, $attr) = getimagesize($img);
}
?>
But it was fixed automatically in PHP7 and above.

Imagecreatefromjpeg With Faulty File

im writing an script that resize and crops the uploaded images.
all valid files are ok...
but some of my visitors are trying to upload non-valid ones.. for example the file extension is jpg, but in fact its a tiff file .. the uploading file's extension looks gif, but in its exif details writes 'its a jpg'.. etc..
As you can imagine, imagecreatefromXX() functions are all giving error in that case (its not a valid jpg etc)..
do you have any idea, how may i solve this problem?
how must i modify my recent codes?
switch($type) {
case 'gif':
$img = imagecreatefromgif($source);
break;
case 'jpg':
case 'JPEG':
case 'jpeg':
$img = imagecreatefromjpeg($source);
break;
case 'png':
$img = imagecreatefrompng($source);
break;
}
Your best bet would probably be to modify the code that sets $type, rather than the code you've shared (though John Conde's suggestion to have a default case is a good one), and use something like exif_imagetype (which your question suggests might already be in play) to determine the type, rather than trusting the extension (which you may even want to change to the appropriate type when writing the file): the extension is user-supplied data, and as such, the least likely to be accurate and/or useful.
e.g.
$type = exif_imagetype($source);
switch ($type){
case IMAGETYPE_GIF:
$img = imagecreatefromgif($source);
break;
case IMAGETYPE_JPG:
$img = imagecreatefromjpeg($source);
break;
case IMAGETYPE_PNG:
... etc ...
default:
//Fail Gracefully
}

Validating image uploads with PHP

I have an image upload program setup that I made with PHP to allow the public to submit their images. I am having trouble finding a method to make sure the file is actually an image. I'm checking the file type, and also using getimagesize(), amongst other checks but if I rename a text file to become a JPG file my validation allows the file. How can I ensure this is actually an image? I don't want my boss to execute any infected files.
you can use Imagick's identifyImage() command.
if it gives you back image data its an image if it hands back an error or no image data then its not an image. there is a command line version of this tool you can use to: http://www.imagemagick.org/script/identify.php if you do not have php compiled with imagemagick
Check allowed extensions
.gif .jpg .jpeg .png should be allowed
How about to use Exif module's exit-imagetype() function?
http://www.php.net/manual/en/function.exif-imagetype.php
<?php
if (exif_imagetype('image.gif') != IMAGETYPE_GIF) {
echo 'The picture is not a gif';
}
?>
Reproduce the uploaded image using gd. If the image isn't reproduced, it's not an image!
If this function returns false, then it's not a valid image. I haven't worked with any more than jpg, png and gif, so there might be some more image types out there that can fit into this function (bmp?)...
function checkFileType($filetype,$tmp_name)
{
$return_val = false;
switch($filetype){
case 'image/jpg':
case 'image/jpeg':
case 'image/pjpeg':
$return_val = #imagecreatefromjpeg($tmp_name);
break;
case 'image/gif':
$return_val = #imagecreatefromgif($tmp_name);
break;
case 'image/png':
case 'image/x-png':
$return_val = #imagecreatefrompng($tmp_name);
break;
}
return $return_val;
}

Not able to get image file extension

I'm using Uploadify to upload an image to the server.
The image is uploaded, and placed in the temp folder of the web server.
Now I need to work with the file beore moving it to it's real location, and I have the following code:
// Get the filepath and filename from server temp dir
$sourceFile = $_FILES[ 'Filedata' ][ 'tmp_name' ]; // e.g. c:\server\path\tmp\php159.tmp
// Solution 1 for getting file extension
$fileExt1 = pathinfo($sourceFile, PATHINFO_EXTENSION); // <-- This only returns .tmp
// Solution 2 with getimagesize
list(,,$extension) = getimagesize($sourceFile);
$fileExt2 = $extension; // this only returns the number 2.
// Solution 3 with getimagesize
$img = getimagesize($sourceFile);
$fileExt3 = $img[2]; // this only returns the number 2.
I'm not using regex to read filename, because a user may name the file anything, so I have to read file data.
Any sugegstions anyone?
Well, first off $sourceFile should be $_FILES['Filedata']['name'] instead of $_FILES['Filedata']['tmp_name'] but only for your first solution.
Now regarding your solutions/problems:
pathinfo($sourceFile, PATHINFO_EXTENSION); // should work now
getimagesize() returns a constant indicating the image type in the second index
same as point 2
Keep in mind that exif_imagetype() returns exactly the same information as the second index of getimagesize(), if you have access to this function it should perform way better.
Now for the image constants, the most common three are:
IMAGETYPE_GIF = 1
IMAGETYPE_JPEG = 2
IMAGETYPE_PNG = 3
Checking is as simple as doing something like this:
switch (exif_imagetype($_FILES['Filedata']['tmp_name']))
{
case IMAGETYPE_GIF:
echo 'is a GIF';
break;
case IMAGETYPE_JPEG:
echo 'is a JPEG';
break;
case IMAGETYPE_PNG:
echo 'is a PNG';
break;
case default:
echo 'is something else;
break;
}
One more thing, it's better to use getimagesize() / exif_imagetype() than to rely on the file extension, since the extension can be easily changed.
Your solutions #2 and #3 both work already. From the getimagesize() manual page:
Returns an array with 7 elements.
...
Index 2 is one of the IMAGETYPE_XXX constants indicating the type of the image.
So for a .gif then this should be the integer 2. To get the file extension use image_type_to_extension() since you already are using the gd library. eg.
$img = getimagesize($sourceFile);
$fileExt = image_type_to_extension($img[2])
exif_imagetype() can determine a number of graphics formats, is fast and doesn't even use GD.
Edit: I see you are already using getimagesize() and have trouble translating the constants. The exif_imagetype() page linked above has a translation of all returned image types that should be valid for getimagesize() as well.

Categories