PHP - sometime getimagesize exchange the dimension of the image - php

I am using Symfony2 and I have a problem with the PHP:getimagesize because sometime the dimensions that this function return are exchanged.
My use of this function is like int the http://php.net/manual/es/function.getimagesize.php page and the images are sent to the server with a POST;
I post a mwe :
//INITIALIZATION OF VARIABLES
for ($i = 0; $i < count($_FILES['filename']['tmp_name']); $i++) {
if ($_FILES['filename']['tmp_name'][$i]) {
$img = strtolower(strtotime(date('Y-m-d h:i:s')) . $random . ".jpg");
if (!is_dir($Tmppath)) {
mkdir($Tmppath, 0777, TRUE);
}
move_uploaded_file($_FILES['filename']['tmp_name'][$i], $Tmppath . $img);
if (file_exists($Tmppath . $img)) {
if (!empty($img)) {
//DO SOMEHTING
list($width, $height) = getimagesize($Tmppath . $img);
//DO SOMEHTING
}
}
}
}
But sometime the $width and $height of the image are exchanged; the images that are uploaded from the clients are of many format and sometime if the same image that is uploaded twice the width and height are exchanged. Anyone has the same problem? there is another function in PHP more precise?
Thanks

Related

PHP Imagick Resizing Gif frames has weird issues

