【ICO/WMF】PNG/JPEG转ICO/WMF工具

工具介绍

工具名称:图形转换工具

工具版本:1.03

功能介绍:

1.支持PNG、JPEG格式转为ICO图标或WMF格式图片
2.可以选择单个图形文件,也可以选择图形文件夹进行批量处理
3.可以选择常见尺寸、倍率、自定义宽和高对ICO图标和WMF图片进行缩放

工具截图:

【ICO/WMF】PNG/JPEG转ICO/WMF工具_第1张图片

下载链接:GitHub下载地址  百度网盘下载地址

源代码:

import PIL.Image as im
import tkinter.filedialog as tf
import tkinter as tk
import tkinter.messagebox as tm
import random
import os
from sys import executable as EXECUTABLE
from win32api import SetFileAttributes
from win32con import FILE_ATTRIBUTE_HIDDEN
from subprocess import Popen, PIPE, STDOUT
import Tool.PackTool as pt
from Tool.ico import ico1
import Tool.MyLogger as ml
from ctypes import windll


class ToIco:
    __filePath = ''
    __foderPath = ''
    __cWidth = 16
    __cHeight = 16
    __sizeMode = 0
    __imgType = '.ico'
    __tips = ('生成的图形文件保存地址为所选PNG或JPG文件所在地址', '可以处理单个文件也可以处理多个文件', '处理图形文件夹时仅处理PNG和JPG文件', '当存在同名图形文件时会覆盖已存在的图形文件')
    __site = [('单个图形文件', 0), ('图形文件夹', 1)]
    __type = [('.ico', 0), ('.wmf', 1)]
    __rotation = [('0.5倍', 0), ('原比例', 1), ('1.5倍', 2), ('2倍', 3), ('3倍', 4), ('5倍', 5)]
    __choice = [('尺寸转换', 0), ('缩放比例', 1), ('自定义宽和高', 2)]
    __isDefineCb = True
    __log = ml.IMyLogger()

    def _windowSize(self, p_width, p_height):
        size = '%dx%d+%d+%d' % (
            p_width, p_height, (self.__screenWidth - p_width) / 2, (self.__screenHeight - p_height) / 2)
        return size

    # 创建快捷方式
    def _createShortcut(self):
        execpath = os.path.dirname(EXECUTABLE)
        batpath = execpath + "\\init.bat"
        if os.path.exists(batpath):
            self.__log.InLog("Create shortcut successful!")
            startcmd = "start " + "shortcut.bat"
            startpath = execpath + "\\shortcut.bat"
            cmd = "cd " + execpath + " && " + startcmd
            pop = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT)
            pop.wait()
            if pop.returncode == 0:
                pop.terminate()
                pop.kill()
                SetFileAttributes(startpath, FILE_ATTRIBUTE_HIDDEN)

    def __init__(self):
        self._createShortcut()
        # 告诉操作系统使用程序自身的dpi适配
        windll.shcore.SetProcessDpiAwareness(1)
        # 获取屏幕的缩放因子
        ScaleFactor = windll.shcore.GetScaleFactorForDevice(0)
        self.__cPIPT = pt.IPackTool(False)
        self.__root = tk.Tk()
        self.__root.title('图形转换工具')
        # 获取屏幕宽高
        self.__screenWidth = self.__root.winfo_screenwidth()
        self.__screenHeight = self.__root.winfo_screenheight()
        # 设置窗口大小
        self.__root.geometry(self._windowSize(int(self.__screenWidth * 0.35), int(self.__screenHeight * 0.625)))
        self.__root.wm_minsize(int(self.__screenWidth * 0.31), int(self.__screenHeight * 0.56))
        self.__cPIPT.IcoBase64Decoder('icoTool', ico1)
        self.__cPIPT.IcoSetToTk(self.__root, 'icoTool')
        # 设置程序缩放
        self.__root.tk.call('tk', 'scaling', ScaleFactor / 75)

        self.__v = tk.IntVar()
        self.__r = tk.IntVar()
        self.__c = tk.IntVar()
        self.__t = tk.IntVar()
        self.__check1 = tk.IntVar()
        self.__check2 = tk.IntVar()
        self.__check3 = tk.IntVar()
        self.__check4 = tk.IntVar()
        self.__check5 = tk.IntVar()
        self.__check6 = tk.IntVar()
        self.__sizeCheck = [('16x16', self.__check1), ('32x32', self.__check2), ('48x48', self.__check3),
                            ('64x64', self.__check4), ('128x128', self.__check5), ('256x256', self.__check6)]

        self.__Fr_m = tk.Frame(self.__root, pady='10px')
        self.__Fr_m.pack(expand='yes')

        self.__Fr_1 = tk.Frame(self.__Fr_m)
        self.__Lb_1 = tk.Label(self.__Fr_1, text='请选择图形文件或图形文件夹', font=('幼圆', 9, 'bold'), fg='red')
        self.__Lb_1.pack(expand='yes', pady='5px')
        for name, index in self.__site:
            Rb = tk.Radiobutton(self.__Fr_1, text=name, font=('幼圆', 9, 'bold'), variable=self.__v, value=index,
                                command=lambda: self._ClearPath())
            Rb.pack(expand='yes')
        self.__Bt_1 = tk.Button(self.__Fr_1, text='选择文件或文件夹', font=('幼圆', 9, 'bold'), width=20,
                                command=lambda: self._ChooseMode(self.__v.get()))
        self.__Bt_1.pack(expand='yes', pady='5px')
        self.__Fr_1_1 = tk.Frame(self.__Fr_1)
        self.__Lb_9 = tk.Label(self.__Fr_1_1, text='请选择待转换图形文件的格式', font=('幼圆', 9, 'bold'), fg='red')
        self.__Lb_9.pack(expand='yes', pady='5px')
        for name, index in self.__type:
            Rb = tk.Radiobutton(self.__Fr_1_1, text=name, font=('幼圆', 9, 'bold'), variable=self.__t, value=index,
                                command=lambda: self._ImageTypeChange(self.__t.get()))
            Rb.pack(expand='yes', padx='5px', side='left')
        self.__Fr_1_1.pack(expand='yes', pady='5px')
        self.__Lb_2 = tk.Label(self.__Fr_1, font=('幼圆', 9, 'bold'), foreground='blue', text='')
        self.__Lb_2.pack(expand='yes', pady='5px')
        for name, index in self.__choice:
            Rb = tk.Radiobutton(self.__Fr_1, text=name, font=('幼圆', 9, 'bold'), variable=self.__c, value=index,
                                command=lambda: self._FrameActive(self.__c.get()))
            Rb.pack(expand='yes', padx='5px', side='left')
        self.__Fr_1.pack(expand='yes', pady='5px')

        self.__Fr_2 = tk.Frame(self.__Fr_m)
        self.__Lb_3 = tk.Label(self.__Fr_2, font=('幼圆', 9, 'bold'), text='请选择转换后的图形文件尺寸', fg='red')
        self.__Lb_3.pack(expand='yes', pady='5px')
        for name, vari in self.__sizeCheck:
            Cb = tk.Checkbutton(self.__Fr_2, text=name, font=('幼圆', 9, 'bold'), variable=vari,
                                command=lambda: self._RandomTip())
            Cb.pack(expand='yes')
            if self.__isDefineCb:
                Cb.select()
                self.__isDefineCb = False
        self.__Fr_2.pack(expand='yes')

        self.__Fr_3 = tk.Frame(self.__Fr_m)
        self.__Lb_4 = tk.Label(self.__Fr_3, text='请选择转换后的图形文件缩放比例', font=('幼圆', 9, 'bold'), fg='red')
        self.__Lb_4.pack(expand='yes', pady='5px')
        for name, index in self.__rotation:
            Rb = tk.Radiobutton(self.__Fr_3, text=name, font=('幼圆', 9, 'bold'), variable=self.__r, value=index,
                                command=lambda: self._RandomTip())
            Rb.pack(expand='yes')
        self.__Fr_3.pack_forget()

        self.__Fr_4 = tk.Frame(self.__Fr_m)
        self.__Lb_5 = tk.Label(self.__Fr_4, text='请输入转换后的图形文件宽和高', font=('幼圆', 9, 'bold'), fg='red')
        self.__Lb_5.pack(expand='yes', pady='5px')
        self.__Fr_4_1 = tk.Frame(self.__Fr_4)
        self.__Lb_5 = tk.Label(self.__Fr_4_1, text='Width:', font=('幼圆', 9, 'bold'))
        self.__Lb_5.pack(expand='yes', side='left')
        self.__Et1_R = self.__root.register(self._CallBack)
        self.__Et_1 = tk.Entry(self.__Fr_4_1, validate='focus', validatecommand=(self.__Et1_R, "%P"))
        self.__Et_1.pack(expand='yes', side='left')
        self.__Fr_4_1.pack(expand='yes', pady='5px')
        self.__Fr_4_2 = tk.Frame(self.__Fr_4)
        self.__Lb_6 = tk.Label(self.__Fr_4_2, text='Height:', font=('幼圆', 9, 'bold'))
        self.__Lb_6.pack(expand='yes', side='left')
        self.__Et2_R = self.__root.register(self._CallBack)
        self.__Et_2 = tk.Entry(self.__Fr_4_2, validate='focus', validatecommand=(self.__Et2_R, "%P"))
        self.__Et_2.pack(expand='yes', side='left')
        self.__Fr_4_2.pack(expand='yes', pady='5px')
        self.__Fr_4.pack_forget()
        self.__Lb_7 = tk.Label(self.__Fr_4, text='', fg='red', font=('幼圆', 9, 'bold'))
        self.__Lb_7.pack_forget()
        self.__Bt_1 = tk.Button(self.__root, text='转换', font=('幼圆', 9, 'bold'), width=20, command=lambda: self._Run())
        self.__Bt_1.pack(expand='yes', pady='5px')
        self.__Lb_8 = tk.Label(self.__root, text='Tip:生成的图形转换文件保存地址为所选PNG或JPG文件所在地址', fg='red', font=('幼圆', 9, 'bold'))
        self.__Lb_8.pack(expand='yes', pady='5px', side='bottom')
        self.__root.mainloop()

    def _ClearPath(self):
        self.__filePath = ""
        self.__foderPath = ""
        self.__Lb_2.config(text="")
        self._RandomTip()

    def _Run(self):
        if self.__filePath == '' and self.__foderPath == '':
            tm.showinfo('提示', '请选择文件或文件夹')
            self._RandomTip()
        if self.__c.get() == 2:
            if self._CustomValueCheck() is True:
                self._Transform(self.__filePath, self.__foderPath)
        else:
            if self._ValueCheck() is True:
                self._Transform(self.__filePath, self.__foderPath)

    def _CallBack(self, p_value):
        p_value = None
        self._RandomTip()
        return True

    def _RandomTip(self):
        i = random.randint(0, len(self.__tips) - 1)
        self.__Lb_8.config(text='Tip:' + self.__tips[i])
        self.__root.update()

    def _ChooseMode(self, p_index):
        self._RandomTip()
        if p_index == 0:
            self.__filePath = tf.askopenfilename()
            self.__foderPath = ''
            self.__Lb_2.config(text=self.__filePath)
        if p_index == 1:
            self.__foderPath = tf.askdirectory()
            self.__filePath = ''
            self.__Lb_2.config(text=self.__foderPath)

    def _GetCheckButtonValue(self):
        v_vari = [self.__check1, self.__check2, self.__check3, self.__check4, self.__check5, self.__check6]
        v_values = []
        for i in range(6):
            v_values.append((i, v_vari[i].get()))
        return v_values

    def _ChooseSize(self, img, i):
        if i == 0:
            return self._Resize(img, self._GetCheckButtonValue())
        elif i == 1:
            return self._RotateSize(img, self.__r.get())
        elif i == 2:
            return self._CustomSize(img)

    def _ImageTypeChange(self, i):
        self._RandomTip()
        if i == 0:
            self.__imgType = '.ico'
        else:
            self.__imgType = '.wmf'

    def _FrameActive(self, i):
        self.__sizeMode = i
        self._RandomTip()
        if i == 0:
            self.__Fr_2.pack()
            self.__Fr_3.pack_forget()
            self.__Fr_4.pack_forget()
            self.__root.update()
        elif i == 1:
            self.__Fr_3.pack()
            self.__Fr_2.pack_forget()
            self.__Fr_4.pack_forget()
            self.__root.update()
        elif i == 2:
            self.__Fr_4.pack()
            self.__Fr_2.pack_forget()
            self.__Fr_3.pack_forget()
            self.__root.update()

    # 图形转换
    def _Transform(self, p_filePath, p_foderPath):
        if p_filePath != '':
            a = im.open(p_filePath)
            v_imgs = self._ChooseSize(a, self.__sizeMode)
            v_isNull = False
            if self.__sizeMode == 0 and (v_imgs is None or len(v_imgs) == 0):
                tm.showwarning('Warning', '请选择图形尺寸!')
                self._RandomTip()
                v_isNull = True
            v_name = p_filePath.split('/')[-1].split('.')
            imageName = v_name[0]
            suffixName = v_name[-1]
            if (suffixName == 'png' or suffixName == 'jpg') and not v_isNull:
                v_path = p_filePath.replace(p_filePath.split('/')[-1], "")
                i = 1
                v_imageInfos = []
                if self.__sizeMode == 0:
                    for v_img in v_imgs:
                        v_filePath = v_path + imageName + str(i) + '.bmp'
                        v_imageInfos.append((imageName + str(i), v_filePath))
                        v_img.save(v_filePath)
                        i += 1
                else:
                    v_filePath = v_path + imageName + str(i) + '.bmp'
                    v_imageInfos.append((imageName + str(i), v_filePath))
                    v_imgs.save(v_filePath)
                try:
                    for v_imageName, v_filePath in v_imageInfos:
                        n_filePath = v_path + v_imageName + self.__imgType
                        if not os.path.exists(n_filePath):
                            os.rename(v_filePath, n_filePath)
                        else:
                            os.remove(n_filePath)
                            os.rename(v_filePath, n_filePath)
                except FileNotFoundError:
                    tm.showerror('错误', '文件不存在')
                    self._RandomTip()
                else:
                    self.__Lb_8.config(text='转换成功')
                    self.__Lb_8.pack(pady='5px', side='bottom')
        elif p_foderPath != '':
            files = os.listdir(p_foderPath)
            isSuccess = False
            v_isNull = True
            v_values = self._GetCheckButtonValue()
            for i, v in v_values:
                if v == 1:
                    v_isNull = False
            if not v_isNull:
                for img in files:
                    path = p_foderPath + '/' + img
                    v_name = path.split('/')[-1].split('.')
                    imageName = v_name[0]
                    suffixName = v_name[-1]
                    if suffixName == 'png' or suffixName == 'jpg':
                        a = im.open(path)
                        v_imgs = self._ChooseSize(a, self.__sizeMode)
                        v_path = path.replace(path.split('/')[-1], "")
                        i = 1
                        v_imageInfos = []
                        for v_img in v_imgs:
                            v_filePath = v_path + imageName + str(i) + '.bmp'
                            v_imageInfos.append((imageName + str(i), v_filePath))
                            v_img.save(v_filePath)
                            i += 1
                        try:
                            for v_imageName, v_filePath in v_imageInfos:
                                n_filePath = v_path + v_imageName + self.__imgType
                                if not os.path.exists(n_filePath):
                                    os.rename(v_filePath, n_filePath)
                                else:
                                    os.remove(n_filePath)
                                    os.rename(v_filePath, n_filePath)
                        except FileNotFoundError:
                            tm.showerror('错误', '文件不存在')
                            self._RandomTip()
                            isSuccess = False
                        else:
                            isSuccess = True
            if isSuccess is True:
                self.__Lb_8.config(text='转换成功')
                self.__Lb_8.pack(pady='5px', side='bottom')

    def _Resize(self, img, p_values):
        width, height = img.size
        v_imgs = []
        if width == height:
            for i, value in p_values:
                if value == 1:
                    if i == 0:
                        v_imgs.append(img.resize((16, 16), im.Resampling.LANCZOS))
                    elif i == 1:
                        v_imgs.append(img.resize((32, 32), im.Resampling.LANCZOS))
                    elif i == 2:
                        v_imgs.append(img.resize((48, 48), im.Resampling.LANCZOS))
                    elif i == 3:
                        v_imgs.append(img.resize((64, 64), im.Resampling.LANCZOS))
                    elif i == 4:
                        v_imgs.append(img.resize((128, 128), im.Resampling.LANCZOS))
                    elif i == 5:
                        v_imgs.append(img.resize((256, 256), im.Resampling.LANCZOS))
        elif width > height:
            for i, value in p_values:
                if value == 1:
                    if i == 0:
                        v_height = int((16 / width) * height)
                        v_imgs.append(img.resize((16, v_height), im.Resampling.LANCZOS))
                    elif i == 1:
                        v_height = int((32 / width) * height)
                        v_imgs.append(img.resize((32, v_height), im.Resampling.LANCZOS))
                    elif i == 2:
                        v_height = int((48 / width) * height)
                        v_imgs.append(img.resize((48, v_height), im.Resampling.LANCZOS))
                    elif i == 3:
                        v_height = int((64 / width) * height)
                        v_imgs.append(img.resize((64, v_height), im.Resampling.LANCZOS))
                    elif i == 4:
                        v_height = int((128 / width) * height)
                        v_imgs.append(img.resize((128, v_height), im.Resampling.LANCZOS))
                    elif i == 5:
                        v_height = int((256 / width) * height)
                        v_imgs.append(img.resize((256, v_height), im.Resampling.LANCZOS))
        else:
            for i, value in p_values:
                if value == 1:
                    if i == 0:
                        v_width = int((16 / height) * width)
                        v_imgs.append(img.resize((v_width, 16), im.Resampling.LANCZOS))
                    elif i == 1:
                        v_width = int((32 / height) * width)
                        v_imgs.append(img.resize((v_width, 32), im.Resampling.LANCZOS))
                    elif i == 2:
                        v_width = int((48 / height) * width)
                        v_imgs.append(img.resize((v_width, 48), im.Resampling.LANCZOS))
                    elif i == 3:
                        v_width = int((64 / height) * width)
                        v_imgs.append(img.resize((v_width, 64), im.Resampling.LANCZOS))
                    elif i == 4:
                        v_width = int((128 / height) * width)
                        v_imgs.append(img.resize((v_width, 128), im.Resampling.LANCZOS))
                    elif i == 5:
                        v_width = int((256 / height) * width)
                        v_imgs.append(img.resize((v_width, 256), im.Resampling.LANCZOS))
        return v_imgs

    def _RotateSize(self, img, p_size):
        width, height = img.size
        if p_size == 0:
            v_size = (int(width * 0.5), int(height * 0.5))
            return img.resize(v_size, im.Resampling.LANCZOS)
        elif p_size == 1:
            v_size = (int(width), int(height))
            return img.resize(v_size, im.Resampling.LANCZOS)
        elif p_size == 2:
            v_size = (int(width * 1.5), int(height * 1.5))
            return img.resize(v_size, im.Resampling.LANCZOS)
        elif p_size == 3:
            return img.resize((width * 2, height * 2), im.Resampling.LANCZOS)
        elif p_size == 4:
            return img.resize((width * 3, height * 3), im.Resampling.LANCZOS)
        elif p_size == 5:
            return img.resize((width * 4, height * 4), im.Resampling.LANCZOS)

    def _CustomSize(self, img):
        return img.resize((self.__cWidth, self.__cHeight), im.Resampling.LANCZOS)

    # 选择文件检测
    def _ValueCheck(self):
        v_filePath = self.__filePath
        if v_filePath != '':
            v_fileSuffix = v_filePath.split('/')[-1].split('.')[-1]
            if v_fileSuffix == 'png' or v_fileSuffix == 'jpg':
                return True
            else:
                tm.showwarning('Warning', '请选择PNG或JPG文件!')
                self.__filePath = ''
                self.__Lb_2.config(text='')
                self._RandomTip()
                return False
        else:
            return True

    # 自定义宽高输入检测
    def _CustomValueCheck(self):
        self.__Lb_7.pack_forget()
        if self.__filePath != "" or self.__foderPath != "":
            v_i = 3
            try:
                pwidth = str(self.__Et_1.get()).strip()
                pheight = str(self.__Et_2.get()).strip()
                if pwidth == '' or pheight == '':
                    width = 16
                    height = 16
                    self.__Lb_7.config(text='你输入的数据为空')
                    self.__Lb_7.pack(pady='5px', side='bottom')
                    self._RandomTip()
                    self.__root.update()
                else:
                    v_i = 0
                    width = int(pwidth)
                    widthInfo = (width, True) if width > 0 else (1, False)
                    print(widthInfo[0])
                    if not widthInfo[1]:
                        tm.showwarning("Warning", "Width不能为负数!")
                        return
                    width = widthInfo[0]
                    widthInfo = (width, True) if width <= 3840 else (3840, False)
                    width = widthInfo[0]
                    if not widthInfo[1]:
                        tm.showwarning("Warning", "Width不能大于3840!")
                        return
                    v_i = 1
                    height = int(pheight)
                    heightInfo = (height, True) if height > 0 else (1, False)
                    if not heightInfo[1]:
                        tm.showwarning("Warning", "Height不能为负数!")
                        return
                    height = heightInfo[0]
                    heightInfo = (height, True) if height <= 2048 else (2048, False)
                    if not heightInfo[1]:
                        tm.showwarning("Warning", "Height不能大于2048!")
                        return
                    height = heightInfo[0]
                    v_i = 2
            except ValueError:
                if v_i == 0:
                    self.__Lb_7.config(text='你输入的Width的数据存在类型错误,请输入整数')
                elif v_i == 1:
                    self.__Lb_7.config(text='你输入的Height的数据存在类型错误,请输入整数')
                self.__Lb_7.pack(pady='5px', side='bottom')
                self._RandomTip()
                self.__root.update()
                return False
            else:
                if v_i == 2:
                    self.__Lb_7.pack_forget()
                    self.__Lb_8.config(text='转换成功')
                    self.__Lb_8.pack(pady='5px', side='bottom')
                    self.__cWidth = width
                    self.__cHeight = height
                    return True


class IToIco:
    def __init__(self):
        self.__ti = ToIco()


cTITI = IToIco()

如果这篇文章对你有帮助,请给作者点个赞吧!

你可能感兴趣的:(个人开发的小工具,python,开源软件,图像处理)