用PHP实现图片压缩显示

PHP实现图片压缩显示的基本原理

图片压缩显示的核心在于通过PHP的GD库或Imagick扩展对原始图片进行缩放和优化处理,生成更小尺寸或更低质量的图片文件。GD库是PHP内置的图像处理库,而Imagick功能更强大但需要额外安装。

图片压缩通常涉及以下步骤:读取原始图片、计算缩放比例、创建新画布、绘制缩放后的图像、输出或保存压缩后的图片。通过调整压缩参数,可以在文件大小和图片质量之间找到平衡。

使用GD库压缩图片

GD库是PHP默认支持的图像处理库,适合简单的图片压缩需求。以下是一个完整的GD库压缩示例:

function compressImageWithGD($sourcePath, $targetPath, $maxWidth, $maxHeight, $quality = 75) {
    // 获取原始图片信息
    list($origWidth, $origHeight, $type) = getimagesize($sourcePath);
    
    // 计算缩放比例
    $ratio = min($maxWidth/$origWidth, $maxHeight/$origHeight);
    $newWidth = $origWidth * $ratio;
    $newHeight = $origHeight * $ratio;
    
    // 创建新画布
    $newImage = imagecreatetruecolor($newWidth, $newHeight);
    
    // 根据不同类型创建原始图像资源
    switch($type) {
        case IMAGETYPE_JPEG:
            $sourceImage = imagecreatefromjpeg($sourcePath);
            break;
        case IMAGETYPE_PNG:
            $sourceImage = imagecreatefrompng($sourcePath);
            imagealphablending($newImage, false);
            imagesavealpha($newImage, true);
            break;
        case IMAGETYPE_GIF:
            $sourceImage = imagecreatefromgif($sourcePath);
            break;
        default:
            return false;
    }
    
    // 缩放图像
    imagecopyresampled($newImage, $sourceImage, 0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);
    
    // 保存压缩后的图片
    switch($type) {
        case IMAGETYPE_JPEG:
            imagejpeg($newImage, $targetPath, $quality);
            break;
        case IMAGETYPE_PNG:
            imagepng($newImage, $targetPath, round(9 * (100 - $quality) / 100));
            break;
        case IMAGETYPE_GIF:
            imagegif($newImage, $targetPath);
            break;
    }
    
    // 释放内存
    imagedestroy($sourceImage);
    imagedestroy($newImage);
    
    return true;
}

// 使用示例
compressImageWithGD('original.jpg', 'compressed.jpg', 800, 600, 80);

使用Imagick扩展压缩图片

Imagick扩展提供了更专业的图像处理能力,适合需要高质量压缩的场景:

function compressImageWithImagick($sourcePath, $targetPath, $maxWidth, $maxHeight, $quality = 80) {
    try {
        $image = new Imagick($sourcePath);
        
        // 设置压缩质量
        $image->setImageCompressionQuality($quality);
        
        // 保持宽高比缩放
        $image->resizeImage($maxWidth, $maxHeight, Imagick::FILTER_LANCZOS, 1, true);
        
        // 优化图片
        $image->stripImage(); // 移除EXIF等元数据
        $image->setInterlaceScheme(Imagick::INTERLACE_JPEG); // 渐进式JPEG
        
        // 根据扩展名保存
        $ext = strtolower(pathinfo($targetPath, PATHINFO_EXTENSION));
        if ($ext == 'jpg' || $ext == 'jpeg') {
            $image->setImageFormat('jpeg');
        } elseif ($ext == 'png') {
            $image->setImageFormat('png');
        }
        
        $image->writeImage($targetPath);
        $image->destroy();
        return true;
    } catch (Exception $e) {
        return false;
    }
}

// 使用示例
compressImageWithImagick('original.png', 'compressed.png', 800, 600, 85);

图片质量与文件大小的平衡

图片压缩需要在质量和文件大小之间找到平衡点。以下是一些实用技巧:

  • JPEG格式适用于照片类图像,质量参数通常在60-85之间
  • PNG格式适合需要透明度的图像,压缩主要通过减少颜色深度实现
  • GIF格式适合简单动画,但压缩率较低
