Crop Uploaded Image To 1:1 Ratio PHP - php

I have my own PHP function allowing users to update their profile image.
It all works fine, however, I am having a problem where users can upload any size image they want; i.e: 564 x 346.
I do not want this to happen. I would like the image that they select to upload to be cropped to a 1:1 ratio and centred; i.e: it goes from 564 x 346 to 346 x 346 and centres to the middle of the image.
None of the scripts that I have found seem to work for my site (at least the way I want them to).
This is the code I am currently using to update their avatar. It consists of checking if they have a correct file extension & if the image is less than 256kb in size:
$ext = array('jpg', 'jpeg', 'png');
$file = $_FILES['avatar']['name'];
$fileext = strtolower(end(explode('.', $file)));
$filetmp = $_FILES['avatar']['tmp_name'];
if(!in_array($fileext, $ext)){
$errors[] = 'Please select a valid file type. (JPG, JPEG or PNG)'; }
if($_FILES['avatar']['size'] > 256000){
$errors[] = 'Avatars cannot exceed a 256kb file size.';
}
if(empty($errors)){
updateAvatar($conn, $username, $filetmp, $fileext);
} else if(!empty($errors)){
echo output_errors($errors);
}
if(isset($_SESSION['updateAvat'])){
flash('You have successfully updated your avatar.');
unset($_SESSION['updateAvat']);
}
This is the updateAvatar() function that I have made and is called on line 13:
function updateAvatar($conn, $username, $filetmp, $fileext){
$file = md5(microtime() . $filetmp) . '.' . $fileext;
$filepth = './data/user_data/img/udid/prof/' . $file;
move_uploaded_file($filetmp, $filepth);
if(mysqli_query($conn, "UPDATE users SET profile = '$file' WHERE username = '$username'")){
$_SESSION['updateAvat'] = md5(microtime() . $filetmp);
} else {
$errors[] = 'There was a problem updating your avatar. Please try again.';
}
}
However, this is not enough and does not allow my users profile page to work or look the way it should, I am going for something along the lines of how Google or Twitter do their avatar's.
All help is appreciated.
Cheers.

There is imagecrop() function in php:
$tmpfile = $_FILES['avatar']['tmp_name'];
switch ($fileext) {
case 'jpg':
case 'jpeg':
$image = imagecreatefromjpeg($tmpfile);
break;
case 'png':
$image = imagecreatefrompng($tmpfile);
break;
default:
die("wtf is this extension??");
}
list($w, $h) = getimagesize($imgfile);
// get width $w and height $h for the image
if ($w < $h) // then keep the width and scale the height
$image = imagecrop($image, array(
"x" => 0,
"y" => ($h - $w) / 2,
"width" => $w,
"height" => $w
));
else if ($h < $w) // then keep the height and scale the width
$image = imagecrop($image, array(
"x" => ($w - $h) / 2,
"y" => 0,
"width" => $h,
"height" => $h
));
I haven't tried this code but I'm quite sure it's right. Try it and tell me if it doesn't work.
UPDATE:
Then you can save the resource $image with imagejpeg() or imagepng() to save the images with the same extensions so you won't have problems with the database:
imagejpeg($image, "/path/to/your/image.jpg");

