-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclassifyImg.py
152 lines (137 loc) · 4.3 KB
/
classifyImg.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
from subprocess import call, run, PIPE
import datetime
import struct
import sys, os
import re, shutil
from config import *
ATOM_HEADER_SIZE = 8
# difference between Unix epoch and QuickTime epoch, in seconds
EPOCH_ADJUSTER = 2082844800
datePatStr = "(?P<y>[0-9]{4})[-_:](?P<m>[0-9]{2})[-_:](?P<d>[0-9]{2})[-_: ](?P<h>[0-9]{2})[-_:](?P<mn>[0-9]{2})[-_:](?P<s>[0-9]{2})"
datePat = re.compile(datePatStr)
filePat = re.compile("(.*/|^)IMG_(?P<y>[0-9]{4})(?P<m>[0-9]{2})(?P<d>[0-9]{2})_(?P<h>[0-9]{2})(?P<mn>[0-9]{2})(?P<s>[0-9]{2})\..*")
exifPat = re.compile("Create Date[^:]+: (?P<date>%s).*" %datePatStr)
def timeFromFileName(filename):
ret=filePat.match(filename)
if ret:
res="%s:%s:%s %s:%s:%s" %(ret.group('y'), ret.group('m'), ret.group('d'), ret.group('h'), ret.group('mn'), ret.group('s'))
else:
res=''
return res
def getYearMonth(datestr):
ret=datePat.match(datestr)
return ret.group('y'), ret.group('m')
def movTime(filename):
# open file and search for moov item
f = open(filename, "rb")
while 1:
atom_header = f.read(ATOM_HEADER_SIZE)
if atom_header[4:8].decode('ascii') == 'moov':
break
else:
if atom_header == b'':
print("ERROR: moov not found, something wrong happen")
return timeFromFileName(filename)
atom_size = struct.unpack(">I", atom_header[0:4])[0]
f.seek(atom_size - 8, 1)
# found 'moov', look for 'mvhd' and timestamps
atom_header = f.read(ATOM_HEADER_SIZE)
if atom_header[4:8].decode('ascii') == 'cmov':
print("ERROR: mov atom is compressed")
s=timeFromFileName(filename)
elif atom_header[4:8].decode('ascii') != 'mvhd':
print("ERROR: expected to find 'mvhd' header got %s" %atom_header[4:8].decode('ascii'))
s=timeFromFileName(filename)
else:
f.seek(4, 1)
creation_date = struct.unpack(">I", f.read(4))[0]
modification_date = struct.unpack(">I", f.read(4))[0]
# print "creation date:",
s="%s" %datetime.datetime.utcfromtimestamp(creation_date - EPOCH_ADJUSTER)
s=s.replace("-",":")
return s
def videoTime(filename):
res = run(['/bin/exiftool', '-CreateDate', filename], stdout=PIPE, stderr=PIPE)
res=res.stdout.decode('ascii').strip()
if res:
ret = exifPat.match(res)
if ret:
res = ret.group("date")
else:
ret = ""
else:
res = timeFromFileName(filename)
return res
def imgTime(filename):
res=run(['/bin/exiv2', '-g', 'Exif.Image.DateTime', '-Pv', filename], stdout=PIPE, stderr=PIPE)
res=res.stdout.decode('ascii').strip()
if not res:
res=run(['/bin/exiv2', '-g', 'DateTimeOriginal', '-Pv', filename], stdout=PIPE, stderr=PIPE)
res=res.stdout.decode('ascii').strip()
if not res:
res = timeFromFileName(filename)
return res
def getDestDirName(datestr):
ret=datePat.match(datestr)
return "%s/%s" %(ret.group('y'), ret.group('m'))
def getTimeFromDateFile(filename):
return datetime.datetime.fromtimestamp(int(os.path.getctime(filename))).strftime('%Y:%m:%d %H:%M:%S')
def mediaTime(filename):
ext = filename[-3:]
if ext.lower() in [ "jpg", "png", "gif" ]:
ret = imgTime(filename)
elif ext.lower() == "mov":
ret = videoTime(filename)
if not ret:
ret=movTime(filename)
elif ext.lower() == "mp4":
ret = videoTime(filename)
else:
ret = ""
if ret:
y,m = getYearMonth(ret)
if y=='0000':
ret = ""
if not ret:
ret=getTimeFromDateFile(filename)
return ret
def move(src, dest):
shutil.move(src, dest)
#shutil.copy2(src, dest)
#os.remove(src)
def safeMove(src, dest):
if os.path.exists(dest):
ret=call(["diff", "-q", src, dest])
if not ret:
move(src, dest)
else:
file, ext = os.path.splitext(dest)
i = 1
newdest = lambda x : file + "_" + str(x) + ext
while os.path.exists(newdest(i)):
ret=call(["diff", "-q", src, newdest(i)])
if not ret:
break
i+=1
move(src, file + "_" + str(i) + ext)
else:
move(src, dest)
def classifyImg(filename, dir=".", testOnly=False):
bname = os.path.basename(filename)
t = mediaTime(filename)
msg=[]
if t:
dname = "%s/%s/%s" %(photoBaseDir, dir, getDestDirName(t))
if not os.path.exists(dname):
if not testOnly:
os.makedirs(dname)
msg.append("\tos.makedirs(%s)" %dname)
destfile = "%s/%s" %(dname, bname)
msg.append("\tmv %s %s" %(filename, destfile))
if not testOnly:
safeMove(filename, destfile)
else:
msg.append("\tunable to compute date, skip file %s" %filename)
return "\n\t".join(msg)
if __name__ == "__main__":
print(classifyImg(sys.argv[1]))