How to crop and image before adding an overlay? (GD) (PHP) - 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.

Related

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 resize an image like facebook cover

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;

Rotate image on top of background-image

I have two images. one is a jpg image of a rotated polaroid frame polaroid.jpg. The other is just an ordinary image image.jpg.
I'm trying to rotate the image, and then put it on top of the polaroid-image, and then show the merged images as one jpg-image.
I think I'm pretty close with the following code, but I can't manage to get the transparancy working. The uncovered zone of the rotated image is black instead of transparent. What am I doing wrong? I've added a comment to the lines that are relevant for getting a transparent background for the top-image.
$bg_src = "polaroid.jpg";
$img_src = "image.jpg";
$outputImage = imagecreatefromjpeg($bg_src);
$img = imagecreatefromjpeg($img_src);
// This should create transparent background.
$bgd_color = imagecolorallocatealpha($img, 0, 0, 0, 127);
// This should assign the transparent background to the uncovered zone after rotation
$img = imagerotate($img, 10, $bgd_color);
// This should make sure the alpha transparency gets saved
imagesavealpha($img, true);
$img_x = imagesx($img);
$img_y = imagesy($img);
imagecopymerge($outputImage,$img,156,50,0,0,$img_x,$img_y,100);
header('Content-type: image/jpeg');
imagejpeg($outputImage);
imagedestroy($outputImage);
Figured it out after some heave searching. Turns out to be real simple.
I just changed this line:
imagesavealpha($img, true);
to this:
imagecolortransparent($img,$bgd_color);
yay! :)

How to maintain image quality with FPDF and PHP?

I'm using FPDF with PHP to add an image to a PDF. But the image quality in the PDF is much worse than the original image, as you can see here:
Relevant code:
$image_height = 40;
$image_width = 40;
$pdf = new FPDF();
$pdf->AddPage();
$start_x = $pdf->GetX();
$start_y = $pdf->GetY();
$pdf->Image('./images/ds_pexeso_ros_0_17.jpg', $pdf->GetX(), $pdf->GetY(), $image_height, $image_width);
$pdf->Output("pexeso".date("Y-m-d"),"I");
The original image is 150x150 pixels.
I faced the same problem in projects for customers.
Blurry pictures in a generated pdf document even with hires images.
It took me a couple of hours, but this is what worked for me.
I have a taken a look at the code and saw that there was a scale factor being set in the constructor of the pdf document:
//Scale factor
if($unit=='pt')
$this->k=1;
elseif($unit=='mm')
$this->k=72/25.4;
elseif($unit=='cm')
$this->k=72/2.54;
elseif($unit=='in')
$this->k=72;
else
$this->Error('Incorrect unit: '.$unit);
The scalefactor is depending on the value given in the constructor of the pdf document:
function FPDF($orientation='P',$unit='mm',$format='A4')
The default is 'mm'. In most of my documents I initiate a pdf document like:
$pdf = new PDF('P');
This means that there will be a scalefactor of 72/25.4 = 2.83 used.
When I placed an image before I just used:
$this->Image('path/to/file', 0, 0);
This way I got the blurry images.
It is also possible to give the width of the image in the command
$this->Image('path/to/file', 0, 0, 200); // for a image width 200
This gave me an image that was far too large. But - and here comes the trick - when you divide the real width by the scalefactor (in my case 2.83) and put this in this statement it gives a perfectly sharp image:
$this->Image('path/to/file', 0, 0, 71); // for a image width 200 / 2.83 = app 71
I hope this works for you too!
I think the problem could be related to:
$image_height = 40;
$image_width = 40;
With these two instructions your are setting the dimensions the image will have in the pdf.
But if the original image is bigger than 40x40 the scaling of the image can cause quality problem.
So what i suggest:
Do a correct resize of the image (php provides GD library). Resize it to 40x40. The GD function imagecopyresampled is your friend: resize and resample the image! Complete reference: http://www.php.net/manual/en/function.imagecopyresampled.php
Insert now the image in the pdf
FPDF with a statement like this to set the user unit to mm
$pdf=new FPDF('P','mm','Letter');
<?php
require_once('fpdf.php');
$image_height = 40;
$image_width = 40;
$pdf = new FPDF('P','mm','Letter');
$pdf->AddPage();
$start_x = $pdf->GetX();
$start_y = $pdf->GetY();
$pdf->Image('./images/ds_pexeso_ros_0_17.jpg',$start_x+0,$start_y-2,40);
$pdf->Output("pexeso".date("Y-m-d"),"I");
?>
FPDF made a very good looking result.

