/
tinyPics.py
168 lines (144 loc) · 5.81 KB
/
tinyPics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import tinify
from tinify import AccountError, ClientError, ConnectionError, ServerError
import os
import threading
import math
#import requests.packages.urllib3
#requests.packages.urllib3.disable_warnings()
#===============tinypng python scripts for android===============
# step 1: run "pip install --upgrade tinify"
# step 2: prepare your tinypng keys, write them to accounts.txt, each account one line
# step 3: copy this dir to your project root dir, cd to tinypng dir & run "python tinyPics.py"
#
#
# tips 1: image files will be add to compressed_file_list.txt automatically
# tips 2: (optional)image files(absolute paths) in white_list.txt will be ignored if you do not want to compress them
# tips 3: if SSL connections error happens , open the import of requests.packages.urllib3
#
#===============tinypng python scripts for android===============
class AccountManager:
def __init__(self):
self.lock = threading.Lock()
self.accounts = {}
flag = False
with open('tinypng/accounts.txt', 'r') as f:
for line in f:
self.accounts[line] = True
if not flag:
tinify.key = line
flag = True
def getAvailableAccount(self):
self.lock.acquire()
result = None
try:
for k, v in self.accounts.items():
if v :
print '\ntry to use account:', k
result = k
finally:
self.lock.release()
return result
def setAccountUnavailable(self, accountKey):
self.lock.acquire()
try:
if None != accountKey:
self.accounts[accountKey] = False
print '\nset account unavailable:', accountKey, self.accounts
finally:
self.lock.release()
class Compresser(threading.Thread):
def __init__(self, filesToBeCompress, accountManager):
threading.Thread.__init__(self)
self.filesToBeCompress = filesToBeCompress
self.accountManager = accountManager
def run(self):
print '\nthread start...' + threading.currentThread().name
for f in self.filesToBeCompress:
if (not self.tiny(f, cwd)):
return
def tiny(self, f, cwd):
try:
tinify.from_file(f).to_file(f)
append_compressed_file(f, cwd)
print "tinypng " , f
except AccountError, e:
print "\nAccountError .. " + e.message, threading.currentThread().name
self.accountManager.setAccountUnavailable(tinify.key)
newKey = self.accountManager.getAvailableAccount()
if (None == newKey):
print "\nAll counts tried , finish"
exit(0)
return False
else:
tinify.key = newKey
self.tiny(f, cwd)
except ClientError, e1:
print "\nClientError ..", e1, f, threading.currentThread().name
# tiny(f,cwd)
# return False
except ServerError, e2:
print "\nServerError ..", e2, f, threading.currentThread().name
# tiny(f,cwd)
# return False
except ConnectionError, e3:
print "\nConnectionError ..", e3, f, threading.currentThread().name
# tiny(f,cwd)
# return False
return True
def get_picpaths(directory):
file_paths = [] # List which will store all of the full filepaths.
for root, directories, files in os.walk(directory):
for filename in files:
# Join the two strings in order to from the full filepath.
filepath = os.path.join(root, filename)
if (filename.endswith(".jpg") or filename.endswith(".png") or filename.endswith(".jpeg")) and not in_compressed_list(filepath,directory) and not in_white_list(filepath,directory) and 'intermediates' not in filepath and '.9' not in filepath:
file_paths.append(filepath)
return file_paths
# ignore all files in tinypng/white_list.txt
def in_white_list(filepath,cwd):
if not os.path.isfile("tinypng/white_list.txt"):
return False
filepath=filepath.replace(cwd,'')
if filepath in open("tinypng/white_list.txt").read():
print "\n*******"+ filepath + "******* in white_list , ignore"
return True
else:
return False
# ignore all files had been compressed
def in_compressed_list(filepath,cwd):
if not os.path.isfile("tinypng/compressed_file_list.txt"):
return False
filepath=filepath.replace(cwd,'')
if filepath in open("tinypng/compressed_file_list.txt").read():
print "\n====== " + filepath + " ====== in compressed_file_list , ignore"
return True
else:
return False
# record file to tinypng/compressed_file_list.txt
def append_compressed_file(filepath,cwd):
filepath=filepath.replace(cwd,'')
fp = open("tinypng/compressed_file_list.txt", "a+")
fp.write(filepath + "\n")
fp.flush()
fp.close()
if __name__ == "__main__":
#cd to projectDir(tinypng parentDir)
os.chdir('..')
cwd=os.getcwd()
accountManager = AccountManager()
full_pic_paths = get_picpaths(cwd)
if len(full_pic_paths) <= 0:
print '\n====Warning!==== there is no image, or all images have been compressed according to compressed_file_list.txt, clear compressed_file_list.txt and try again\n'
exit(0)
threadCount = int(math.sqrt(len(full_pic_paths)))
groupSize = len(full_pic_paths)/threadCount
index=0
while index < threadCount :
if index < threadCount - 1:
files = full_pic_paths[index * groupSize: (index + 1) * groupSize]
else:
files = full_pic_paths[index * groupSize: len(full_pic_paths)]
# print files
index = index + 1
Compresser(files, accountManager).start()
print '====Done!===='