Advertisement
Guest User

iOS Downsampler

a guest
Mar 26th, 2015
670
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.57 KB | None | 0 0
  1. #!/usr/bin/env python
  2. from PIL import Image as PilImage
  3. import sys, os.path, ConfigParser
  4. from Tkinter import *
  5. import ttk
  6. import tkFileDialog, tkMessageBox
  7. import codecs
  8.  
  9. # Fix for Unicode Filenames ( http://habrahabr.ru/post/119405/ )
  10. class UnicodeConfigParser(ConfigParser.RawConfigParser):
  11.  
  12.     def __init__(self, *args, **kwargs):
  13.         ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
  14.  
  15.     def write(self, fp):
  16.         """Fixed for Unicode output"""
  17.         if self._defaults:
  18.             fp.write("[%s]\n" % DEFAULTSECT)
  19.             for (key, value) in self._defaults.items():
  20.                 fp.write("%s = %s\n" % (key, unicode(value).replace('\n', '\n\t')))
  21.             fp.write("\n")
  22.         for section in self._sections:
  23.             fp.write("[%s]\n" % section)
  24.             for (key, value) in self._sections[section].items():
  25.                 if key != "__name__":
  26.                     fp.write("%s = %s\n" %
  27.                              (key, unicode(value).replace('\n','\n\t')))
  28.             fp.write("\n")
  29.  
  30.     # This function is needed to override default lower-case conversion
  31.     # of the parameter's names. They will be saved 'as is'.
  32.     def optionxform(self, strOut):
  33.         return strOut
  34.  
  35. resolutions = [("", 1.0), ("@2x", 2.0), ("@3x", 3.0)]
  36. configFile = "config.txt"
  37. configSection = "configuration"
  38. configLastDir = "LastDir"
  39.  
  40. imagePath = ""
  41. imageDir = ""
  42. imageName = ""
  43. image = None
  44. defWidth = defHeight = 1
  45.  
  46. root = Tk()
  47. root.title("IOS ImageAsset Downsampler")
  48. root.resizable(0, 0)
  49. pyfilepath = ""
  50. if hasattr(sys, 'frozen'):
  51.     pyfilepath = sys.executable
  52. else:
  53.     pyfilepath = os.path.realpath(__file__)
  54. pyfilepath = os.path.dirname(pyfilepath)
  55. # iconpath = pyfilepath + "/iasdownsampler.ico"
  56. # if os.path.exists(iconpath):
  57. #     root.iconbitmap(iconpath)
  58. widthVar = StringVar()
  59. heightVar = StringVar()
  60. suffix = StringVar()
  61. labelFileName = convertButton = buttonCalculateSizes = None
  62.  
  63. configdir = os.path.expanduser("~") + "/.downsampler/"
  64. if not os.path.exists(configdir):
  65.     os.makedirs(configdir)
  66. configpath = configdir + configFile
  67.  
  68. def loadParameter(param, defval):
  69.     if os.path.exists(configpath):
  70.         parser = ConfigParser.ConfigParser()
  71.         parser.optionxform = unicode
  72.         parser.readfp(codecs.open(configpath, "rb", "utf8"))
  73.         items = parser.items(configSection)
  74.         itemsDict = dict(items)
  75.         return itemsDict[param]
  76.     else:
  77.         return defval
  78.  
  79. def storeParameter(param, value):
  80.     parser = UnicodeConfigParser()
  81.     if os.path.exists(configpath):
  82.         parser.read(configpath)
  83.     else:
  84.         parser.add_section(configSection)
  85.     parser.set(configSection, param, value)
  86.     with codecs.open(configpath, "wb", "utf8") as cfile:
  87.         parser.write(cfile)
  88.  
  89. def onSelectFile():
  90.     global imagePath, imageDir, imageName, image, defHeight, defWidth
  91.     options = dict()
  92.     options['initialdir'] = loadParameter(configLastDir, pyfilepath)
  93.     options['title'] = 'Select original large image'
  94.     options['filetypes'] = [('PNG files', '.png')]
  95.     imagePath = tkFileDialog.askopenfilename(**options)
  96.  
  97.     if len(imagePath) == 0:
  98.         return
  99.  
  100.     imageDir = os.path.dirname(imagePath)
  101.     storeParameter(configLastDir, imageDir)
  102.     imageName = os.path.basename(imagePath)
  103.  
  104.     image = PilImage.open(imagePath)
  105.     defWidth, defHeight = image.size
  106.  
  107.     labelFileName["text"] = imageName + " (%dx%d)" % (defWidth, defHeight)
  108.     convertButton["state"] = "enabled"
  109.     buttonCalculateSizes["state"] = "enabled"
  110.  
  111. def calculateSizes():
  112.     if len(widthVar.get()) == 0 and len(heightVar.get()) > 0:
  113.         height = int(heightVar.get())
  114.         width = int(1.0 * defWidth / defHeight * height)
  115.         widthVar.set(str(width))
  116.     if len(widthVar.get()) > 0 and len(heightVar.get()) == 0:
  117.         width = int(widthVar.get())
  118.         height = int(1.0 * defHeight / defWidth * width)
  119.         heightVar.set(str(height))
  120.  
  121. def convert():
  122.     if len(widthVar.get()) == 0 or len(heightVar.get()) == 0:
  123.         tkMessageBox.showinfo("Error", "Please, specify width and height for @1x resolution")
  124.         return
  125.     convertButton["state"] = "disabled"
  126.  
  127.     width = int(widthVar.get())
  128.     height = int(heightVar.get())
  129.     sizes = {resolution[0]: (int(width * resolution[1]), int(height * resolution[1])) for resolution in resolutions}
  130.  
  131.     (imageRootName, imageExt) = os.path.splitext(imageName)
  132.  
  133.     for category, (width, height) in sizes.iteritems():
  134.         finaldir = imageDir + "/result-images"
  135.         if not os.path.exists(finaldir):
  136.             os.makedirs(finaldir)
  137.         print("Resizing for %s to %dx%d" % (category, width, height))
  138.         imageResized = image.resize((width, height), PilImage.ANTIALIAS)
  139.         imageResized.save(finaldir + "/" + imageRootName + category + suffix.get() + imageExt)
  140.  
  141.     convertButton["state"] = "enabled"
  142.  
  143. labelFileName = ttk.Label(root, text = "Please, select original image")
  144. labelFileName.grid(row = 0, column = 0, columnspan = 2)
  145.  
  146. buttonSelectFile = ttk.Button(root, text="Choose file...", width = 40, command = onSelectFile)
  147. buttonSelectFile.grid(row = 1, column = 0, columnspan = 2)
  148.  
  149. ttk.Label(root, text = "@1x Width").grid(row = 2, column = 0)
  150. ttk.Label(root, text = "@1x Height").grid(row = 2, column = 1)
  151.  
  152. textWidth = ttk.Entry(root, width = 30, textvariable = widthVar, justify = "center")
  153. textWidth.grid(row = 3, column = 0)
  154. textHeight = ttk.Entry(root, width = 30, textvariable = heightVar, justify = "center")
  155. textHeight.grid(row = 3, column = 1)
  156.  
  157. buttonCalculateSizes = ttk.Button(root, text = "Width <==> Height", width = 40, command = calculateSizes)
  158. buttonCalculateSizes.grid(row = 4, column = 0, columnspan = 2)
  159. buttonCalculateSizes["state"] = "disabled"
  160.  
  161. ttk.Label(root,
  162.     text = "If you left width OR height empty, press button above to maintain aspect ratio").\
  163.     grid(row = 5, column = 0, columnspan = 2)
  164.  
  165. ttk.Checkbutton(root, text = "Add ~ipad suffix", variable = suffix,
  166.     onvalue = "~ipad", offvalue = "").grid(row = 6, column = 0, columnspan = 2)
  167.  
  168. convertButton = ttk.Button(root, text = "_____  DO  IT  _____", width = 40, command = convert)
  169. convertButton.grid(row = 7, column = 0, columnspan = 2)
  170. convertButton["state"] = "disabled"
  171.  
  172. ttk.Label(root,
  173.     text = "Result files will be placed to result-images folder in original image directory").\
  174.     grid(row = 8, column = 0, columnspan = 2)
  175.  
  176. ttk.Label(root,
  177.     text = "Version 0.1 by Egor Aristov (ef@efprojects.com). Based on Android Drawable Downsampler").\
  178.     grid(row = 9, column = 0, columnspan = 2)
  179.  
  180. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement