鱼C论坛

 找回密码
 立即注册
查看: 4013|回复: 72

[其他] 火爆全球的主流图片压缩方案自动化脚本(有彩蛋)

[复制链接]
发表于 2023-3-4 03:12:42 | 显示全部楼层 |阅读模式
购买主题 已有 12 人购买  本主题需向作者支付 10 鱼币 才能浏览
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-3-19 21:16:06 | 显示全部楼层
import os, sys
import tinify

tinify.key = 'key'
ext = ['.jpg', '.png', '.webp']

def compressPictures(showProgress):
    def compress(*args):
        progress = showProgress(*args)
        pic = args[0]
        wh = args[1]
        try:
            source = tinify.from_file(pic)
            if wh:
                picWidth = wh[0]
                picHeight = wh[1]
                if picWidth==0 or picHeight==0:
                    method = 'scale'
                    if picWidth==0:
                        resized = source.resize(method=method, height=picHeight)
                    else:
                        resized = source.resize(method=method, width=picWidth)
                else:
                    resized = source.resize(method='fit', width=picWidth, height=picHeight)
                resized.to_file(pic)   
            else:
                source.to_file(pic)
                
        except tinify.AccountError as e:
            print('错误 -> 请检查tinify密钥 或 帐户限制。\n')
        except tinify.ClientError as e:
            print('错误 -> 请检查源图片 或 请求选项。\n')
        except tinify.ServerError as e:          
            print('错误 -> Tinify API临时问题。\n')
        except tinify.ConnectionError as e:
            print('错误 -> 网络连接错误。\n')
        except Exception as e:
            print(f'错误 -> {str(e)}。\n')
        
        return progress
    
    return compress

@compressPictures
def showProgress(pic, wh, idx, total):
    pic = os.path.basename(pic)
    print(f'({idx}/{total})图片<{pic}>正在压缩处理中,请稍后...')
    
def startCompress(picList, wh):
    total = len(picList)
    for i, pic in enumerate(picList):
        showProgress(pic, wh, i+1, total)
    print('全部处理完成~')    
    
if __name__ == '__main__':
    picList = []
    pathList = sys.argv
    if len(pathList)>1:
        # 实现拖拽到源文件上进行压缩
        for path in pathList:
            if not os.path.isdir(path) and os.path.splitext(path)[1].lower() in ext:
                picList.append(path)
    else:
        src = input('请输入需要压缩的图片名称(回车优化当前文件夹):')        
        if src.strip()=='':
            print('开始优化当前文件夹下所有的jpg/png/webp图片')        
            pyPath = os.getcwd()
            for file in os.listdir(pyPath):
                path = os.path.join(pyPath, file)
                if not os.path.isdir(path) and os.path.splitext(path)[1].lower() in ext:
                    picList.append(path)       
        else:
            picList.append(src)
    if not picList:            
        input('当前未选择jpg/png/webp类型的图片。按回车退出程序...')
        exit()

    wh = input('请输入尺寸(宽度 高度)')
    wh = [int(n) for n in wh.strip().split()]

    startCompress(picList, wh)

    input('按回车退出程序...')
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2023-3-20 02:11:25 | 显示全部楼层
本帖最后由 hrpzcf 于 2023-3-20 12:18 编辑
# coding: utf-8

import os
import sys
from typing import *

import tinify

SUPPORTED = ".jpg", ".jpeg", ".png", ".webp"
OPTED_PREFIX = "optimized"
tinify.key = "xxxxxxxxxxxx"


def clean_filenames(files: List[str]) -> List[str]:
    valid_files = []
    for f in files:
        if f and os.path.isfile(f):
            if os.path.splitext(f)[1].lower() in SUPPORTED:
                valid_files.append(f)
    return valid_files


def receive_filenames() -> List[str]:
    if len(sys.argv) > 1:
        image_files = clean_filenames(sys.argv[1:])
        if not image_files:
            input("没有拖入任何有效的图片文件,按回车关闭后请重试...")
            sys.exit(1)
        return image_files
    while True:
        names = input("请输入要压缩的图片名称(回车压缩当前文件夹):")
        if names:
            image_files = clean_filenames(names.split())
        else:
            try:
                image_files = clean_filenames(os.listdir(os.curdir))
            except PermissionError:
                print("无法列举当前文件夹下的文件,请用其他方式指定...")
                continue
        if not image_files:
            print("没有找到符合要求的图片,请重新指定...")
            continue
        return image_files


def compression_config() -> Tuple[int, int]:
    width, height = 0, 0
    while True:
        input_str = input("请输入尺寸(宽度 高度):")
        if not input_str:
            break
        config = input_str.split(" ", 1)
        if len(config) != 2:
            print("请以空格分隔宽度和高度数值...")
            continue
        try:
            width = int(config[0])
            height = int(config[1])
        except ValueError:
            print("请输入正确的宽度和高度数值...")
            continue
        if width >= 0 and height >= 0 and not (width == 0 and height == 0):
            break
        else:
            print("宽高数值必须大于等于零且不能同时等于零...")
    return width, height


