利用Python批量壓縮項目內(nèi)圖片

一般我們項目中用的圖片許多都是簡單的圖標或小型圖片休傍,并沒有太高的質(zhì)量要求锹淌,雖然每個圖片都不大,但是多了的話也導致最后打的包很大,這里就來對項目內(nèi)的png和jpg圖片壓縮一下哥放。

壓縮png圖片用的是pngquant各墨,壓縮jpg用的是guetzli缕棵,都是非常著名的開源庫识椰,都能在保證一定品質(zhì)的前提下,極大地壓縮圖片鄙漏,對這兩個庫不了解的可以自行搜索嗤谚,這里提供一下兩個的項目的GitHub地址

guetzli
pngquant

首先看一下效果吧:

以我的項目中某個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í)行文件在此處

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末崎岂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子址愿,更是在濱河造成了極大的恐慌该镣,老刑警劉巖冻璃,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件响谓,死亡現(xiàn)場離奇詭異损合,居然都是意外死亡,警方通過查閱死者的電腦和手機娘纷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門嫁审,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赖晶,你說我怎么就攤上這事律适。” “怎么了遏插?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵捂贿,是天一觀的道長。 經(jīng)常有香客問我胳嘲,道長厂僧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任了牛,我火速辦了婚禮颜屠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鹰祸。我一直安慰自己甫窟,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布蛙婴。 她就那樣靜靜地躺著粗井,像睡著了一般。 火紅的嫁衣襯著肌膚如雪街图。 梳的紋絲不亂的頭發(fā)上背传,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音台夺,去河邊找鬼径玖。 笑死,一個胖子當著我的面吹牛颤介,可吹牛的內(nèi)容都是我干的梳星。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼滚朵,長吁一口氣:“原來是場噩夢啊……” “哼冤灾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起辕近,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤韵吨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后移宅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體归粉,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡椿疗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了糠悼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片届榄。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖倔喂,靈堂內(nèi)的尸體忽然破棺而出铝条,到底是詐尸還是另有隱情,我是刑警寧澤席噩,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布班缰,位于F島的核電站,受9級特大地震影響悼枢,放射性物質(zhì)發(fā)生泄漏鲁捏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一萧芙、第九天 我趴在偏房一處隱蔽的房頂上張望给梅。 院中可真熱鬧,春花似錦双揪、人聲如沸动羽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽运吓。三九已至,卻和暖如春疯趟,著一層夾襖步出監(jiān)牢的瞬間拘哨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工信峻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留倦青,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓盹舞,卻偏偏與公主長得像产镐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踢步,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,312評論 25 707
  • 與書結(jié)緣始于小學時候癣亚,具體什么時候我忘了。只記得有一回看見二哥在看書获印,但不是學校的書述雾,便拿來看看,結(jié)果一發(fā)不可收拾...
    小生_490e閱讀 341評論 0 1
  • I'd rather stay stay at the position not faraway I cheris...
    alabiubiubiu閱讀 182評論 0 1
  • 你昨天的吃喝拉撒決定了今天的健康狀況唆缴,今天的吃喝拉撒又決定了未來的健康情況。 人往往“很有”勇氣面對失去健康的痛苦...
    農(nóng)爸爸閱讀 161評論 0 0
  • 今天是星期五取募,又是一個餐飲課的日子,看著每個家長和老師的忙碌蟆技,我知道了他們是多么的為我們辛苦玩敏,今天做的是零食,...
    荊玉淋閱讀 168評論 0 0