Tutorial for compressing png images using pngquant in Python

  • 2020-05-07 19:59:54
  • OfStack

Speaking of png image compression, many of you probably know TinyPNG. But the PS plug-in costs money (though it's cracked), Developer API connects to his server, not to mention the network speed, and Key has a monthly limit.
       
      but it seems that tinyPNG is using technology from pngquant, at least as claimed in http:// pngquant.org / : TinyPNG and Kraken.io -- on interfaces for pngquant. If so, I'd like to say hehe to TinyPNG. The latter is open source, as are the GUI tools available on the home page. And TinyPNG is not mentioned once in the principle description on the home page

      I took the sample diagram on tinyPNG's home page and ran it 1 run from the pngquant command line. The compression rate is about the same as the display.

      pngquant homepage provides the tools, Pngyu (http: / / nukesaq88. github. io Pngyu /) is a cross-platform and open source, personal feel has been pretty good, drag the folder to can directly recursive processing, support various forms of generation (name, cover, stored in other directories, etc.), the compression end compression ratio is given, and it also supports preview.

      but I would still like to be able to handle it in a script, 1 more customizable and 1 more easily integrated into the whole automated process chain. So I took out python and tried to write something, and who knows...

      pngquant The parameter description in help is different from the actual effect

      1. -- the force parameter is invalid. As long as the output file exists, an error is reported, ignoring the parameter used to specify the overwrite
      2. -- skip-if-larger parameter is abnormal, sometimes the generated file is obviously small, but it will be dropped by skip......

     , however, is good for python. These problems cannot be handled from the command line itself, but python can be handled from the top.


'''
pngquant.py
use pngquant to reduces png file size
Ruoqian, Chen<piao.polar@gmail.com> 

----------
2015/4/3
1. del option --quality=50-90, special pic need skip can config in lod ini

  lod ini format:

[PixelFormat]
map_01.png=0

  0 means skip in file

----------
2015/4/2
1. desDir can be the same to srcDir, or another dir
2. lod ini config can be not exist

----------
2015/3/31
create
'''

import os
import os.path
import sys
import ConfigParser
import string

PngquantExe="pngquant"

thisFilePath = sys.path[0];

print "this py file in dir : " + thisFilePath

projectPath = thisFilePath + "/../CMWar_2dx/CMWar_2dx/";
srcResDir = "Resources/";
dstResDir = "Resources/";

lodIniPath = projectPath + srcResDir + "ini/pic.ini"
keepOrgPaths = [];
if os.path.exists(lodIniPath):
  config = ConfigParser.SafeConfigParser()
  config.read(lodIniPath)
  section = "PixelFormat";
  options = config.options(section)
  for option in options:
    value = string.atoi(config.get(section, option))
    if not value:
      keepOrgPaths.append(option);

print keepOrgPaths

srcResPath = projectPath + srcResDir;

pngCount = 0;
transCount = 0;

#pngquant --force --skip-if-larger --ext .png --quality 50-90 --speed 1

for parent,dirnames,filenames in os.walk(srcResPath):
  print "----- process Dir " + parent
  dstDir = parent.replace(srcResDir, dstResDir)
  if not os.path.exists(dstDir):
    os.makedirs(dstDir)
  for filename in filenames:
    if os.path.splitext(filename)[1] == '.png':
      pngCount += 1;
      srcFilePath = os.path.join(parent, filename);
      dstFilePath = os.path.join(dstDir, filename);
      tmpFilePath = dstFilePath + ".tmp";

      if filename in keepOrgPaths:
        print "----- keep ----- " + filename;
      else:
#        print "----- process ----- " + filename;
#        cmd = "\"" + PngquantExe + "\"" + " --force --speed=1 --quality=50-90 -v " + srcFilePath + " -o " + tmpFilePath;
        cmd = "\"" + PngquantExe + "\"" + " --force --speed=1 " + srcFilePath + " -o " + tmpFilePath;
#        print cmd;
        os.system(cmd)
        if os.path.exists(tmpFilePath):
          sizeNew = os.path.getsize(tmpFilePath);
          sizeOld = os.path.getsize(srcFilePath);
          if sizeNew < sizeOld:
            open(dstFilePath, "wb").write(open(tmpFilePath, "rb").read())
            transCount += 1;
          os.remove(tmpFilePath)
      if not os.path.exists(dstFilePath):
        open(dstFilePath, "wb").write(open(srcFilePath, "rb").read())

print "Done. Trans Pngs: %d/%d" %(transCount, pngCount)



Related articles: