一般我們項目中用的圖片許多都是簡單的圖標或小型圖片休傍,并沒有太高的質(zhì)量要求锹淌,雖然每個圖片都不大,但是多了的話也導致最后打的包很大,這里就來對項目內(nèi)的png和jpg圖片壓縮一下哥放。
壓縮png圖片用的是pngquant各墨,壓縮jpg用的是guetzli缕棵,都是非常著名的開源庫识椰,都能在保證一定品質(zhì)的前提下,極大地壓縮圖片鄙漏,對這兩個庫不了解的可以自行搜索嗤谚,這里提供一下兩個的項目的GitHub地址
首先看一下效果吧:
以我的項目中某個drawable文件夾為例棺蛛,壓縮前
壓縮后
可見還是很明顯的。
那么圖片質(zhì)量如何呢巩步,如下旁赊,壓縮前
壓縮后
可能上傳上來并不清晰,可以自行驗證椅野,效果還是可以的彤恶,基本肉眼很難觀察出區(qū)別。
看一下打包后區(qū)別鳄橘,以源碼中Music模塊為例声离,壓縮前
壓縮后
效果就是這些,如果想要做更多嘗試的話可以自行試驗瘫怜。
下面看代碼术徊,Python主要完成的是目錄的掃描,根據(jù)后綴名處理文件鲸湃,具體壓縮還是要根據(jù)兩個開源庫完成赠涮,整個過程要在Linux下完成,關于兩個開源庫的使用暗挑,首先要自己編譯笋除,這里我已經(jīng)編譯好了,在代碼中炸裆,代碼位置文末給出垃它,可以直接拿過去嘗試能否直接使用。
主要看一下Python掃描文件并處理的部分:
# -*- coding: UTF-8 -*-
import os
import random
import time
import shutil
class Compress(object):
DEBUG = True
MODE_OVERLAY = 0
MODE_MOVE = 1
MODE_EXPLAIN = ["覆蓋源文件","在新目錄下輸出"]
COUNT_EXEC = 0
COUNT_IGNORE = 0
PATCH9 = ".9.png"
PNG = ".png"
SUFFIX = [PNG,".jpg","jpeg",".jpe",".jfif",".jif"]
#檢查文件是否是可轉(zhuǎn)換的圖片
def checkFile(self, file):
res = False
for suf in self.SUFFIX:
if file.lower().endswith(suf):
res = True
break;
return res
def ignore(self, file):
self.log("忽略文件 : " + file)
self.COUNT_IGNORE += 1
def execf(self, file):
self.log("處理文件 : " + file)
self.COUNT_EXEC += 1
def log(self, info):
if self.DEBUG:
print(info)
self.logFile.write(info)
self.logFile.write('\n')
#將目錄內(nèi)文件入棧
def listFile(self, root):
for file in os.listdir(root):
self.stack.append(root + file)
#逐個處理棧內(nèi)文件
def scanFile(self):
while len(self.stack) != 0 :
child = self.stack.pop() #出棧
if os.path.isfile(child): #判斷是否是文件
#判斷是否需要壓縮
self.compressImg(child) if self.checkFile(child) else self.ignore(child)
elif os.path.isdir(child):
#若是目錄根據(jù)需求決定是否循環(huán)掃描
if self.recursive:
self.log("進入目錄 : " + child)
if self.mode == self.MODE_MOVE:
os.mkdir(self.imgOut + child.replace(self.imgDir,""))
self.listFile(child + "/")
#實際執(zhí)行壓縮的代碼
def compressImg(self, file):
#過濾掉.9圖片
if file.lower().endswith(self.PATCH9):
self.ignore(file)
return
#處理PNG或jpg圖片烹看,并根據(jù)是否覆蓋源文件進行處理
if file.lower().endswith(self.PNG) :
self.execf(file)
if self.mode == self.MODE_OVERLAY:
os.system("./png --force --ext .png --quality=80 " + file)
else:
os.system("./png --force --quality=80 " + file)
fpath,tfname = os.path.split(file)
fname,fsuf = os.path.splitext(tfname)
newJpg = fpath + "/" +fname + "-fs8" + fsuf
shutil.move(newJpg,self.imgOut + file.replace(self.imgDir,""))
return
if self.mode == self.MODE_OVERLAY:
os.system("./jpg --quality 85" + file + " " + file)
else:
os.system("./jpg --quality 85" + file + " " + self.imgOut + file.replace(self.imgDir,""))
self.execf(file)
pass
def run(self):
self.log("開始執(zhí)行国拇! 源文件夾:" + self.imgDir +
" 輸出模式:" + self.MODE_EXPLAIN[self.mode] +
" 遍歷模式:" + "遞歸遍歷所有子目錄" if self.recursive else "僅遍歷一級目錄")
self.listFile(self.imgDir)
self.scanFile()
self.log("運行結(jié)束! 所用時間 :" + str(time.time() - self.startTime) +
" 處理文件數(shù)量:" + str(self.COUNT_EXEC) +
" 忽略文件數(shù)量:" + str(self.COUNT_IGNORE) +
" 輸出目錄:" + self.imgOut)
self.logFile.close()
def __init__(self, imgDir, mode, recursive, quality):
self.startTime = time.time()
self.imgDir = imgDir if imgDir.endswith("/") else imgDir+"/"
self.src = os.getcwd() + "/"
self.mode = mode
if self.mode == self.MODE_MOVE:
out = "out" + str(random.uniform(10, 20))[3:]
try:
os.mkdir(self.src + out)
self.imgOut = self.src + out + "/"
except Exception as e:
print(e)
exit(0)
else:
self.imgOut = self.imgDir
self.recursive = recursive
self.quality = quality
self.stack = []
self.match = False
self.logFile = open(self.imgOut + "log" + str(random.uniform(10, 20))[3:], 'a')
首先要設定一下輸出模式:覆蓋源文件還是在新目錄下存儲惯殊,之后設定一下遍歷模式:只遍歷給定目錄的一級目錄還是給定目錄下的所有子目錄酱吝。然后執(zhí)行run方法。接著便是掃描--入棧--出棧--判斷(是目錄便根據(jù)模式?jīng)Q定是否繼續(xù)深層次掃描土思,是文件便進行后綴判斷然后壓縮處理)务热。整個邏輯還是很簡單的,關鍵部分都有注釋己儒,完整代碼及庫可執(zhí)行文件在此處