mirror of
https://github.com/sashacmc/photo-importer.git
synced 2024-11-24 08:02:14 +02:00
Add jpegtran support
This commit is contained in:
parent
3aee11e42c
commit
bf79a40056
@ -29,8 +29,8 @@ Standalone web server for fast media import for headless computer
|
||||
* PyExifTool (pip3 install PyExifTool)
|
||||
* python3-progressbar
|
||||
* python3-psutil
|
||||
* exiftran
|
||||
* pmount
|
||||
* exiftran or jpegtran
|
||||
* pmount (only for server)
|
||||
|
||||
|
||||
### Installation Options:
|
||||
|
@ -35,6 +35,9 @@ move_mode = 1
|
||||
# umask for new folder and copied files
|
||||
umask = 0o000
|
||||
|
||||
# use jpegtran in place of exiftran 0/1
|
||||
use_jpegtran = 0
|
||||
|
||||
[server]
|
||||
# server port
|
||||
port = 8080
|
||||
|
@ -26,6 +26,7 @@ class Config(object):
|
||||
'move_mode': 1,
|
||||
'threads_count': 2,
|
||||
'umask': '0o000',
|
||||
'use_jpegtran': 0,
|
||||
},
|
||||
'server': {
|
||||
'port': 8080,
|
||||
|
@ -1,11 +1,28 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import os
|
||||
import logging
|
||||
import exiftool
|
||||
import tempfile
|
||||
import subprocess
|
||||
import concurrent.futures
|
||||
|
||||
from photo_importer import config
|
||||
|
||||
JPEGTRAN_COMMAND = {
|
||||
0: None,
|
||||
1: None,
|
||||
2: '-flip horizontal',
|
||||
3: '-rotate 180',
|
||||
4: '-flip vertical',
|
||||
5: '-transpose',
|
||||
6: '-rotate 90',
|
||||
7: '-transverse',
|
||||
8: '-rotate 270'
|
||||
}
|
||||
|
||||
ORIENTATION_TAG = 'EXIF:Orientation'
|
||||
|
||||
|
||||
class Rotator(object):
|
||||
def __init__(self, config, filenames, dryrun):
|
||||
@ -17,11 +34,20 @@ class Rotator(object):
|
||||
self.__errors = 0
|
||||
|
||||
def run(self):
|
||||
os.umask(int(self.__config['main']['umask'], 8))
|
||||
tc = int(self.__config['main']['threads_count'])
|
||||
processor = self.__process_exiftran
|
||||
self.__exiftool = None
|
||||
if int(self.__config['main']['use_jpegtran']):
|
||||
self.__exiftool = exiftool.ExifTool()
|
||||
self.__exiftool.start()
|
||||
processor = self.__process_jpegtran
|
||||
tc = 1
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=tc) as executor:
|
||||
|
||||
futures = {
|
||||
executor.submit(self.__process, fn):
|
||||
executor.submit(processor, fn):
|
||||
fn for fn in self.__filenames}
|
||||
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
@ -31,7 +57,10 @@ class Rotator(object):
|
||||
else:
|
||||
self.__errors += 1
|
||||
|
||||
def __process(self, filename):
|
||||
if self.__exiftool is not None:
|
||||
self.__exiftool.terminate()
|
||||
|
||||
def __process_exiftran(self, filename):
|
||||
ok = False
|
||||
try:
|
||||
cmd = 'exiftran -aip "%s"' % filename
|
||||
@ -43,12 +72,13 @@ class Rotator(object):
|
||||
p = subprocess.Popen(
|
||||
cmd,
|
||||
shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE).stderr
|
||||
|
||||
error = ''
|
||||
while 1:
|
||||
line = p.readline().decode("utf-8")
|
||||
while True:
|
||||
line = p.readline()
|
||||
if not line:
|
||||
break
|
||||
|
||||
@ -66,6 +96,65 @@ class Rotator(object):
|
||||
|
||||
return ok
|
||||
|
||||
def __process_jpegtran(self, filename):
|
||||
try:
|
||||
orientation_cmd = self.__get_orientation_cmd(filename)
|
||||
if orientation_cmd is None:
|
||||
return True
|
||||
|
||||
logging.debug('rotate: jpegtran %s %s' %
|
||||
(orientation_cmd, filename))
|
||||
|
||||
if self.__dryrun:
|
||||
return True
|
||||
|
||||
handle, tmpfile = tempfile.mkstemp(dir=os.path.dirname(filename))
|
||||
os.close(handle)
|
||||
|
||||
cmd = 'jpegtran -copy all -outfile %s %s %s' % \
|
||||
(tmpfile, orientation_cmd, filename)
|
||||
|
||||
p = subprocess.Popen(
|
||||
cmd,
|
||||
shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE).stderr
|
||||
|
||||
line = p.readline()
|
||||
if line:
|
||||
logging.error('jpegtran (%s) failed: %s' % (filename, line))
|
||||
return False
|
||||
|
||||
self.__clear_orientation_tag(tmpfile)
|
||||
|
||||
os.remove(filename)
|
||||
os.rename(tmpfile, filename)
|
||||
|
||||
return True
|
||||
except Exception as ex:
|
||||
logging.error('Rotator exception (%s): %s' % (filename, ex))
|
||||
raise
|
||||
return False
|
||||
|
||||
def __get_orientation_cmd(self, fullname):
|
||||
orientation = self.__exiftool.get_tag(ORIENTATION_TAG, fullname)
|
||||
if orientation is not None and \
|
||||
0 <= orientation and orientation < len(JPEGTRAN_COMMAND):
|
||||
return JPEGTRAN_COMMAND[orientation]
|
||||
else:
|
||||
return None
|
||||
|
||||
def __clear_orientation_tag(self, fullname):
|
||||
res = self.__exiftool.set_tags(
|
||||
{ORIENTATION_TAG: 1}, fullname).decode('utf-8')
|
||||
if not exiftool.check_ok(res):
|
||||
raise SystemError('exiftool error: ' + exiftool.format_error(res))
|
||||
try:
|
||||
os.remove(fullname + '_original')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def status(self):
|
||||
return {
|
||||
'total': len(self.__filenames),
|
||||
|
Loading…
Reference in New Issue
Block a user