PHP if image exceeds 1000px using getimagesize() - php

I'm using the remote method used in jQuery Validation.
I'm referring to a PHP file shown below:
<?php
$title = mysql_real_escape_string($right_form_url);
$size = getimagesize($title);
$size[3] = $width;
if ($width > 1000) {
$output = false;
} else {
$output = true;
}
echo json_encode($output);
?>
It never returns anything no matter how I put the $output variables. I've tried other PHP files that I know work in validation, so I think it has something to do with my IF statement, although I'm fairly certain the width is being declared correctly.

You code is invalid. You are setting $size[3] = $width; which sould be $width = $size[0];
Two mistakes:
1. You were setting $size[3] to $width, but should set $width to $size[3]
2. $size[3] containts string valu t use with html image tag(height="yyy" width="xxx"), $size[0] conatins numeric value of width

I think i know your problem, here, the json_enconde function only supports data with UTF-8 encoding, then if your site uses another encoding, the function will return NULL, so try this:
<?php
$title = mysql_real_escape_string($right_form_url);
$size = getimagesize($title);
$size[3] = $width;
$output = true;
if ($width > 1000) {
$output = false;
}
echo json_encode(base64_encode($output));
?>

Related

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.

PHP code working on local server but not on domain

I seem to be having a problem with a few lines of code in the sense that it works on my local server on xampp but when I upload over FTP to my domain it not longer works. I have attached the code snippet as well as the file it includes. What the domain does is just completely disregard the code and proceed as if it wasn't there. Any help is much appreciated in advance!
code snippet
<?php
include_once("colors.inc.php");
$ex=new GetMostCommonColors();
$ex->image="http://maps.googleapis.com/maps/api/staticmap?center=25.437484181498,-89.594942854837&zoom=50&size=600x300&maptype=roadmap&markers=color:blue&sensor=false";
$colors=$ex->Get_Color();
$how_many=12;
$colors_key=array_keys($colors);
?>
colors.inc.php
<?php
class GetMostCommonColors
{
var $image;
function Get_Color()
{
if (isset($this->image))
{
$PREVIEW_WIDTH = 150; /
$PREVIEW_HEIGHT = 150;
$size = GetImageSize($this->image);
$scale=1;
if ($size[0]>0)
$scale = min($PREVIEW_WIDTH/$size[0], $PREVIEW_HEIGHT/$size[1]);
if ($scale < 1)
{
$width = floor($scale*$size[0]);
$height = floor($scale*$size[1]);
}
else
{
$width = $size[0];
$height = $size[1];
}
$image_resized = imagecreatetruecolor($width, $height);
if ($size[2]==1)
$image_orig=imagecreatefromgif($this->image);
if ($size[2]==2)
$image_orig=imagecreatefromjpeg($this->image);
if ($size[2]==3)
$image_orig=imagecreatefrompng($this->image);
imagecopyresampled($image_resized, $image_orig, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);
$im = $image_resized;
$imgWidth = imagesx($im);
$imgHeight = imagesy($im);
for ($y=0; $y < $imgHeight; $y++)
{
for ($x=0; $x < $imgWidth; $x++)
{
$index = imagecolorat($im,$x,$y);
$Colors = imagecolorsforindex($im,$index);
$Colors['red']=intval((($Colors['red'])+15)/32)*32;
$Colors['green']=intval((($Colors['green'])+15)/32)*32;
$Colors['blue']=intval((($Colors['blue'])+15)/32)*32;
if ($Colors['red']>=256)
$Colors['red']=240;
if ($Colors['green']>=256)
$Colors['green']=240;
if ($Colors['blue']>=256)
$Colors['blue']=240;
$hexarray[]=substr("0".dechex($Colors['red']),-2).substr("0".dechex($Colors['green']),-2).substr("0".dechex($Colors['blue']),-2);
}
}
$hexarray=array_count_values($hexarray);
natsort($hexarray);
$hexarray=array_reverse($hexarray,true);
return $hexarray;
}
else die("You must enter a filename! (\$image parameter)");
}
}
?>
I agree with #Rodrigo Brun but would also encourage you to see if your hosting client has support for the GD library in PHP. You can check by creating a page in your directory with the contents <?php phpinfo(); ?> and see if it supports GD. Sometimes this is turned off and can be easily fixed by editing your php.ini file. I had a similar problem and this solved it so best of luck and hope this helped!
Most web servers by default, not permit open files from url ( Remote files ), using basic functions, like, file_get_contents("http://...") or getimagesize("http://..."). This is a security problem, is not recommended to use this methods to get properties of remote images or files. Try the Curl library, it's more safe, and builded for this.
But in your local server , generally your php is enabled to open remote files, via basic functions.
So, you can modify your php.ini ( searching for "allow_url_fopen" , and setting the value to "1"), or, you can use direct in your php code (first line),
ini_set("allow_url_fopen",1);
this function is to "replace" the config in php.ini, but without change the original php.ini file , only in execution time.
Resuming: two answers to your question are avaible, CURL or INI_SET (allow_url_fopen).
Hope I have helped.
[EDITED] -----------
Hi, the following code adapted to your requirements, using curl library to get Width, height and Mime-type of image ( in a INTEGER and STRING values ).
Just add this 3 functions into your class "{}". after var $image
function getImageBytes(){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->image);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$info = curl_exec($ch);
curl_close($ch);
return $info;
}
function getSize(){
$bytes = $this->getImageBytes();
$img = imagecreatefromstring($bytes);
$out = array();
$out[0] = imagesx($img);
$out[1] = imagesy($img);
$f = finfo_open();
$mime = finfo_buffer($f, $bytes, FILEINFO_MIME_TYPE);
$out[2] = $this->getIntMimeType($mime);
$out[3] = $mime;
return $out;
}
function getIntMimeType($m){
switch ($m) {
case "image/gif":
return 1;
case "image/jpeg":
return 2;
case "image/png":
return 3;
default:
return 0;
}
}
Now, for correct result, change this line
$size = GetImageSize($this->image);
To new function
$size = $this->getSize();
It's not necessary to pass parameters in new function. The $this->image variable it's used in "getImageBytes" function.
The function getIntMimeType($m) is for your conditions $size[2]==1... Just a translator of string to integer.
Value of index 3 in $size now is the mime-type in string (ex. image/png or image/gif ).
:)

