2018-08-13 18:07:52 +02:00
#!/usr/bin/env python3
2016-09-19 18:54:19 +02:00
# Copyright (c) 2014-2015 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
2015-08-04 12:06:12 +02:00
'''
2015-09-26 18:01:28 +02:00
Run this script every time you change one of the png files . Using pngcrush , it will optimize the png files , remove various color profiles , remove ancillary chunks ( alla ) and text chunks ( text ) .
2015-08-04 12:06:12 +02:00
#pngcrush -brute -ow -rem gAMA -rem cHRM -rem iCCP -rem sRGB -rem alla -rem text
'''
2014-12-17 09:00:16 +01:00
import os
import sys
import subprocess
2015-01-14 13:49:43 +01:00
import hashlib
2018-08-13 18:07:52 +02:00
from PIL import Image # pip3 install Pillow
2015-01-14 13:49:43 +01:00
def file_hash ( filename ) :
''' Return hash of raw file contents '''
with open ( filename , ' rb ' ) as f :
return hashlib . sha256 ( f . read ( ) ) . hexdigest ( )
def content_hash ( filename ) :
''' Return hash of RGBA contents of image '''
i = Image . open ( filename )
i = i . convert ( ' RGBA ' )
2015-09-26 18:01:28 +02:00
data = i . tobytes ( )
2015-01-14 13:49:43 +01:00
return hashlib . sha256 ( data ) . hexdigest ( )
2014-12-17 09:00:16 +01:00
2015-01-14 13:49:43 +01:00
pngcrush = ' pngcrush '
git = ' git '
2018-06-29 00:22:48 +02:00
folders = [ " src/qt/res/movies " , " src/qt/res/icons " , " src/qt/res/icons/crownium " , " src/qt/res/icons/drkblue " , " src/qt/res/icons/light " , " src/qt/res/icons/light-retro " , " src/qt/res/icons/trad " , " src/qt/res/images " , " src/qt/res/images/crownium " , " src/qt/res/images/drkblue " , " src/qt/res/images/light " , " src/qt/res/images/light-retro " , " src/qt/res/images/trad " , " share/pixmaps " ]
2018-08-13 18:07:52 +02:00
basePath = subprocess . check_output ( [ git , ' rev-parse ' , ' --show-toplevel ' ] , universal_newlines = True ) . rstrip ( ' \n ' )
2014-12-17 09:00:16 +01:00
totalSaveBytes = 0
2015-08-04 12:06:12 +02:00
noHashChange = True
2014-12-17 09:00:16 +01:00
outputArray = [ ]
for folder in folders :
absFolder = os . path . join ( basePath , folder )
for file in os . listdir ( absFolder ) :
extension = os . path . splitext ( file ) [ 1 ]
if extension . lower ( ) == ' .png ' :
2018-08-13 18:07:52 +02:00
print ( " optimizing {} ... " . format ( file ) , end = ' ' )
2014-12-17 09:00:16 +01:00
file_path = os . path . join ( absFolder , file )
2017-01-23 13:22:32 +01:00
fileMetaMap = { ' file ' : file , ' osize ' : os . path . getsize ( file_path ) , ' sha256Old ' : file_hash ( file_path ) }
2015-01-14 13:49:43 +01:00
fileMetaMap [ ' contentHashPre ' ] = content_hash ( file_path )
2014-12-17 09:00:16 +01:00
try :
2018-08-13 18:07:52 +02:00
subprocess . call ( [ pngcrush , " -brute " , " -ow " , " -rem " , " gAMA " , " -rem " , " cHRM " , " -rem " , " iCCP " , " -rem " , " sRGB " , " -rem " , " alla " , " -rem " , " text " , file_path ] ,
stdout = subprocess . DEVNULL , stderr = subprocess . DEVNULL )
2014-12-17 09:00:16 +01:00
except :
2018-08-13 18:07:52 +02:00
print ( " pngcrush is not installed, aborting... " )
2014-12-17 09:00:16 +01:00
sys . exit ( 0 )
#verify
2018-08-13 18:07:52 +02:00
if " Not a PNG file " in subprocess . check_output ( [ pngcrush , " -n " , " -v " , file_path ] , stderr = subprocess . STDOUT , universal_newlines = True ) :
print ( " PNG file " + file + " is corrupted after crushing, check out pngcursh version " )
2014-12-17 09:00:16 +01:00
sys . exit ( 1 )
2015-01-14 13:49:43 +01:00
fileMetaMap [ ' sha256New ' ] = file_hash ( file_path )
fileMetaMap [ ' contentHashPost ' ] = content_hash ( file_path )
if fileMetaMap [ ' contentHashPre ' ] != fileMetaMap [ ' contentHashPost ' ] :
2018-08-13 18:07:52 +02:00
print ( " Image contents of PNG file {} before and after crushing don ' t match " . format ( file ) )
2015-01-14 13:49:43 +01:00
sys . exit ( 1 )
2014-12-17 09:00:16 +01:00
fileMetaMap [ ' psize ' ] = os . path . getsize ( file_path )
outputArray . append ( fileMetaMap )
2018-08-13 18:07:52 +02:00
print ( " done " )
2014-12-17 09:00:16 +01:00
2018-08-13 18:07:52 +02:00
print ( " summary: \n +++++++++++++++++ " )
2014-12-17 09:00:16 +01:00
for fileDict in outputArray :
2015-01-14 13:49:43 +01:00
oldHash = fileDict [ ' sha256Old ' ]
newHash = fileDict [ ' sha256New ' ]
2014-12-17 09:00:16 +01:00
totalSaveBytes + = fileDict [ ' osize ' ] - fileDict [ ' psize ' ]
2015-08-04 12:06:12 +02:00
noHashChange = noHashChange and ( oldHash == newHash )
2018-08-13 18:07:52 +02:00
print ( fileDict [ ' file ' ] + " \n size diff from: " + str ( fileDict [ ' osize ' ] ) + " to: " + str ( fileDict [ ' psize ' ] ) + " \n old sha256: " + oldHash + " \n new sha256: " + newHash + " \n " )
2014-12-17 09:00:16 +01:00
2018-08-13 18:07:52 +02:00
print ( " completed. Checksum stable: " + str ( noHashChange ) + " . Total reduction: " + str ( totalSaveBytes ) + " bytes " )