PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

imagecopyresized> <imagecopymergegray
Last updated: Fri, 16 May 2008

view this page in

imagecopyresampled

(PHP 4 >= 4.0.6, PHP 5)

imagecopyresampled — Copy and resize part of an image with resampling

Description

bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )

imagecopyresampled() copies a rectangular portion of one image to another image, smoothly interpolating pixel values so that, in particular, reducing the size of an image still retains a great deal of clarity.

In other words, imagecopyresampled() will take an rectangular area from src_image of width src_w and height src_h at position (src_x ,src_y ) and place it in a rectangular area of dst_image of width dst_w and height dst_h at position (dst_x ,dst_y ).

If the source and destination coordinates and width and heights differ, appropriate stretching or shrinking of the image fragment will be performed. The coordinates refer to the upper left corner. This function can be used to copy regions within the same image (if dst_image is the same as src_image ) but if the regions overlap the results will be unpredictable.

Parameters

dst_im

Destination image link resource

src_im

Source image link resource

dst_x

x-coordinate of destination point

dst_y

y-coordinate of destination point

src_x

x-coordinate of source point

src_y

y-coordinate of source point

dst_w

Destination width

dst_h

Destination height

src_w

Source width

src_h

Source height

Return Values

Returns TRUE on success or FALSE on failure.

Examples

Example #1 Simple example

This example will resample an image to half its original size.

<?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$image0000$new_width$new_height$width$height);

// Output
imagejpeg($image_pnull100);
?>

The above example will output something similar to:

Example #2 Resampling an image proportionally

This example will display an image with the maximum width, or height, of 200 pixels.

<?php
// The file
$filename 'test.jpg';

// Set a maximum height and width
$width 200;
$height 200;

// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width_orig$height_orig) = getimagesize($filename);

$ratio_orig $width_orig/$height_orig;

if (
$width/$height $ratio_orig) {
   
$width $height*$ratio_orig;
} else {
   
$height $width/$ratio_orig;
}

// Resample
$image_p imagecreatetruecolor($width$height);
$image imagecreatefromjpeg($filename);
imagecopyresampled($image_p$image0000$width$height$width_orig$height_orig);

// Output
imagejpeg($image_pnull100);
?>

The above example will output something similar to:

Notes

Note: There is a problem due to palette image limitations (255+1 colors). Resampling or filtering an image commonly needs more colors than 255, a kind of approximation is used to calculate the new resampled pixel and its color. With a palette image we try to allocate a new color, if that failed, we choose the closest (in theory) computed color. This is not always the closest visual color. That may produce a weird result, like blank (or visually blank) images. To skip this problem, please use a truecolor image as a destination image, such as one created by imagecreatetruecolor().



imagecopyresized> <imagecopymergegray
Last updated: Fri, 16 May 2008
 
add a note add a note User Contributed Notes
imagecopyresampled
bobbyboyojones at hotmail dot com
18-Mar-2008 12:41
I hated that enlarging an image resulted in giant pixels rather than a smoother look, so I wrote this function.  It takes longer, but gives a much nicer look.

<?php

function imagecopyresampledSMOOTH(&$dst_img, &$src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $mult=1.25){
   
// don't use a $mult that's too close to an int or this function won't make much of a difference

   
$tgt_w = round($src_w * $mult);
   
$tgt_h = round($src_h * $mult);
   
   
// using $mult <= 1 will make the current step w/h smaller (or the same), don't allow this, always resize by at least 1 pixel larger
   
if($tgt_w <= $src_w){ $tgt_w += 1; }
    if(
$tgt_h <= $src_h){ $tgt_h += 1; }
   
   
// if the current step w/h is larger than the final height, adjust it back to the final size
    // this check also makes it so that if we are doing a resize to smaller image, it happens in one step (since that's already smooth)
   
if($tgt_w > $dst_w){ $tgt_w = $dst_w; }
    if(
$tgt_h > $dst_h){ $tgt_h = $dst_h; }

   
$tmpImg = imagecreatetruecolor($tgt_w, $tgt_h);

   
imagecopyresampled($tmpImg, $src_img, 0, 0, $src_x, $src_y, $tgt_w, $tgt_h, $src_w, $src_h);
   
imagecopy($dst_img, $tmpImg, $dst_x, $dst_y, 0, 0, $tgt_w, $tgt_h);
   
imagedestroy($tmpImg);

   
// as long as the final w/h has not been reached, reep on resizing
   
if($tgt_w < $dst_w OR $tgt_h < $dst_h){
       
imagecopyresampledSMOOTH($dst_img, $dst_img, $dst_x, $dst_y, $dst_x, $dst_y, $dst_w, $dst_h, $tgt_w, $tgt_h, $mult);
    }
}