// 动态调整JPEG质量以达到目标文件大小
function compressToTargetSize($sourcePath, $targetPath, $targetSizeKB) {
    $quality = 90; // 初始质量
    do {
        compressImageWithGD($sourcePath, $targetPath, 1000, 1000, $quality);
        $currentSizeKB = filesize($targetPath) / 1024;
        $quality -= 5;
    } while ($currentSizeKB > $targetSizeKB && $quality > 10);
}

// 使用示例
compressToTargetSize('large_image.jpg', 'optimized.jpg', 200); // 目标200KB

批量处理图片压缩

对于需要处理大量图片的场景,可以结合目录遍历实现批量压缩:

function batchCompressImages($sourceDir, $targetDir, $maxWidth, $maxHeight, $quality = 80) {
    if (!file_exists($targetDir)) {
        mkdir($targetDir, 0755, true);
    }
    
    $files = scandir($sourceDir);
    foreach ($files as $file) {
        if ($file == '.' || $file == '..') continue;
        
        $sourcePath = $sourceDir . '/' . $file;
        $targetPath = $targetDir . '/' . $file;
        
        $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif'])) {
            compressImageWithGD($sourcePath, $targetPath, $maxWidth, $maxHeight, $quality);
        }
    }
}

// 使用示例
batchCompressImages('uploaded_images', 'compressed_images', 1024, 768, 75);

浏览器直接输出压缩图片

有时可能需要直接将压缩后的图片输出到浏览器而不保存文件:

function outputCompressedImage($imagePath, $maxWidth, $maxHeight, $quality = 75) {
    list($origWidth, $origHeight, $type) = getimagesize($imagePath);
    
    $ratio = min($maxWidth/$origWidth, $maxHeight/$origHeight);
    $newWidth = $origWidth * $ratio;
    $newHeight = $origHeight * $ratio;
    
    $newImage = imagecreatetruecolor($newWidth, $newHeight);
    
    switch($type) {
        case IMAGETYPE_JPEG:
            $sourceImage = imagecreatefromjpeg($imagePath);
            header('Content-Type: image/jpeg');
            break;
        case IMAGETYPE_PNG:
            $sourceImage = imagecreatefrompng($imagePath);
            imagealphablending($newImage, false);
            imagesavealpha($newImage, true);
            header('Content-Type: image/png');
            break;
        case IMAGETYPE_GIF:
            $sourceImage = imagecreatefromgif($imagePath);
            header('Content-Type: image/gif');
            break;
        default:
            return false;
    }
    
    imagecopyresampled($newImage, $sourceImage, 0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);
    
    switch($type) {
        case IMAGETYPE_JPEG:
            imagejpeg($newImage, null, $quality);
            break;
        case IMAGETYPE_PNG:
            imagepng($newImage, null, round(9 * (100 - $quality) / 100));
            break;
        case IMAGETYPE_GIF:
            imagegif($newImage);
            break;
    }
    
    imagedestroy($sourceImage);
    imagedestroy($newImage);
}

// 使用示例
outputCompressedImage('photo.jpg', 800, 600, 80);

性能优化建议

图片压缩可能消耗较多服务器资源,以下方法可以优化性能:

  • 缓存已压缩的图片,避免重复处理
  • 使用PHP的OPcache加速脚本执行
  • 对大图片处理设置适当的超时限制
  • 考虑使用队列系统异步处理大量图片
// 带缓存功能的图片压缩
function cachedImageCompress($sourcePath, $cachePath, $maxWidth, $maxHeight, $quality = 80) {
    $cacheKey = md5($sourcePath.$maxWidth.$maxHeight.$quality);
    $cachedFile = $cachePath.'/'.$cacheKey.'.jpg';
    
    if (file_exists($cachedFile) && (filemtime($cachedFile) > filemtime($sourcePath))) {
        return $cachedFile;
    }
    
    if (compressImageWithGD($sourcePath, $cachedFile, $maxWidth, $maxHeight, $quality)) {
        return $cachedFile;
    }
    
    return false;
}

// 使用示例
$compressedImage = cachedImageCompress('original.jpg', 'cache', 800, 600, 85);
if ($compressedImage) {
    header('Content-Type: image/jpeg');
    readfile($compressedImage);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值