Add styled backgrounds to images in PHP

I am working on improving one of my Facebook apps by allowing the user to upload an image and apply a styled border, or frame to it (i.e. clouds, stars, sky etc). The user chould also be able to save the image, with the border after it has been applied. This explains a little better what I need:
http://zbrowntechnology.info/ImgDisp/imgdisp.php
If you have any other questions or need more details, please let me know.. I'll edit this post.
Use imagecopy(). The example on that page is done using the transparency option with imagecopymerge() but I don't think you need that.
Using imagecopy() you'll specify the X/Y coordinates to use for positioning:
imagecopy( $borderimage, $topimage, 20, 20, 0, 0, $width, $height);
Where $width and $height will be the entire width and height of the top image. You'll want to replace 20 and 20 with the measurement for how much of the border image will be showing around the borders. You will probably have to resize the top image to the exact dimensions you want, or else it might overlap the border a little too far to the right or bottom. (see imagecopyresampled())
Edit:
Here's a rough way to do the whole process (assuming chosenborder.png is the border they chose, and uploadedimage.png is the image they uploaded. If it's a different image type you'll use the corresponding function).
$borderx = 20; // The width of our border
$border = imagecreatefrompng("chosenborder.png");
$topimage = imagecreatefrompng("uploadedimage.png");
$bordersize = getimagesize($border);
$topimagesize = getimagesize($topimage);
/* The new dimensions of topimage. $borderx*2 means we account for
the border on both left and right, top and bottom. */
$newx = $bordersize[0] - ($borderx*2);
$newy = $bordersize[1] - ($borderx*2);
imagecopyresampled( $topimage_scaled, $topimage, 0, 0, 0, 0,
$newx, $newy, $topimagesize[0], $topimagesize[1]);
/* Merge the images */
imagecopy( $border, $topimage_scaled, $borderx, $borderx,
0, 0, $width, $height);
/* Output the image */
imagepng($border, "newimage.png");
/* Free up the memory occupied by the image resources */
imagedestroy($border);
imagedestroy($topimage);
After the user uploads their image, find chosenborder.png and uploadedimage.png, run the above script, then display newimage.png to the user and you're good to go. Just make sure you call imagedestroy() on the temporary image resources or they'll eat up memory.
If you don't want to keep the generated image on your server, you can omit the second argument to imagepng() which will make it send the image information directly as an image to the browser, in which case you'll want to write the correct image HTTP headers.
Client-side solution by using css3:
checkout the css3 property border-image
(dosen't meet the requirement of saving the img with the border)
Server-side solution by merging 2 different images:
<?php
$imgFile = 'img.jpg';
$brdFile = 'brd.jpg';
$img = addBorder($imgFile,$brdFile);
outputImage($img);
function addBorder($imgFile,$brdFile)
{
$img=imagecreatefromjpeg($imgFile);
$brd=imagecreatefromjpeg($brdFile);
$imgSize = getimagesize($imgFile);
$brdSize = getimagesize($brdFile);
//NOTE: the border img MUST be bigger then the src img
$dst_x = ceil(($brdSize[0] - $imgSize[0])/2);
$dst_y = ceil(($brdSize[1] - $imgSize[1])/2);
imagecopymerge ( $brd, $img, $dst_x, $dst_y, 0, 0, $imgSize[0], $imgSize[1] ,100 );
return $brd;
}
function outputImage($img)
{
header('Content-type: image/png');
imagepng($img);
}
?>

Categories