?>
arnar at netvistun dot is
16-Mar-2008 11:58
A small thumb script. Lets you specify max height and width. The thumb will always be of a rectangular shape while the image itself retains it's proportions. Very clean.

<?php
// The file
$filename = 'a.jpg';

// Set a maximum height and width
$width = 80;
$height = 80;

$thumbsize = 80;

// Content type
header('Content-type: image/jpeg');

// Get new dimensions
list($width_orig, $height_orig) = getimagesize($filename);

$ratio_orig = $width_orig/$height_orig;

if (
$width/$height > $ratio_orig) {
  
$width = $height*$ratio_orig;
} else {
  
$height = $width/$ratio_orig;
}

// Resample
$image_p = imagecreatetruecolor($thumbsize, $thumbsize);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, -($width/2) + ($thumbsize/2), -($height/2) + ($thumbsize/2), 0, 0, $width, $height, $width_orig, $height_orig);

// Output
imagejpeg($image_p, null, 100);
?>
rayg at daylongraphics dot com
07-Mar-2008 02:45
Here's a simple function to resample one JPEG imagefile to another while keeping aspect ratio of the source within the destination's dimensions. You can also tune the allowable distortion if you end up making too many thumbnails with thin blank areas around them. Should work when enlarging images too. Function returns true if it worked, false if not.

function resample_picfile($src, $dst, $w, $h)
{
    // If distortion stretching is within the range below,
    // then let image be distorted.
    $lowend = 0.8;
    $highend = 1.25;

    $src_img = imagecreatefromjpeg($src);
    if($src_img)
    {
        $dst_img = ImageCreateTrueColor($w, $h);
        /* if you don't want aspect-preserved images
to have a black bkgnd, fill $dst_img with the color of your choice here.
        */

        if($dst_img)
        {
            $src_w = imageSX($src_img);
            $src_h = imageSY($src_img);

            $scaleX = (float)$w / $src_w;
            $scaleY = (float)$h / $src_h;
            $scale = min($scaleX, $scaleY);

            $dstW = $w;
            $dstH = $h;
            $dstX = $dstY = 0;

            $scaleR = $scaleX / $scaleY;
            if($scaleR < $lowend || $scaleR > $highend)
            {
                $dstW = (int)($scale * $src_w + 0.5);
                $dstH = (int)($scale * $src_h + 0.5);

                // Keep pic centered in frame.
                $dstX = (int)(0.5 * ($w - $dstW));
                $dstY = (int)(0.5 * ($h - $dstH));
            }
           
            imagecopyresampled(
                $dst_img, $src_img, $dstX, $dstY, 0, 0,
                $dstW, $dstH, $src_w, $src_h);
            imagejpeg($dst_img, $dst);
            imagedestroy($dst_img);
        }
        imagedestroy($src_img);
        return file_exists($dst);
    }
    return false;
}
RandomFeatureRequest
02-Mar-2008 07:51
If anyone felt like implementing Bicubic Sharper and/or Bicubic Smoother, that would seriously rock.
wm at violet dot bg
20-Feb-2008 01:16
This is a fixed version of ImageCopyResampledBicubic posted by liviu.malaescu
The original version wasn't respecting src_x & src_y args

<?php
   
function ImageCopyResampledBicubic(&$dst_image, &$src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)  {
       
// we should first cut the piece we are interested in from the source
       
$src_img = ImageCreateTrueColor($src_w, $src_h);
       
imagecopy($src_img, $src_image, 0, 0, $src_x, $src_y, $src_w, $src_h);

       
// this one is used as temporary image
       
$dst_img = ImageCreateTrueColor($dst_w, $dst_h);

       
ImagePaletteCopy($dst_img, $src_img);
       
$rX = $src_w / $dst_w;
       
$rY = $src_h / $dst_h;
       
$w = 0;
        for (
$y = 0; $y < $dst_h; $y++)  {
           
$ow = $w; $w = round(($y + 1) * $rY);
           
$t = 0;
            for (
$x = 0; $x < $dst_w; $x++)  {
               
$r = $g = $b = 0; $a = 0;
               
$ot = $t; $t = round(($x + 1) * $rX);
                for (
$u = 0; $u < ($w - $ow); $u++)  {
                    for (
$p = 0; $p < ($t - $ot); $p++)  {
                       
$c = ImageColorsForIndex($src_img, ImageColorAt($src_img, $ot + $p, $ow + $u));
                       
$r += $c['red'];
                       
$g += $c['green'];
                       
$b += $c['blue'];
                       
$a++;
                    }
                }
               
ImageSetPixel($dst_img, $x, $y, ImageColorClosest($dst_img, $r / $a, $g / $a, $b / $a));
            }
        }

       
// apply the temp image over the returned image and use the destination x,y coordinates
       
imagecopy($dst_image, $dst_img, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h);

       
// we should return true since ImageCopyResampled/ImageCopyResized do it
       
return true;
    }
