Hướng dẫn resize image (thu nhỏ ảnh) đơn giản với PHP

03/03/2014

Resize Image là một kỹ thuật mà hầu như bất kì website nào cũng sử dụng để tạo các hình ảnh thumbnail của bài viết. Nếu bạn đang làm đồ án môn học , và tự thiết kế một trang web bằng PHP , thì đoạn code mà mình giới thiệu cho các bạn trong bài viết này không nên bỏ qua. Ngoài ra, các bạn cũng có thể tham khảo bài viết Resizing images với PHP để có thêm lựa chọn cho chính mình.

resize_and_optimization

Trước hết mình xin giới thiệu các bạn 3 functions giúp chúng ta resize hình ảnh như sau :

resize_image_crop ($image,$width,$height)

Hàm này sẽ giúp chúng ta tạo ra một hình ảnh mới với đúng kích thước mà chúng ta chỉ định trong các tham số.

<?php

function resize_image_crop($image,$width,$height) {
    $w = @imagesx($image); //current width
    $h = @imagesy($image); //current height
    if ((!$w) || (!$h)) { $GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.'; return false; }
    if (($w == $width) && ($h == $height)) { return $image; } //no resizing needed

    //try max width first...
    $ratio = $width / $w;
    $new_w = $width;
    $new_h = $h * $ratio;

    //if that created an image smaller than what we wanted, try the other way
    if ($new_h < $height) {
        $ratio = $height / $h;
        $new_h = $height;
        $new_w = $w * $ratio;
    }

    $image2 = imagecreatetruecolor ($new_w, $new_h);
    imagecopyresampled($image2,$image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);

    //check to see if cropping needs to happen
    if (($new_h != $height) || ($new_w != $width)) {
        $image3 = imagecreatetruecolor ($width, $height);
        if ($new_h > $height) { //crop vertically
            $extra = $new_h - $height;
            $x = 0; //source x
            $y = round($extra / 2); //source y
            imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
        } else {
            $extra = $new_w - $width;
            $x = round($extra / 2); //source x
            $y = 0; //source y
            imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
        }
        imagedestroy($image2);
        return $image3;
    } else {
        return $image2;
    }
}

?>

resize_image_max($image,$max_width,$max_height)

Hàm này sẽ tạo ra một hình với hình ảnh được thu nhỏ không vượt quá các kích thước mà bạn chỉ định.

<?php

function resize_image_max($image,$max_width,$max_height) {
    $w = imagesx($image); //current width
    $h = imagesy($image); //current height
    if ((!$w) || (!$h)) { $GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.'; return false; }

    if (($w <= $max_width) && ($h <= $max_height)) { return $image; } //no resizing needed

    //try max width first...
    $ratio = $max_width / $w;
    $new_w = $max_width;
    $new_h = $h * $ratio;

    //if that didn't work
    if ($new_h > $max_height) {
        $ratio = $max_height / $h;
        $new_h = $max_height;
        $new_w = $w * $ratio;
    }

    $new_image = imagecreatetruecolor ($new_w, $new_h);
    imagecopyresampled($new_image,$image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);
    return $new_image;
}

?>

resize_image_force ($image,$width,$height)

Hàm này cũng tạo một hình ảnh đúng với kích thước mà bạn chỉ định, nhưng khác là nó không crop hình lại.

<?php

function resize_image_force($image,$width,$height) {
    $w = @imagesx($image); //current width
    $h = @imagesy($image); //current height
    if ((!$w) || (!$h)) { $GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.'; return false; }
    if (($w == $width) && ($h == $height)) { return $image; } //no resizing needed

    $image2 = imagecreatetruecolor ($width, $height);
    imagecopyresampled($image2,$image, 0, 0, 0, 0, $width, $height, $w, $h);

    return $image2;
}

?>

Cuối cùng, chúng ta sẽ tập hợp những hàm này lại để tạo ra một hàm resize image duy nhất .

<?php

function resize_image($method,$image_loc,$new_loc,$width,$height) {
    if (!is_array(@$GLOBALS['errors'])) { $GLOBALS['errors'] = array(); }

    if (!in_array($method,array('force','max','crop'))) { $GLOBALS['errors'][] = 'Invalid method selected.'; }

    if (!$image_loc) { $GLOBALS['errors'][] = 'No source image location specified.'; }
    else {
        if ((substr(strtolower($image_loc),0,7) == 'http://') || (substr(strtolower($image_loc),0,7) == 'https://')) { /*don't check to see if file exists since it's not local*/ }
        elseif (!file_exists($image_loc)) { $GLOBALS['errors'][] = 'Image source file does not exist.'; }
        $extension = strtolower(substr($image_loc,strrpos($image_loc,'.')));
        if (!in_array($extension,array('.jpg','.jpeg','.png','.gif','.bmp'))) { $GLOBALS['errors'][] = 'Invalid source file extension!'; }
    }

    if (!$new_loc) { $GLOBALS['errors'][] = 'No destination image location specified.'; }
    else {
        $new_extension = strtolower(substr($new_loc,strrpos($new_loc,'.')));
        if (!in_array($new_extension,array('.jpg','.jpeg','.png','.gif','.bmp'))) { $GLOBALS['errors'][] = 'Invalid destination file extension!'; }
    }

    $width = abs(intval($width));
    if (!$width) { $GLOBALS['errors'][] = 'No width specified!'; }

    $height = abs(intval($height));
    if (!$height) { $GLOBALS['errors'][] = 'No height specified!'; }

    if (count($GLOBALS['errors']) > 0) { echo_errors(); return false; }

    if (in_array($extension,array('.jpg','.jpeg'))) { $image = @imagecreatefromjpeg($image_loc); }
    elseif ($extension == '.png') { $image = @imagecreatefrompng($image_loc); }
    elseif ($extension == '.gif') { $image = @imagecreatefromgif($image_loc); }
    elseif ($extension == '.bmp') { $image = @imagecreatefromwbmp($image_loc); }

    if (!$image) { $GLOBALS['errors'][] = 'Image could not be generated!'; }
    else {
        $current_width = imagesx($image);
        $current_height = imagesy($image);
        if ((!$current_width) || (!$current_height)) { $GLOBALS['errors'][] = 'Generated image has invalid dimensions!'; }
    }
    if (count($GLOBALS['errors']) > 0) { @imagedestroy($image); echo_errors(); return false; }

    if ($method == 'force') { $new_image = resize_image_force($image,$width,$height); }
    elseif ($method == 'max') { $new_image = resize_image_max($image,$width,$height); }
    elseif ($method == 'crop') { $new_image = resize_image_crop($image,$width,$height); }

    if ((!$new_image) && (count($GLOBALS['errors'] == 0))) { $GLOBALS['errors'][] = 'New image could not be generated!'; }
    if (count($GLOBALS['errors']) > 0) { @imagedestroy($image); echo_errors(); return false; }

    $save_error = false;
    if (in_array($extension,array('.jpg','.jpeg'))) { imagejpeg($new_image,$new_loc) or ($save_error = true); }
    elseif ($extension == '.png') { imagepng($new_image,$new_loc) or ($save_error = true); }
    elseif ($extension == '.gif') { imagegif($new_image,$new_loc) or ($save_error = true); }
    elseif ($extension == '.bmp') { imagewbmp($new_image,$new_loc) or ($save_error = true); }
    if ($save_error) { $GLOBALS['errors'][] = 'New image could not be saved!'; }
    if (count($GLOBALS['errors']) > 0) { @imagedestroy($image); @imagedestroy($new_image); echo_errors(); return false; }

    imagedestroy($image);
    imagedestroy($new_image);

    return true;
}

function echo_errors() {
    if (!is_array(@$GLOBALS['errors'])) { $GLOBALS['errors'] = array('Unknown error!'); }
    foreach ($GLOBALS['errors'] as $error) { echo '<p style="color:red;font-weight:bold;">Error: '.$error.'</p>'; }
}

?>

Lời nói dù có hay đến đâu cũng không thể diễn tả bằng hình ảnh minh họa, vì thế mình sẽ làm ví dụ về cách sử dụng hàm bên trên như sau. Giả sử ta có một hình với kích thước ban đầu là 111 x 193 pixels .

penguin

Nếu các bạn sử dụng hàm resize_image với khai báo như sau :

resize_image('crop','penguin.jpg','penguin_crop.jpg',100,100);

Thì kết quả mà chúng ta có được sẽ là :

penguin_crop

Như các bạn thấy , ảnh đã được thu nhỏ đúng với kích thước là 100×100 nhưng chỉ có điều nó cắt đầu , cắt chân nên nhìn sẽ không được đẹp cho lắm.

Còn nếu như các bạn sử dụng với khai báo như sau :

resize_image('max','penguin.jpg','penguin_max.jpg',100,100);

Kết quả sẽ là :

penguin_max

Đây có lẽ là ảnh thu nhỏ trông giống như ảnh lớn nhất, nhưng kích thước thì lại không như chúng ta chỉ định, chiều cao thì đúng là 100 pixels , nhưng chiều ngang bây giờ chỉ còn 57 pixels.

Cuối cùng là nếu chúng ta khai báo các tham số như sau :

resize_image('force','penguin.jpg','penguin_force.jpg',100,100);

Kết quả :

penguin_force

Bây giờ, chúng ta có hình ảnh thu nhỏ đúng với kích thước chỉ định, hình ảnh cũng không bị cắt , nhưng nó sẽ bị bóp méo mó cho đúng.

Dựa vào các hàm trên, mình mong các bạn sẽ có lựa chọn đúng cho những mục đích resize image để tạo thumbnail cho bài viết của mình.

Chúc các bạn thành công !

Chuyên Mục:

Bài viết được đăng bởi webmaster

Nếu các bạn thấy bài viết hữu ích thì giúp mình Like cái nhé !
  • Tori Tran

    lại có nhiều phương án để lựa chọn, cám ơn TTW

  • Nguyễn Văn Hưởng

    Bài này hay quá, cảm ơn Thủ thuật web, hy vọng có nhiều bài viết thật hữu ích nữa