PHP图片文件大小压缩求助:保持尺寸不变压缩至指定大小
解决PHP图片上传时保持原宽高压缩大小的问题
看起来你之前尝试的压缩方法可能错误地修改了图片尺寸,或者在使用GD库处理时参数配置不当,导致出现黑图和过度压缩的情况。下面我结合你的现有代码,给出一套能保持原宽高、仅压缩文件体积的解决方案:
完整修改后的代码
<?php $allowedExts = array("gif", "jpeg", "jpg", "png"); $temp = explode(".", $_FILES["file"]["name"]); $extension = end($temp); $name = $_FILES["file"]["name"]; $type = $_FILES["file"]["type"]; $size = $_FILES["file"]["size"]; $tmp = $_FILES["file"]["tmp_name"]; $error = $_FILES["file"]["error"]; $savepath = "gallery/"; $filelocation = $savepath . $name; // 确保保存目录存在,避免上传失败 if (!is_dir($savepath)) { mkdir($savepath, 0755, true); } // 检查图片尺寸和原文件大小 list($width, $height) = getimagesize($tmp); if ($width > 800 || $height > 600) { echo "Error: Image size must be a maximum of 800 x 600 pixels."; exit; } // 自定义压缩函数:保持原宽高,通过调整质量压缩体积 function compressImage($source, $destination, $quality, $extension, $width, $height) { // 根据图片类型创建对应资源 switch($extension) { case 'jpg': case 'jpeg': $image = imagecreatefromjpeg($source); break; case 'png': // PNG需保留透明度,初始化时开启透明支持 $image = imagecreatefrompng($source); imagealphablending($image, false); imagesavealpha($image, true); break; case 'gif': $image = imagecreatefromgif($source); break; default: return false; } // 创建与原图尺寸一致的目标画布 $compressedImage = imagecreatetruecolor($width, $height); // 针对PNG/GIF处理透明背景,避免黑图 if($extension == 'png' || $extension == 'gif') { imagealphablending($compressedImage, false); imagesavealpha($compressedImage, true); $transparent = imagecolorallocatealpha($compressedImage, 255, 255, 255, 127); imagefill($compressedImage, 0, 0, $transparent); } // 复制原图到目标画布(不缩放,仅压缩) imagecopyresampled($compressedImage, $image, 0, 0, 0, 0, $width, $height, $width, $height); // 根据图片类型输出压缩后的文件 $success = false; switch($extension) { case 'jpg': case 'jpeg': // JPG质量范围0-100,数值越低体积越小 $success = imagejpeg($compressedImage, $destination, $quality); break; case 'png': // PNG质量范围0-9,0最小体积,9最高质量 $pngQuality = 9 - ($quality * 0.09); // 转换JPG质量到PNG范围 $success = imagepng($compressedImage, $destination, (int)$pngQuality); break; case 'gif': $success = imagegif($compressedImage, $destination); break; } // 释放内存资源,避免溢出 imagedestroy($image); imagedestroy($compressedImage); return $success; } // 处理上传和压缩逻辑 if (!file_exists($filelocation) && $error == 0) { // 压缩质量设置:JPG建议50-70,可根据需求调整(比如要压到200KB内可尝试50) $compressionQuality = 60; // 调用压缩函数生成目标文件 if(compressImage($tmp, $filelocation, $compressionQuality, $extension, $width, $height)) { // 保留你原来的数据库插入逻辑 $album = escape_sql(CleanUp($_POST['album'])); $caption = escape_sql(CleanUp($_POST['caption'])); // ... 你的数据库操作代码 ... echo "Image uploaded and compressed successfully!"; } else { echo "Error: Failed to compress image."; } } else { if(file_exists($filelocation)) { echo "Error: File already exists."; } else { echo "Error: Upload error code " . $error; } } ?>
关键细节说明
- 保持原宽高:使用
imagecopyresampled时,目标与源的宽高参数完全一致,仅复制原图像素,不做缩放处理。 - 解决黑图问题:针对PNG和GIF的透明属性做了特殊处理,创建目标画布时设置透明背景,避免透明区域被填充为黑色。
- 质量与体积平衡:
- JPG格式通过调整
$compressionQuality(0-100)控制体积,数值越低压缩率越高,建议50-70兼顾画质和体积。 - PNG格式自动转换质量参数范围,确保压缩效果统一。
- JPG格式通过调整
- 内存优化:处理完成后调用
imagedestroy释放GD库资源,避免服务器内存占用过高。
调试建议
如果还是达不到预期的压缩体积,可以:
- 适当降低
$compressionQuality的值(比如从60降到40)。 - 检查原图是否本身已是高压缩格式(部分PNG或优化过的JPG压缩空间有限)。
内容的提问来源于stack exchange,提问作者Aki
相关产品推荐
相关产品推荐

