Here's my Image Resize Class. The Class can get the Result that you want (cropping/centered cropping/etc.)... and a lot more ;-)
I dont explain everything but if you got any questions just ask me.
<?php
final class Img {
    /**
     * Usage:
     * Img::resizeImage( 'sample.png', null, array( 'x' => 150, 'y' => 150 ) )
     * Outputs a Image
     * 
     * Img::resizeImage( 'sample.png', 'crop.jpg', array( 'x' => 200, 'y' => 200 ) )
     * Saves a Image
     *
     * @static
     * @param string $source
     * @param null|string $destination
     * @param array $options
     * @return void
     * @throws Exception
     */
    public static function resizeImage( $source, $destination = null, $options = array() ) {
        if( !file_exists( $source ) || ( is_string( $destination ) && !is_writable( dirname( $destination ) ) ) ) {
            throw new Exception( 'Quelldatei existiert nicht oder Zielverzeichnis ist nicht beschreibbar.' );
        }
        #@ini_set ('memory_limit', '64M' );
        $defaultOptions = array(
            'x' => 100,
            'y' => 100,
            'maxX' => 1000,
            'maxY' => 1000,
            'zoom_crop' => 1,
            'quality' => 90,
            'align' => 'c', // [c]enter, [b]ottom, [t]op, [l]eft, [r]ight
            'filters' => '',
            'sharpen' => 0,
            'canvas' => 'ffffff',
        );
        $options = array_merge( $defaultOptions, $options );
        $sData = getimagesize( $source );
        $origType = $sData[2];
        $mimeType = $sData['mime'];
        if( !preg_match( '/^image\/(?:gif|jpg|jpeg|png)$/i', $mimeType ) ) {
            throw new Exception( 'The image being resized is not a valid gif, jpg or png.' );
        }
        if( !function_exists( 'imagecreatetruecolor' ) ) {
            throw new Exception( 'GD Library Error: imagecreatetruecolor does not exist' );
        }
        if( function_exists( 'imagefilter' ) && defined( 'IMG_FILTER_NEGATE' ) ) {
            $imageFilters = array (
                    1 => array (IMG_FILTER_NEGATE, 0),
                    2 => array (IMG_FILTER_GRAYSCALE, 0),
                    3 => array (IMG_FILTER_BRIGHTNESS, 1),
                    4 => array (IMG_FILTER_CONTRAST, 1),
                    5 => array (IMG_FILTER_COLORIZE, 4),
                    6 => array (IMG_FILTER_EDGEDETECT, 0),
                    7 => array (IMG_FILTER_EMBOSS, 0),
                    8 => array (IMG_FILTER_GAUSSIAN_BLUR, 0),
                    9 => array (IMG_FILTER_SELECTIVE_BLUR, 0),
                    10 => array (IMG_FILTER_MEAN_REMOVAL, 0),
                    11 => array (IMG_FILTER_SMOOTH, 0),
            );
        }
        $destX = min( $options['x'], $options['maxX'] );
        $destY = min( $options['y'], $options['maxY'] );
        switch( $mimeType ) {
            case 'image/jpg':
            case 'image/jpeg':
            case 'image/pjgpg':
                $image = imagecreatefromjpeg( $source );
                break;
            case 'image/png':
                $image = imagecreatefrompng( $source );
                break;
            case 'image/gif':
                $image = imagecreatefromgif( $source );
                break;
        }
        if( !isset( $image ) ) {
            throw new Exception( 'Could not open Image' );
        }
        $width = imagesx( $image );
        $height = imagesy( $image );
        $originX = $originY = 0;
        if( $destX > 0 && $destY == 0 ) {
            $destY = floor( $height * ( $destX / $width ) );
        } else if( $destY > 0 && $destX == 0 ) {
            $destX = floor( $width * ( $destY / $height ) );
        }
        // scale down and add borders
        if( $options['zoom_crop'] == 3 ) {
            $finalY = $height * ( $destX / $width );
            if( $finalY > $destY ) {
                $destX = $width * ( $destY / $height );
            } else {
                $destY = $finalY;
            }
        }
        $canvas = imagecreatetruecolor( $destX, $destY );
        imagealphablending( $canvas, false );
        if( strlen( $options['canvas'] ) < 6 ) {
            $options['canvas'] = 'ffffff';
        }
        $canvasColorR = hexdec( substr( $options['canvas'], 0, 2 ) );
        $canvasColorG = hexdec( substr( $options['canvas'], 2, 2 ) );
        $canvasColorB = hexdec( substr( $options['canvas'], 2, 2 ) );
        // transparentes bild erstellen
        $color = imagecolorallocatealpha( $canvas, $canvasColorR, $canvasColorG, $canvasColorB, 127 );
        imagefill( $canvas, 0, 0, $color );
        // scale down and add borders
        if( $options['zoom_crop'] == 2 ) {
            $finalY = $height * ( $destX / $width );
            if( $finalY > $destY ) {
                $originX = $destX / 2;
                $destX = $width * ( $destY / $height );
                $originX = round( $originX - ( $destX / 2 ) );
            } else {
                $originY = $destY / 2;
                $destY = $finalY;
                $originY = round( $originY - ( $destY / 2 ) );
            }
        }
        // restore transparency blending
        imagesavealpha( $canvas, true );
        if( $options['zoom_crop'] > 0 ) {
            $srcX = $srcY = 0;
            $srcW = $width;
            $srcH = $height;
            $cmpX = $width / $destX;
            $cmpY = $height / $destY;
            // calculate x or y coordinate and width or height of source
            if( $cmpX > $cmpY ) {
                // breitformat
                $srcW = round( $width / $cmpX * $cmpY );
                $srcX = round( ( $width - ( $width / $cmpX * $cmpY ) ) / 2 );
            } elseif( $cmpY > $cmpX ) {
                $srcH = round( $height / $cmpY * $cmpX );
                $srcY = round( ( $height - ( $height / $cmpY * $cmpX ) ) / 2 );
            }
            // pos cropping
            if( strlen( $options['align'] ) ) {
                if( strpos( $options['align'], 't') !== false) {
                    $srcY = 0;
                }
                if( strpos( $options['align'], 'b') !== false) {
                    $srcY = $height - $srcH;
                }
                if( strpos( $options['align'], 'l') !== false) {
                    $srcX = 0;
                }
                if( strpos( $options['align'], 'r') !== false) {
                    $srcX = $width - $srcW;
                }
            }
            imagecopyresampled( $canvas, $image, $originX, $originY, $srcX, $srcY, $destX, $destY, $srcW, $srcH );
        } else {
            imagecopyresampled( $canvas, $image, 0, 0, 0, 0, $destX, $destY, $width, $height );
        }
        // @todo filtermöglichkeit über optionen ausbessern
        if( strlen( $options['filters'] ) && function_exists( 'imagefilter' ) && defined( 'IMG_FILTER_NEGATE' ) ) {
            // apply filters to image
            $filterList = explode( '|', $options['filters'] );
            foreach( $filterList as $fl ) {
                $filterSettings = explode (',', $fl);
                if (isset ($imageFilters[$filterSettings[0]])) {
                    for ($i = 0; $i < 4; $i ++) {
                        if (!isset ($filterSettings[$i])) {
                            $filterSettings[$i] = null;
                        } else {
                            $filterSettings[$i] = (int) $filterSettings[$i];
                        }
                    }
                    switch ($imageFilters[$filterSettings[0]][1]) {
                        case 1:
                            imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);
                            break;
                        case 2:
                            imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);
                            break;
                        case 3:
                            imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);
                            break;
                        case 4:
                            imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]);
                            break;
                        default:
                            imagefilter ($canvas, $imageFilters[$filterSettings[0]][0]);
                            break;
                    }
                }
            }
        }
        if( $options['sharpen'] > 0 && function_exists( 'imageconvolution' ) ) {
            $sharpenMatrix = array (
                            array (-1,-1,-1),
                            array (-1,16,-1),
                            array (-1,-1,-1),
                            );
            $divisor = 8;
            $offset = 0;
            imageconvolution( $canvas, $sharpenMatrix, $divisor, $offset );
        }
        //Straight from Wordpress core code. Reduces filesize by up to 70% for PNG's
        if( ( IMAGETYPE_PNG == $origType || IMAGETYPE_GIF == $origType ) &&
            function_exists( 'imageistruecolor' ) && !imageistruecolor( $image ) &&
            imagecolortransparent( $image ) > 0 ) {
            imagetruecolortopalette( $canvas, false, imagecolorstotal( $image ) );
        }
        if( null === $destination ) {
            header( "Cache-Control: no-store, no-cache, must-revalidate" );
            header( "Cache-Control: post-check=0, pre-check=0", false);
            header( "Pragma: no-cache" );
            header( "Expires: Sat, 26 Jul 1997 05:00:00 GMT" );
            header( "Last-Modified: " . date( "D, d M Y H:i:s" ) . " GMT" );
        }
        switch( $mimeType ) {
            case 'image/jpg':
            case 'image/jpeg':
            case 'image/pjgpg':
                if( null === $destination ) {
                    header("Content-type: image/jpeg");
                }
                @imagejpeg( $canvas, $destination, $options['quality'] );
                break;
            case 'image/png':
                if( null === $destination ) {
                    header("Content-type: image/png");
                }
                @imagepng( $canvas, $destination, floor( $options['quality'] * 0.09 ) );
                break;
            case 'image/gif':
                if( null === $destination ) {
                    header("Content-type: image/gif");
                }
                @imagegif( $canvas, $destination );
                break;
            default:
                throw new Exception( 'Fehler beim schreiben' );
                break;
        }
        imagedestroy( $canvas );
        imagedestroy( $image );
    }
}