How to resize an image like facebook cover - php

What basically I am trying to do is to create a cover page for my personal website, just like facebook. Basically I am after the same layout of the cover as on facebook, so that user can get the same result while using the same cover on my site as well as on facebook.
The part I am stucked at is the "Drag image to position cover" thing.
The Facebook uses some algorithm to convert the cover image size to something different during dragging thing. For example, if the original image dimensions are 920x720, the dimensions of same image while it is on facebook setting-cover page(drag image to position cover thing), the dimensions of the image are 851x638.
I just wanted to know what algorithm facebook uses to set the image dimensions(from 720 to 638)
NOTE: The cover has to be the pixel perfect
I know that the cover dimension of facebook is 851x315, so here is what I am doing:
//$x = X origin cordinate variable obtained by dragging image
//$y = Y origin cordinate variable obtained by dragging image
list($k, $l) = getimagesize($src); // $src == image source
//$w = Needs to be calculated
//$h = Needs to be calculated
$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( 854,316 );
imagecopyresampled($dst_r,$img_r,0,0,$x,$y,$w,$h,$k,$l);
imagejpeg($dst_r,$src,$jpeg_quality);
$img_name = writeToImage($src, $des); //writeToImage() is just a demo function created by me to do some other things with them which do not affect this part of code
echo $img_name;
I need to figure out how facebook calculates the new dimension of the image from previous one. Is it dependent of the actual(original) size of the image or is it dependent on some other factors?

The formulas for scaling images are quite simple.
$aspect_ratio = $original_width / $original_height;
$new_width = $new_height * $aspect_ratio;
or
$new_height = $new_width / $aspect_ratio;

Related

Best approach to create thumbnails?

Im working on a template for a website that has already more than 50,000 articles and images assigned to every article.
Before now the article image was visible only inside every article, but now I would like to use thumbnails.
I don't have access to modify the upload image form, so the solution should be something like virtual thumbs created from the original images...
What will be the best approach in this case?
Using Mr. Thumb like I advised a simple script to get it working would be
<?php
include './mrthumb.class.php';
// The image you are resizing. Can be a local path as well.
$image = $_GET['i'];
$quality = 100; // percent
// In this example we are resizing the image in proportionate sizes.
// Below we are specifying the MAX width and height.
$width = 100; // Pixels
$height = 130; // Pixels
// Start Mr. Thumb v1.0
$mrthumb = new MrThumb();
// Render the image
$mrthumb->render( $image );
// Resize the image proportionately
// $mrthumb->constrain( $width, $height );
$mrthumb->proportion( $width, $height );
// Finally, output the image to the browser!
// Optionally we can save the image to a destination
// $mrthumb->saveto( $destination, $filename, $quality );
$mrthumb->output( $quality );
// Clean up after you are done! ;)
$mrthumb->clear_cache();
?>
Then save that to your web server along with the mrthumb class and call a thumbnail in your webpage like
<img src="./mrthumb.php?i=images/myimage.jpg" alt="My Image" />

Upload Large Image & Crop Easier