?>
Michael Shepanski
14-Jan-2008 10:09
Here is a function I thought I would share that will resample and copy an image with rounded corners.

<?php
/** ------------------------------------------------------------
 * Copy and resample an image with rounded corners.
 * ----------------------------------------------------------- */
function imageRoundedCopyResampled(&$dstimg, &$srcimg, $dstx, $dsty, $srcx,
                                  
$srcy, $dstw, $dsth, $srcw, $srch, $radius) {
   
# Resize the Source Image
   
$srcResized = imagecreatetruecolor($dstw, $dsth);
   
imagecopyresampled($srcResized, $srcimg, 0, 0, $srcx, $srcy,
                      
$dstw, $dsth, $srcw, $srch);
   
# Copy the Body without corners
   
imagecopy($dstimg, $srcResized, $dstx+$radius, $dsty,
             
$radius, 0, $dstw-($radius*2), $dsth);
   
imagecopy($dstimg, $srcResized, $dstx, $dsty+$radius,
             
0, $radius, $dstw, $dsth-($radius*2));
   
# Create a list of iterations; array(array(X1, X2, CenterX, CenterY), ...)
    # Iterations in order are: Top-Left, Top-Right, Bottom-Left, Bottom-Right
   
$iterations = array(
        array(
0, 0, $radius, $radius),
        array(
$dstw-$radius, 0, $dstw-$radius, $radius),
        array(
0, $dsth-$radius, $radius, $dsth-$radius),
        array(
$dstw-$radius, $dsth-$radius, $dstw-$radius, $dsth-$radius)
    );
   
# Loop through each corner 'iteration'
   
foreach($iterations as $iteration) {
        list(
$x1,$y1,$cx,$cy) = $iteration;
        for (
$y=$y1; $y<=$y1+$radius; $y++) {
            for (
$x=$x1; $x<=$x1+$radius; $x++) {
               
# If length (X,Y)->(CX,CY) is less then radius draw the point
               
$length = sqrt(pow(($cx - $x), 2) + pow(($cy - $y), 2));
                if (
$length < $radius) {
                   
imagecopy($dstimg, $srcResized, $x+$dstx, $y+$dsty,
                             
$x, $y, 1, 1);
                }
            }
        }
    }
}
?>
matt1walsh DESPAMMER gmail dot com
19-Nov-2007 07:15
None of the stuff I've seen for resizing transparent GIFs works consistently and yields a good image. The hack I thought of is silly, but it works okay -- convert GIF to PNG. This worked for me.

$g_iw is new image width
$g_ih is new image height

$img_src=imagecreatefromgif($g_srcfile);
$img_dst=imagecreatetruecolor($g_iw,$g_ih);

//preserve alpha
imagecolortransparent($img_dst, imagecolorallocate($img_dst, 0, 0, 0));
imagealphablending($img_dst, false);
imagesavealpha($img_dst, true);
imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, $g_iw, $g_ih, $g_is[0], $g_is[1]);