def show_progress(func: Callable[[str], None]):
    def inner_func(files: List[str], width: int, height: int):
        length = len(files)
        for i, p in enumerate(files, 1):
            base = os.path.basename(p)
            print("(%d/%d)图片<%s>正在压缩处理中,请稍后..." % (i, length, base))
            func(os.path.abspath(p), width, height)
        print("全部处理完成 ~")

    return inner_func


@show_progress
def start_compression(filepath: str, width: int, height: int):
    count = 0
    parent, base = os.path.split(filepath)
    while True:
        new_name = "%s%d_%s" % (OPTED_PREFIX, count, base)
        new_fullpath = os.path.join(parent, new_name)
        if not os.path.exists(new_fullpath):
            break
        count += 1
    try:
        source = tinify.from_file(filepath)
        if width > 0 and height == 0:
            source = source.resize(method="scale", width=width)
        elif width == 0 and height > 0:
            source = source.resize(method="scale", height=height)
        elif width > 0 and height > 0:
            source = source.resize(method="fit", width=width, height=height)
        source.to_file(new_fullpath)
    except tinify.AccountError:
        print("帐户异常~")
    except tinify.ClientError:
        print("客户端异常~")
    except tinify.ServerError:
        print("服务器异常~")
    except tinify.ConnectionError:
        print("网络连接异常~")
    except Exception as e:
        print("未知异常:%s" % e)


def main():
    filenames = receive_filenames()
    config = compression_config()
    start_compression(filenames, *config)


if __name__ == "__main__":
    main()
    input("按回车退出...")
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-4 08:20:25 | 显示全部楼层
好东西,学习学习~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-4 08:55:25 | 显示全部楼层
小甲鱼解决了我的pip不是内部或外部指令,好耶
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-4 09:04:08 | 显示全部楼层
sfqxx 发表于 2023-3-4 08:55
小甲鱼解决了我的pip不是内部或外部指令,好耶

那不就是
py -m
吗?
(python可以简写成py)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-5 20:18:22 | 显示全部楼层

嗯嗯呐
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-12 15:56:29 | 显示全部楼层
竟然有C币!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-13 19:59:39 | 显示全部楼层
本帖最后由 liuhongrun2022 于 2023-3-13 20:18 编辑

甲鱼老师,花一点时间写了一个,您看一下
有什么建议可以修改
import tinify
import os
from tkinter.filedialog import *

tinify.key = "API Key"

print("图片压缩程序".center(20, "-"))


def compressed_image():
    print("-" * 20)
    select_url_or_file = int(input("从本地文件还是URL上传?\n输入1从本地文件上传\n输入2从URL上传\n请选择模式:"))
    if select_url_or_file == 1:
        file = askopenfilename(
            title="选择图像文件", filetypes=[("图像文件", "*.jpg;*.png;*.jpeg;*.webp")]
        )
        size = input("请输入图片宽高,使用空格隔开,如果没有请留空:")
        if len(size.split()) == 0:
            print(f"正在处理图片 {os.path.split(file)[1]} ...")
            source = tinify.from_file(file)
            source.to_file(f"{os.path.split(file)[0]}/opt_{os.path.split(file)[1]}")
            print("压缩成功!")
            print("-" * 20)
        elif len(size.split()) == 2:
            print(f"正在处理图片 {os.path.split(file)[1]} ...")
            source = tinify.from_file(file)
            resized = source.resize(
                method="fit", width=int(size.split()[0]), height=int(size.split()[1])
            )
            resized.to_file(f"{os.path.split(file)[0]}/opt_{os.path.split(file)[1]}")
            print("压缩成功!")
            print("-" * 20)
        else:
            print("请输入正确的宽高数值!")
    elif select_url_or_file == 2:
        url = input("请输入要压缩图片的URL:")
        size = input("请输入图片宽高,使用空格隔开,如果没有请留空:")
        if len(size.split()) == 0:
            print(f"正在处理图片 {os.path.split(url)[1]} ...")
            source = tinify.from_url(url)
            source.to_file(f"{os.getcwd()}/{os.path.split(url)[1]}")
            print("压缩成功!")
            print("-" * 20)
        elif len(size.split()) == 2:
            print(f"正在处理图片 {os.path.split(file)[1]} ...")
            source = tinify.from_url(url)
            resized = source.resize(
                method="fit", width=int(size.split()[0]), height=int(size.split()[1])
            )
            resized.to_file(f"{os.getcwd()}/{os.path.split(url)[1]}")
            print("压缩成功!")
            print("-" * 20)


