Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> PHP

ปรับขนาดรูปภาพใน PHP ด้วย GD Library

PHP มี Extension หลัก 2 ตัวสำหรับจัดการรูปภาพ: GD (มาตรฐาน, ติดตั้งง่าย) และ ImageMagick (ทรงพลังกว่า, รองรับฟอร์แมตมากกว่า) บทความนี้เน้น GD

ฟังก์ชันปรับขนาดรูปภาพครบวงจร

/**
 * ปรับขนาดรูปภาพด้วย GD
 * 
 * @param string $sourcePath   ไฟล์ต้นทาง
 * @param int    $maxWidth     ความกว้างสูงสุด
 * @param int    $maxHeight    ความสูงสูงสุด
 * @param bool   $crop         true = ตัดครอปให้พอดีขนาด, false = ย่อให้พอดีในกรอบ (คงสัดส่วน)
 * @param int    $quality      คุณภาพ JPEG (0-100)
 * @return resource|false      Image Resource หรือ false ถ้าล้มเหลว
 */
function resizeImage($sourcePath, $maxWidth, $maxHeight, $crop = false, $quality = 85) {
    // 1. ตรวจสอบไฟล์และอ่านข้อมูล
    if (!file_exists($sourcePath)) {
        throw new Exception("File not found: $sourcePath");
    }
    
    $imageInfo = getimagesize($sourcePath);
    if (!$imageInfo) {
        throw new Exception("Not a valid image file");
    }
    
    $srcWidth = $imageInfo[0];
    $srcHeight = $imageInfo[1];
    $mimeType = $imageInfo['mime'];
    
    // 2. สร้าง Image Resource ตามประเภทไฟล์
    switch ($mimeType) {
        case 'image/jpeg':
            $source = imagecreatefromjpeg($sourcePath);
            break;
        case 'image/png':
            $source = imagecreatefrompng($sourcePath);
            break;
        case 'image/gif':
            $source = imagecreatefromgif($sourcePath);
            break;
        case 'image/webp':
            $source = imagecreatefromwebp($sourcePath);
            break;
        default:
            throw new Exception("Unsupported image type: $mimeType");
    }
    
    if (!$source) {
        throw new Exception("Failed to create image resource");
    }
    
    // 3. คำนวณขนาดใหม่
    if ($crop) {
        // โหมด Crop: ตัดให้พอดีขนาดเป๊ะๆ (อาจตัดส่วนข้าง/บนล่าง)
        $srcRatio = $srcWidth / $srcHeight;
        $dstRatio = $maxWidth / $maxHeight;
        
        if ($srcRatio > $dstRatio) {
            // รูปกว้างเกิน -> ตัดซ้าย/ขวา
            $cropWidth = $srcHeight * $dstRatio;
            $cropHeight = $srcHeight;
            $srcX = ($srcWidth - $cropWidth) / 2;
            $srcY = 0;
        } else {
            // รูปสูงเกิน -> ตัดบน/ล่าง
            $cropWidth = $srcWidth;
            $cropHeight = $srcWidth / $dstRatio;
            $srcX = 0;
            $srcY = ($srcHeight - $cropHeight) / 2;
        }
        
        $dstWidth = $maxWidth;
        $dstHeight = $maxHeight;
    } else {
        // โหมด Fit: ย่อให้พอดีในกรอบ คงสัดส่วน
        $ratio = min($maxWidth / $srcWidth, $maxHeight / $srcHeight);
        $dstWidth = (int)round($srcWidth * $ratio);
        $dstHeight = (int)round($srcHeight * $ratio);
        $srcX = $srcY = 0;
        $cropWidth = $srcWidth;
        $cropHeight = $srcHeight;
    }
    
    // 4. สร้าง Destination Image
    $dest = imagecreatetruecolor($dstWidth, $dstHeight);
    
    // รองรับ Transparency (PNG, GIF, WebP)
    if (in_array($mimeType, ['image/png', 'image/gif', 'image/webp'])) {
        imagealphablending($dest, false);
        imagesavealpha($dest, true);
        $transparent = imagecolorallocatealpha($dest, 255, 255, 255, 127);
        imagefilledrectangle($dest, 0, 0, $dstWidth, $dstHeight, $transparent);
    }
    
    // 5. Resample (คุณภาพดีกว่า Resize ธรรมดา)
    imagecopyresampled(
        $dest, $source,
        0, 0, $srcX, $srcY,
        $dstWidth, $dstHeight,
        $cropWidth, $cropHeight
    );
    
    // 6. คืนค่า Resource (Caller ต้อง save เอง)
    return $dest;
}

วิธีใช้งาน: บันทึกไฟล์

try {
    // ปรับขนาดสูงสุด 800x600 คงสัดส่วน
    $resized = resizeImage('uploads/photo.jpg', 800, 600, false, 90);
    
    // บันทึกเป็น JPEG
    imagejpeg($resized, 'uploads/photo_resized.jpg', 90);
    
    // หรือบันทึกเป็น PNG
    // imagepng($resized, 'uploads/photo_resized.png', 9);
    
    // หรือ WebP (PHP 5.5+)
    // imagewebp($resized, 'uploads/photo_resized.webp', 90);
    
    // ปล่อยหน่วยความจำ
    imagedestroy($resized);
    
    echo "Resized successfully!";
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

ตัวอย่าง: สร้าง Thumbnail แบบ Crop (Square)

$thumb = resizeImage('uploads/photo.jpg', 200, 200, true, 85);
imagejpeg($thumb, 'uploads/thumb_200x200.jpg', 85);
imagedestroy($thumb);

หมายเหตุสำคัญ

  • Memory Limit: รูปภาพขนาดใหญ่ (เช่น 4000x3000 px) ใช้ RAM มาก ควรเพิ่ม memory_limit ใน php.ini
  • EXIF Orientation: รูปจากมือถือมักมี Orientation tag GD ไม่หมุนอัตโนมัติ ต้องใช้ Library เพิ่ม (เช่น lsolesen/exif)
  • ImageMagick: สำหรับ Production ที่ต้องการประสิทธิภาพ/คุณภาพสูง แนะนำใช้ imagick extension แทน