imagepng($img_dst, $g_dstfile);
imagedestroy($img_dst);
Dave McCourt
12-Nov-2007 05:32
This function is taken from lots of web sources so thanks to all for posting. It creates square or landscape thumbnails from .jpgs  from either portait or landscape original images. I decide in advance which way I want the thumbs to display for consistency. I usually sharpen the images as well post-upload, to save on server resources. I can post this code if anyone wants it. I hope this helps someone...

    # create thumbnails from jpgs
    # usage:
    # create_jpgthumb(uploaded file, final file (with path), thumb height, thumb width, jpg quality, scale thumb (true) or fixed size (false);
    function create_jpgthumb($original, $thumbnail, $max_width, $max_height, $quality, $scale = true) {
       
        list ($src_width, $src_height, $type, $w) = getimagesize($original);
       
        if (!$srcImage = @imagecreatefromjpeg($original)) {
            return false;
        }

        # image resizes to natural height and width
        if ($scale == true) {
                       
            if ($src_width > $src_height ) {
                $thumb_width = $max_width;
                $thumb_height = floor($src_height * ($max_width / $src_width));
            } else if ($src_width < $src_height ) {
                $thumb_height = $max_height;
                $thumb_width = floor($src_width * ($max_height / $src_height));
            } else {
                $thumb_width = $max_height;
                $thumb_height = $max_height;
            }

            if (!@$destImage = imagecreatetruecolor($thumb_width, $thumb_height)) {
                return false;
            }
           
            if (!@imagecopyresampled($destImage, $srcImage, 0, 0, 0, 0, $thumb_width, $thumb_height, $src_width, $src_height)) {
                return false;
            }
                       
        # image is fixed to supplied width and height and cropped
        } else if ($scale == false) {
       
            $ratio = $max_width / $max_height;
               
            # thumbnail is landscape
             if ($ratio > 1) {
            
                # uploaded pic is landscape
                if ($src_width > $src_height) {

                    $thumb_width = $max_width;
                    $thumb_height = ceil($max_width * ($src_height / $src_width));
                   
                    if ($thumb_height > $max_width) {
                        $thumb_height = $max_width;
                        $thumb_width = ceil($max_width * ($src_width / $src_height));
                    }

                # uploaded pic is portrait
                } else {
               
                    $thumb_height = $max_width;
                    $thumb_width = ceil($max_width * ($src_height / $src_width));
                   
                    if ($thumb_width > $max_width) {
                        $thumb_width = $max_width;
                        $thumb_height = ceil($max_width * ($src_height / $src_width));
                    }
                   
                    $off_h = ($src_height - $src_width) / 2;
           
                }
   
                if (!@$destImage = imagecreatetruecolor($max_width, $max_height)) {
                    return false;
                }
       
                if (!@imagecopyresampled($destImage, $srcImage, 0, 0, 0, $off_h, $thumb_width, $thumb_height, $src_width, $src_height)) {
                    return false;
                }

            # thumbnail is square
             } else {
            
                if ($src_width > $src_height) {
                    $off_w = ($src_width - $src_height) / 2;
                    $off_h = 0;
                    $src_width = $src_height;
                } else if ($src_height > $src_width) {
                    $off_w = 0;
                    $off_h = ($src_height - $src_width) / 2;
                    $src_height = $src_width;
                } else {
                    $off_w = 0;
                    $off_h = 0;
                }

                if (!@$destImage = imagecreatetruecolor($max_width, $max_height)) {
                    return false;
                }
       
                if (!@imagecopyresampled($destImage, $srcImage, 0, 0, $off_w, $off_h, $max_width, $max_height, $src_width, $src_height)) {
                    return false;
                }

             }
        
                           
        }
       
        @imagedestroy($srcImage);

        if (!@imageantialias($destImage, true)) {
            return false;
        }
       
        if (!@imagejpeg($destImage, $thumbnail, $quality)) {
            return false;
        }
                       
        @imagedestroy($destImage);
       
        return true;
    }
tim dot daldini at gmail dot be
03-Oct-2007 08:57
Tim's function is a whole lot faster, however, the quality setting doesnt seem right since resizing very big images doesnt affect quality of the resulting thumbnails that much on quality 1 for example.

Anyone has figured out how to use a more correct quality setting by comparing image surfaces (for example) basing on Tim's function?

images with a total of 10Megapixels that contain 5Megapixels when resized should use the same quality setting like images that contain 1Megapixels but only 0.5 when resized.

Not hard to understand, but the memoryload would be a lot lower if the function could decide to use a setting of quality 1 automatically when resizing big images to small thumbnails. This would be handy especially when using the function for images of various sizes in the same application.
liviu dot malaescu at gmail dot com
25-Sep-2007 12:37
3800x2500px - 2s
3807x6768 - 4.7s
Tested on a core2duo e4300/1gb ram - only one core used.
It reduces first with nearest-neighbour and then with bicubic on the smaller image.
Thumb quality is fine :)

<?php
$cale_in
= "test.jpg"; //input-file
$cale_out = "test_thumb.jpg"; //output-file
$make_thumbs = "YES";
$thumbsize[0] = 100;
$thumbsize[1] = 75;
ini_set("memory_limit", "134217728"); // needed for huge pictures

// Bicubic resampling, not written by me
function ImageCopyResampleBicubic
(&$dst_img, &$src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)  {
   
ImagePaletteCopy ($dst_img, $src_img);
   
$rX = $src_w / $dst_w;
   
$rY = $src_h / $dst_h;
   
$w = 0;
    for (
$y = $dst_y; $y < $dst_h; $y++)  {
       
$ow = $w; $w = round(($y + 1) * $rY);
       
$t = 0;
        for (
$x = $dst_x; $x < $dst_w; $x++)  {
           
$r = $g = $b = 0; $a = 0;
           
$ot = $t; $t = round(($x + 1) * $rX);
            for (
$u = 0; $u < ($w - $ow); $u++)  {
                for (
$p = 0; $p < ($t - $ot); $p++)  {
                   
$c = ImageColorsForIndex ($src_img,
ImageColorAt ($src_img, $ot + $p, $ow + $u));
                   
$r += $c['red'];
                   
$g += $c['green'];
                   
$b += $c['blue'];
                   
$a++;
                }
            }
           
ImageSetPixel ($dst_img, $x, $y,
ImageColorClosest ($dst_img, $r / $a, $g / $a, $b / $a));
        }
    }
}

function
makeThumb($cale_in)  {
    global
$thumbsize;
   
$sursa = imagecreatefromjpeg($cale_in);
   
$is_jpeg = getimagesize($cale_in);
   
$ws = $is_jpeg[0];
   
$hs = $is_jpeg[1];
    if(
$ws > $thumbsize[0] && $hs > $thumbsize[1])
    {
       
$aspect = $ws/$hs;
        if(
$aspect <= 1.333333)  {
           
$hd = $thumbsize[1];
           
$wd = floor($hd*$aspect);
        }
        else  {
           
$wd = $thumbsize[0];
           
$hd = floor($wd/$aspect);
        }
       
$Z = ceil(log(($ws*$hs)/(4*$thumbsize[0]*$thumbsize[1])))+1;
        if(
log(($ws*$hs)/(4*$thumbsize[0]*$thumbsize[1])) < 0) $Z=1;
       
$dx = $dy = 0;
        if(
$Z > 1) {
           
$dest = imagecreatetruecolor(round($ws/$Z), round($hs/$Z));
            for(
$i=0; $i < $hs; $i+=$Z) {
                for(
$j=0; $j < $ws; $j+=$Z) {
                   
$rgb = imagecolorat($sursa, $j, $i);
                   
$r = ($rgb >> 16) & 0xFF;
                   
$g = ($rgb >> 8) & 0xFF;
                   
$b = $rgb & 0xFF;
                   
$pcol = imagecolorallocate($dest, $r, $g, $b);
                   
imagesetpixel($dest, $dx, $dy, $pcol);
                   
$dx++;
                }
               
$dx=0;
               
$dy++;
            }
        }
        else
        {
           
$dest = imagecreatetruecolor($ws, $hs);
           
imagecopy($dest, $sursa, 0, 0, 0, 0, $ws, $hs );   
        }
       
imagedestroy($sursa);
       
$destrs = imagecreatetruecolor($wd, $hd);
       
ImageCopyResampleBicubic($destrs,$dest,0,0,0,0,
$wd,$hd,round($ws/$Z),round($hs/$Z));
       
ImageJpeg($destrs, $cale_out, 100);   
        echo
"Z:$Z <b>|</b> ($ws x $hs) -> ($wd x $hd) @ ".$ws/$hs;
    }   
}

function
mf() {
    list(
$usec, $sec) = explode(" ", microtime());
   
$x[0] = $sec$x[1] = $usec;
    return
$x;
}

$timp1 = mf(); //starting to count
makeThumb($cale_in); //makes the actual thumb
$timp2 = mf(); //timer ends
$dsec = $timp2[0] - $timp1[0];
$dusec = $timp2[1] - $timp1[1];
echo
"<b>|</b> Time : <b>".round($dusec+$dsec,6)."s</b> <b>|</b><br />";