def compressed_images():
    folder = askdirectory(title="选择目录")
    size = input("请输入图片宽高,使用空格隔开,如果没有请留空:")
    dirs = os.listdir(folder)
    for i in dirs:
        if (
            os.path.splitext(i)[1] == ".jpg"
            or os.path.splitext(i)[1] == ".png"
            or os.path.splitext(i)[1] == ".jpeg"
            or os.path.splitext(i)[1] == ".webp"
        ):
            if len(size.split()) == 0:
                print(f"正在处理图片 {i} ...")
                source = tinify.from_file(f"{folder}/{i}")
                source.to_file(f"{folder}/opt_{i}")
                print("压缩成功!")
                print("-" * 20)
            elif len(size.split()) == 2:
                print(f"正在处理图片 {i} ...")
                source = tinify.from_file(f"{folder}/{i}")
                resized = source.resize(
                    method="fit",
                    width=int(size.split()[0]),
                    height=int(size.split()[1]),
                )
                resized.to_file(f"{folder}/opt_{i}")
                print("压缩成功!")
                print("-" * 20)


while True:
    select = int(input("输入1为单个图片压缩\n输入2为批量压缩\n输入-1退出\n请选择模式:"))
    if select == -1:
        break
    elif select == 1:
        compressed_image()
    elif select == 2:
        compressed_images()

点评

很遗憾,代码并没有按【需求描述】进行实现。  发表于 2023-3-25 03:11
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-15 08:35:59 | 显示全部楼层
代码发不出去呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-15 08:36:44 | 显示全部楼层
import os
import tinify
import sys

# tinify.key ='dMKLVMY#####4lkBDK6BVKYY' 
def yasuo(file):
#     source = tinify.from_file(file)
#     source.to_file(file)
    pass
def get_name():
    name = input('请输入您要压缩的图片名称(回车优化当前文件夹):') #输入名称
    if len(name)>0:  #确认已经输入成功
        dir_exist(name)   #判断输入的信息是否存在
    else:   #如果没有输入信息,就批判当前文件夹
        print('当前文件夹为{}\\'.format(sys.path[0]))
        file_dir = os.listdir(sys.path[0])
        j = 0
        for i in file_dir:
            if i.find('jpg') > 0 or i.find('png')>0 or i.find('webp')>0:
                print("图片{}正在压缩处理中,请稍后。。。".format(i))
                j = j + 1
            else:
                pass
        if j == 0:
            print("在该文件夹下面啥呀没找到啊!!")

def dir_exist(path):
    if os.path.exists(path):   #如果存在,就准备执行脚本
        res=doit(path)
    else:       #如果不存在,就只能再让人工核对
        print('您输入的文件名称地址[{}]不对,请核实您填入的地址!'.format(path))
        print('==================')
        get_name()

#判断传入的文件或者文件夹中是否有 jpg/png/webp 图片
def doit(file):
    print('哇塞!你输入的地址是对的哎!现在需要判断你输入的是文件名还是文件夹名!')
    print('你输入的是{}'.format(file))
    if file.find('.')>0: #如果输入的信息里面有'.'就代表是文件
        print('很棒!你直接输入的是文件!我看看是不是jpg/png/webp 图片')
        if file.find('jpg')>0 or file.find('png')>0 or file.find('webp')>0:
            print('************************')
            print("图片{}正在压缩处理中,请稍后。。。".format(file))
            print('************************')
        else:
            print("你输入的地址{}虽然找到了,但是它不是jpg/png/webp 图片,我也没法操作!".format(file))
            print('您输入的文件名称地址[{}]不对,请核实您填入的地址!'.format(file))
            print('==================')
            get_name()
    else:                   # 那就是文件夹了
        print('你输入的是文件夹!我看看它里面是不是jpg/png/webp 图片')
        file_dir = os.listdir(file)
        j = 0
        for i in file_dir:
            if i.find('jpg') > 0 or i.find('png')>0 or i.find('webp')>0:
                print("图片{}正在压缩处理中,请稍后。。。".format(i))
                yasuo(i)
                j = j + 1
            else:
                pass
        if j == 0:
            print("在该文件夹下面啥呀没找到啊!!")
            print('您输入的文件名称地址[{}]不对,请核实您填入的地址!'.format(file))
            print('==================')
            get_name()


    pass


if __name__ == '__main__':
    file_name=get_name()


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-24 12:09:39 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-3-24 18:05:53 | 显示全部楼层
代码揭晓呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-5 11:54:55 | 显示全部楼层
1111111
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-6 22:02:33 | 显示全部楼层
打卡!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-7 11:15:50 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-13 20:34:04 | 显示全部楼层
6
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-13 23:17:46 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-28 10:30:27 | 显示全部楼层
朕想知道
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-29 18:51:15 | 显示全部楼层
朕想知道
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-7-27 15:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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