[enh] Same cache logic for thumbs and fullsize pictures

- store gm settings in the cache as a dict
- generalize usage of the gm settings to resize
- can be used to resize fullsize versions of the pictures
- without -quality switch, gm defaults to -quality 75.
  use -define jpeg:preserve-settings for fullsize versions to
  avoid altering them
- do not store "name" in the cache, because when the same image
  is used in a gallery and as the cover, it invalidates the cache
  entry and becomes always generated
This commit is contained in:
Julien Malik 2016-02-18 14:27:13 +01:00 committed by Laurent Peuch
parent 31298be91b
commit 947bbe9470
2 changed files with 41 additions and 47 deletions

View File

@ -3,6 +3,10 @@ import json
CACHE_VERSION = 1
def remove_name(options):
noname_options = options.copy()
del noname_options["name"]
return noname_options
class Cache(object):
cache_file_path = os.path.join(os.getcwd(), ".prosopopee_cache")
@ -22,39 +26,23 @@ class Cache(object):
print "info: cache format as changed, prune cache"
self.cache = {"version": CACHE_VERSION}
def thumbnail_needs_to_be_generated(self, source, target, image):
def needs_to_be_generated(self, source, target, options):
if not os.path.exists(target):
return True
if target not in self.cache:
return True
cached_thumbnail = self.cache[target]
cached_picture = self.cache[target]
if cached_thumbnail["size"] != os.path.getsize(source) or cached_thumbnail["options"] != image.options:
if cached_picture["size"] != os.path.getsize(source) or cached_picture["options"] != remove_name(options):
return True
return False
def image_needs_to_be_oritend(self, source, target, command):
if not os.path.exists(target):
return True
if target not in self.cache:
return True
cached_image = self.cache[target]
if cached_image["size"] != os.path.getsize(source) or cached_image["command"] != command:
return True
return False
def cache_thumbnail(self, source, target, image):
self.cache[target] = {"size": os.path.getsize(source), "options": image.options}
def cache_auto_oriented_image(self, source, target, command):
self.cache[target] = {"size": os.path.getsize(source), "command": command}
def cache_picture(self, source, target, options):
self.cache[target] = {"size": os.path.getsize(source), "options": remove_name(options)}
def __del__(self):
self.json.dump(self.cache, open(self.cache_file_path, "w"))

View File

@ -19,7 +19,9 @@ SETTINGS = {
"show_date": True,
"gm": {
"quality": 75,
"auto-orient": True
"auto-orient": True,
"strip": True,
"resize": None
}
}
@ -46,6 +48,24 @@ class Image(object):
def autoorient(self):
return self.options["auto-orient"]
def gm(self, source, target, options):
if CACHE.needs_to_be_generated(source, target, options):
gm_switches = {
"source": source,
"target": target,
"auto-orient" : "-auto-orient" if options["auto-orient"] else "",
"strip": "-strip" if options["strip"] else "",
"quality": "-quality %s" % options["quality"] if options.has_key("quality") else "-define jpeg:preserve-settings",
"resize": "-resize %s" % options["resize"] if options.has_key("resize") else ""
}
command = "gm convert {source} {auto-orient} {strip} {quality} {resize} {target}".format(**gm_switches)
print command
os.system(command)
CACHE.cache_picture(source, target, options)
else:
print "skipped %s since it's already generated (based on source unchanged size and images options set in your gallery's settings.yaml)" % target
def copy(self):
source, target = os.path.join(self.base_dir, self.name), os.path.join(self.target_dir, self.name)
@ -53,40 +73,26 @@ class Image(object):
# if os.path.exists(target) and os.path.getsize(source) == os.path.getsize(target):
# print "Skipped %s since the file hasn't been modified based on file size" % source
# return ""
if not self.autoorient:
options = self.options.copy()
if not options["auto-orient"] and not options["strip"]:
shutil.copyfile(source, target)
print source, "->", target
return ""
command = "gm convert %s -strip -auto-orient %s" % (source, target)
if CACHE.image_needs_to_be_oritend(source, target, command):
print command
os.system(command)
CACHE.cache_auto_oriented_image(source, target, command)
else:
print "skipped %s since it's already generated (based on source unchanged size and images options)" % target
# Do not consider quality settings here, since we aim to copy the input image
# better to preserve input encoding setting
del options["quality"]
self.gm(source, target, options)
return ""
def generate_thumbnail(self, gm_geometry):
thumbnail_name = self.name.split(".")
thumbnail_name[-2] += "-%s" % gm_geometry
thumbnail_name = ".".join(thumbnail_name)
source, target = os.path.join(self.base_dir, self.name), os.path.join(self.target_dir, thumbnail_name)
if CACHE.thumbnail_needs_to_be_generated(source, target, self):
gm_options = ""
if self.autoorient:
gm_options = "-auto-orient"
command = "gm convert %s -strip %s -resize %s -quality %s %s" % (source, gm_options, gm_geometry, self.quality, target)
print command
os.system(command)
CACHE.cache_thumbnail(source, target, self)
else:
print "skipped %s since it's already generated (based on source unchanged size and images options set in your gallery's settings.yaml)" % target
options = self.options.copy()
options.update({"resize": gm_geometry})
self.gm(source, target, options)
return thumbnail_name
def __repr__(self):