[
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nenv/\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*,cover\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n"
  },
  {
    "path": "README.md",
    "content": "# GGTinypng\n批量压缩png和jpg图片python脚本\n减少图片50%以上的大小，肉眼看不出差别。减量不减质。\n图片数量少的话可以在tinypng.com上试一下。看下效果。\n\n已经支持子文件夹里面的图片，会按原始的相对路径存放到输出文件夹内\n\n7.30 新加功能：一条命令压缩整个项目内的图片。\n\n显著降低app的大小\n\n## 使用方法\n可以使用alias来简化命令\npython3 tinypng.py -i <picDocPath> -o <outputDocPath>\n\n -o 参数可以为空，因为要遍历picDocPath子文件夹 所以默认outputDocPath改为picDocPath父目录\n 内的outputTinypng文件夹，与picDocPath同级。\n\n 7.30 新参数：python3 tinypng.py -r <项目路径或者项目内某个图片文件夹的路径>\n\n -r 参数会压缩文件夹内的图片并替换原图片\n\n去 https://tinypng.com/developers 免费申请自己的key 每key每月免费压缩500个图\n\n默认并发数为10 可以自己调整\n\n##to do\n\n如果有时间的话可能会做成处理mac程序或者xcode插件。不过短时间内不会，因为我自己用的话\n脚本就足够了。\n"
  },
  {
    "path": "tinypng.py",
    "content": "#!/usr/bin/env python3\n# coding=utf-8\n\n# from os.path import dirname\nimport os,sys, getopt\nfrom urllib.request import Request, urlopen\nfrom base64 import b64encode\nfrom multiprocessing import Pool\n\npoolLimite = 10\nkey = \"PX-pm9lAY3siS8cHIWz44zWFZHj6TtYX\"\n# input = \"large-input.png\"\n# output = \"tiny-output.png\"\nopts, args = getopt.getopt(sys.argv[1:], \"hi:o:r:\")\ninput_doc_path=\"\"\noutput_doc_path = ''\nfilePaths=[]\n\nfor op, value in opts:\n    if op == \"-i\":\n        input_doc_path = value\n    elif op == \"-o\":\n        output_doc_path = value\n    elif op == \"-r\":\n        input_doc_path = value\n        output_doc_path = value\n    elif op == \"-h\":\n        print('''\n        使用方法 python3 tinypng.py -i picDocPath -o outputDocPath\n        -o 参数可以为空，默认存在picDocPath/tinypng 内\n        去 https://tinypng.com/developers 申请自己的key 每key每月免费压缩500个图\n        默认并发数为10 可以自己调整''')\n\n\ndef absFilePath(fileName):\n    return os.path.join(input_doc_path,fileName)\ndef getTinyPng(filePath):\n    print('开始'+filePath)\n    request = Request(\"https://api.tinify.com/shrink\", open(filePath, \"rb\").read())\n\n    cafile = None\n    # Uncomment below if you have trouble validating our SSL certificate.\n    # Download cacert.pem from: http://curl.haxx.se/ca/cacert.pem\n    # cafile = dirname(__file__) + \"/cacert.pem\"\n\n    auth = b64encode(bytes(\"api:\" + key, \"ascii\")).decode(\"ascii\")\n    request.add_header(\"Authorization\", \"Basic %s\" % auth)\n\n    response = urlopen(request, cafile = cafile)\n    if response.status == 201:\n      # Compression was successful, retrieve output from Location header.\n      result = urlopen(response.getheader(\"Location\"), cafile = cafile).read()\n\n      output = os.path.join(output_doc_path, os.path.relpath(filePath,input_doc_path))\n      open(output, \"wb\").write(result)\n      print('完成'+output)\n    else:\n      print('失败'+filePath)\n      # Something went wrong! You can parse the JSON body for details.\n      print(\"Compression failed\")\n\ndef main():\n    global output_doc_path\n    if output_doc_path == '':\n        output_doc_path = os.path.join(os.path.split(input_doc_path)[0], 'outputTinypng')\n    if not os.path.exists(output_doc_path):\n        os.mkdir(output_doc_path)\n\n    for parent,dirnames,filenames in os.walk(input_doc_path):    #三个参数：分别返回1.父目录 2.所有文件夹名字（不含路径） 3.所有文件名字\n      for dirname in  dirnames:                       #输出文件夹信息\n        # print(\"parent is:\" + parent)\n        # print(\"dirname is\" + dirname)\n        outDir = os.path.join(output_doc_path,os.path.relpath(os.path.join(parent,dirname),input_doc_path))\n        if not os.path.exists(outDir):\n            os.mkdir(outDir)\n\n      for filename in filenames:                        #输出文件信息\n        # print(\"parent is:\" + parent)\n        # print(\"filename is:\" + filename)\n        filePaths.append(os.path.join(parent,filename))\n\n    pngFilePaths = filter(lambda x:os.path.splitext(x)[1]=='.png' or os.path.splitext(x)[1]=='.jpg',filePaths)\n    print('Parent process %s.' % os.getpid())\n    p = Pool(poolLimite)\n    for fileName in pngFilePaths:\n        p.apply_async(getTinyPng, args=(fileName,))\n    print('Waiting for all subprocesses done...')\n    p.close()\n    p.join()\n    print('All subprocesses done.')\n\nif __name__=='__main__':\n    if os.path.isdir(input_doc_path):\n        main()\n"
  }
]