?>
tim at leethost dot com
07-Sep-2007 09:25
Here's an improved and corrected version of my fastimagecopyresampled script.  Because I typically scale entire images it appears my previous code was not properly tested.  In any case, this new script has been thoroughly tested, cleaned up, and enhanced.  The code is a little tighter and quality values between 0 and 1 will yield a mosaic effect (basically lowering quality below the pervious lowest value of 1).  I would still suggest using a quality of 2 to 4 as that's the primary purpose of this script, which is high quality and fast results.  Don't be afraid of using a quality value of 1.5 for extreme cases where you have a bunch of very large images from digital cameras (like those 10M pixel cameras theses days) and creating thumbnails in batch mode.  Even a quality of 1.5 is a big improvement over imagecopyresized and is ultra-fast.

Anyway, enjoy and I hope this is the bug-free last version.

<?
function fastimagecopyresampled (&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) {
  // Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled.
  // Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled".
  // Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting.
  // Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain.
  //
  // Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero.
  // Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect.
  // 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized.
  // 2 = Up to 95 times faster.  Images appear a little sharp, some prefer this over a quality of 3.
  // 3 = Up to 60 times faster.  Will give high quality smooth results very close to imagecopyresampled, just faster.
  // 4 = Up to 25 times faster.  Almost identical to imagecopyresampled for most images.
  // 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled.

  if (empty($src_image) || empty($dst_image) || $quality <= 0) { return false; }
  if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) {
    $temp = imagecreatetruecolor ($dst_w * $quality + 1, $dst_h * $quality + 1);
    imagecopyresized ($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h);
    imagecopyresampled ($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality);
    imagedestroy ($temp);
  } else imagecopyresampled ($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
  return true;
}
?>
eblejr AT phrebh DOT com
05-Sep-2007 11:38
Tim's code is fast, but if you're trying to put resampled images anywhere but in the top-left corner, it doesn't work.
Blendermf
04-Jul-2007 08:48
tim, your resampling gives me better results than the gd function. It looks just as good as what my image resizing software does.
kristijan at leftor dot ba
05-Jun-2007 02:09
There is bug in POST from tim at leethost dot com
25-Jan-2007 02:00.

Function work correctly when you making thumb from 0,0 to width/height. But if you want copy resized picture to other coordinates then you must change code in this:

function fastimagecopyresampled (&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) {
 if (empty($src_image) || empty($dst_image)) { return false; }
 if ($quality <= 1)
 {
   $temp = imagecreatetruecolor ($dst_w + 1, $dst_h + 1);
   imagecopyresized ($temp, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w + 1, $dst_h + 1, $src_w, $src_h);
   imagecopyresized ($dst_image, $temp, 0, 0, 0, 0, $dst_w, $dst_h, $dst_w, $dst_h);
   imagedestroy ($temp);
 }
 elseif ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h))
 {
   $tmp_w = $dst_w * $quality;
   $tmp_h = $dst_h * $quality;
   $temp = imagecreatetruecolor ($tmp_w + 1, $tmp_h + 1);
   imagecopyresized ($temp, $src_image, 0, 0, $src_x, $src_y, $tmp_w + 1, $tmp_h + 1, $src_w, $src_h);
   imagecopyresampled ($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $tmp_w, $tmp_h);
   imagedestroy ($temp);
 } else
 {
   imagecopyresampled ($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
 }
 return true;
}
rich at corephp dot co dot uk
20-May-2007 03:05
Be wary of this function when resizing images to make them *larger* than the original due to the memory consumption rate. For example a 200KB JPEG file (1024x768) will take up 4MB of memory when loaded, but when resampled to twice the the size the memory use jumps to 20.1MB. imagecopyresized does the same. Allow approx. 5 bytes per *pixel* for memory allowance when dealing with true colour images.
tim at leethost dot com
25-Jan-2007 02:00
Here's a simple plug-and-play replacement to imagecopyresampled that will deliver results that are almost identical except MUCH faster (very typically 30 times faster).  I've been using this function for a few years but figured everyone could benefit from it.

For example, a 10 megapixel camera image (3872x2592 resolution) converted to thumbnail size using the default quality is 60 times faster than using imagecopyresampled (only 0.15 seconds from 8.9 seconds) and the image quality is almost identical.  There's also an optional "quality" parameter that allows you to select the quality you want (1 is lowest quality but fastest, 5 is highest quality but slowest, 3 is default).  All existing imagecopyresampled parameters fully work so it's truly plug-and-play.  It also automatically decides if it would be better to just use imagecopyresampled depending on source and destination image sizes.

My image analysis shows imagecopyresized renders on average 2.4% of pixels significantly different than imagecopyresampled.  These significantly different pixels give imagecopyresized the jagged, blocky, aliasing look.  Using fastimagecopyresampled with a quality of 2, the significantly different pixel rate is reduced to 0.8%.  With a quality of 3 (the default) it's reduced to 0.5% and at a quality of 4 it's reduced to only 0.03% but is still very typically 10-15 times faster for thumbnail creation.

Enjoy!

<?
function fastimagecopyresampled (&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) {
  // Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled.
  // Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled".
  // Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting.
  // Author: Tim Eckel - Date: 12/17/04 - Project: FreeRingers.net - Freely distributable.
  //
  // Optional "quality" parameter (defaults is 3).  Fractional values are allowed, for example 1.5.
  // 1 = Up to 600 times faster.  Poor results, just uses imagecopyresized but removes black edges.
  // 2 = Up to 95 times faster.  Images may appear too sharp, some people may prefer it.
  // 3 = Up to 60 times faster.  Will give high quality smooth results very close to imagecopyresampled.
  // 4 = Up to 25 times faster.  Almost identical to imagecopyresampled for most images.
  // 5 = No speedup.  Just uses imagecopyresampled, highest quality but no advantage over imagecopyresampled.

  if (empty($src_image) || empty($dst_image)) { return false; }
  if ($quality <= 1) {
    $temp = imagecreatetruecolor ($dst_w + 1, $dst_h + 1);
    imagecopyresized ($temp, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w + 1, $dst_h + 1, $src_w, $src_h);
    imagecopyresized ($dst_image, $temp, 0, 0, 0, 0, $dst_w, $dst_h, $dst_w, $dst_h);
    imagedestroy ($temp);
  } elseif ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) {
    $tmp_w = $dst_w * $quality;
    $tmp_h = $dst_h * $quality;
    $temp = imagecreatetruecolor ($tmp_w + 1, $tmp_h + 1);
    imagecopyresized ($temp, $src_image, $dst_x * $quality, $dst_y * $quality, $src_x, $src_y, $tmp_w + 1, $tmp_h + 1, $src_w, $src_h);
    imagecopyresampled ($dst_image, $temp, 0, 0, 0, 0, $dst_w, $dst_h, $tmp_w, $tmp_h);
    imagedestroy ($temp);
  } else {
    imagecopyresampled ($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
  }
  return true;
}
?>
mr bitmap
17-Nov-2006 07:18
For all those that are using imagecreatefromwbmp() for.BMP files, I believe you are wrong.

imagecreatefromwbmp() is for WBMP image files used for WAP devices not windows BMP images.

I don't think PHP has any built in Windows BMP functions.

There are many examples here that make this mistake.

