作者: Jet L

  • 【音乐】《深海》——魔力娜娜森七菜

    一首来自Mori Nana的让人印象深刻的作品。

    作词作曲是YOASOBI的Ayase,所以曲调听起来,你懂的。

    我觉得最值得一提的是其MV,构图、调色可圈可点,视频还采用了4:3的画幅,呈现出非常别样的视觉体验,与一些伪4:3画幅MV不同,本曲在Youtube(视频油管链接)上真的是4:3的原生视频比例。

    可惜索尼音乐在B站上传的视频则是加了黑边的16:9视频,让人不快。

    点击展开歌词

    专辑:深海

    歌手:森七菜

    作词: Ayase

    作曲: Ayase

    编曲: Ayase

    歌词翻译来自网易云音乐

    慌ただしく——时光匆忙

    過ぎてゆく日々——流逝而过

    帰る場所は——我并没有

    間違ってなんかないのに——搞错该回的地方

    君の声が聞きたくて——想要听见你的声音

    そっと瞳閉じる——于是轻轻闭上双眼

    深い海の底たゆたう体——幽深的海底 飘荡的身体

    彷徨うだけの私は魚——只懂得彷徨的我仿佛化身游鱼

    水面から差し込む光の彼方——水面上透来的光芒彼方

    届けと願うように——希望能够到达

    手を伸ばす——努力地伸出手

    君には見えてますか——你是否能够看得见呢

    あの星が夢が——那颗星星、梦想

    私のこの想いが——还有我的思念

    どこかで泣いていませんか——你是否正躲在哪里偷偷地哭泣

    ただ願う声は——唯有祈祷的声音

    泡になって——化作泡影

    忙しなく街に灯る——城市匆匆忙忙

    煌びやかな明かり——华灯悠悠初上

    休むことなく日々は——我也知道时光会

    続いてくんだと知る——毫不停歇地流淌

    吐き出すため息から——倾吐的叹息之中

    零れた「会いたいな」——漏出一句「好想见你」

    他人の声にかき消されていく——却被别人的声音掩盖抹消

    今日はこんなことが——今天发生了这样的事

    昨日はこんなことが——昨天发生了这样的事

    私は変わらず元気でいるよ——我依旧如往常一般安好

    今日はどんなことが?——今天会发生什么样的事呢?

    昨日はどんなことが?——昨天发生了什么样的事呢?

    ねえ君は元気にしていますか?——呐,你过得还好吗?

    深い夜の底に沈む体——身躯沉入深夜的渊底

    ざわつく胸、瞳閉じたまま——心中躁动 眼眸紧闭

    気付けば差し込む朝日のかけらが——回过神来 朝阳的碎片穿透而来

    優しく頬を撫でる——温柔地抚摸着我的脸颊

    窓から見えた木々が——每当从窗户看到的树木

    揺れる度——随风摇曳

    君の住むあの町の思い出が——你栖身之于那座城市的回忆

    溢れて溺れそうになるけど——便要涌起 快将我淹没

    同じ空の下でほら——但我们就在同一片天空下

    生きている——共同生活着

    君にはいつまでもただ——你绝不会

    理不尽な悲しみに——永远沉浸在

    飲み込まれることなく——不讲道理的悲伤中

    優しく穏やかな暮らしの中——温柔安宁的生活中

    笑っていて欲しいから——我希望你可以微笑

    君は覚えてますか——不知道你是否还记得

    あの日々を——那些日子

    共に過ごした風景を——我们一起经过的风景

    私が帰る場所は今でも

    君と同じ——时至今日 我的归处

    いつの日かもう——一度仍然与你相同

    笑い合えるその日を——我会想念着

    想いながら——能与你再度共同欢笑的那一天

    眠りにつく——安心地进入梦乡

    大家对森七菜最熟悉的作品其实应该是《天气之子》,其在电影中担任女主——天野阳菜的CV。

    Mori Nana是她的英文名,人如其名,魔力娜娜的照片充满了活力与魔力,看着就让人心情愉悦,推荐关注!

    森七菜的ins——mori.chan.7

    森七菜Staff的官方ins——nana_mori_official

    最后,一起欣赏一些MV中的画面吧~个人觉得调色和构图可以作为写真的拍摄参考。

    最后,在MV的结尾,我看到了视频的导演——林響太朗 Kyotaro Hayash,搜索到了他的个人网站,内容与网页设计都非常不错,推荐给大家。

  • 【HTML】输入Pixiv ID跳转对应画师主页

    Pixiv的应用内部居然没这个功能,不科学,非常基础的功能。

    收录进了小工具页面。👉点击使用小工具

    <body>
        <h1>Pixiv用户跳转</h1>
        <input id="input-id" type="text" placeholder="请输入数字ID" oninput="validateInput()" />
        <div>
            <button onclick="generateLink()">生成链接</button>
            <button onclick="openLink()">跳转</button>
        </div>
        <div id="output"></div>
    
        <script>
            function validateInput() {
                const input = document.getElementById('input-id');
                input.value = input.value.replace(/\D/g, ''); // 只保留数字
            }
    
            function generateLink() {
                const input = document.getElementById('input-id').value.trim();
                const output = document.getElementById('output');
                if (input === '') {
                    output.innerHTML = '<p style="color: red;">请输入有效的数字ID!</p>';
                    return;
                }
                const link = `https://www.pixiv.net/member.php?id=${input}`;
                output.innerHTML = `<a href="${link}" target="_blank">点击跳转到 Pixiv 用户页面</a>`;
            }
    
            function openLink() {
                const input = document.getElementById('input-id').value.trim();
                if (input === '') {
                    alert('您还没有输入ID~');
                    return;
                }
                const link = `https://www.pixiv.net/member.php?id=${input}`;
                window.open(link, '_blank');
            }
        </script>
    </body>
  • 【网站美化】如何为WordPress添加Prism JS代码美化脚本?

    推荐使用Prism.js

    具体方法大神们早已经一笔一划的写出来了

    点击跳转!

    其中通过标签来非全局加载Js的方法非常棒!推荐参考学习。

    本网站则是全局加载JS,通过声明不同的CSS来实现美化效果。

    不加载Prism JS:

       <div class="container">
            <div class="diamond"></div> <!-- 第一个菱形 -->
            <div class="diamond"></div> <!-- 第二个菱形 -->
            <div class="diamond"></div> <!-- 第三个菱形 -->
            <div class="diamond"></div> <!-- 第四个菱形 -->
        </div>

    加载Prism JS:

       <div class="container">
            <div class="diamond"></div> <!-- 第一个菱形 -->
            <div class="diamond"></div> <!-- 第二个菱形 -->
            <div class="diamond"></div> <!-- 第三个菱形 -->
            <div class="diamond"></div> <!-- 第四个菱形 -->
        </div>

    很棒!

  • 【Node.js】批量导出微信联系人到Excel表格(基于Wechaty)

    用到的库:

    wechaty: 一个用于开发微信聊天机器人的框架。

    qrcode-terminal: 用于生成终端二维码的库。

    xlsx: 用于处理 Excel 文件的库。

    fspath: Node.js 的内置文件系统模块,用于文件操作。

    file-box: 用于处理文件(如图片)的库。

    uuid: 用于生成唯一标识符(UUID)的库。

    工作原理:

    基于wechaty的api,获取相应信息并批量导出到excel表格中,头像文件夹单独放置。可以在WPS中依靠UUID生成的唯一ID来快速批量嵌入头像。

    可惜标签功能不在Wechaty的功能中,也没法导出手机号等更有价值的信息,目前能导出的信息不多,图一乐。

    const { WechatyBuilder } = require('wechaty');
    const qrcode = require('qrcode-terminal');
    const xlsx = require('xlsx');
    const fs = require('fs');
    const path = require('path');
    const { FileBox } = require('file-box');
    const { v4: uuidv4 } = require('uuid');  // 引入 UUID 库
    
    const outputDir = './avatars/';  // 存储头像的文件夹
    
    // 确保头像目录存在
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir);
    }
    
    class WeChaty {
      bot = null;
    
      constructor() {
        this.bot = WechatyBuilder.build();
        this.bot.on('scan', code => {
          qrcode.generate(code, { small: true });
        });
        this.bot.on('login', user => {
          console.log(`登录成功,欢迎 ${user}`);
          this.waitForContacts();  // 登录后开始等待联系人同步
        });
      }
    
      // 随机延时函数,返回一个 Promise,用于模拟短时延时
      delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
      }
    
      // 每10秒检查一次联系人数量,最多检查10次
      async waitForContacts() {
        let previousCount = 0;
        let currentCount = 0;
        let attempts = 0;
    
        while (attempts < 10) {
          const allContacts = await this.bot.Contact.findAll();  // 获取所有联系人
          currentCount = allContacts.length;
    
          if (currentCount === previousCount) {
            console.log('联系人数量没有变化,开始导出');
            break;  // 如果联系人数量没有变化,则认为同步完成
          }
    
          console.log(`当前联系人数量: ${currentCount}, 尝试次数: ${attempts + 1}`);
          previousCount = currentCount;
          attempts++;
    
          await this.delay(10000);  // 每次等待10秒再检查
        }
    
        if (attempts >= 10) {
          console.log('尝试多次后联系人数量没有变化,开始导出');
        }
    
        // 导出联系人
        this.getAllFriendContacts();
      }
    
      // 获取所有好友联系人
      async getAllFriendContacts() {
        const allContacts = await this.bot.Contact.findAll();  // 获取所有联系人
    
        // 只筛选出好友联系人
        const friendContacts = allContacts.filter(contact => 
          contact.friend() && contact.type() === this.bot.Contact.Type.Individual
        );
    
        console.log(`总共获取了 ${friendContacts.length} 个好友联系人`);
    
        if (friendContacts.length > 0) {
          await this.exportContacts(friendContacts);  // 导出好友联系人
        }
      }
    
      // 获取并保存联系人头像
      async saveAvatar(contact) {
        try {
          const avatarFile = await contact.avatar();
          if (avatarFile) {
            const cleanName = contact.name().replace(/[\/\\:*?"<>|]/g, '_');  // 清理非法字符
            const uniqueName = `${cleanName}_${uuidv4()}`;  // 使用清理后的昵称 + UUID 作为文件名
            const avatarPath = path.join(outputDir, uniqueName + '.jpg');  // 存储路径
    
            await avatarFile.toFile(avatarPath, true);  // 保存头像文件
            return uniqueName;  // 返回不带后缀的文件名
          }
        } catch (error) {
          console.log(`获取 ${contact.name()} 头像失败`);
        }
        return '';  // 如果获取失败,返回空字符串
      }
    
      // 导出联系人信息
      async exportContacts(allContacts) {
        try {
          const contactList = [];
    
          const avatarPromises = allContacts.map(async (contact) => {
            // 获取头像文件名
            const avatarFileName = await this.saveAvatar(contact);  
    
            // 只导出有头像的联系人,且即使没有昵称也会保留
            return {
              昵称: contact.name().trim() || '无昵称',  // 如果没有昵称,则使用 '无昵称'
              备注: (await contact.alias())?.trim() || '',  // 获取备注信息
              性别: contact.gender() === this.bot.Contact.Gender.Male ? '男' : 
                    contact.gender() === this.bot.Contact.Gender.Female ? '女' : '未知',  // 性别
              省份: contact.province()?.trim() || '',  // 获取省份
              城市: contact.city()?.trim() || '',  // 获取城市
              文件名: avatarFileName,  // 保存文件名(不带后缀)
            };
          });
    
          // 等待所有头像保存完毕
          const contactData = await Promise.all(avatarPromises);
    
          // 使用 xlsx 库导出 Excel 表格
          const ws = xlsx.utils.json_to_sheet(filteredContactData);  // 将联系人信息转换为 Excel 表格
          const wb = xlsx.utils.book_new();  // 创建一个新的 Excel 工作簿
          xlsx.utils.book_append_sheet(wb, ws, '联系人');  // 将联系人数据添加到工作簿
    
          // 将工作簿保存为 Excel 文件
          xlsx.writeFile(wb, 'contacts_with_details.xlsx');
          console.log('好友联系人信息已成功导出到 contacts_with_details.xlsx');
        } catch (error) {
          console.error('导出联系人信息失败:', error);
        }
      }
    
      run() {
        this.bot.start();
      }
    }
    
    new WeChaty().run();
    
  • 【动漫音乐】ED60《Sissy Sky》——灰原哀的第一首专属ED

    Ⅰ.《Sissy Sky》的CD专辑总共三个版本,一共四首曲子,都很好听;

    Ⅱ.这张专辑分为柯南版、初回限定盘、通常盘三个版本;

    Ⅲ.柯南版和初回限定盘两个版本,均含有立牌特典,其中立牌型号随机,柯南版立牌就是封绘上的造型,灰原哀的经典小白裙和柯南的回眸~

    Ⅳ.值得一提的是这俩专辑主题色一红一蓝,盘面也是,自古红蓝出cp~

    Ⅴ.两个CD中都有三个曲子,其中前两首是一样的; 柯南版的第三首是TV版的《Sissy Sky》;初回限定中的第三首曲子是《夕立ち》; 通常盘中似乎是只有前两个曲子。

  • 【Python】按照关键词查找相应PPT

    今天巧了,好几个同事问我要PPT,但是他们只能记得起来一些关键词,而我恰好也没有很足的印象,毕竟那是两三年前,还可能不是我做的东西!

    WPS只能按照云文档进行查找关键词,那么电脑中几千个PPT要怎么找呢?(没错我电脑里真有2000个PPT (((φ(◎ロ◎;)φ))))

    我们可以根据他们截取的画面关键词,来对PPT进行索引,这样可以节约一些查找文件的时间,然后采用olefile库,查找对应PPT即可。

    import os
    from pptx import Presentation
    import olefile
    
    def is_powerpoint_file(file_path):
        """检查文件是否为PPT或PPTX格式"""
        valid_extensions = ['.ppt', '.pptx']
        return any(file_path.lower().endswith(ext) for ext in valid_extensions)
    
    def index_powerpoint_files(search_dir):
        """索引指定目录中的所有PPT和PPTX文件"""
        ppt_files = []
        total_files = 0
    
        for root, _, files in os.walk(search_dir):
            total_files += len(files)
            for file in files:
                if file.startswith("~$"):  # 跳过临时文件
                    continue
                file_path = os.path.join(root, file)
                if is_powerpoint_file(file_path):
                    ppt_files.append(file_path)
        
        print(f"[信息] 已索引文件总数:{total_files},PPT文件总数:{len(ppt_files)}")
        return ppt_files
    
    def search_text_in_pptx(file_path, target_text):
        """在PPTX文件中搜索目标文字"""
        try:
            presentation = Presentation(file_path)
            for slide in presentation.slides:
                for shape in slide.shapes:
                    if shape.has_text_frame and target_text in shape.text:
                        return True
        except Exception as e:
            print(f"[错误] 无法处理文件:{file_path},错误信息:{e}")
        return False
    
    def search_text_in_ppt(file_path, target_text):
        """在PPT文件中搜索目标文字"""
        try:
            if olefile.isOleFile(file_path):
                with olefile.OleFileIO(file_path) as ole:
                    if "PowerPoint Document" in ole.listdir():
                        stream = ole.openstream("PowerPoint Document")
                        content = stream.read().decode(errors="ignore")
                        if target_text in content:
                            return True
        except Exception as e:
            print(f"[错误] 无法处理文件:{file_path},错误信息:{e}")
        return False
    
    def search_text_in_powerpoint_files(ppt_files, target_text):
        """在索引的PPT文件中搜索目标文字"""
        result_files = []
        total_files = len(ppt_files)
    
        print(f"[信息] 开始内容搜索,共需处理 {total_files} 个文件")
        for idx, file_path in enumerate(ppt_files, start=1):
            print(f"[处理中] {idx}/{total_files} - 正在处理文件:{file_path}")
            if file_path.lower().endswith(".pptx") and search_text_in_pptx(file_path, target_text):
                result_files.append(file_path)
            elif file_path.lower().endswith(".ppt") and search_text_in_ppt(file_path, target_text):
                result_files.append(file_path)
    
        return result_files
    
    if __name__ == "__main__":
        search_dir = "D:\\"
        target_text = input("请输入要查找的文字(支持中文):")
        
        print(f"[信息] 正在索引盘中的PPT文件,请稍候...\n")
        ppt_files = index_powerpoint_files(search_dir)
        
        if ppt_files:
            print(f"\n[信息] 索引完成,开始搜索包含 '{target_text}' 的文件...\n")
            matching_files = search_text_in_powerpoint_files(ppt_files, target_text)
            if matching_files:
                print("\n[结果] 找到包含目标文字的PPT文件:")
                for file in matching_files:
                    print(file)
            else:
                print("\n[结果] 未找到包含该文字的PPT文件。")
        else:
            print("\n[信息] 未在指定目录中找到任何PPT文件。")
    
  • 【音乐】《最终便》(我循环最多的一首日语歌曲)

    这首歌的歌手是久米小百合,她此前(从 1979 年到 1984 年)叫做:久保田 早紀,因此我们可能在不同的平台看到两种叫法,这都是一个人。

    她最有名的一首曲子应该是《异邦人》,一首具有中东风情的日语歌曲,非常有意思。

    而《最终便》则是其第六张专辑——《纳芙蒂蒂》(于 1983 年 4 月 21 日发行)中的一首歌曲,翻译成中文意思是:最后一班航班,该歌曲的编曲为:若草惠。

    纳芙蒂蒂(Nefertiti,公元前1370年—前1330年)是埃及法老阿肯纳顿的王后。

    在创作这张专辑的时候,久保田 早紀受到了圣经中描述的埃及、土耳其、希腊等地的吸引,也顺势进行了一场旅行,所以作为专辑最后一首歌的《最终便》,似乎也相当合理了。

    作词: 久保田 早紀

    作曲: 久保田 早紀

    编曲 : 若草恵

    空港のロビーから——已经不再在机场大厅

    長い電話をする事もない——讲长电话了

    こうして独りの今は——如今这般一个人的日子里

    サテライトに降る星くずに誘われ——在星海感召下

    北の空へ向かう——向北方天空遥望

    戸惑いも空しさも荷造りをして——将惘然与空虚打包收起

    トランクにつめ込んだ思い出数える——然后细数箱中的回忆

    男でも女でも旅立つ朝は——清晨启程的男女们

    きっとこんな気持ちにふるえるはず——一定都有体味过这感觉

    空港のロビーでは——在机场大厅

    花をかかえて見送る人が——送行的人怀抱鲜花

    私の背中を追い越す——从我身后穿行而过

    凍えた夜の灯も一粒の真珠に——寒夜中夜灯如珍珠般弥散微光

    やがて変わるわ 最終便で——末班航班(的场景)已不再如昨

    少しだけ優しさが違ってた事——与温柔稍许不同的是

    悲しい程わかっていた愛なのに——才明白过来 既然爱到如此伤悲

    出来るならわがままに私を抱いて——如果可以 多想将时间定格在点头之前

    引き止めてほしかった うなずく前に——就那般好好抱着我

    空港のロビーから——已经不再在机场大厅

    長い電話をする事もない——讲长电话了

    こうして独りの今は——如今这般一个人的日子里

    あなたより早く夜明けを迎えるわ——与其等你不如静待黎明

    闇を脱け出す 最終便で——末班航班(的等待)里 从黑暗中抽离出来

  • 【设计】军事类宣传中,如何避免出现误用他国或地区的武器装备图片?

    最简单的方法:

    找一个军迷来问一下,,,军迷识别武器就像是女生识别口红色号一样。

    咳咳,真的不开玩笑。

  • 【音乐】ラブ・ストーリーは突然に(突如其来的爱情)

    突如其来的爱情》(日语:ラブ・ストーリーは突然に),是日本男性创作歌手小田和正的歌曲。最初收录于双A面单曲《Oh! Yeah!/突如其来的爱情》(1991年2月6日发行)中。1990年代日本电视剧主题曲的代表歌曲、经典情歌。

    国内的周深、李克勤同台唱过这首歌曲,另外在《繁花》电视剧中,也有一段剧情的配乐用到了该曲子。

    ラブ・ストーリーは突然に

    收录这首歌曲的单曲《Oh! Yeah!/突如其来的爱情》刷新了当时日本CD单曲最高销量、J-POP单曲最高销量的纪录,并成为1991年度日本单曲销量冠军。

    剧集制作阶段,富士电视台的制作人大多亮想找像Off Course时期的《Yes-No》这样的歌,于是找到了小田邀歌。最初小田作了另一首歌曲《FAR EAST CLUB BAND SONG》(后收录于精选辑《Oh! Yeah!》),但是这首歌和剧情气氛不相衬,因而改用《突如其来的爱情故事》。

    不过尽管《东京爱情故事》播放时期,《突如其来的爱情》已经很受欢迎,小田一开始并不打算将这首歌作为A面曲发售CD单曲,而是想将《Oh! Yeah!》作为单独A面曲发售。

    但是唱片公司却想发行《突如其来的爱情故事》,作为折衷才决定发行双A面。而在多处不同的地方,这张单曲的标记都有“Oh! Yeah!”和“Oh! Yeah!/突如其来的爱情”两种情况。

    《突如其来的爱情》和同年恰克与飞鸟的《SAY YES》都是作为富士月九剧的主题曲,前者是1991年度单曲销量的冠军,后者则是亚军。可以说自此之后月九成为日本电视剧黄金档中的黄金档,对主题曲的重视大大提高,大多向著名歌手邀歌,“月九的主题曲必定大卖”也成为普遍定律。因此更多的歌手争相为月九剧献唱。

    这首歌也成为小田个人活动的代表歌曲,由于小田甚少上电视节目演出,多次调查显示大众最期待小田上NHK红白歌合战等音乐节目演唱《突如其来的爱情》,但1991年本曲走红当时他并未参加该年度的红白,而是到同年富士电视台的“FNS歌谣祭”中演唱。本曲也成为日本流行乐坛的一首经典情歌,在朝日电视台音乐节目《MUSIC STATION》的多次情歌或国民名曲调查中均名列前茅。

    此外,《Yes-No》也是一首值得一听的歌曲:(突然发现这首歌和突如其来的爱情都是一样的时长~)

    另一个版本的《Yes-No》,收录在专辑《SELECTION 1978-81》,这个版本的鼓点很抓耳。

  • 【Python】对彩色LOGO进行批量反白处理

    为了制作一些高大上的风格化 PPT,有时我们需要很多客户的反白色LOGO,以符合当下的一些设计潮流。

    目前常用的做法是在 PPT中对图片本身进行亮度调整,可以理解为一键过曝,但是这对于一些本身就含有白色的图片不适用,也无法处理JPG的图片,更没法快速将反白的图片进行批量保存,以便存储成库,在其他场景继续使用。

    因此使用脚本可以防止原来的白色部分混成一团,预先对原LOGO白色区域进行透明化,然后对其他颜色区域反白。

    这个脚本目前适用于我的工作环境,包含一些问题,例如如果原来的图标包含白色文字,这样会将其透明化,因此还需按照使用情况进行调整。

    后续考虑加入对JPG进行处理的过程,原理上是对白色部分预先透明度处理,然后后续步骤基本一致,不过使用JPG作为LOGO的客户较少,该功能并不急迫。若要实现该功能,可能需要使用OCR对文字部分预先识别处理,流程上麻烦不少,不过由于wechat-ocr的强大功能,应该也可以稳定呈现,wechat-ocr此前有过一些实践,效果出众,推荐大家使用。

    此外脚本尚未测试灰色部分是否会有问题,目前感觉应该会有问题,若使用中有其他问题会随时更新。

    import tkinter as tk
    from tkinter import filedialog
    from PIL import Image, ImageTk
    import random
    import string
    class ImageProcessor(tk.Tk):
        def __init__(self):
            super().__init__()
            self.title("Logo Image Processor")
            self.geometry("600x600")
            self.image_path = None
            self.images = []  # 用于存储多个图像
            self.image_label = tk.Label(self)
            self.image_label.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
            
            # 设置拖放区域
            self.drop_area = tk.Label(self, text="拖动PNG图片到此区域", relief="solid", width=30, height=4)
            self.drop_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
            self.drop_area.bind("<Enter>", self.on_drag_enter)
            self.drop_area.bind("<Leave>", self.on_drag_leave)
            self.drop_area.bind("<ButtonRelease-1>", self.on_drop)
            # 添加处理按钮
            self.process_button = tk.Button(self, text="处理图片并保存", command=self.process_images)
            self.process_button.pack(pady=10)
        def on_drag_enter(self, event):
            self.drop_area.config(bg="lightblue")
        def on_drag_leave(self, event):
            self.drop_area.config(bg="white")
        def on_drop(self, event):
            file_paths = filedialog.askopenfilenames(filetypes=[("PNG files", "*.png")])
            if file_paths:
                self.load_images(file_paths)
        def load_images(self, paths):
            self.images = []  # 清空当前图像列表
            for path in paths:
                image = Image.open(path).convert("RGBA")  # 确保加载为RGBA格式以处理透明度
                self.images.append((path, image))  # 存储图像及其路径
            if self.images:
                self.display_image(self.images[0][1])  # 显示第一张图片
        def display_image(self, image):
            image_tk = ImageTk.PhotoImage(image)
            self.image_label.config(image=image_tk)
            self.image_label.image = image_tk
        def process_images(self):
            if self.images:
                for original_path, image in self.images:
                    # 获取图像的每个像素
                    pixels = image.load()
                    width, height = image.size
                    
                    for x in range(width):
                        for y in range(height):
                            r, g, b, a = pixels[x, y]
                            
                            # 将白色部分透明化
                            if r == 255 and g == 255 and b == 255:
                                pixels[x, y] = (255, 255, 255, 0)  # 将白色变为透明
                            elif a != 0:  # 如果是非透明区域
                                # 将所有非透明区域变为纯白色
                                pixels[x, y] = (255, 255, 255, a)  # 变为白色,保持原透明度
                    
                    # 生成随机字符并保存处理后的图像
                    random_suffix = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
                    output_path = f"processed_logo_{random_suffix}.png"
                    image.save(output_path)
                    print(f"处理后的LOGO图片已保存为 {output_path}")
                    
                # 更新显示处理后的图片(显示第一张图像)
                self.display_image(self.images[0][1])
    if __name__ == "__main__":
        app = ImageProcessor()
        app.mainloop()
    

    此外,还可以对JPG进行处理:

    注意保证输入图片的分辨率,其平滑操作对分辨率会有一定的损失。

    import tkinter as tk
    from tkinter import filedialog, messagebox
    from PIL import Image, ImageFilter
    import random
    import string
    import os
    class ImageProcessor(tk.Tk):
        def __init__(self):
            super().__init__()
            self.title("Logo Image Processor")
            self.geometry("400x200")  # 设置主窗口大小
            self.image_path = None
            self.images = []  # 用于存储多个图像
            self.processed_images = []  # 用于存储处理后图像路径
            # 设置拖放区域
            self.drop_area = tk.Label(self, text="拖动PNG或JPG图片到此区域", relief="solid", width=30, height=4)
            self.drop_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
            self.drop_area.bind("<Enter>", self.on_drag_enter)
            self.drop_area.bind("<Leave>", self.on_drag_leave)
            self.drop_area.bind("<ButtonRelease-1>", self.on_drop)
            # 添加处理按钮
            self.process_button = tk.Button(self, text="处理图片并保存", command=self.process_images)
            self.process_button.pack(pady=10)
            # 添加选择输出路径按钮
            self.output_dir = None
            self.select_output_button = tk.Button(self, text="选择保存路径", command=self.select_output_dir)
            self.select_output_button.pack(pady=5)
        def on_drag_enter(self, event):
            self.drop_area.config(bg="lightblue")
        def on_drag_leave(self, event):
            self.drop_area.config(bg="white")
        def on_drop(self, event):
            file_paths = filedialog.askopenfilenames(filetypes=[("Image files", "*.png *.jpg *.jpeg")])
            if file_paths:
                self.load_images(file_paths)
        def load_images(self, paths):
            self.images = []  # 清空当前图像列表
            for path in paths:
                try:
                    image = Image.open(path)
                    # 将JPG图像转换为支持透明度的RGBA格式
                    if image.mode != "RGBA":
                        image = image.convert("RGBA")
                    self.images.append((path, image))  # 存储图像及其路径
                except Exception as e:
                    print(f"无法加载图像 {path}: {e}")
                    messagebox.showerror("错误", f"无法加载图像 {path}")
                    
        def select_output_dir(self):
            self.output_dir = filedialog.askdirectory()
            if self.output_dir:
                print(f"选择的输出目录是: {self.output_dir}")
            
        def process_images(self):
            if not self.images:
                messagebox.showwarning("警告", "请先加载图片")
                return
            
            if not self.output_dir:
                messagebox.showwarning("警告", "请先选择保存路径")
                return
            for original_path, image in self.images:
                pixels = image.load()
                width, height = image.size
                
                for x in range(width):
                    for y in range(height):
                        r, g, b, a = pixels[x, y]
                        
                        # 将接近白色的区域透明化,设置阈值范围 (240, 240, 240) 到 (255, 255, 255)
                        if r >= 240 and g >= 240 and b >= 240:
                            pixels[x, y] = (255, 255, 255, 0)  # 将接近白色的部分变为透明
                        elif a != 0:  # 如果是非透明区域
                            # 将所有非透明区域变为纯白色
                            pixels[x, y] = (255, 255, 255, a)  # 变为白色,保持原透明度
                # 对图像进行边缘平滑处理,减少杂色
                image = image.filter(ImageFilter.GaussianBlur(radius=2))
                
                # 生成随机字符并保存处理后的图像
                random_suffix = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
                output_path = os.path.join(self.output_dir, f"processed_logo_{random_suffix}.png")
                image.save(output_path)
                print(f"处理后的LOGO图片已保存为 {output_path}")
                self.processed_images.append(output_path)
    if __name__ == "__main__":
        app = ImageProcessor()
        app.mainloop()