吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 994|回复: 58
上一主题 下一主题
收起左侧

[原创工具] 图片压缩工具

  [复制链接]
跳转到指定楼层
楼主
okeo 发表于 2024-12-23 10:53 回帖奖励
  在为网站上传图片时,经常会遇到对图片文件大小和分辨率的限制。为了确保图片符合这些要求而不失质量,图片压缩工具成为不可或缺的好帮手。这类工具不仅能够有效减小文件体积,还能保持图像的清晰度,确保网页加载速度不受影响。
主要功能与优势:
  1.智能压缩:利用先进的算法,在几乎不影响视觉效果的情况下减少图片文件的大小,确保图片符合网站的上传要求

  2.格式转换:部分工具还提供格式转换功能,可以将图片转换为最适合网络使用的格式(如 JPEG、PNG 等多种图片格式),进一步优化文件大小。

  3.自定义设置:允许用户调整压缩级别,根据具体需求平衡图片质量和文件大小。

  4.即时预览:一些工具提供即时预览功能,让用户可以在压缩前后对比图片质量,确保最终效果满意。




   软件下载地址:https://wwtg.lanzouo.com/isxNl2isztqj    密码:52pj

   代码源码如下,有需要的可以自行修改研究:
[Python] 纯文本查看 复制代码
import os
import re
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from PIL import Image, ImageTk, UnidentifiedImageError
import threading
import logging

# 设置日志配置
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

class ImageCompressorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图片压缩工具 by ke")
        self.root.geometry("1024x650")
        self.root.configure(bg="#f0f0f0")

        # 初始化变量
        self.image_path = None  # 图片路径
        self.output_location = None  # 输出位置
        self.target_size_kb = tk.IntVar(value=400)  # 默认目标大小为400KB
        self.new_filename = tk.StringVar()  # 新文件名
        self.output_format = tk.StringVar(value="JPG")  # 修改默认输出格式为JPG

        # 创建界面元素
        self.create_widgets()

    def create_widgets(self):
        main_frame = tk.Frame(self.root, bg="#f0f0f0")
        main_frame.pack(expand=True, fill='both', padx=20, pady=20)

        # 文件选择和预览
        img_frame = tk.Frame(main_frame, bg="#f0f0f0")
        img_frame.pack(fill='x')

        self.img_label = tk.Label(img_frame, text="请加载一张图片", bg="#f0f0f0")
        self.img_label.pack(side=tk.LEFT, padx=10, pady=10)

        browse_button = tk.Button(img_frame, text="选择图片...", command=self.browse_files)
        browse_button.pack(side=tk.RIGHT, padx=10, pady=10)

        # 目标大小输入框
        size_frame = tk.Frame(main_frame, bg="#f0f0f0")
        size_frame.pack(fill='x', pady=5)
        tk.Label(size_frame, text="目标大小 (KB):", bg="#f0f0f0").pack(side=tk.LEFT, padx=5)
        self.size_entry = tk.Entry(size_frame, textvariable=self.target_size_kb, width=10)
        self.size_entry.pack(side=tk.LEFT, padx=5)

        # 设置新文件名
        filename_frame = tk.Frame(main_frame, bg="#f0f0f0")
        filename_frame.pack(fill='x', pady=5)
        tk.Label(filename_frame, text="新文件名:", bg="#f0f0f0").pack(side=tk.LEFT, padx=5)
        tk.Entry(filename_frame, textvariable=self.new_filename, width=30).pack(side=tk.LEFT, padx=5)

        # 选择输出格式
        format_frame = tk.Frame(main_frame, bg="#f0f0f0")
        format_frame.pack(fill='x', pady=5)
        tk.Label(format_frame, text="输出格式:", bg="#f0f0f0").pack(side=tk.LEFT, padx=5)
        format_combobox = ttk.Combobox(format_frame, textvariable=self.output_format,
                                       values=["JPG", "JPEG", "PNG", "BMP", "GIF"], width=10)
        format_combobox.current(0)  # 设置默认选中项为第一个选项,即"JPG"
        format_combobox.pack(side=tk.LEFT, padx=5)

        # 输出位置选择
        output_frame = tk.Frame(main_frame, bg="#f0f0f0")
        output_frame.pack(fill='x', pady=5)
        tk.Label(output_frame, text="输出位置:", bg="#f0f0f0").pack(side=tk.LEFT, padx=5)
        self.output_location_var = tk.StringVar()
        tk.Entry(output_frame, textvariable=self.output_location_var, width=50).pack(side=tk.LEFT, padx=5)
        tk.Button(output_frame, text="选择...", command=self.select_output_location).pack(side=tk.LEFT, padx=5)

        # 创建一个容器用于放置压缩并保存按钮和进度条
        bottom_frame = tk.Frame(self.root, bg="#f0f0f0")
        bottom_frame.pack(side=tk.BOTTOM, fill='x', pady=20)

        # 压缩并保存按钮
        compress_button = tk.Button(bottom_frame, text="压缩并保存", command=self.start_compress_and_save)
        compress_button.pack(side=tk.LEFT, padx=10)

        # 进度条放在最下方
        self.progress = ttk.Progressbar(bottom_frame, orient="horizontal", length=700, mode="determinate")
        self.progress.pack(side=tk.RIGHT, padx=10)

    def load_image(self, path):
        """加载并显示图片预览"""
        try:
            self.image_path = path
            img = Image.open(path)
            img.thumbnail((300, 300))
            self.photo = ImageTk.PhotoImage(img)
            self.img_label.config(image=self.photo)
        except Exception as e:
            logging.error(f"加载图片时出错: {str(e)}")
            self.show_message("错误", f"加载图片时出错: {str(e)}")

    def browse_files(self):
        """打开文件对话框选择图片"""
        filename = filedialog.askopenfilename(
            title="选择图片",
            filetypes=[("Image files", "*.png *.jpg *.jpeg *.bmp *.gif")]
        )
        if filename:
            self.load_image(filename)

    def select_output_location(self):
        """选择图片压缩后的输出位置"""
        directory = filedialog.askdirectory(title="选择输出位置")
        if directory:
            self.output_location_var.set(directory)

    def start_compress_and_save(self):
        """启动压缩线程并在UI上显示进度条"""
        self.progress["value"] = 0  # 初始化进度条为0%
        self.progress["maximum"] = 100  # 设置进度条的最大值为100%
        compress_thread = threading.Thread(target=self.compress_and_save)
        compress_thread.start()

    def compress_and_save(self):
        """执行图片压缩并保存到指定位置"""
        try:
            if not self.image_path or not self.output_location_var.get():
                self.show_message("警告", "请选择图片和输出位置!")
                return

            new_filename = sanitize_filename(self.new_filename.get().strip())
            if not new_filename:
                self.show_message("警告", "请输入有效的文件名!")
                return

            output_filename = f"{new_filename}.{self.get_output_extension()}"
            output_path = os.path.join(self.output_location_var.get(), output_filename)

            # 检查输出路径有效性
            if not os.path.isdir(self.output_location_var.get()):
                logging.error(f"输出位置不存在: {self.output_location_var.get()}")
                self.show_message("错误", "选择的输出位置无效,请重新选择。")
                return

            # 检查是否有写权限
            if not os.access(self.output_location_var.get(), os.W_OK):
                logging.error(f"没有写入权限: {self.output_location_var.get()}")
                self.show_message("错误", "没有足够的权限在选择的位置写入文件。")
                return

            target_size_kb = self.target_size_kb.get()
            original_size_kb = os.path.getsize(self.image_path) / 1024

            if original_size_kb <= target_size_kb:
                self.show_message("提示", "原图大小已经小于或等于目标大小,无需压缩。")
                return

            self.compress_image(self.image_path, output_path, target_size_kb)

            self.set_progress_value(100)  # 完成后设置进度条为100%
            self.show_message("成功", "图片已成功压缩并保存!")
        except Exception as e:
            logging.error(f"压缩失败: {str(e)}")
            self.show_message("错误", f"压缩失败: {str(e)}")
        finally:
            self.progress.stop()

    def compress_image(self, image_path, output_path, target_size_kb):
        """压缩图片至指定大小"""
        try:
            img = Image.open(image_path).convert('RGB')  # 确保图片模式兼容
            quality = 95
            original_size_kb = os.path.getsize(image_path) / 1024
            format_name = self.get_output_format()  # 获取正确的格式名称

            while original_size_kb > target_size_kb and quality >= 10:
                try:
                    img.save(output_path, format=format_name, optimize=True, quality=quality)
                    original_size_kb = os.path.getsize(output_path) / 1024
                    quality -= 5
                    self.update_progress(quality)
                except IOError as e:
                    logging.error(f"IO 错误: {str(e)}")
                    raise ValueError(f"IO 错误: {str(e)}")
                except Exception as e:
                    logging.error(f"保存图片时出错: {str(e)}")
                    raise ValueError(f"保存图片时出错: {str(e)}")

            if original_size_kb > target_size_kb:
                raise ValueError("无法将图片压缩到指定大小!请尝试增加目标大小或减少图片复杂度。")
        except UnidentifiedImageError:
            logging.error("无法识别的图片格式")
            self.show_message("错误", "无法识别的图片格式,请选择其他图片。")
        except Exception as e:
            logging.error(f"压缩图片时出错: {str(e)}")
            self.show_message("错误", f"压缩图片时出错: {str(e)}")

    def get_output_extension(self):
        """根据输出格式返回正确的文件扩展名"""
        format_name = self.output_format.get().upper()
        if format_name in ["JPG", "JPEG"]:
            return "jpg"
        elif format_name == "PNG":
            return "png"
        elif format_name == "BMP":
            return "bmp"
        elif format_name == "GIF":
            return "gif"
        else:
            return "jpg"

    def get_output_format(self):
        """根据输出格式返回正确的Pillow格式名称"""
        format_name = self.output_format.get().upper()
        if format_name in ["JPG", "JPEG"]:
            return "JPEG"
        elif format_name == "PNG":
            return "PNG"
        elif format_name == "BMP":
            return "BMP"
        elif format_name == "GIF":
            return "GIF"
        else:
            return "JPEG"

    def update_progress(self, quality):
        """更新进度条的值"""
        max_quality = 95
        min_quality = 10
        progress_value = ((max_quality - quality) / (max_quality - min_quality)) * 100
        self.root.after(0, lambda: self.set_progress_value(min(progress_value, 100)))

    def set_progress_value(self, value):
        """设置进度条的值"""
        self.progress["value"] = value

    def show_message(self, title, message):
        """显示消息框并停止进度条"""
        self.root.after(0, lambda: messagebox.showinfo(title, message))