See the documentation for imagecreatefromwbmp()
caio at daisuki dot com dot br
14-Jul-2006 02:51
Ok guys, the ultimate image merging tool, enjoy:

  function watermark($sourcefile, $watermarkfiles, $destination, $quality=90) {
  /*
 
    $sourcefile = Filename of the picture to be watermarked.
    $watermarkfile = files to add. Each is: array ( 'filename' => filename , 'position' => position to show(array), 'resample' => new dimension(array) )
       You can omit any except filename
    $destination = jpg or png file to output (jpg if source is jpg, png if source is png). Send blank to direct output 
    Sample:
 
    $batch = array ( array ( 'filename' => "watermark.png",
                             'position' => array(100,0),
                           ),
                    array ( 'filename' => "brilho.png",
                            'position' => array(200,200),
                            'resample' => array(30,30)
                           )
                   );
    watermark("picture.jpg", $batch, "", 90); <--  will add both images in bath on top of picture, preserving transparency
 
  */
 
  $ih = getimagesize($sourcefile);
  $ispng = $ih[2] == 3;
  if ($ispng)
    $sourcefile_id = imagecreatefrompng($sourcefile);
  else
    $sourcefile_id = imagecreatefromjpeg($sourcefile);
  
  $sourcefile_width=imageSX($sourcefile_id);
  $sourcefile_height=imageSY($sourcefile_id);  
 
  foreach ($watermarkfiles as $x => $watermarkfile) {
    $watermarkfile_id = imagecreatefrompng($watermarkfile['filename']);
    imageAlphaBlending($watermarkfile_id, false);
    imageSaveAlpha($watermarkfile_id, true);    
    $watermarkfile_width=imageSX($watermarkfile_id);
    $watermarkfile_height=imageSY($watermarkfile_id);
   
    // resample?
    if (isset($watermarkfile['resample'])) {
      $im_dest = imagecreatetruecolor ($watermarkfile['resample'][0], $watermarkfile['resample'][1]);
      imagealphablending($im_dest, false);
      imagecopyresampled($im_dest, $watermarkfile_id, 0, 0, 0, 0, $watermarkfile['resample'][0], $watermarkfile['resample'][1], $watermarkfile_width, $watermarkfile_height);
      imagesavealpha($im_dest, true);
      imagedestroy($watermarkfile_id);
      $watermarkfile_id = $im_dest;
      $watermarkfile_width = $watermarkfile['resample'][0];
      $watermarkfile_height = $watermarkfile['resample'][1];
    }
   
    // position ? if none given, centered
    if (isset($watermarkfile['position']))
      list($dest_x,$dest_y) = $watermarkfile['position'];
    else {
      $dest_x = ( $sourcefile_width / 2 ) - ( $watermarkfile_width / 2 ); // centered
      $dest_y = ( $sourcefile_height / 2 ) - ( $watermarkfile_height / 2 ); // centered
    }
   
    imagecopy($sourcefile_id, $watermarkfile_id, $dest_x, $dest_y, 0, 0, $watermarkfile_width, $watermarkfile_height);
    imagedestroy($watermarkfile_id);
  }
  if ($ispng)
    imagepng($sourcefile_id,$destination);
  else
    imagejpeg($sourcefile_id,$destination,$quality);
  imagedestroy($sourcefile_id);
}
spencejames2000 at yahoo dot co dot uk
13-May-2006 06:27
For anyone suffering from the srcX and srcY bug (some versions of gd ignore them completely - see http://bugs.php.net/bug.php?id=12780 for details), a quick solution is to use this code snippet:

<?php
function imgcopyresampled(&$dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
{
   
$tmp_img = imagecreatetruecolor($src_w, $src_h);
   
$rv2 = imagecopy($tmp_img, $src_img, 0,0, $src_x, $src_y, $src_w, $src_h);
   
$rv1 = imagecopyresampled($dst_img, $tmp_img, $dst_x,$dst_y, 0,0, $dst_w, $dst_h, $src_w, $src_h);
   
imagedestroy($tmp_img);
    return(
$rv1 and $rv2);
}
?>

By using imagecopy to extract the relevant portion of the source image, it works a lot more quickly than pike's solution below, and also without the extra blur.

It may be useful to use override_function in existing projects, although I have not tested this myself.
Tyron Madlener (tyron.at)
11-May-2006 01:43
Creating a thumbnail (120x90 pixel) of a big image (3000x2000 pixel) took me about 5 seconds with imagecopyresampled()

Thats pretty much, so I tested a little how I could improve the speed. I found that imagecopyresized is way faster but results in poor quality.
So I combined both - I first reduce the big image via imagecopyresized to 1024x768 pixel and then create the small thumbnail via imagecopyresampled. The resulting quality is almost the same. In my tests, resizing took only about 2.2 seconds now - twice as fast :)

I also tried using that bicubic image resizing function in some earlier post here, but it was only faster when the thumbnails were smaller than 120x90 and the quality was not very good.

Here's the code if you wanna (I guess there are still a few possibilites to do some more optimiztions tough):

<?php
function CreateThumb($file,$maxwdt,$maxhgt, $dest) {
    list(
$owdt,$ohgt,$otype)=@getimagesize($file);

  switch(
$otype) {
    case
1$newimg=imagecreatefromgif($file); break;
    case
2$newimg=imagecreatefromjpeg($file); break;
    case
3$newimg=imagecreatefrompng($file); break;
    default: echo
"Unkown filetype (file $file, typ $otype)"; return;
  }
   
  if(
$newimg) {
    if(
$owdt>1500 || $ohgt>1200)
            list(
$owdt, $ohgt) = Resample($newimg, $owdt, $ohgt, 1024,768,0);
           
   
Resample($newimg, $owdt, $ohgt, $maxwdt, $maxhgt);
       
        if(!
$dest) return $newimg;
       
        if(!
is_dir(dirname($dest)))
           
mkdir(dirname($dest));
   
    switch(
$otype) {
      case
1: imagegif($newimg,dest