PHP: get largest image - performance issue - php

The below code finds all the images on a given website and returns the largest, BUT it is terribly slow. Can anyone help? Thanks!
$largest = 0;
$images = array();
reg_match_all('/(img|src)\=(\"|\')[^\"\'\>]+/i', $html, $media);
unset($html);
$data=preg_replace('/(img|src)(\"|\'|\=\"|\=\')(.*)/i',"$3",$media[0]);
foreach($data as $imgUrl) {
$info = pathinfo($imgUrl);
if (isset($info['extension'])) {
if (($info['extension'] == 'jpg') ||
($info['extension'] == 'jpeg') ||
($info['extension'] == 'gif') ||
($info['extension'] == 'png')) {
array_push($images, $imgUrl);
$imgUrl = $this->rel2abs($imgUrl, $this->url);
list($width, $height, $type, $attr) = getimagesize($imgUrl);
$size = $width * $height;
if ($size > $largest) {
$this->image = $imgUrl;
$largest = $size;
}
}
}

I had same issue as you, the problem is that getimagesize is downloading image back to server then gets it's size, so i have written my own wrapper, who only reads img meta information and returns size back.
Here: http://pastebin.com/3XuSAw0q is class. It can handle jpg, png and gif files.
Use it like:
$image = new Parser_Provider_Image();
$sizes = $image->getImageSize('http://../../img.jpg');

Related

How do I easily resize and rename images on upload? (php)

What code would I use to:
Resize all images being uploaded to 600px width while maintaining aspect ratio for height
Rename the file being uploaded to the current time-stamp
and how exactly would I add that to or edit my existing code (preferably without using classes):
$target_dir2 = "creature_pics/";
$target_file2 = $target_dir2 . basename($_FILES["u_c2pic"]["name"]);
$uploadOk2 = 1;
$imageFileType2 = pathinfo($target_file2,PATHINFO_EXTENSION);
if(isset($_POST["submit"])) {
$check2 = getimagesize($_FILES["u_c2pic"]["tmp_name"]);
if($check2 !== false) {
$uploadOk2 = 1;
} else {
$uploadOk2 = 0;
}
}
if (file_exists($target_file2)) {
$uploadOk2 = 0;
}
if ($_FILES["u_c2pic"]["size"] > 5000000) {
$uploadOk2 = 0;
}
if($imageFileType2 != "jpg" && $imageFileType2 != "png" && $imageFileType2 != "jpeg"
&& $imageFileType2 != "gif" ) {
$uploadOk2 = 0;
}
if ($uploadOk2 == 0) {
$ercode2 = "Sorry, your file was not uploaded.";
} else {
if (move_uploaded_file($_FILES["u_c2pic"]["tmp_name"], $target_file2)) {
} else {
$ercode2 = "Sorry, there was an error uploading your file.";
}
}
I'm new to php coding and would like the simplest solution possible.
If you can use Imagick on your server then the following code should help you out.
First the function to do the resizing.
if(!defined('APPLICATION_PATH')) define('APPLICATION_PATH', dirname(__FILE__));
function popupImage($width, $height, $code, $name) {
$file = APPLICATION_PATH.'/creature_pics/'.$name.'.jpg';
$im = new Imagick($file);
$imageprops = $im->getImageGeometry();
$r_width = $imageprops['width'];
$r_height = $imageprops['height'];
if($width > $height){
$newHeight = $height;
$newWidth = ($width / $r_height) * $r_width;
}else{
$newWidth = $width;
$newHeight = ($height / $r_width) * $r_height;
}
$im->resizeImage($newWidth,$newHeight, imagick::FILTER_LANCZOS, 0.9, true);
$im->cropImage ($width,$height,0,0);
$im->writeImage(APPLICATION_PATH.'/creature_pics/'.$code.'.jpg');
$im->destroy();
$newFile = APPLICATION_PATH.'/creature_pics/'.$code.'.jpg';
}
then in your code just add
if (move_uploaded_file($_FILES["u_c2pic"]["tmp_name"], $target_file2)) {
//This is the new line calling the function
$timestamp = microtime(true);
$newFile = popupImage(600,1200,$timestamp,$_FILES["u_c2pic"]["tmp_name"]);
} else {
$ercode2 = "Sorry, there was an error uploading your file.";
}
That should create a new file in /creature_pics/ which will be named something like 142023023.9777.jpg which is the timestamp passed into the function as the code.
EDIT
Missed the timestamp element so this is now added in

Recognize if image is landscape or portrait

How can I recognize if image stored in same folder as PHP script is landscape or portrait ? I need to implement it to this function:
if ($dir = #opendir($folder))
{
while ($file = readdir($dir))
{
if (in_array(strtolower(FileExt($file)), $extensions))
{
if (!is_dir($file))
{
if (isLandsape($file))
{
$files[] = $file;
}
}
}
}
closedir($dir);
}
A function like this :
function isLandsape($file)
{
list($width, $height) = getimagesize($file);
return $width > $height;
}
list($width, $height) = getimagesize($file);
if ($width > $height) {
$orientation = "Landscape"; }
else {
$orientation = "Portrait"; }

Php resize width fix

I have this function in PHP.
<?php
function zmensi_obrazok($max_dimension, $image_max_width, $image_max_height, $dir, $obrazok, $obrazok_tmp, $obrazok_size, $filename){
$postvars = array(
"image" => $obrazok,
"image_tmp" => $obrazok_tmp,
"image_size" => $obrazok_size,
"image_max_width" => $image_max_width,
"image_max_height" => $image_max_height
);
// Array of valid extensions.
$valid_exts = array("jpg","jpeg","gif","png");
// Select the extension from the file.
$ext = end(explode(".",strtolower($obrazok)));
// Check not larger than 175kb.
if($postvars["image_size"] <= 256000){
// Check is valid extension.
if(in_array($ext,$valid_exts)){
if($ext == "jpg" || $ext == "jpeg"){
$image = imagecreatefromjpeg($postvars["image_tmp"]);
}
else if($ext == "gif"){
$image = imagecreatefromgif($postvars["image_tmp"]);
}
else if($ext == "png"){
$image = imagecreatefrompng($postvars["image_tmp"]);
}
list($width,$height) = getimagesize($postvars["image_tmp"]);
if($postvars["image_max_width"] > $postvars["image_max_height"]){
if($postvars["image_max_width"] > $max_dimension){
$newwidth = $max_dimension;
}
else
{
$newwidth = $postvars["image_max_width"];
}
}
else
{
if($postvars["image_max_height"] > $max_dimension)
{
$newheight = $max_dimension;
}
else
{
$newheight = $postvars["image_max_height"];
}
}
$tmp = imagecreatetruecolor($newwidth,$newheight);
imagecopyresampled($tmp,$image,0,0,0,0,$newwidth,$newheight,$width,$height);
imagejpeg($tmp,$filename,100);
return "fix";
imagedestroy($image);
imagedestroy($tmp);
}
}
}
?>
Now if I want to use it, and I upload image for example 500x300px and I have set max size to 205x205px it don't want to make resized picture proportion. It make something like 375x205 (height is still OK). Can somebody help how to fix it?
Just scale your image twice, once to match the width, once to match the height. To save on processing, get your scaling first, then do the resizing:
$max_w = 205;
$max_h = 205;
$img_w = ...;
$img_h = ...;
if ($img_w > $max_w) {
$img_h = $img_h * $max_w / $img_w;
$img_w = $max_w;
}
if ($img_h > $max_h) {
$img_w = $img_w * $max_h / $img_h;
$img_h = $max_h;
}
// $img_w and $img_h should now have your scaled down image complying with both restrictions.

How to save jpeg image as Progressive JPEG?

I have below function to save JPEG as Progressive JPEG. It saved, but not as progressive JPEG. Is this correct ?
function save($filename, $image_type = IMAGETYPE_JPEG, $compression = 75, $permissions = null) {
if ($image_type == IMAGETYPE_JPEG) {
imageinterlace($this->image, true); //convert to progressive ?
imagejpeg($this->image, $filename, $compression);
} elseif ($image_type == IMAGETYPE_GIF) {
imagegif($this->image, $filename);
} elseif ($image_type == IMAGETYPE_PNG) {
imagepng($this->image, $filename);
}
if ($permissions != null) {
chmod($filename, $permissions);
}
}
This is how i called save() function :
function img_reconstruct($saveto) {
$image = new SimpleImage();
$image->load($saveto);
list($width, $height) = getimagesize($saveto);
if ($width > 800 && $width < 1200) {
$image->resize(800, $height);
$image->save($saveto);
}
}
try like below
imageinterlace($this->image, 1); //convert to progressive ?
may be issue with type casting

php resize images script

I am using directory iterator to iterate through directories and resize images found in that directory, I am doing this from browser cause I don't have ssh access to that server.
Most pictures resize fine but for every 10 pictures (more or less) I get jiberish data out.
I think it's a picture source. in that data there is always a string CREATOR: gd-jpeg v1.0 so I'm wondering what is this? I disabled any error output with # sign.
EDIT:
Here is the code, and also I disabled error output cause there aren't any errors and I thought that disabling error output would disable this jiberish data, but data is displayed no matter.
Code:
<?php
/*
big = 350
thumb = 90
thumb2 = 70
top = 215
*/
set_time_limit(0);
ini_set('memory_limit', '128M');
ini_set('display_errors', 'On');
class ResizeImages
{
private $dir = 'images/articles_backup_2009-12-19';
private $imageType = array(
'_big' => 'h:350',
'_thumb' => 'm:90',
'_thumb2' => 'h:70',
'_top' => 'h:215'
);
public function __construct()
{
$this->deleteImages();
$this->resizeImages();
}
private function resizeImages()
{
$n = 0;
$dh = opendir($this->dir);
while (($file = readdir($dh)) !== false)
{
if(is_dir($this->dir."/".$file) && $file != '.' && $file != '..')
{
echo $this->dir."/".$file.'<br />';
$deldir = opendir($this->dir."/".$file);
while (($filedel = readdir($deldir)) !== false)
{
if ($filedel != '.' && $filedel != '..' && $filedel != 'Thumbs.db')
{
$val = $this->resize($this->dir."/".$file."/".$filedel);
$n++;
}
}
}
}
closedir($dh);
}
private function resize($target)
{
$img = $target;
$origSize = getimagesize($img);
$origWidth = $origSize[0];
$origHeight = $origSize[1];
foreach($this->imageType as $key=>$value)
{
$attr = explode(':', $value);
if(strpos($attr[0], 'w') !== false)
{
$this->imageWidth = $attr[1];
$this->imageHeight = false;
}
if(strpos($attr[0], 'h') !== false)
{
$this->imageHeight = $attr[1];
$this->imageWidth = false;
}
$imageTmp = explode('.', $img);
if(count($imageTmp) == 2) $image_name_fin = $imageTmp[0].$key.'.'.$imageTmp[1];
else if(count($imageTmp) == 4) $image_name_fin = $imageTmp[0].'.'.$imageTmp[1].$key.'.'.$imageTmp[2];
if($this->imageWidth != false)
{
if($origWidth <= $this->imageWidth)
{
$resizeHeight = $origHeight;
$resizeWidth = $origWidth;
}
else
{
$resizeHeight = round($origHeight / ($origWidth / $this->imageWidth));
$resizeWidth = $this->imageWidth;
}
}
else if($this->imageHeight != false)
{
if($origHeight <= $this->imageHeight)
{
$resizeHeight = $origHeight;
$resizeWidth = $origWidth;
}
else
{
$resizeWidth = round($origWidth / ($origHeight / $this->imageHeight));
$resizeHeight = $this->imageHeight;
}
}
$im = ImageCreateFromJPEG ($img) or // Read JPEG Image
$im = ImageCreateFromPNG ($img) or // or PNG Image
$im = ImageCreateFromGIF ($img) or // or GIF Image
$im = false; // If image is not JPEG, PNG, or GIF
if (!$im)
{
$this->error = array(
'error' => true,
'notice' => 'UPLOADUNSUCCESSFULL'
);
return $this->error;
}
$thumb = ImageCreateTrueColor ($resizeWidth, $resizeHeight);
ImageCopyResampled ($thumb, $im, 0, 0, 0, 0, $resizeWidth, $resizeHeight, $origWidth, $origHeight);
ImageJPEG ($thumb, $image_name_fin, $this->imageQuality);
//echo $image_name_fin.'<br />';
}
$this->error = array(
'imageUrl' => $image_name,
'error' => false,
'notice' => 'IMAGEUPLOADED'
);
return $this->error;
}
private function deleteImages()
{
$dh = opendir($this->dir);
while (($file = readdir($dh)) !== false)
{
if(is_dir($this->dir."/".$file))
{
//echo $file.'<br />';
$deldir = opendir($this->dir."/".$file);
while (($filedel = readdir($deldir)) !== false)
{
if(strpos($this->dir."/".$file."/".$filedel, '_big.') !== false || strpos($this->dir."/".$file."/".$filedel, '_thumb.') !== false || strpos($this->dir."/".$file."/".$filedel, '_thumb2.') !== false || strpos($this->dir."/".$file."/".$filedel, '_top.') !== false)
{
unlink($this->dir."/".$file."/".$filedel);
}
}
}
}
closedir($dh);
}
}
$batch = new ResizeImages;
?>
At the top add this:
error_reporting(E_ALL);
And try changing this:
$im = ImageCreateFromJPEG ($img) or // Read JPEG Image
$im = ImageCreateFromPNG ($img) or // or PNG Image
$im = ImageCreateFromGIF ($img) or // or GIF Image
$im = false; // If image is not JPEG, PNG, or GIF
To this:
$im = ImageCreateFromString(file_get_contents($img));
Did it help? Also is there any pattern on the corrupted images? Are they all of the same type?
Well, the first thing would be to remove the error suppression to see if there is any errors. Seeing some of your code could be helpful as well.
EDIT
Ok, too late to fix your problem, but here is another suggestion for your code. All that "readdir, decide if file, build path" stuff is just a pain to use (and look at). Try this for an alternative:
class ImageFilterIterator extends FilterIterator
{
public function accept()
{
$ext = pathinfo($this->current()->getRealPath(), PATHINFO_EXTENSION);
return stripos('.gif|.jpg|.png', $ext);
}
}
$path = '.';
$images = new ImageFilterIterator(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path)));
Iterators are from the SPL and while they are somewhat puzzling to use at first, they can make development much easier once you understood them. With the above you can now loop over $image and get all filenames ending in .gif, .jpg or .png from all directories below path, like this:
foreach($images as $image) {
echo $image;
}
In fact, $image is not just a string, but an SplFileInfo object, so you also get a bunch of useful other methods with it.

Categories