用来快速合并贴图  
前言 
  忽然接到一个需求 写一个 PS 的工具。   自动合并图片序列的通道。
 
  之前写过一个 PS 的小脚本,10-20 行的。   解决了 PS 动作进行批处理保存贴图,输出的时候却带有副本的名称。   用脚本替换掉动作的输出,就可以保存出不带 副本 字样的图片。
 
  但是感受了这次给的需求,做 PS 的工具感觉不太香,如果不是 立足 于 PS 的环境,做 PS 的脚本其实并不是好方案。   毕竟 Python 也有 cv 和 PIL 等等的图像处理库,直接 Python 来处理那不香吗~
 
github 地址 
GUI 开发 
  这次界面依然选择了 Tkinter 进行开发,因为最近做 Bilibili 字幕上传工具。   我发现 Tkinter 用得好也可以实现和 PyQt 差不多的界面效果,但是 Tkinter 打包起来比起 Qt 可小了很多。
 
  因为有了之前搞 Tkinter 工具经验,这次开发就很快了,毕竟需求不复杂界面也相对简单。
 
  这次依然利用之前搞过的 ConfigDumperMixin 类,实现 GUI 界面的数据记录。   然后统一数据之后将数据存储到 临时目录里面。
 
  关于进度条处理,这里使用了之前写好的进度条类
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class  ProgressDialog (tk.Toplevel):    canceled = False      def  __init__ (self, *args, **kwargs ):         self.parent = kwargs.pop("parent" , None )         tk.Toplevel.__init__(self, self.parent, *args, **kwargs)                  self.grab_set()         self.progress = ttk.Progressbar(             self, orient=tk.HORIZONTAL, length=100 , mode="determinate"          )         self.progress.pack(side="top" , fill="x" , expand=1 , padx=5 , pady=5 )         self.button = tk.Button(             self, text="Cancel" , command=lambda : [None  for  self.canceled in  [True ]]         )         self.button.pack()     @classmethod     def  loop (cls, seq, **kwargs ):         self = cls(**kwargs)         maximum = len (seq)         for  i, item in  enumerate (seq):             if  self.canceled:                 break              try :                 yield  i, item               except :                 import  traceback                 traceback.print_exc()                 self.destroy()             self.progress["value" ] = i / maximum * 100              self.update()         self.destroy() 
 
  用 classmethod 方便实例化对象   通过 yield 实现迭代器直接直接放到 for 循环里面使用~
 
图像处理 
  图像处理上使用的是简单 Pillow PIL 图像库。   其实混合通道不难,可以晚上搜索一下,又很多文章 链接    我这里只是读取两个目录里图片的序号批量匹配,然后融合通道之后批量根据序号进行输出。
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 @error_log def  img_combine (self ):    output_path = self.output_path.get()     input_path_1 = self.input_path_1.get()     input_path_2 = self.input_path_2.get()     if  not  os.path.exists(output_path):         self.output_path.set ("" )         messagebox.showwarning("警告" , "输出路径不存在" )         return      elif  not  os.path.exists(input_path_1):         self.self.input_path_1.set ("" )         messagebox.showwarning("警告" , "第一种贴图路径不存在" )         return      elif  not  os.path.exists(input_path_2):         self.input_path_2.set ("" )         messagebox.showwarning("警告" , "第二种贴图路径不存在" )         return           regx = re.compile (r".*?(\d+)\..*?$" )     input_path_1_dict = {         regx.search(f).group(1 ): os.path.join(input_path_1, f)         for  f in  os.listdir(input_path_1)         if  regx.search(f)     }     for  i, img in  ProgressDialog.loop(os.listdir(input_path_2)):         match  = regx.search(img)         if  not  match :             continue          num = match .group(1 )         img_1 = input_path_1_dict.get(num, "" )         img_2 = os.path.join(input_path_2, img)         if  not  os.path.exists(img_1):             continue          img_1 = Image.open (img_1).convert("RGBA" )         img_2 = Image.open (img_2).convert("RGBA" )         r_1, g_1, b_1, a_1 = img_1.split()         r_2, g_2, b_2, a_2 = img_2.split()         R = r_1 if  self.R.get() == "1"  else  r_2         G = g_1 if  self.G.get() == "1"  else  g_2         B = b_1 if  self.B.get() == "1"  else  b_2         A = a_1 if  self.A.get() == "1"  else  a_2         image = Image.merge("RGBA" , [R, G, B, A])         img = os.path.splitext(img)[0 ]         ext = self.image_extension.get()         image.save(os.path.join(output_path, f"{img} .{ext} " ))     messagebox.showinfo("恭喜您" , "合并完成" )     subprocess.Popen(["start" , "" , output_path], shell=True ) 
 
总结 
  这个工具的功能不复杂,一个早上就写完了。   简单记录一下。
 
补充 2020-12-30 
  混合通道使用 imagemagick 命令行高效秒杀这个需求。 
 
分离 合并