I want to allow users to upload large photos of their home and crop it to fit properly into a slideshow. So I set it up that when the user uploads their large home photo it will store that and copy it and re-size the new copy to be a more manageable size. (ex. resizing a 5000x3333px image to 600x400px) Then this new image is displayed to the user to allow them to crop that image. After the image has been cropped 4 values are returned: x, y, w, and h. These are the values of the cropped area on the smaller image, but now we want to crop the original image not this smaller one. This means the w & h have to be increased and the x & y got to stay in correct position but this is the part that I'm so confused about. How do I properly scale up the w & h and keep x & y in right place to match the crop from the small image to the original large one?
Here is a code snippet of the final function that crops. This is using some of my homemade function, understand they are just there for convenience.
//User inputs from the crop area on the small image
$user_input_x = $_POST['x'];
$user_input_y = $_POST['y'];
$user_input_w = $_POST['w'];
$user_input_h = $_POST['h'];
//Grab original, small, and final image locations
$original_image_src = '/tmp/original_image';
$small_image_src = '/tmp/small_image';
$final_image_location = '/final/image';
//Return the extension for both the original and small image
if(($image_ext = imageCheck($original_image_src)) === false) die('Could not find original image source!');
$original_image_src .= $image_ext;
$small_image_src .= $image_ext;
$final_image_location .= $image_ext;
//Get the width and height of both the original and small image
list($original_image_width, $original_image_height) = getimagesize($original_image_src);
list($small_image_width, $small_image_height) = getimagesize($small_image_src);
//Converts string location of image into php resource
//This function helps determine the type of image and create the resource
$src_image = createImage($original_image_src);
//This is the area where I am having trouble
//I need to scale up the users input x,y,w,h because they are from small image and need to match to original
//These are the vars to go into all the final fields
$src_x = $user_input_x;
$src_y = $user_input_y;
$src_w = 0;
$src_h = 0;
$crop_x = 0;
$crop_y = 0;
$crop_w = 0;
$crop_h = 0;
$final_image = imagecreatetruecolor($crop_w, $crop_h);
if(!imagecopyresampled($final_image, $src_image, $crop_x, $crop_y, $src_x, $src_y, $crop_w, $crop_h, $src_w, $src_h)) die('Could not resmaple image!');
//Saves image to final location retains the extension and destroys the resource
if(imageSave($final_image, $final_image_location, $image_ext) === false) die('Count not save image!');
Oh and if it help any, this crop is being done by jCrop which is pretty much providing the x, y, w & h.
As far as I understand x and w, and y and h scale at the same ratio.
$crop_y = $original_image_height/$small_image_height*$user_input_y;
$crop_h = $original_image_height/$small_image_height*$user_input_h;
$crop_w = $original_image_width/$small_image_width*$user_input_w;
$crop_x = $original_image_width/$small_image_width*$user_input_x;
I drew this to try and visualise it.
http://i58.tinypic.com/32zm0it.jpg

How to set original image height & width on resize script?

I've finally been able to complete the script for an multiple image resizer, currently it's resizing the original image into 3 other sizes, but I am unable to figure out how to set the original height and width. I have used the getimagesize() but it does not seem to work.
The whole code is here but I don't think it's necessary to post all of it here. http://pastebin.com/UR75tdj3
I have done the following to set each of the images height and width I'd like them to resize into.
$uploadedfile = $_FILES['file']['tmp_name'];
list($width,$height)= getimagesize($uploadedfile);
#large
$largeWidth = 670;
$largeHeight = 330;
$largeTmp = imagecreatetruecolor($largeWidth, $largeHeight);
#medium
$mediumwidth = 330;
$mediumheight = 330;
$mediumTmp = imagecreatetruecolor($mediumWidth,$mediumHeight);
#small
$smallWidth = 327;
$smallHeight = 158;
$smallTmp = imagecreatetruecolor($smallWidth,$smallHeight);
but I wanted to enter the orignal into another folder as well, so I did the following thinking that getimagesize($_FILES['file']['tmp_name']) would return them correctly but it did not.
#original
$originalWidth = $width; //here and
$originalHeight = $height; // here
$originalTmp = imagecreatetruecolor($originalWidth,$originalHeight);
So how do I get the original image height and width as I have tried to do above?
$originalWidth and $originalHeight should return the specific images width & height, but it does not, that is the only issue I am having.
you want to check the size of
$_FILES['file']['tmp_name']
the actull uploaded file as stored on the system
not $_FILES['file']['name'] which is just the filename

How to crop and image before adding an overlay? (GD) (PHP)