def sanitize_filename(filename):
    """清理文件名中的非法字符"""
    return re.sub(r'[\\/*?:"<>|]', "", filename)

if __name__ == "__main__":
    root = tk.Tk()
    app = ImageCompressorApp(root)
    root.mainloop()

免费评分

参与人数 9吾爱币 +13 热心值 +8 收起 理由
xzkr + 1 + 1 谢谢@Thanks!
lgh978 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
jdhnp + 1 + 1 谢谢@Thanks!
laoda1228 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
墨与非 + 1 + 1 谢谢@Thanks!
alomoi + 1 + 1 我很赞同!
antikou + 1 谢谢@Thanks!
confiant + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| okeo 发表于 2024-12-24 08:52 |楼主

1.谢邀,楼主还在学习python,要是改好了 我又继续发布。
2.目前版本只支持单个压缩。
3.网站一般上传的是点毕业证,学位证还有奖状之类的。
推荐
妖精的旋律 发表于 2024-12-24 16:28
okeo 发表于 2024-12-24 08:52
1.谢邀,楼主还在学习python,要是改好了 我又继续发布。
2.目前版本只支持单个压缩。
3.网站一般上传 ...

选择照片可以设置成拖拽 比如一次性拖拽个三张五张。 输出目录也可以直接默认成当前目录。或者原图片目录 都可以!   输出格式可以默认和原图一致  文件名可以 原图的文件名 随便加什么  我只是站在使用时方便的角度思考。 冒犯!
沙发
妖精的旋律 发表于 2024-12-23 21:18
3#
eonion 发表于 2024-12-24 07:58
好东西,试了一下,很好用。
4#
laoda1228 发表于 2024-12-24 08:05
这个能批量压缩吗 ?  楼主
5#
xlwllm 发表于 2024-12-24 08:33
好东西啊 支持支持!
6#
petereda 发表于 2024-12-24 08:34
谢谢分享,正需要
7#
antikou 发表于 2024-12-24 08:37
感谢楼主!
8#
 楼主| okeo 发表于 2024-12-24 08:41 |楼主
laoda1228 发表于 2024-12-24 08:05
这个能批量压缩吗 ?  楼主

1.谢邀,楼主还在学习python,要是改好了 我又继续发布。
2.目前版本只支持单个压缩。
3.网站一般上传的是点毕业证,学位证还有奖状之类的。

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
laoda1228 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

9#
 楼主| okeo 发表于 2024-12-24 08:41 |楼主
eonion 发表于 2024-12-24 07:58
好东西,试了一下,很好用。

哈哈 感谢支持,
10#
 楼主| okeo 发表于 2024-12-24 08:42 |楼主

好的呢。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-27 13:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表