How do I resize/downscale the images that gets uploaded with my upload script down to 350x100 if they are over 350x100?
My script:
$allowed_filetypes = array('.png','.PNG');
$filename = $_FILES['strUpload']['name'];
$ext = substr($filename, strpos($filename,'.'), strlen($filename)-1);
if(in_array($ext,$allowed_filetypes))
{
list($width, $height, $type, $attr) = getimagesize($_FILES['strUpload']['tmp_name']);
if ($width > 350 || $height > 100)
{
echo "That file dimensions are not allowed. Only 350x100 is allowed";
exit();
}
if ($_FILES['strUpload']['size'] > 2097152 )
{
echo "ERROR: Large File Size. Only less than 2mb accepted";
exit();
}
$imagename = uniqid('ff') . ".png";
move_uploaded_file ( $_FILES['strUpload']['tmp_name'], $imagename );
print ( "<script type=\"text/javascript\">" );
if(file_exists($imagename) && $_FILES['strUpload']['name'] != '')
{
print ( "self.opener.SetImageFile(\"" . $imagename . "\");" );
echo "\n";
print ( "self.opener.setInputFile(\"" . $imagename . "\");" );
}
echo "\n";
print ( "window.close();" );
echo "\n";
print ( "</script>" );
$open = new dbconnect();
$open->callDB("localhost","pema2201_william","lindberg","pema2201_siggen");
$ip = $_SERVER['REMOTE_ADDR'];
$dattum = date('Y-m-d H:i:s', time());
mysql_query("INSERT INTO piclist (ip,pic,datum) VALUES('$ip','$imagename','$dattum')") or die(mysql_error());
}
else
{
echo "WRONG FILE TYPE ONLY PNG ALLOWED"
}
PHP has several image handling libraries. The GD library has shipped since PHP 4.3 so I suggest using that. Just read the docs to find what you need.
Use imagecopyresized - there's a good example of how to use it on the PHP manual page.
Have a look at this question someone else asked a few days ago.
That not only explains how it's done, but also how it's done in an efficient way. (ImageMagick should be used over the GD library)
Hope that helps.
The general gist is to create a new "canvas" of the desired dimensions for the image to go in.
Take your uploaded image and copy it onto the new canvas giving setting a source width x height (take all of the source image) and destination width x height (use all of the destination canvas), offsets are available to shift the image around a bit if you need to.
Then finally save it where you need it to go, or insert it into a database field, (this will replace your move_uploaded_file call).
Related
I know that this topic is probably easy for most of you but i've been fighting over this for the last 2 days without any progress.
I'm doing a web app for myself, no security needed as it is non production intended.
Following scripts work fine, the problem remains when i upload picture directly from camera using:
<input
id="photoBox"
type="file"
class="form-control-file"
accept="image/*"
capture="camera"
name="photo"/>
When i upload from browser everything works fine, however from smartphone the server does not respect EXIF orientation therefore images are wrongly rotated.
As per upload i am using the following script: (pastebin provided as well).
https://pastebin.com/mvgah9Ud
function photoPlant($pID){
// db
include "includes/dbConfig.php";
// init
$out = null;
// gen hash
$varA = microtime();
$varB = time();
$varC = $varA . $varB;
$hash = md5($varC);
// prepare upload
$currentDir = getcwd();
$uploadDirectory = "/gallery/";
$errors = []; // Store all foreseen and unforseen errors here
$fileExtensions = ['jpeg','jpg','png', '']; // Get all the file
extensions, including empty for mobile
// reformat empty file extension
if ($fileExtension === ""){
$fileExtension = "jpg";
}
$fileName = $_FILES['photo']['name'];
$fileTmpName = $_FILES['photo']['tmp_name'];
$fileSize = $_FILES['photo']['size'];
$fileType = $_FILES['photo']['type'];
$fileExtension = strtolower(end(explode('.',$fileName)));
// reformat filename
$fileName = $hash . "." . $fileExtension;
$uploadPath = $currentDir . $uploadDirectory . basename($fileName);
if (! in_array($fileExtension,$fileExtensions)) {
$errors[] = "This file extension is not allowed. Please upload a
JPEG or PNG file";
}
if ($fileSize > 8000000) {
$errors[] = "This file is more than 8MB. Sorry, it has to be less
than or equal to 8MB";
}
if (empty($errors)) {
$didUpload = move_uploaded_file($fileTmpName, $uploadPath);
if ($didUpload) {
$out .= "ok"; // everything is ok give feedback ok
} else {
$out .= "An error occurred somewhere. Try again or contact the
admin";
}
} else {
foreach ($errors as $error) {
$out .= $error . "These are the errors" . "\n";
}
}
// store img on db
// prepare data
$timeStamp = time();
// query
$query = mysqli_query($con, "INSERT INTO photo_table
(photo_parent_id, photo_name, photo_timestamp) VALUES ($pID,
'$fileName', $timeStamp)");
// run query
if (!$query){
$out = mysqli_error($con);
}
// return
return $out;
}
My intentions are clear. Rotate img BEFORE upload according to EXIF orientation and then proceed to store it on the disk.
If possible i intend to do it in the very same photoPlant(arg) function.
Thanks.
Well. After a few unexplained downvotes and a very useful comment from DinoCoderSaurus this is the answer i was looking for.
I had to install and enable Imagick for PHP7.
It was not a plain simple job but there are a few guides available to google. Depending on your version / os installation notes are different so proceed with care.
My upload function (from original post) changed on the upload part.
Where it says:
if (empty($errors)){
// old code here.
}
It was changed for the following validation:
if (empty($errors)) {
// this is my new validation code.
$img = new Imagick($fileTmpName);
$orient = $img->getImageOrientation();
if($orient === 6){
// we need to rotate it 90deg
$img->rotateImage("rgba(255, 255, 255, 0.0)", 90);
}
if ($orient === 3){
// we need to rotate it 180deg
$img->rotateImage("rgba(255, 255, 255, 0.0)", 180);
}
// Note that imagick does the storage for me as well!
$img->writeImage("gallery/" . $fileName);
}
else{
$out .= "Errors on upload";
}
This fixed ALL of my issues with a reasonably good response time.
Hopefully some newbies like me will take some skill profit from this post.
As a farewell note i need to add... If you downvote a post, comment the reason why you did that, because this topic was already discussed here countless times, but after 2 days researching on SO old posts i didn't manage to find WHY it was not working!
A special thanks to DinoCoderSaurus who sent me in the right direction with around 10 words.
I am working on an uploader and slowly getting it working, I am uploading 3 images at once, and setting arrays for each one as keys, with an increment of ++1. I am wanting to resize the image before it gets copied to the thumbnail folder.
I have this code.
Everything works with it.
As you see, I started on getting the file info, but after that I am totally stuck on what to do after to resize the image proportionally with a maximum width of xpx and height to match it without looking distorted.
Any help would be really appreciated. Thank You.
EDIT --- I started working on it myself and wondering if this is the right approach to what i am doing.
<?php
if (isset($_POST['addpart'])) {
$image = $_FILES['images']['tmp_name'];
$name = $_POST['username'];
$i = 0;
foreach ($image as $key) {
$fileData = pathinfo(basename($_FILES["images"]["name"][$i]));
$fileName[] = $name . '_' . uniqid() . '.' . $fileData['extension'];
move_uploaded_file($key, "image/" . end($fileName));
copy("image/" . end($fileName), "image_thumbnail/" . end($fileName));
// START -- THE RESIZER THAT IS BEING WORKED ON
$source = "image_thumb/" . end($fileName);
$dest = "image_thumb/" . end($fileName);
$quality = 100;
$scale = 1 / 2;
$imsize = getimagesize($source);
$x = $scale * $imsize[0];
$y = $scale * $imsize[1];
$im = imagecreatefromjpeg($source);
$newim = imagecreatetruecolor($x, $y);
imagecopyresampled($newim, $im, 0, 0, 0, 0, $x, $y, $imsize[0], $imsize[1]);
imagejpeg($newim, $dest, $quality);
// END -- THE RESIZER THAT IS BEING WORKED ON
$i++;
}
echo 'Uploaded<br>';
echo 'Main Image - ' . $fileName[0] . '<br>';
echo 'Extra Image 1 - ' . $fileName[1] . '<br>';
echo 'Extra Image 2 - ' . $fileName[2] . '<br>';
echo '<hr>';
}
?>
thanks
Use GD library.
Create input image object using imagecreatefromstring() for example: imagecreatefromstring(file_get_contents($_FILES['images']['tmp_name'][$i]))
It's the simplest way.
Another option is to detect file type and use functions like imagecreatefromjpeg (), imagecreatefrompng(), etc.
Create output empty image using imagecreate()
Use imagecopyresampled() or imagecopyresized() to resize image and copy+paste it from input image to output image
Save output image using function like imagejpeg()
Clean memory using imagedestroy()
The built-in image manipulation commands of PHP makes your code difficult to understand and to maintain. I suggest you to use a library which wraps it into a more productive way.
If you use Intervention/image, for example, your code will look like this:
<?php
// target file to manipulate
$filename = $_FILES['images']['tmp_name'];
// create image instance
$img = Image::make($filename);
// resize to width, height
$img->resize(320, 240);
// save it!
$img->save('thumbs/'. uniqid() . '.' . pathinfo($filename, PATHINFO_EXTENSION));
Read the full documentation here: http://image.intervention.io/use/uploads
I am a newbie to programming, and this is my first exposure to PHP. I am building a mobile web app where users can upload pictures to the site while at the social event.
I used the PHP script from W3schools (don't hate me please, but it works for my limited knowledge).
Because it is a mobile app I need to add extra functionality but cannot figure out how with the multitude of scripts and my lack of knowledge.
Before the image is uploaded in the script, I would like first do the following.
1) Reduce the dimension to 500px wide and 'auto' the height to retain picture ratio.
2) Compress the file so it is more appropriately filesized for resolution on mobile devices (it will never be printed) and to speed up the upload over cell network.
3) Ensure that the display is correct by way of EXIF data. Right now, iOS, Android and Windows all display portrait and landscape images differently,...I need consistency
Here is my code,...I have remarked where I think it should go but I am not entirely sure.
This code comes up in a pop-up div tag over the page that displays the images.
<?php
$target_dir = "uploads/";
$target_dir = $target_dir . basename( $_FILES["uploadFile"]["name"]);
$target_dir1 = $target_dir . basename( $_FILES["uploadFile"]["tmp_name"]);
$fileTmpLoc = $_FILES["uploadFile"]["tmp_name"];
$uploadOk=1;
// Check if Upload is done without file.
if (!$fileTmpLoc) { // if file not chosen
echo '<script language="javascript">';
echo 'alert("Please browse for a file before clicking the upload button")';
echo '</script>';
echo '<script language="javascript">';
echo 'window.history.back()';
echo '</script>';
}
// Check if file already exists
if (file_exists($target_dir . $_FILES["uploadFile"]["name"])) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($uploadFile_size > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
//Check no php files
if ($uploadFile_type == "text/php") {
echo "Sorry, no PHP files allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk==0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
//Reduce file to 500px wide
//Compress file
//Rotate file with EXIF data to properly display.
if (move_uploaded_file($_FILES["uploadFile"]["tmp_name"], $target_dir1)) {
echo header( 'Location: gallery.php' ) ;
} else {
echo "Sorry, there was an error uploading your file.";
}
}
?>
Thanks for any help and as mentioned this is my first exposure to PHP.
There is a free utility called SimpleImage.php, available at http://www.white-hat-web-design.co.uk/articles/php-image-resizing.php that will handle resizing and compression and might be a good starting point. There are great examples on their page on how to use it, below is an example of how I use it to resize uploaded images to a certain width:
require_once("SimpleImage.php");
function createThumbnail($cat_code) {
// Check for full size product image
$fname = $this->getImageFilename($cat_code);
if($fname === "") {
echo "<b>createThumbnail: No image file found for " . $cat_code . "!</b><br>";
return false;
}
$thumb = "images/t/" . $cat_code . ".100.jpg";
if($fname !== "") {
$image = new SimpleImage();
$image->load($fname);
$image->resizeToWidth(100);
$image->save($thumb);
}
return true;
}
function process_upload($file, $cat_code, $format, $price=NULL) {
$imageFileExtensions = array('jpg', 'gif', 'png');
$target_path = "uploads/";
$target_path1 = $target_path . basename($file['name']);
$path_info1 = pathinfo($target_path1);
$ext = $path_info1['extension'];
if(move_uploaded_file($file['tmp_name'], $target_path1)) {
if(rename($target_path1, $main_path1)) {
echo "File ". $file['name'] . " verified and uploaded.<br>";
//Create thumbnail if this is an image file
if(in_array($ext, $imageFileExtensions))
$createThumbnail($cat_code);
} else {
echo "<b>ERROR renaming " . $file['name'] . "</b><br>";
}
}
else
echo "<b>move_uploaded_file(" . $file['tmp_name'] . ", $target_path1) failed</b><br>\n";
}
To do a rotate just add another function to the SimpleImage class that uses imagerotate(), for example the following:
function rotate($angle, $bgd_color, $ignore_transparent=0) {
imagerotate($this->image, $angle, $bgd_color, $ignore_transparent);
}
The php.net page for imagerotate has more details on the function parameters.
To work with EXIF data, I use another free utility called PelJpeg.php, available at http://lsolesen.github.io/pel/. There are many examples on how to use this if you google PelJpeg.php. It can get kind of complicated, because as you mention, every platform handles images and meta data a little differently, so you have to do a lot of testing to see what things are handled the same on various platforms, what things are different, and how to bridge across those gaps.
I have a client that sends me text messages from his iPhone with images for me to upload into his gallery. I'm trying to create a admin system so I can simply take the images from the texts, go to the admin page on my iPhone and upload the images straight to the gallery.
This would save me tons of time in my day to day work schedule.
Using the provided code. How can I add the following functions:
I would like to compress the file size down to a smaller size if possible, similar to the save to web jpg function in Photoshop. (Most images I get are around 1-3 MB. I would like to get them down to around 150-500kb max)
I would like to automatically change the width to 760px, but keep the aspect ratio so the images are not squished. He sends me landscape and portrait images.
Beings they are iPhone images. They have an extension .JPG (all caps) I would like this to change to .jpg (all lower case.) This is not a deal breaker I would just like to know how to do this for future use.
Either one of these functions would be very helpful, but all 3 would be ideal for my situation.
Here is the code I'm working with?
THIS IS THE FINAL CORRECT CODE FOR UPLOADING AND RESIZING IMAGES PROVIDED By #tman
Make sure you have imagick installed in your php.ini file. Check with your hosting provider to install it.
<?php
include($_SERVER['DOCUMENT_ROOT'] . "/connections/dbconnect.php");
for($i=0;$i<count($_FILES["image"]["name"]);$i++){
if($_FILES["image"]["name"][$i] != ''){ // don't insert if file name empty
$dataType = mysql_real_escape_string($_POST["dataType"][$i]);
$title = mysql_real_escape_string($_POST["title"][$i]);
$fileData = pathinfo($_FILES["image"]["name"][$i]);
$fileName = uniqid() . '.' . $fileData['extension'];
$target_path = $_SERVER['DOCUMENT_ROOT'] . "/images/gallery/" . $fileName;
if (move_uploaded_file($_FILES["image"]["tmp_name"][$i], $target_path)){ // The file is in the images/gallery folder.
// Insert record into database by executing the following query:
$sql="INSERT INTO images (data_type, title, file_name) "."VALUES('$dataType','$title','$fileName')";
$retval = mysql_query($sql);
///NEW
$size = getimagesize($target_path);
$width=$size[0];
$height=$size[1];
$newwidth = 760;
$newheight = $height*($newwidth/$width);
$pic = new Imagick($target_path);//specify name
$pic->resizeImage($newwidth,$newhight,Imagick::FILTER_LANCZOS,1);
unlink($target_path);
$pic->writeImage($target_path);
$pic->destroy();
///NEW
echo "The image {$_FILES['image']['name'][$i]} was successfully uploaded and added to the gallery<br />
<a href='index.php'>Add another image</a><br />";
}
else
{
echo "There was an error uploading the file {$_FILES['image']['name'][$i]}, please try again!<br />";
}
}
} // close your foreach
?>
uploader.php Original code. Allows me to upload 4 images at once. WORKS!!!
<?php
include($_SERVER['DOCUMENT_ROOT'] . "/connections/dbconnect.php");
for($i=0;$i<count($_FILES["image"]["name"]);$i++){
if($_FILES["image"]["name"][$i] != ''){ // don't insert if file name empty
$dataType = mysql_real_escape_string($_POST["dataType"][$i]);
$title = mysql_real_escape_string($_POST["title"][$i]);
$fileData = pathinfo($_FILES["image"]["name"][$i]);
$fileName = uniqid() . '.' . $fileData['extension'];
$target_path = $_SERVER['DOCUMENT_ROOT'] . "/images/gallery/" . $fileName;
if (move_uploaded_file($_FILES["image"]["tmp_name"][$i], $target_path)){ // The file is in the images/gallery folder.
// Insert record into database by executing the following query:
$sql="INSERT INTO images (data_type, title, file_name) "."VALUES('$dataType','$title','$fileName')";
$retval = mysql_query($sql);
echo "The image {$_FILES['image']['name'][$i]} was successfully uploaded and added to the gallery<br />
<a href='index.php'>Add another image</a><br />";
}
else
{
echo "There was an error uploading the file {$_FILES['image']['name'][$i]}, please try again!<br />";
}
}
} // close your foreach
?>
FYI, This will allow you to give a unique names to your images, resize the width, but keep the correct aspect ratio and upload multiple file at the same time.
Awesome Stuff!
Like this:
$filelocation='http://help.com/images/help.jpg';
$newfilelocation='http://help.com/images/help1.jpg';
$size = getimagesize($filelocation);
$width=$size[0];//might need to be ['1'] im tired .. :)
$height=$size[1];
// Plz note im not sure of units pixles? & i could have the width and height confused
//just had some knee surgery so im kinda loopy :)
$newwidth = 760;
$newheight = $height*($newwidth/$width)
$pic = new Imagick( $filelocation);//specify name
$pic->resizeImage($newwidth,$newhight,Imagick::FILTER_LANCZOS,1);
//again might have width and heing confused
$pic->writeImage($newfilelocation);//output name
$pic->destroy();
unlink($filelocation);//deletes image
Here is something kind of similar, lets check the size and compress if the image seems that it is too big. I didn't resize it which just requires that you get the dimensions and resize based on desire.
All this is doing is if the file is greater than 250KB compress it to 85% ..
$bytes = filesize($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName);
//$maxSizeInBytes = 26400; //is 250KB? No? compress it.
if ($bytes > 26400) {
$img = new Imagick($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName);
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->stripImage();
$img->setImageCompressionQuality(85);
$img->writeImage($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName);
}
OR:
// resize with imagejpeg ($image, $destination, $quality); if greater than byte size KB
// Assume only supported file formats on website are jpg,jpeg,png, and gif. (any others will not be compressed)
$bytes = filesize($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName);
//$maxSizeInBytes = 26400; //is gtr than 250KB? No? compress it.
if ($bytes > 26400) {
$info = getimagesize($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName);
$quality = 85; //(1-100), 85-92 produces 75% quality
if ($info['mime'] == 'image/jpeg') {
$image = imagecreatefromjpeg($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName);
imagejpeg($image,$inventory_path.DIRECTORY_SEPARATOR.$this->uploadName,$quality);
} elseif ($info['mime'] == 'image/gif') {
$image = imagecreatefromgif($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName);
imagejpeg($image,$inventory_path.DIRECTORY_SEPARATOR.$this->uploadName,$quality);
} elseif ($info['mime'] == 'image/png') {
$image = imagecreatefrompng($inventory_path.DIRECTORY_SEPARATOR.$this->uploadName
imagejpeg($image,$inventory_path.DIRECTORY_SEPARATOR.$this->uploadName,$quality);
}
}
I have a page while is used only for print, and some of the images on there are uploaded through a script I have. It seems to always reduce the image to 72 dpi, reguardless of what I set imagejpeg() and imagepng() to for quality.
I've used my own personal script and this one on git hub
https://github.com/maxim/smart_resize_image
I was hoping for a little guidance on preserving the dpi at the original 300dpi.
Here is my own personal script
if (!empty($_FILES['image']['name'])) //checking if file upload box contains a value
{
$saveDirectory = 'pics/'; //name of folder to upload to
$tempName = $_FILES['image']['tmp_name']; //getting the temp name on server
$fileName1 = $_FILES['image']['name']; //getting file name on users computer
$count = 1;
do{
$location = $saveDirectory . $_GET['section'] . $count . $fileName1;
$count++;
}while(is_file($location));
if (move_uploaded_file($tempName, $location)) //Moves the temp file on server
{ //to directory with real name
$image = $location;
// Get new sizes
list($width, $height, $type) = getimagesize($image); //gets information about new server image
$framewidth = 932;
$frameheight = 354;
$realwidth = $width; //setting original width and height
$realheight = $height;
// Load
$file1new = imagecreatetruecolor($framewidth, $frameheight); //creates all black image with target w/h
if($type == 2){
$source = imagecreatefromjpeg($image);
imagecopyresampled($file1new, $source , 0, 0, 0, 0, $framewidth, $frameheight, $realwidth, $realheight);
}
elseif($type == 3){
$source = imagecreatefrompng($image);
imagecopyresampled($file1new, $source , 0, 0, 0, 0, $framewidth, $frameheight, $realwidth, $realheight);
}
else{
echo "Wrong file type";
}
if($type == 2){
//creates jpeg image from file1new for file1 (also retains quality)
imagejpeg($file1new, $image,100);
//frees space
imagedestroy($file1new);
}
elseif($type == 3){
//creates png image from file1new for file1 (also retains quality)
imagepng($file1new, $image,10);
//frees space
imagedestroy($file1new);
}
else{
echo "Wrong file type";
}
}
else
{
echo '<h1> There was an error while uploading the file.</h1>';
}
}
}
Edit: Even if dpi isn't the answer, as I see jpgs in specific don't retain that information. I need some way of keeping these images very clear and crisp.
If you generate image and open with a browser, the browser will reduce it to 72dpi before rendering.
If you open with gimp/phptoshop/whatever image editor , it should preserve the same dpi quality.
Though on a screen, there is no difference since your screen is 72 dpi.
Not tested on new browsers, but it was like this in netscape and first firefox versions, I assume it has not changed since.
The function posted by lorezyra (at) lorezyra (dot) com here: http://www.php.net/manual/es/function.imagejpeg.php#85712 might do the trick.