PHP - Get information about image (Height and Width) without loading it

Is it possible to get image information without loading the actual image with PHP? In my case I want the Height and Width.
I have this code to fetch images from a directory. I echo out the image's url and fetch it with JS.
<?php
$directory = "./images/photos/";
$sub_dirs = glob($directory . "*");
$i = 0;
$len = count($sub_dirs);
foreach($sub_dirs as $sub_dir)
{
$images = glob($sub_dir . '/*.jpg');
$j = 0;
$len_b = count($images);
foreach ($images as $image)
{
if ($j == $len_b - 1) {
echo $image;
} else {
echo $image . "|";
}
$j++;
}
if ($i == $len - 1) {
} else {
echo "|";
}
$i++;
}
?>
getImageSize() is the proper way to get this information in PHP
It does a minimal amount of work based on the type of image. For example, a GIF image's height/width are stored in a header. Very easy to access and read. So this is how the function most likely gets that information from the file. For a JPEG, it has to do a little more work, using the SOFn markers.
The fastest way to access this information would be to maintain a database of file dimensions every time a new one is uploaded.
Given your current situation. I recommend writing a PHP script that takes all of your current image files, gets the size with this function, and then inserts the info into a database for future use.
It depends what you mean by "without loading it".
The built-in getimagesize() does this.
list($w, $h) = getimagesize($filename);
You can programmatically get the image and check the dimensions using Javascript...
var img = new Image();
img.onload = function() {
alert(this.width + 'x' + this.height);
}
img.src = 'http://www.google.com/intl/en_ALL/images/logo.gif';
This can be useful if the image is not a part of the markup ;)
You can store the width'n'height information in a text file, and load it later on.
list($width, $height, $type, $attr) = getimagesize($_FILES["Artwork"]['tmp_name']);
Use this.

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.

Rails + AMcharts (with export image php script) - PHP script converted to controller?

This one might be a little confusing. I'm using AMCharts with rails. Amcharts comes with a PHP script to export images called "export.php"
I'm trying to figure out how to take the code in export.php and put it into a controller.
Here is the code:
<?php
// amcharts.com export to image utility
// set image type (gif/png/jpeg)
$imgtype = 'jpeg';
// set image quality (from 0 to 100, not applicable to gif)
$imgquality = 100;
// get data from $_POST or $_GET ?
$data = &$_POST;
// get image dimensions
$width = (int) $data['width'];
$height = (int) $data['height'];
// create image object
$img = imagecreatetruecolor($width, $height);
// populate image with pixels
for ($y = 0; $y < $height; $y++) {
// innitialize
$x = 0;
// get row data
$row = explode(',', $data['r'.$y]);
// place row pixels
$cnt = sizeof($row);
for ($r = 0; $r < $cnt; $r++) {
// get pixel(s) data
$pixel = explode(':', $row[$r]);
// get color
$pixel[0] = str_pad($pixel[0], 6, '0', STR_PAD_LEFT);
$cr = hexdec(substr($pixel[0], 0, 2));
$cg = hexdec(substr($pixel[0], 2, 2));
$cb = hexdec(substr($pixel[0], 4, 2));
// allocate color
$color = imagecolorallocate($img, $cr, $cg, $cb);
// place repeating pixels
$repeat = isset($pixel[1]) ? (int) $pixel[1] : 1;
for ($c = 0; $c < $repeat; $c++) {
// place pixel
imagesetpixel($img, $x, $y, $color);
// iterate column
$x++;
}
}
}
// set proper content type
header('Content-type: image/'.$imgtype);
header('Content-Disposition: attachment; filename="chart.'.$imgtype.'"');
// stream image
$function = 'image'.$imgtype;
if ($imgtype == 'gif') {
$function($img);
}
else {
$function($img, null, $imgquality);
}
// destroy
imagedestroy($img);
?>
There are some versions in existence in a thread I found here: http://www.amcharts.com/forum/viewtopic.php?id=341
But I have a feeling the PHP code above has changed since then - because neither implementation worked for me.
What this code more or less dose is grabs the informations, that were sent to the script (POST).
The informations include the height and width of the picture and the RGB values of every pixel. The script draws every pixel and sends the images at the end to the client.
You can use Rmagick's method to draw a pixel. This will give you the same result.
The incomming post data looks like this:
height = number -> cast to int
width = number -> cast to int
// first row with a repeating part of R:G:B,R:G:B,... (n = width)
r0 = 255:0:0,150:120:0,77:88:99,...
r1 = ...
.
.
r100 = ... -> the row count is the height - 1
Actually, I found a discussion about speeding up pixel by pixel drawing.
So apparently I was running into other errors which made me think the already existing code didnt work. However, the code on the thread I linked to in the original question does in fact work!

Categories