My code so far (it creates an overlay to a youtube thumbnail):
<?php
header("Content-type:image/png");
$background=imagecreatefromjpeg("http://img.youtube.com/vi/".$_GET['v']."/default.jpg");
$insert=imagecreatefrompng("play.png");
imagecolortransparent($insert,imagecolorat($insert,0,0));
$insert_x=imagesx($insert);
$insert_y=imagesy($insert);
imagecopymerge($background,$insert,5,57,0,0,$insert_x,$insert_y,100);
imagepng($background,NULL);
The output image is 120x90px, but i need it to have 90x90px.
Anyone knows how this is possible?
Thanks in advance!
http://www.johnconde.net/blog/cropping-an-image-with-php-and-the-gd-library/
<?php
header("Content-type:image/png");
$background = imagecreatefromjpeg("http://img.youtube.com/vi/".$_GET['v']."/default.jpg");
$insert = imagecreatefrompng("play.png");
imagecolortransparent($insert,imagecolorat($insert,0,0));
list($current_width, $current_height) = getimagesize($background);
$left = 0;
$top = 0;
$crop_width = 90;
$crop_height = 90;
$canvas = imagecreatetruecolor($crop_width, $crop_height);
$current_image = $background;
imagecopy($canvas, $current_image, 0, 0, $left, $top, $current_width, $current_height);
imagecopymerge($canvas,$insert,5,57,0,0,$current_width,$current_height,100);
imagepng($canvas);
?>
try that it should work if not comment as to otherwise.
This is taken from a function I wrote to create square thumbnails. You may find the commentary I wrote for myself helpful. Depending on your needs (i.e if you can't afford to make assumptions about the type and dimensions of incoming images) you may need to add additional checks. To avoid smashed or stretched thumbnails we take a central part of the image which is most likely to contain something distinguishable as source co-ordinates.
The basic idea is: Since imagecopyresampled or imagecopyresized also allow you to specify destination and source coordinates, you can copy only part of your original image to a new canvas and save that (or directly output to browser). To avoid smashed or stretched dimensions we take a central part of the original image which is most likely to contain distinguishable content.
//assuming you have already merged your $background image with your overlay at this point
//original dimensions
$original_width = imagesx($background);
$original_height = imagesy($background);
//new dimensions
$new_width = 90;
$new_height = 90;
//the center of the rectangular image
$center = $original_width/2, $original_height/2
//the coordinates from where to start on the original image
//assuming you want to crop the center part
$src_x = floor(($original_width/2) - ($new_width/2));
$src_y = floor(($original_height/2) - ($new_height/2));
//create a new canvas with the new desired width, height
$temp = imagecreatetruecolor(90,90);
//copy the large image to this new canvas
imagecopyresampled($temp,$background,0,0,$src_x,$src_y,$new_width,$new_height,$original_width,$original_height);
//from right to left: source image, destination image, dest x, dest y,
//source x, source y, new width, new height, original width, original height
//save the canvas as an image
imagepng($temp);
This could be improved to handle larger images by first taking a central part relative to it's size and then scaling it down to the new canvas.

Slow getimagesize

I need to show multiple posts on my website. These posts are combined of internal and external posts. The external posts are periodically imported and saved in my DB using a cronjob.
Before showing the posts I extract the text from all HTML. In addition I try to locate the first image contained in the post, continuing until I find an image which height & width meets my requirements. (I only show a small version of the text, and one picture from the post as a teaser)
For the purpose of finding the most suitable picture, I use getimagesize, but unfortunately this often creates PHP Execution time of several seconds!
How can I speed up my function below? I'm desperate for tips and good tweaking methods!!
Thanks in advance
//extract text without tags from blog post
$content = str_get_html("".$post_text."")->plaintext;
$max_width = 475;
$picture_id = 0;
//fetch images from blog post
foreach($html->find('img') as $e) {
//get picture attributes
list($width, $height, $type, $attr) = getimagesize((is_absolute_url($e->src) ? $e->src : $_SERVER['DOCUMENT_ROOT'].$e->src));
//adjust image width & height, so it's the size of the page
$new_width = $max_width;
$new_height = $new_width / $width * $height;
//find percentage of current width versus max width
$percentage = ($width / $max_width) * 100;
//select picture for display and resizing if the picture is large enough (we don't want to stretch it too much)
if($percentage >= 60) {
$e->width = $new_width;
$e->height = $new_height;
$picture = array('src' => $e->src, 'width' => $e->width, 'height' => $e->height);
//stop after first picture is found :: we only need one per post
if (++$picture_id == 1) break;
}
}
Reason: It is a very well known issue that getimagesize works slow on remote files.
Solution: It is advised to store the files on your local server (temporarily) and then do getimagesize on it.
When you pass a url as a parameter to getimagesize, it gets the image through HTTP, what is a slow process.
You should get its size only the first time and save it in a database for the future.

Categories