0
点赞
收藏
分享

微信扫一扫

python二分法压缩图片

我希望对本地的图片进行压缩,用python实现此功能

steo1:C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\hello.py 其中,生成的图片,在py同路径下

from PIL import Image
from enum import Enum
import io


class ImageCompressionQuality(Enum):
    LOW = 0.3
    MEDIUM = 0.5
    HIGH = 0.7

    @staticmethod
    def custom(value):
        return max(0.0, min(1.0, value))


class ImageCompression:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def _convert_image_mode(self, image):
        """Convert image to RGB mode if needed"""
        img = image.copy()
        if img.mode in ('RGBA', 'LA', 'P'):
            img = img.convert('RGB')
        return img

    def compress_image(self, image, quality=0.5):
        """Compress image with specified quality (0.0-1.0 or ImageCompressionQuality enum)"""
        try:
            # Handle quality parameter
            if isinstance(quality, ImageCompressionQuality):
                quality_value = quality.value
            else:
                quality_value = max(0.0, min(1.0, float(quality)))

            img = self._convert_image_mode(image)
            quality_percent = int(quality_value * 100)

            # Save to bytes buffer
            img_io = io.BytesIO()
            img.save(img_io, format='JPEG', quality=quality_percent, optimize=True)
            img_io.seek(0)
            return img_io.getvalue()
        except Exception as e:
            print(f"Compression error: {e}")
            return None

    def compress_to_target_size(self, image, target_size_kb):
        """Compress image to target size in KB using binary search"""
        target_size_bytes = target_size_kb * 1024
        min_quality = 0.0
        max_quality = 1.0
        quality = 0.8
        best_data = None

        # Initial check
        current_data = self.compress_image(image, quality)
        if current_data and len(current_data) <= target_size_bytes:
            return current_data

        # Binary search
        for _ in range(6):
            quality = (min_quality + max_quality) / 2
            current_data = self.compress_image(image, quality)
            if not current_data:
                break

            if len(current_data) > target_size_bytes:
                max_quality = quality
            else:
                min_quality = quality
                best_data = current_data

        return best_data or self.compress_image(image, min_quality)

    def resize_image(self, image, max_dimension):
        """Resize image to maximum dimension while maintaining aspect ratio"""
        img = image.copy()
        img.thumbnail((max_dimension, max_dimension))
        return img

    def optimize_for_upload(self, image):
        """Optimize image for upload (resize + compress to 500KB)"""
        resized_img = self.resize_image(image, 1200)
        return self.compress_to_target_size(resized_img, 500)


# 使用示例
if __name__ == "__main__":
    img_path = r"C:\Users\wangrusheng\Downloads\apple.jpg"

    try:
        # 加载图片
        with Image.open(img_path) as img:
            # 创建压缩器实例
            compressor = ImageCompression()

            # 示例1: 使用中等质量压缩
            compressed_data = compressor.compress_image(img, ImageCompressionQuality.MEDIUM)
            with open("compressed_medium.jpg", "wb") as f:
                f.write(compressed_data)

            # 示例2: 压缩到300KB
            target_data = compressor.compress_to_target_size(img, 300)
            if target_data:
                with open("compressed_300kb.jpg", "wb") as f:
                    f.write(target_data)

            # 示例3: 调整尺寸并优化上传
            optimized_data = compressor.optimize_for_upload(img)
            if optimized_data:
                with open("optimized_upload.jpg", "wb") as f:
                    f.write(optimized_data)

    except Exception as e:
        print(f"Error processing image: {e}")

end

举报

相关推荐

0 条评论