I am trying to resize all frames of a gif and sometimes they turn out extremely weird.
I've seen examples using the command line and I would like to try and avoid this for now.
Original:
Resized:
You can see clearly the problem.
Now my code:
$imgBlob = file_get_contents(__DIR__ . '/../assets/test_gif.gif');
if ($imgBlob === false) {
echo 'img blob failed!' . PHP_EOL;
return;
}
$img = new Imagick();
$img->readImageBlob($imgBlob);
$img->coalesceImages();
$count = 0;
foreach ($img as $_img) {
// $_img->coalesceImages();
$imgWidth = $_img->getImageWidth();
$imgHeight = $_img->getImageHeight();
$ratio = $imgHeight / $imgWidth;
$resizeWidth = 200;
$resizeHeight = 300;
if ($ratio > 0) {
$resizeWidth = round($resizeHeight / $ratio, 0);
} else {
$resizeHeight = round($resizeWidth / $ratio, 0);
}
//if ($_img->adaptiveResizeImage($resizeWidth, $resizeHeight) === false) {
if ($_img->resizeImage($resizeWidth, $resizeHeight, Imagick::FILTER_CATROM, 1, 0) === false) {
echo 'FAILED' . PHP_EOL;
}
$count++;
}
$thumbnailOnDisk = __DIR__ . '/../assets/test_resized.gif';
if (file_exists($thumbnailOnDisk)) {
unlink($thumbnailOnDisk);
}
$img = $img->deconstructImages();
if ($count > 1) {
$file = $img->writeImages($thumbnailOnDisk, true);
} else {
$file = $img->writeImage($thumbnailOnDisk);
}
echo 'DONE' . PHP_EOL;
Not sure exactly what coalesceImages or deconstructImages is doing and I am having a hard time finding an example online that would fix my problem.
$img->coalesceImages();
Returns an imagick object, which I was discarding.
$img = $img->coalesceImages();
Works.
As you resize the image, you need to set size of image page as well.
http://php.net/manual/en/imagick.setimagepage.php
I have read once that the header of the gif might not say the correct image size in some cases. This is why it is useful to set the image page any way.
Example:
`$image->resizeImage(120, 110, imagick::FILTER_CATROM, 1);
// Set the page size
$image->setImagePage(120, 110, 0, 0);

Scrape a webpage and get images more than particular width and particular height using php

Am able to scrape the images from a website using php but I want to scrape the only first image that has height greater than 200px and width 200px. How can I get the dimensions of first image source? Here is my code..
$html_3 = file_get_contents('http://beignindian.com');
preg_match_all( '|<img.*?src=[\'"](.*?)[\'"].*?>|i',$html_3, $matches );
$main_image_1 = $matches[ 1 ][ 0 ];
You can use getimagesize function to get the image height and width. Once you get it then add if condition to execute further code.
list($width, $height) = getimagesize($main_image_1); // I am assuming that $main_image_1 has image source.
echo "width: " . $width . "<br />";
echo "height: " . $height;
if($width > 200 && $height > 200) {
// perform something here.
}
Update:
If you need to loop through all the images from a website then use following code:
$host = "http://www.beingindian.com/";
$html = file_get_contents($host);
// create new DOMDocument
$document = new DOMDocument('1.0', 'UTF-8');
// set error level
$internalErrors = libxml_use_internal_errors(true);
// load HTML
$document->loadHTML($html);
// Restore error level
libxml_use_internal_errors($internalErrors);
$images = $document->getElementsByTagName('img');
foreach ($images as $image) {
$image_source = $image->getAttribute('src');
// check if image URL is an absolute URL or relative URL
$image_url = (filter_var($image_source, FILTER_VALIDATE_URL))?$image_source:$host.$image_source;
list($width, $height) = getimagesize($image_url);
if($width > 200 && $height > 200) {
// perform something here.
}
else {
// perform something here.
}
}

Compress and RESCALE uploaded image

I have a function that uploads files up to 8MB but now I also want to compress or at least rescale larger images, so my output image won't be any bigger than 100-200 KB and 1000x1000px resolution. How can I implement compress and rescale (proportional) in my function?
function uploadFile($file, $file_restrictions = '', $user_id, $sub_folder = '') {
global $path_app;
$new_file_name = generateRandomString(20);
if($sub_folder != '') {
if(!file_exists('media/'.$user_id.'/'.$sub_folder.'/')) {
mkdir('media/'.$user_id.'/'.$sub_folder, 0777);
}
$sub_folder = $sub_folder.'/';
}
else {
$sub_folder = '';
}
$uploadDir = 'media/'.$user_id.'/'.$sub_folder;
$uploadDirO = 'media/'.$user_id.'/'.$sub_folder;
$finalDir = $path_app.'/media/'.$user_id.'/'.$sub_folder;
$fileExt = explode(".", basename($file['name']));
$uploadExt = $fileExt[count($fileExt) - 1];
$uploadName = $new_file_name.'_cache.'.$uploadExt;
$uploadDir = $uploadDir.$uploadName;
$restriction_ok = true;
if(!empty($file_restrictions)) {
if(strpos($file_restrictions, $uploadExt) === false) {
$restriction_ok = false;
}
}
if($restriction_ok == false) {
return '';
}
else {
if(move_uploaded_file($file['tmp_name'], $uploadDir)) {
$image_info = getimagesize($uploadDir);
$image_width = $image_info[0];
$image_height = $image_info[1];
if($file['size'] > 8000000) {
unlink($uploadDir);
return '';
}
else {
$finalUploadName = $new_file_name.'.'.$uploadExt;
rename($uploadDirO.$uploadName, $uploadDirO.$finalUploadName);
return $finalDir.$finalUploadName;
}
}
else {
return '';
}
}
}
For the rescaling I use a function like this:
function dimensions($width,$height,$maxWidth,$maxHeight)
// given maximum dimensions this tries to fill that as best as possible
{
// get new sizes
if ($width > $maxWidth) {
$height = Round($maxWidth*$height/$width);
$width = $maxWidth;
}
if ($height > $maxHeight) {
$width = Round($maxHeight*$width/$height);
$height = $maxHeight;
}
// return array with new size
return array('width' => $width,'height' => $height);
}
The compression is done by a PHP function:
// set limits
$maxWidth = 1000;
$maxHeight = 1000;
// read source
$source = imagecreatefromjpeg($originalImageFile);
// get the possible dimensions of destination and extract
$dims = dimensions(imagesx($source),imagesy($source),$maxWidth,$maxHeight);
// prepare destination
$dest = imagecreatetruecolor($dims['width'],$dims['height']);
// copy in high-quality
imagecopyresampled($dest,$source,0,0,0,0,
$width,$height,imagesx($source),imagesy($source));
// save file
imagejpeg($dest,$destinationImageFile,85);
// clear both copies from memory
imagedestroy($source);
imagedestroy($dest);
You will have to supply $originalImageFile and $destinationImageFile. This stuff comes from a class I use, so I edited it quite a lot, but the basic functionality is there. I left out any error checking, so you still need to add that. Note that the 85 in imagejpeg() denotes the amount of compression.
you can use a simple one line solution through imagemagic library the command will like this
$image="path to image";
$res="option to resize"; i.e 25% small , 50% small or anything else
exec("convert ".$image." -resize ".$res." ".$image);
with this you can rotate resize and many other image customization
Take a look on imagecopyresampled(), There is also a example that how to implement it, For compression take a look on imagejpeg() the third parameter helps to set quality of the image, 100 means (best quality, biggest file) and if you skip the last option then default quality is 75 which is good and compress it.

resize multiple images while uploading

Hi im trying to resize multiple image while uploading i have the function that resize but its only work for one image so please can anyone shom me how to loop this for multiple file upload
if( $_FILES['image']['size']< $max_file_size ){
// get file extension
$ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION));
// $ext = pathinfo($_FILES['files']['name'][$f], PATHINFO_EXTENSION);
if (in_array($ext, $valid_exts)) {
/* resize image */
foreach ($sizes as $w => $h) {
$files[] = resize($w, $h);
}
} else {
$msg = 'Unsupported file';
}
} else{
$msg = 'Please upload image smaller than 200KB';
}
This is untested, but might give you an idea.
The way this works is by looping through all of the $_FILES of the variable $iname which is 'image'. I set this since it's used multiple times, so if you ever change it, its easier.
I create a new variable called $image which will be the variables for that specific image. I do this by looping through all of the variables of $_FILES[$iname]. I set the $image variable to the $key and the new value, which will be an array. We reference the correct array using the $i variable.
Next I simply use your existing code. Since the resize() function only calls for width and height, I am unsure what happens here. Another parameter should be passed to reference the image you want to resize, which will be $image.
From the visible code I typed, not knowing what resize() is, this code is insecure. You should really check more than just the file extension since it can easily be changed. I usually use exif to check the image header. I also never store the data users upload unless I re-encode it using a GDI function in PHP.
Hopefully this will get you started.
$i = 0;
$iname = 'image';
for($i = 0; $i < count($_FILES[$iname]['size']); $i++) {
// Create new Image Array
$image = array();
foreach($_FILES[$iname] as $key => $val) {
$image[$key] = $val[$i];
}
if( $image['size'] < $max_file_size ) {
$ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION));
if (in_array($ext, $valid_exts)) {
foreach ($sizes as $w => $h) {
// How is resize getting the $_FILES?
// Should pass a variable of $image and use it instead
$files[] = resize($w, $h);
}
} else {
$msg = 'Unsupported file';
}
} else{
$msg = 'Please upload image smaller than 200KB';
}
}

Thumbnail generation time

Idea
I have a function that checks to see if a thumbnail exists in cache folder for a particular image. If it does, it returns the path to that thumbnail. If it does not, it goes ahead and generates the thumbnail for the image, saves it in the cache folder and returns the path to it instead.
Problem
Let's say I have 10 images but only 7 of them have their thumbnails in the cache folder. Therefore, the function goes to generation of thumbnails for the rest 3 images. But while it does that, all I see is a blank, white loading page. The idea is to display the thumbnails that are already generated and then generate the ones that do not exist.
Code
$images = array(
"http://i49.tinypic.com/4t9a9w.jpg",
"http://i.imgur.com/p2S1n.jpg",
"http://i49.tinypic.com/l9tow.jpg",
"http://i45.tinypic.com/10di4q1.jpg",
"http://i.imgur.com/PnefW.jpg",
"http://i.imgur.com/EqakI.jpg",
"http://i46.tinypic.com/102tl09.jpg",
"http://i47.tinypic.com/2rnx6ic.jpg",
"http://i50.tinypic.com/2ykc2gn.jpg",
"http://i50.tinypic.com/2eewr3p.jpg"
);
function get_name($source) {
$name = explode("/", $source);
$name = end($name);
return $name;
}
function get_thumbnail($image) {
$image_name = get_name($image);
if(file_exists("cache/{$image_name}")) {
return "cache/{$image_name}";
} else {
list($width, $height) = getimagesize($image);
$thumb = imagecreatefromjpeg($image);
if($width > $height) {
$y = 0;
$x = ($width - $height) / 2;
$smallest_side = $height;
} else {
$x = 0;
$y = ($height - $width) / 2;
$smallest_side = $width;
}
$thumb_size = 200;
$thumb_image = imagecreatetruecolor($thumb_size, $thumb_size);
imagecopyresampled($thumb_image, $thumb, 0, 0, $x, $y, $thumb_size, $thumb_size, $smallest_side, $smallest_side);
imagejpeg($thumb_image, "cache/{$image_name}");
return "cache/{$image_name}";
}
}
foreach($images as $image) {
echo "<img src='" . get_thumbnail($image) . "' />";
}
To elaborate on #DCoder's comment, what you could do is;
If the thumb exists in the cache, return the URL just as you do now. This will make sure that thumbs that are in the cache will load quickly.
If the thumb does not exist in the cache, return an URL similar to /cache/generatethumb.php?http://i49.tinypic.com/4t9a9w.jpg where the script generatethumb.php generates the thumbnail, saves it in the cache and returns the thumbnail. Next time, it will be in the cache and the URL won't go through the PHP script.

Categories