This is an explanation of how the process works, this is not a copy
and paste code but a description of the logic processes you need to
understand to resize images in PHP
You want to be using PHP imagecopyresampled to take the original image and then work out mathematically the margins to make it a square and then resize that square.
Process:
Uploaded image is checked is a genuine image and genuine filetype.
Using imagecreatefromjpeg (or similar ones for PNG etc.) you can import the uploaded image file resource.
Using getimagesize you can find the dimensions, you can then find the aspect ratio of the image.
If the aspect ratio is > 1 then width is larger than height so you then need to assume a square the same size as height (as it's the smaller value). For example:
.
Width: 450
Height: 300
Ratio = 450/300 = 3/2 = 1.5 = >1
If the aspect ratio is <1 then the height is larger than the width.
So you want a square that is 300x300 so you need to cut off the excess 150 from the width. This is called the Margin, and to centre the image you need to cut off half of the margin from each side so:
.
$fullMargin = (width- height)
$margin = $fullMargin/2
Just before resizing and saving the new image, a new image resource should be generated:
.
$max_width = $max_height = 256;
$smallestDimensionValue = $originalHeight //(in this example);
$newImage = imagecreatetruecolor($max_width,$max_height);
$sourceHeight = $originalHeight;
$sourceWidth = $originalWidth - $fullMargin;
Finally, Image copy and resample and the output should be as intended:
.
imagecopyresampled($nwImage, $sourceImage, 0,0,$margin,0,$max_width,$max_height,$sourceWidth,$sourceHeight);
PHP scales the image in the imagecopyresampled automatically, but to understand it, Once you've established the Margin size for the full size image you then have to multiply the margin by the same value as the width and the height to scale the overall image to the appropriate size.
Say for example you want the avatar to have a maximum size of 256px then:
maximum_allowed_width / original_width = scale_factor.
So for the example above this is:
256 / 450 = 0.56888888
This is the value the margin value defined above, as well as the height and width of the destination image, is multiplied by.

Related

How i can resize Adobe Illustrator Artwork (AI) File to increased Dimension without losing quality in PHP using ImageMagick?

When user upload AI file then if Dimension of an uploaded file is less than or equal to (180 x 180) then I want to resize this file to increased dimension (277 x 277) and then convert it to JPG. I tried code mentioned below. I tried all ways which are commented in the code.
$image_rs = new Imagick();
$image_rs->readimage(realpath(SOURCE_UPLOAD_PATH.$source_file_name));
if($fileType == "ai"){
$image_rs->setIteratorIndex(0);
}
$dimensions = $image_rs->getImageGeometry();
$width = $dimensions['width'];
$height = $dimensions['height'];
if($width <= 180 && $height <= 180){
//$image_rs->magnifyImage();
$image_rs->setImageFormat($source_file_ext);
$image_rs->scaleImage(277,0);
// $image_rs->adaptiveResizeImage(277,277);
// $image_rs->resizeImage(277,277,\Imagick::FILTER_CATROM, 1, true);
$image_rs->writeImage(realpath(RESIZED_UPLOAD_PATH)."/". $source_file_name);
$image = new Imagick();
$image->readimage(realpath(RESIZED_UPLOAD_PATH.$source_file_name));
if($fileType == "ai"){
$image->setIteratorIndex(0);
}
$dimensions = $image->getImageGeometry();
$width = $dimensions['width'];
$height = $dimensions['height'];
$image->thumbnailImage($width, $height);
$image->writeImage(realpath(CONVERTED_UPLOAD_PATH)."/". $source_file_name_without_ext.".jpg");
}
Issue: By using this code image is resized successfully but resized AI file also becomes blurry. because of Imagick library when resizing the image it converts AI file to jpg. AI file is vector file so there is no chance to become blurry even if we increase dimension. So how I can do this by imagemagick?

Image crop and comparision

When i submit a new image to database which is extracted from pdf,it should be cropped image of original image. If the image already exists in database, than image should not be inserted and if its not inserted,i have to generate an identification value for that.
The identification value will also be inserted to the same table as of image.
There are keys involved. table page have the following identies
pid,qid,pidentifierval,image
$record = array('pid' => "NULL",
'qid' => $qid,
'pidentifierval' => $pid,
'image' => $crop,
'rotation' => 0);
function newquestionnaire($filename,$desc = "",$type="pngmono"){
global $db;
if ($desc == "") $desc = $filename;
//generate temp file
$tmp = tempnam(TEMPORARY_DIRECTORY, "FORM");
//print "Creating PNG files<br/>";
//use ghostscript to convert to PNG
exec(GS_BIN . " -sDEVICE=$type -r300 -sOutputFile=\"$tmp\"%d.png -dNOPAUSE -dBATCH \"$filename\"");
//add to questionnaire table
//
//create form entry in DB
//
$db->StartTrans();
$sql = "INSERT INTO questionnaires (qid,description,sheets)
VALUES (NULL,'$desc',0)";
$db->Execute($sql);
$qid = $db->Insert_Id();
//Number of imported pages
$pages = 0;
//read pages from 1 to n - stop when n does not exist
$n = 1;
$file = $tmp . $n . ".png";
while (file_exists($file))
{
$data = file_get_contents($file);
$images = split_scanning($data);
unset($image);
unset($data);
foreach($images as $data)
{
//header Cropped Function
// Original image
$filename = $data;
// Get dimensions of the original image
list($current_width, $current_height) = getimagesize($filename);
// The x and y coordinates on the original image where we
// will begin cropping the image
$left = 50;
$top = 50;
// This will be the final size of the image (e.g. how many pixels
// left and down we will be going)
$crop_width = 200;
$crop_height = 200;
// Resample the image
$canvas = imagecreatetruecolor($crop_width, $crop_height);
$current_image = imagecreatefromjpeg($filename);
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
$crop = imagepng($canvas, $filename, 100);
//check for header Cropped Image
what function should i made here ?
$pid = $pid.$pages;
if ($pid)
{
$pages++;
$record = defaultpage($qid,$pid,$crop);
$db->AutoExecute('pages',$record,'INSERT');
}
else
print T_("INVALID - IGNORING BLANK PAGE");
unset($data);
unset($crop);
i am confused here,that how should i check and compare if the image exists in the database or not. Please help
For cropping the image
i have found a solution
$data = '1.png';
list($current_width, $current_height) = getimagesize($data);
// The x and y co-ordinates on the original image where we will begin cropping the image
$left = 1100;
$top = 30;
// final size of image
$crop_width = 200;
$crop_height = 200;
//Resample the Image
$canvas = imagecreatefromtruecolor($crop_width, $crop_height);
$current_image = imagecreatefrompng($data);
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
imagepng($canvas, $data, 100);
For comparing two images
array image_compare(mixed $image1, mixed $image2, int $RTolerance, int $GTolerance, int $BTolerance, int $WarningTolerance, int $ErrorTolerance)
Parameters
image1
- A string containing the path to the image, or a resource of an image already created by GD Library. This is the first image to be compared.
image2
- A string containing the path to the second image, or a resource of the second image already created by GD Library. This will be the second image to be compared.
RTolerance, GTolerance, BTolerance (0-255)
- Specifies the maximum deviation for the red, green, or blue (respectively) channel before throwing a flag.
WarningTolerance (0-100)
- Percentage of channel differences before warning returned.
ErrorTolerance (0-100)
- Percentage of channel differences before error (flag) returned.
Return Values
An array will be returned with the following information:
PixelsByColors
- Pixel quantity * 3 (for each of R,G, and B channels).
PixelsOutOfSpec
- (If a pixel varies outside of xTolerance, for each red, green, and blue. Where x = R/G/B) If any channel exceeds the threshhold, this number is incremented.
PercentDifference
- The percentage of difference comparing PixelsOutOfSpec to PixelsByColors
WarningLevel and ErrorLevel
- If the percentage was large enough to trigger either the specified warning, or error level.
For comparison i have to work, i am thinking to use array.Using Select query for
getting images from the database,using while loop and fetching the result in array,calling array keys for the image to be stored in variable and using if else condition in the compare function above will work i think. What you people think ?
For image comparision, No Scanned image can be 100 percent accurate, so image comparision is not so easy. It is quite hectic task.
After a Lot of Research and work, I came to a point that if it is 100 percent necessary to do image comparision. I will have to use Php-OpenCV Library. If i have to allow some sort of error tolerance, the above class can work properly. My work can was achieved using Php-tesseract. I have simply used tesseract-OCR. I used ghostscript for converting the PDF into png, cropped the image, convert that particular part of image into text using Php-tesseract OCR Library that is placed on google Code website. Called that text into variable,using regexpression i was able to check that whether a particular text exists in the variable or not and used it in the condition as requried for me.
Consider this as end of my problem.
For convenience of the visitors i am pasting my Code Snippet so that it can be used.
// Cropping the image
// Get dimensions of the original image
list($current_width, $current_height) = getimagesize($file);
// The x and y co-ordinates on the original image where we will begin cropping the image
$left = 1100;
$top = 30;
// final size of image
$crop_width = 700;
$crop_height = 200;
//Resample the Image
$canvas = imagecreatetruecolor($crop_width,$crop_height);
$current_image = imagecreatefrompng($file);
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
imagepng($canvas, $file, 1);
// Note you will have to install Php tesseract Library before making the API Call.
$api= new TessBaseAPI;
$api->Init(".","eng",$mode_or_oem=OEM_DEFAULT);
$api->SetPageSegMode(PSM_AUTO);
$mImgFile = $file;
$handle=fopen($mImgFile,"rb");
$mBuffer=fread($handle,filesize($mImgFile));
//print strlen($mBuffer);
$result=ProcessPagesBuffer($mBuffer,strlen($mBuffer)*4,$api);
//print $result;
$result = ProcessPagesFileStream($mImgFile,$api);
//print "result(ProcessPagesFileStream)=";
print $result;
$txtchk = 'FORM';
if(preg_match("/$txtchk/i", $result)) {
echo true;
}
I hope it will be helpful for lot of people.

PHP Uploading a Large image and resizing with proportion like Photoshop

A quick brief. We currently have to make small, medium and large images based on product images we have on our site. Not being a wiz on PHP I thought I would still try to automate this nightmare.
The image we upload and dimension of the thumb is below
800 width x 1400 width LARGE
300 width x 525 width THUMB
The problem with my PHP script is that it just resizes with scaling to proportion. I want to it to be able to scale down like in Photoshop, you just click shift and the image scales. I am trying to use imagecopyresized but with little luck.
<?php
// PHP UPLOAD SCRIPT
// VALIDATION OF FORM
if($_FILES['user_image']['type'] == "image/jpeg" && $_FILES['user_image']['size'] < 3000000)
{
// VARS
$target_folder = 'images/';
$upload_image = $target_folder.basename($_FILES['user_image']['name']);
// UPLOAD FUNCTION
if(move_uploaded_file($_FILES['user_image']['tmp_name'], $upload_image))
{
// VARS FOR FILE NAMES
$thumbnail = $target_folder."medium_x.jpg";
$actual = $target_folder."large_x.jpg";
// THUMBNAIL SIZE
list($width, $height) = getimagesize($upload_image);
$newwidth = "300";
$newheight = "525";
// VARS FOR CALL BACK
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($upload_image);
// RESIZE WITH PROPORTION LIKE PHOTOSHOP HOLDING SHIFT
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// MAKE NEW FILES
imagejpeg($thumb, $thumbnail, 100);
// FILE RENAMES
rename($upload_image, $actual);
{
// SUCCESS MESSAGES
?>
<p>
Image Successfully uploaded!<br />
Actual image: <?=$actual;?><br />
Thumbnail image: <?=$thumbnail;?><br />
<h1>Large</h1>
<img src="<?=$actual;?>"/><br /><br />
<h1>Medium</h1>
<img src="<?=$thumbnail;?>"/><br /><br />
</p>
<?
}
// FAILED MESSAGES
}
else
{
echo 'Upload failed.';
}
}
else
{
// NOT A JPEG
echo 'Not a JPEG';
}
// END OF SCRIPT
?>
How can I resize properly without having a stretched image? Is it possible?
The easiest way to achieve this without buckets of PHP code is with Image Magick. See examples and sample command line here: http://www.imagemagick.org/Usage/resize/#fill
(can call from PHP using exec() or similar)
Edit: Implementation as follows:
if($_FILES['user_image']['type'] == "image/jpeg" && $_FILES['user_image']['size'] < 3000000)
{
// VARS
$target_folder = 'images/';
$upload_image = $target_folder.basename($_FILES['user_image']['name']);
$thumbnail = $target_folder."medium_x.jpg";
$actual = $target_folder."large_x.jpg";
$newwidth = "300";
$newheight = "525";
if(move_uploaded_file($_FILES['user_image']['tmp_name'], $upload_image))
{
exec('convert '.$upload_image.' -resize '.$newwidth.'x'.$newheight.'^ '.$thumbnail);
rename($upload_image, $actual);
}
}
...
etc
You could optimise the way you handle the upload but I didn't want too totally change the structure of your code as I don't know what surrounds it. But basically, you push the image to ImageMagick's convert, and it will work it's magic.
If you want to crop as well as scale, the exec command would be:
exec('convert '.$upload_image.' -resize '.$newwidth.'x'.$newheight.'^ -gravity center -extent '.$newwidth.'x'.$newheight.' '.$thumbnail);
Look at this code snippet. Does what you need. Basically used to maintain ratio when creating the thumb.
http://snipplr.com/view/753/

PHP GD imagecreatefromjpeg cant handle big size image?

my project is when im uploading an image automatically my program will create the thumb size.My program work normally if the size of picture about 1024x768 But when i'm uploading image with size 1576x2379 showing error like this:
Allowed memory size of 8388608 bytes exhausted (tried to allocate 1576 bytes)
I'm using method imagcreatefromjpeg().How can I create thumb version from big size image using PHP???
thanks
You have to edit your php.ini
Find the line with Memory limit statement and change its default value for something bigger - for example 128M
For me this problem solved with next peace of code:
first of all you need imagemagick on your server;
and install it also as part of php (php5-imagick)
my part of code (for Smart Image Resizer 1.4.1 )
i found line "$src = $creationFunction($docRoot . $image);"
and replace with
if ( $width >= 1900 )
{
// Read original image and create Imagick object
$thumb = new Imagick($docRoot . $image);
$newX = 1600;
$newY = 1200;
// Scale the image
$thumb->thumbnailImage($newX,$newY);
#$thumb->cropThumbnailImage(600,600);
// make new file-name
$_ext_pos = strrpos($image,'.');
$_image_name_p1 = substr($image, 0, $_ext_pos);
$_image_name_p2 = substr($image, $_ext_pos);
$thumbnailFilename = $_image_name_p1.'_s600'.$_image_name_p2;
// Write the new image to a file
$thumb->writeImage($docRoot . $thumbnailFilename);
$thumb->destroy();
// Read in the original image
$src = $creationFunction($docRoot . $thumbnailFilename);
// reset w-h
$size = GetImageSize($docRoot . $thumbnailFilename);
$width = $size[0];
$height = $size[1];
// Setting up the ratios needed for resizing.
// resize the image (based on height or based on width)
$xRatio = 1;#$maxWidth / $width;
$yRatio = 1;#$maxHeight / $height;
if ($xRatio * $height < $maxHeight)
{ // Resize the image based on width
$tnHeight = ceil($xRatio * $height);
$tnWidth = $maxWidth;
}
else // Resize the image based on height
{
$tnWidth = ceil($yRatio * $width);
$tnHeight = $maxHeight;
}
}
else
{
// Read in the original image
$src = $creationFunction($docRoot . $image);
}
so I replace the "ImageCreateFromJpeg" for large images with imagick-workflow
good luck!

I'm working on a website that sells different artwork, what's the best way to handle different image sizes?

I'm working on a website that will allow users to upload and sell their artwork in different sizes. I was wondering what the best way would be to handle the different file sizes automatically. A few points I was curious on:
How to define different size categories (small, medium, large) in such a way that I'll be able to dynamically re-size images with proportional dimensions.
Should I store actual jpegs of the different sizes for download? Or would it be easier to generate these different sizes for download on the fly
My thumbnails will be somewhat larger than your average thumbnails, should I store a second 'thumbnail image' with the sites watermark overlaying it? Or once again, generate this on the fly?
All opinions, advice are greatly appreciated!
I do something like this with aarongriffin.co.uk.
There, some images are resized on the fly the first time they are requested, and then they are stored; whilst others are generated at upload time. Images that tend to be requested in groups (i.e. thumbnails) are generated at upload time, and images that tend to be displayed one at a time are generated on the fly. This has worked well for me, but that's a site without too much traffic.
I'm working in Python and Django, so I use sorl-thumbnail for this. In PHP you've got access to the various imagecreatefrom* functions that do (sort of) the same thing.
I generate watermarked versions of photos (if a particular album should be watermarked), and store those instead of unwatermarked copies.
you can check php thumbnails for this. Here's a code snippet that maybe useful.
<?php
# Constants
define(IMAGE_BASE, '/var/www/html/mbailey/images');
define(MAX_WIDTH, 150);
define(MAX_HEIGHT, 150);
# Get image location
$image_file = str_replace('..', '', $_SERVER['QUERY_STRING']);
$image_path = IMAGE_BASE . "/$image_file";
# Load image
$img = null;
$ext = strtolower(end(explode('.', $image_path)));
if ($ext == 'jpg' || $ext == 'jpeg') {
$img = #imagecreatefromjpeg($image_path);
} else if ($ext == 'png') {
$img = #imagecreatefrompng($image_path);
# Only if your version of GD includes GIF support
} else if ($ext == 'gif') {
$img = #imagecreatefrompng($image_path);
}
# If an image was successfully loaded, test the image for size
if ($img) {
# Get image size and scale ratio
$width = imagesx($img);
$height = imagesy($img);
$scale = min(MAX_WIDTH/$width, MAX_HEIGHT/$height);
# If the image is larger than the max shrink it
if ($scale < 1) {
$new_width = floor($scale*$width);
$new_height = floor($scale*$height);
# Create a new temporary image
$tmp_img = imagecreatetruecolor($new_width, $new_height);
# Copy and resize old image into new image
imagecopyresized($tmp_img, $img, 0, 0, 0, 0,
$new_width, $new_height, $width, $height);
imagedestroy($img);
$img = $tmp_img;
}
}
# Create error image if necessary
if (!$img) {
$img = imagecreate(MAX_WIDTH, MAX_HEIGHT);
imagecolorallocate($img,0,0,0);
$c = imagecolorallocate($img,70,70,70);
imageline($img,0,0,MAX_WIDTH,MAX_HEIGHT,$c2);
imageline($img,MAX_WIDTH,0,0,MAX_HEIGHT,$c2);
}
# Display the image
header("Content-type: image/jpeg");
imagejpeg($img);
?>

Categories