I'm currently trying to work with pictures and PHP, thanks to GD functions.
Now I would like to modify the size of PNG pictures. Here is an example of a PNG I'd like to resize :
The dotted line represent the border of the PNG, the background is transparent, and I only have a star lost on the middle of a large space. I'd like to crop this star, to get a simple square of the star (even if the new background becomes blank, It doesn't matter).
How could I do something like that efficiently ? I thought about doing a loop checking every pixel of the picture.. Trying to find where the image is, to finally crop with a little margin based on the minimum x / maximum X and minimum y / maximum y values, but If I start working with hundreds of pictures, It would be really long.
EDIT :
<?php
$file = "./crop.png";
$ext = pathinfo($file, PATHINFO_EXTENSION);
$image;
switch ($ext){
case 'png':
$image = imagecreatefrompng($file);
break;
case 'jpeg':
case 'jpg':
$image = imagecreatefromjpeg($file);
break;
case 'gif':
$image = imagecreatefromgif($file);
break;
}
$cropped = imagecropauto($image, IMG_CROP_DEFAULT);
if ($cropped !== false) { // in case a new image resource was returned
echo "=> Cropping needed\n";
imagedestroy($image); // we destroy the original image
$image = $cropped; // and assign the cropped image to $im
}
imagepng($image, "./cropped.png");
imagedestroy($image);
If you read and follow the php php-gd documentation, you'll find a function called imagecropauto which does exactly what you want, it crops the alpha channel of the image.
Crop an PNG image with alpha channel
$im = imagecreatefrompng("./star-with-alpha.png");
$cropped = imagecropauto($im, IMG_CROP_DEFAULT);
if ($cropped !== false) { // in case a new image resource was returned
imagedestroy($im); // we destroy the original image
$im = $cropped; // and assign the cropped image to $im
}
imagepng($im, "./star-with-alpha-crop.png");
imagedestroy($im);
You can try it dirrectly to a php page using this code:
<body>
<img src="star-with-alpha.png">
<?php
$im = imagecreatefrompng("./star-with-alpha.png");
$cropped = imagecropauto($im, IMG_CROP_DEFAULT);
if ($cropped !== false) { // in case a new image resource was returned
imagedestroy($im); // we destroy the original image
$im = $cropped; // and assign the cropped image to $im
}
imagepng($im, "./star-with-alpha-crop.png");
imagedestroy($im);
?>
<img src="star-with-alpha-crop.png">
</body>
The result
http://zikro.gr/dbg/php/crop-png/
[This is for ubuntu 12]
The only problem with the imagecropauto is that it works only on Mac & Windows.
And since most of the servers today use ubuntu/debain - this function is of no use.
Instead use Imagick() for this.
Here is a sample code I wrote which does exactly this:
//Add background transmparent
$background = 'none';
$image = new Imagick($path);
$image->trimImage(0);
//add transparent border
//border add start
/** Set border format **/
$borderWidth = 20;
$borderColor = 'none';
$borderPadding = 10;
$imageWidth = $image->getImageWidth() + ( 2 * ( $borderWidth +
$borderPadding ) );
$imageHeight = $image->getImageHeight() + ( 2 * ( $borderWidth +
$borderPadding ) );
Create Imagick object for final image with border
$imageWithBorder = new Imagick();
// Set image canvas
$imageWithBorder->newImage( $imageWidth, $imageHeight, new ImagickPixel(
'none' ));
// Create ImagickDraw object to draw border
$border = new ImagickDraw();
// Set fill color to transparent
$border->setFillColor( 'none' );
// Set border format
$border->setStrokeColor( new ImagickPixel( $borderColor ) );
$border->setStrokeWidth( $borderWidth );
$border->setStrokeAntialias( false );
Draw border
$border->rectangle(
$borderWidth / 2 - 1,
$borderWidth / 2 - 1,
$imageWidth - ( ($borderWidth / 2) ),
$imageHeight - ( ($borderWidth / 2) )
);
// Apply drawed border to final image
$imageWithBorder->drawImage( $border );
$imageWithBorder->setImageFormat('png');
Save Image
// Put source image to final image
$imageWithBorder->compositeImage(
$image, Imagick::COMPOSITE_DEFAULT,
$borderWidth + $borderPadding,
$borderWidth + $borderPadding
);
$imageWithBorder->writeImage($path);
Recenter and fit to original image height and width
$imageWithBorder->scaleImage(FINAL_WIDTH, FINAL_HEIGHT, true);
$imageWithBorder->setImageBackgroundColor($background);
$w = $imageWithBorder->getImageWidth();
$h = $imageWithBorder->getImageHeight();
$imageWithBorder->extentImage(FINAL_WIDTH, FINAL_HEIGHT, ($w -
FINAL_WIDTH) / 2, ($h - FINAL_HEIGHT)/ 2);
$imageWithBorder->writeImage($path);
Hope it helps.
Cheers!
Related
in my project i just do image watermarking or image combine it's working fine and code for that.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<?php
if(isset($_POST['submit']))
{
// Give the Complete Path of the folder where you want to save the image
$folder="uploads/";
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], "$folder".$_FILES["fileToUpload"]["name"]);
$file='uploads/'.$_FILES["fileToUpload"]["name"];
$uploadimage=$folder.$_FILES["fileToUpload"]["name"];
$newname= time();
$ext = pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_EXTENSION);
// Set the thumbnail name
$thumbnail = $folder.$newname.".".$ext;
$imgname=$newname.".".$ext;
// Load the mian image
if ($ext=="png" || $ext=="PNG") {
$source = imagecreatefrompng($uploadimage);
}
else if ($ext=="gif" || $ext=="GIF") {
$source = imagecreatefromgif($uploadimage);
}
else if ($ext=="bmp" || $ext=="BMP") {
$source = imagecreatefrombmp($uploadimage);
}
else{
$source = imagecreatefromjpeg($uploadimage);
}
// load the image you want to you want to be watermarked
$watermark = imagecreatefrompng('uploads/logo1.png');
// get the width and height of the watermark image
$water_width = imagesx($source)/2;
$water_height = imagesy($watermark);
// get the width and height of the main image image
$main_width = imagesx($source);
$main_height = imagesy($source);
$im_middle_w = $main_width/2;
$im_middle_h = $main_height/2;
// Set the dimension of the area you want to place your watermark we use 0
// from x-axis and 0 from y-axis
$dime_x = $im_middle_w - $water_width/2;
$dime_y = $im_middle_h - $water_height/2;
// copy both the images
imagecopy($source, $watermark, $dime_x, $dime_y, 0, 0, $water_width, $water_height);
// Final processing Creating The Image
imagejpeg($source, $thumbnail, 100);
unlink($file);
}
?>
<img src='uploads/<?php echo $imgname;?>'>
</body>
</html>
but problem with setting $water_width and i want set as half of my source image. but when i have source image of less width or more width compare to $water_width it's set it like that. see image when source image width is more.
and when width is less.
so my problem is how to set $water_width as half of source image width?
by Alex your answer it's came up like this.
This will resize watermark to half-width of original image and put it in the centre:
// load the image you want to you want to be watermarked
$watermark = imagecreatefrompng('uploads/logo1.png');
// get the width and height of the watermark image
$water_width = imagesx($watermark);
$water_height = imagesy($watermark);
// get the width and height of the main image image
$main_width = imagesx($source);
$main_height = imagesy($source);
// resize watermark to half-width of the image
$new_height = round($water_height * $main_width / $water_width / 2);
$new_width = round($main_width / 2);
$new_watermark = imagecreatetruecolor($new_width, $new_height);
// keep transparent background
imagealphablending( $new_watermark, false );
imagesavealpha( $new_watermark, true );
imagecopyresampled($new_watermark, $watermark, 0, 0, 0, 0, $new_width, $new_height, $water_width, $water_height);
// Set the dimension of the area you want to place your watermark we use 0
// from x-axis and 0 from y-axis
$dime_x = round(($main_width - $new_width)/2);
$dime_y = round(($main_height - $new_height)/2);
// copy both the images
imagecopy($source, $new_watermark, $dime_x, $dime_y, 0, 0, $new_width, $new_height);
// Final processing Creating The Image
imagejpeg($source, $thumbnail, 100);
imagedestroy($source);
imagedestroy($watermark);
imagedestroy($new_watermark);
You can try imagettftext method, if you don't want any such high perfection in transparency. You can have try of this code. You have to save a font file in your directory, here I used arial.ttf.
$im = imagecreatefrompng("png.png"); //create image data
$font = 'arial.ttf'; //font file name
$randomString = "example.com"; //string need to be shown
$main_width = imagesx($im); //finding width and height
$main_height = imagesy($im);
$posx= $main_width/2; //finding center
$posy = $main_height/2;
$color = imagecolorallocate($im, 200, 200, 200); //Creating color
$size = ($main_width/25)+1; //determine size of font. +1 to avoid 0
$temp = $size*5;
$posx = $posx-$temp; //adjust to average center
imagettftext($im,$size,0, $posx, $posy, $color, $font , $randomString); //apply a text
You have to adjust posx and posy for your text position. Size also can be adjusted with some logics.
$color = imagecolorallocate($im, 0, 0, 0);= black
and $color = imagecolorallocate($im, 255, 255, 255); = white.
You have to adjust this for your required text color.
I'm trying to redesign my site so that my original square, tile-based rendering of images can be more of a cutout of the image... to get rid of that grid pattern.
Here's how it looked originally...
Here's a rough mock-up of what I'm going for:
So I resaved an image thumbnail with a transparent background... I just want the dog to show, and the square is transparent which will show the site's background underneath.
Yet when I render it on the page, it has this black background.
I've checked my CSS to see if there is some sort of img class, or class for the rendered comics... or even the bootstrap to see where there may be a background-color being assigned to black (and also searched for hex code 000000), but didn't find one...
Do you know why this may be happening?
Thanks!
EDIT: I've just noticed something...
My logo at the top renders with a transparent background... and the element is a png file... therefore, its MIME type is image/png.
I'm using a thumbnailing script to make the thumbnails smaller, but now the element is of thumber.php, which puts it as MIME type image/jpeg.
So I guess it's my thumbnailing script that changing the MIME type.
So I checked it, and it's creating the file as a jpeg
//imagejpeg outputs the image
imagejpeg($img);
Is there a way to change it so that the resampled image is output as a png?
Thumbnailing script:
<?php
#Appreciation goes to digifuzz (http://www.digifuzz.net) for help on this
$image_file = $_GET['img']; //takes in full path of image
$MAX_WIDTH = $_GET['mw'];
$MAX_HEIGHT = $_GET['mh'];
global $img;
//Check for image
if(!$image_file || $image_file == "") {
die("NO FILE.");
}
//If no max width, set one
if(!$MAX_WIDTH || $MAX_WIDTH == "") {
$MAX_WIDTH="100";
}
//if no max height, set one
if(!$MAX_HEIGHT || $MAX_HEIGHT == "") {
$MAX_HEIGHT = "100";
}
$img = null;
//create image file from 'img' parameter string
$img = imagecreatefrompng($image_file);
//if image successfully loaded...
if($img) {
//get image size and scale ratio
$width = imagesx($img);
$height = imagesy($img);
//takes min value of these two
$scale = min($MAX_WIDTH/$width, $MAX_HEIGHT/$height);
//if desired new image size is less than original, output new image
if($scale < 1) {
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
$tmp_img = imagecreatetruecolor($new_width, $new_height);
//copy and resize old image to new image
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagedestroy($img);
//replace actual image with new image
$img = $tmp_img;
}
}
//set the content type header
header("Content-type: image/png");
//imagejpeg outputs the image
imagealphablending($img, false);
imagesavealpha($img, true);
imagepng($img);
imagedestroy($img);
?>
You will need to make some changes in the image generator and see if that works out for you.
The crucial changes are within the setting of the header and the method of image generation. You will be looking for these following two
header('Content-Type: image/jpeg');
change to:
header('Content-Type: image/png');
imagejpeg($im);
change to:
imagepng($im)
When dealing with png images with an alpha channel you should take a few extra steps.
Before spitting it out with imagepng(), these lines will need to be added.
imagealphablending($img, false);
imagesavealpha($img, true);
This information can be found on php.net
Edit:
Try with these alterations to this code:
if($scale < 1) {
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
$tmp_img = imagecreatetruecolor($new_width, $new_height);
imagealphablending($tmp_img,true); // add this line
//copy and resize old image to new image
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
$img = $tmp_img;
// remove line here
}
}
header("Content-type: image/png");
imagesavealpha($img, true);
imagepng($img);
imagedestroy($img);
imagedestroy($tmp_img); // add this line here
Basically you create new layers and put these together. For each layer you will need to set the alpha blending. I was successful in creating alpha images. Let me know what your findings are .. :-) ..
I am trying to add a watermark to an image using PHP and the GD image library. I can apply the watermark where I specify with the correct opacity setting.
The problem is that my watermark itself has a transparent background. When I try to apply this watermark to the image I get a black background.
The image which the watermark is being applied to is a jpeg. Could this be the problem? If so how would I convert the jpeg into a format which supports transparency, apply watermark, then convert it back?
This is the key bit of code I have at the moment.
// Determine image size and type
$size = getimagesize($this->image_path);
$size_x = $size[0];
$size_y = $size[1];
$image_type = $size[2]; // This is always a JPEG
// load source image
$image = $this->ImageCreateFromType($image_type, $this->image_path);
// Determine watermark size and type
$wsize = getimagesize($watermark_path);
$watermark_x = $wsize[0];
$watermark_y = $wsize[1];
$watermark_type = $wsize[2]; // This is typically a PNG
// load watermark
$watermark = $this->ImageCreateFromType($watermark_type, $watermark_path);
$dest_x = $this->setX($size_x, $watermark_x);
$dest_y = $this->setY($size_y, $watermark_y);
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_x, $watermark_y, $this->opacity);
While not really relevant, here is the code for the ImageCreateFromType function
function ImageCreateFromType($type,$filename) {
$im = null;
switch ($type) {
case 1:
$im = ImageCreateFromGif($filename);
break;
case 2:
$im = ImageCreateFromJpeg($filename);
break;
case 3:
$im = ImageCreateFromPNG($filename);
imagealphablending($im, true);
imagesavealpha($im, true);
break;
}
return $im;
}
Have a read about the imagecolortransparent() function: http://php.net/manual/en/function.imagecolortransparent.php
You may also want to look at this question: Can PNG image transparency be preserved when using PHP's GDlib imagecopyresampled?
I have a quick question that I'm not quite sure to set up. I've seen examples elsewhere but nothing specifically like my situation. I would like to resize images using PHP so they're readable and not just wonkily stretched like if you use HTML. If they're not 250 pixels wide, or 160 pixels tall, how can I resize the picture so it's proportionate but fits within that space?
Thanks!
PHP does not manipulate images directly. You will need to use an image manipulation library such as gd or ImageMagick to accomplish this goal.
In ImageMagick, image resizing is accomplished like this:
$thumb = new Imagick('myimage.gif');
$thumb->resizeImage(320,240,Imagick::FILTER_LANCZOS,1);
$thumb->writeImage('mythumb.gif');
With GD, you can do it like this:
<?php
// The file
$filename = 'test.jpg';
$percent = 0.5;
// Content type
header('Content-Type: image/jpeg');
// Get new dimensions
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;
// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// Output
imagejpeg($image_p, null, 100);
?>
Ok, so below is an Image object that I use in my store. It maintains scale - requires GD
<?php
class Store_Model_Image extends My_Model_Abstract
{
const PATH = STORE_MODEL_IMAGE_PATH;
const URL = "/store-assets/product-images/";
public function get_image_url($width, $height)
{
$old_file = self::PATH . $this->get_filename();
$basename = pathinfo($old_file, PATHINFO_FILENAME);
$new_name = sprintf("%s_%sx%s.jpg", $basename, $width, $height);
if(file_exists(self::PATH . $new_name))
{
return self::URL . $new_name;
}
else
{
list($width_orig, $height_orig, $image_type) = #getimagesize($old_file);
$img = FALSE;
// Get the image and create a thumbnail
switch($image_type)
{
case 1:
$img = #imagecreatefromgif($old_file);
break;
case 2:
$img = #imagecreatefromjpeg($old_file);
break;
case 3:
$img = #imagecreatefrompng($old_file);
break;
}
if(!$img)
{
throw new Zend_Exception("ERROR: Could not create image handle from path.");
}
// Build the thumbnail
if($width_orig > $height_orig)
{
$width_ratio = $width / $width_orig;
$new_width = $width;
$new_height = $height_orig * $width_ratio;
}
else
{
$height_ratio = $height / $height_orig;
$new_width = $width_orig * $height_ratio;
$new_height = $height;
}
$new_img = #imagecreatetruecolor($new_width, $new_height);
// Fill the image black
if(!#imagefilledrectangle($new_img, 0, 0, $new_width, $new_height, 0))
{
throw new Zend_Exception("ERROR: Could not fill new image");
}
if(!#imagecopyresampled($new_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig))
{
throw new Zend_Exception("ERROR: Could not resize old image onto new bg.");
}
// Use a output buffering to load the image into a variable
ob_start();
imagejpeg($new_img, NULL, 100);
$image_contents = ob_get_contents();
ob_end_clean();
// lastly (for the example) we are writing the string to a file
$fh = fopen(self::PATH . $new_name, "a+");
fwrite($fh, $image_contents);
fclose($fh);
return self::URL . $new_name;
}
}
}
I resize the image at request time, so the first time the page loads an image will be resized to the required size for the template. (this means I don't have to crash a shared host trying to regenerate image thumbnails everytime my design changes)
So in the template you pass your image object, and when you need a image thumb,
<img src="<?php echo $image->get_image_url(100, 100); ?>" />
you now have a 100x100 thumb, which is saved to the Server for reuse at a later date
gd and imagemagick are two tools that may work for you
http://php.net/manual/en/book.image.php
http://php.net/manual/en/book.imagick.php
Here is something I used to use
class cropImage{
var $imgSrc,$myImage,$cropHeight,$cropWidth,$x,$y,$thumb;
function setImage($image,$moduleWidth,$moduleHeight,$cropPercent = "1") {
//Your Image
$this->imgSrc = $image;
//getting the image dimensions
list($width, $height) = getimagesize($this->imgSrc);
//create image from the jpeg
$this->myImage = imagecreatefromjpeg($this->imgSrc) or die("Error: Cannot find image!");
if($width > $height) $biggestSide = $width; //find biggest length
else $biggestSide = $height;
//The crop size will be half that of the largest side
//$cropPercent = 1.55; // This will zoom in to 50% zoom (crop)
if(!$cropPercent) {
$cropPercent = 1.50;
}
$this->cropWidth = $moduleWidth*$cropPercent;
$this->cropHeight = $moduleHeight*$cropPercent;
//$this->cropWidth = $biggestSide*$cropPercent;
//$this->cropHeight = $biggestSide*$cropPercent;
//getting the top left coordinate
$this->x = ($width-$this->cropWidth)/2;
$this->y = ($height-$this->cropHeight)/2;
}
function createThumb($moduleWidth,$moduleHeight){
$thumbSize = 495; // will create a 250 x 250 thumb
$this->thumb = imagecreatetruecolor($moduleWidth, $moduleHeight);
//$this->thumb = imagecreatetruecolor($thumbSize, $thumbSize);
imagecopyresampled($this->thumb, $this->myImage, 0, 0,$this->x, $this->y, $moduleWidth, $moduleHeight, $this->cropWidth, $this->cropHeight);
//imagecopyresampled($this->thumb, $this->myImage, 0, 0,$this->x, $this->y, $thumbSize, $thumbSize, $this->cropWidth, $this->cropHeight);
}
function renderImage(){
header('Content-type: image/jpeg');
imagejpeg($this->thumb);
imagedestroy($this->thumb);
}
}
Call it by using
$image = new cropImage;
$image->setImage($imagepath,$moduleWidth,$moduleHeight,$scaleRelation);
$image->createThumb($moduleWidth,$moduleHeight);
$image->renderImage();
Use GD or ImageMagick. Here you may find a real production example of code (used by MediaWiki) that supports consoled ImageMagick interface (transformImageMagick method), ImageMagick extension interface (transformImageMagickExt method) and GD (transformGd method).
There a simple to use, open source library called PHP Image Magician that will can help you out.
Example of basis usage:
$magicianObj = new imageLib('racecar.jpg');
$magicianObj -> resizeImage(100, 200, 'crop');
$magicianObj -> saveImage('racecar_small.png');
i am using this code to create watermark.
$image = '1.jpg';
$overlay = 'stamp.png';
$opacity = "20";
if (!file_exists($image)) {
die("Image does not exist.");
}
// Set offset from bottom-right corner
$w_offset = 0;
$h_offset = 100;
$extension = strtolower(substr($image, strrpos($image, ".") + 1));
// Load image from file
switch ($extension)
{
case 'jpg':
$background = imagecreatefromjpeg($image);
break;
case 'jpeg':
$background = imagecreatefromjpeg($image);
break;
case 'png':
$background = imagecreatefrompng($image);
break;
case 'gif':
$background = imagecreatefromgif($image);
break;
default:
die("Image is of unsupported type.");
}
// Find base image size
$swidth = imagesx($background);
$sheight = imagesy($background);
// Turn on alpha blending
imagealphablending($background, true);
// Create overlay image
$overlay = imagecreatefrompng($overlay);
// Get the size of overlay
$owidth = imagesx($overlay);
$oheight = imagesy($overlay);
// Overlay watermark
imagecopymerge($background, $overlay, $swidth - $owidth - $w_offset, $sheight - $oheight - $h_offset, 0, 0, $owidth, $oheight, $opacity);
imagejpeg($background,$image);
// Destroy the images
imagedestroy($background);
imagedestroy($overlay);
the png image contains a text with all other region as transparent.
but when i execute this code , it applys the png over jpg, but the transparecy is not maintained of the png. it shows in a box.
how can i acheive that . ie if a png contains transaparent part , it should show the below image in that part....?
replacing imagecopymerge with imagecopy solved the issue. here is the new code
function watermark($image){
$overlay = '../../../photos/photosets/stamp.png';
$opacity = "20";
if (!file_exists($image)) {
die("Image does not exist.");
}
// Set offset from bottom-right corner
$w_offset = 0;
$h_offset = 100;
$extension = strtolower(substr($image, strrpos($image, ".") + 1));
// Load image from file
switch ($extension)
{
case 'jpg':
$background = imagecreatefromjpeg($image);
break;
case 'jpeg':
$background = imagecreatefromjpeg($image);
break;
case 'png':
$background = imagecreatefrompng($image);
break;
case 'gif':
$background = imagecreatefromgif($image);
break;
default:
die("Image is of unsupported type.");
}
// Find base image size
$swidth = imagesx($background);
$sheight = imagesy($background);
// Turn on alpha blending
imagealphablending($background, true);
// Create overlay image
//$overlay = imagecreatefrompng($overlay);
// Get the size of overlay
$owidth = imagesx($overlay);
$oheight = imagesy($overlay);
$photo = imagecreatefromjpeg($image);
$watermark = imagecreatefrompng($overlay);
// This is the key. Without ImageAlphaBlending on, the PNG won't render correctly.
imagealphablending($photo, true);
// Copy the watermark onto the master, $offset px from the bottom right corner.
$offset = 10;
imagecopy($photo, $watermark, imagesx($photo) - imagesx($watermark) - $offset, imagesy($photo) - imagesy($watermark) - $offset, 0, 0, imagesx($watermark), imagesy($watermark));
// Output to the browser
header("Content-Type: image/jpeg");
imagejpeg($photo,$image);
// Overlay watermark
// Destroy the images
imagedestroy($background);
imagedestroy($overlay);
}
The jpg format doesn't support transparency, so conceptually you will have to:
grab the pixels from the larger image (the jpeg) and put them into a buffer
grab the non-transparent pixels from the smaller image (the watermark) and move them into that buffer, applying the alpha along the way
You probably want to let a library do this. I like ImageMagick, especially since it's built in to php... here's an example of how to use it for this purpose from PHP:
// Let's read the images.
$glasses = new Imagick();
if (FALSE === $glasses->readImage($dir . '/glasses.png'))
{
throw new Exception();
}
$face = new Imagick();
if (FALSE === $face->readImage($dir . '/face.jpg'))
{
throw new Exception();
}
// Let's put the glasses on (10 pixels from left, 20 pixels from top of face).
$face->compositeImage($glasses, Imagick::COMPOSITE_DEFAULT, 10, 20);
And here's the link to the PHP manual page for ImageMagick::compositeImage (from which the above example came).
Have you tried using imagecopyresampled()?
http://php.net/manual/en/function.imagecopyresampled.php