mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-30 19:00:09 +00:00
almost done with gen3 implementation of buildcache (buildcache2.py)...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
a10097daa1
commit
c8cd7d1bf0
217
buildcache2.py
217
buildcache2.py
@ -1,7 +1,7 @@
|
|||||||
#=======================================================================
|
#=======================================================================
|
||||||
|
|
||||||
__version__ = '''0.0.01'''
|
__version__ = '''0.0.01'''
|
||||||
__sub_version__ = '''20130521232425'''
|
__sub_version__ = '''20130522014220'''
|
||||||
__copyright__ = '''(c) Alex A. Naanou 2011'''
|
__copyright__ = '''(c) Alex A. Naanou 2011'''
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ import gid
|
|||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
|
||||||
config = {
|
CONFIG = {
|
||||||
'absolute-path': False,
|
'absolute-path': False,
|
||||||
|
|
||||||
'cache-image-name': '%(guid)s - %(name)s',
|
'cache-image-name': '%(guid)s - %(name)s',
|
||||||
@ -49,12 +49,12 @@ config = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
DATA = {
|
||||||
'version': '2.0',
|
'version': '2.0',
|
||||||
'current': None,
|
'current': None,
|
||||||
'ribbons': [],
|
'ribbons': (),
|
||||||
'order': [],
|
'order': (),
|
||||||
'image_file': 'images.json',
|
'image_file': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
IMAGE_EXT = OR(*(
|
IMAGE_EXT = OR(*(
|
||||||
@ -71,17 +71,30 @@ TARGET: %(target-file)s
|
|||||||
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
# Helpers...
|
||||||
|
|
||||||
|
#------------------------------------------------------------pathjoin---
|
||||||
def pathjoin(*p):
|
def pathjoin(*p):
|
||||||
'''
|
'''
|
||||||
'''
|
'''
|
||||||
return ('/'.join(p)).replace('//', '/')
|
return ('/'.join(p)).replace('//', '/')
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------getpath---
|
||||||
|
def getpath(root, path, absolute=False):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
if absolute == True:
|
||||||
|
return 'file:///' + urllib2.quote(pathjoin(root, path), safe='/:')
|
||||||
|
else:
|
||||||
|
return urllib2.quote(path, safe='/')
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------log_err---
|
||||||
def log_err(path, e, source_file, target_file):
|
def log_err(path, e, source_file, target_file):
|
||||||
'''
|
'''
|
||||||
'''
|
'''
|
||||||
err_file = pathjoin(path, config['error'])
|
err_file = pathjoin(path, CONFIG['error'])
|
||||||
if not os.path.exists(err_file):
|
if not os.path.exists(err_file):
|
||||||
err = open(err_file, 'w')
|
err = open(err_file, 'w')
|
||||||
else:
|
else:
|
||||||
@ -94,6 +107,7 @@ def log_err(path, e, source_file, target_file):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------hash_gid---
|
||||||
def hash_gid(img, force=False):
|
def hash_gid(img, force=False):
|
||||||
'''
|
'''
|
||||||
Generate gid based on preview file content.
|
Generate gid based on preview file content.
|
||||||
@ -105,7 +119,58 @@ def hash_gid(img, force=False):
|
|||||||
return sha.sha(img.tostring()).hexdigest()
|
return sha.sha(img.tostring()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def build_cache_dirs(path, config=config):
|
#-----------------------------------------------------report_progress---
|
||||||
|
def report_progress(img, status):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
# created all previews...
|
||||||
|
if False not in status:
|
||||||
|
print '.',
|
||||||
|
# created no previews...
|
||||||
|
elif True not in status:
|
||||||
|
print '-',
|
||||||
|
# created some previews...
|
||||||
|
else:
|
||||||
|
print 'p',
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------make_inline_report_progress---
|
||||||
|
def make_inline_report_progress(state=None):
|
||||||
|
if state == None:
|
||||||
|
state = {}
|
||||||
|
def _inline_report_progress(img, status):
|
||||||
|
created = state.get('created', 0)
|
||||||
|
skipped = state.get('skipped', 0)
|
||||||
|
partial = state.get('partial', 0)
|
||||||
|
|
||||||
|
# created all previews...
|
||||||
|
if False not in status:
|
||||||
|
created += 1
|
||||||
|
state['created'] = created
|
||||||
|
|
||||||
|
# created no previews...
|
||||||
|
elif True not in status:
|
||||||
|
skipped += 1
|
||||||
|
state['skipped'] = skipped
|
||||||
|
|
||||||
|
# created some previews...
|
||||||
|
else:
|
||||||
|
partial += 1
|
||||||
|
state['partial'] = partial
|
||||||
|
|
||||||
|
print 'Previews created: %s partial: %s skipped: %s...\r' % (created, partial, skipped),
|
||||||
|
|
||||||
|
return img
|
||||||
|
return _inline_report_progress
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# API...
|
||||||
|
|
||||||
|
#----------------------------------------------------build_cache_dirs---
|
||||||
|
def build_cache_dirs(path, config=CONFIG):
|
||||||
'''
|
'''
|
||||||
Build cache directory tree.
|
Build cache directory tree.
|
||||||
'''
|
'''
|
||||||
@ -116,14 +181,15 @@ def build_cache_dirs(path, config=config):
|
|||||||
os.makedirs(p)
|
os.makedirs(p)
|
||||||
|
|
||||||
|
|
||||||
def build_images(path, config=config, gid_generator=hash_gid):
|
#--------------------------------------------------------build_images---
|
||||||
|
def build_images(path, config=CONFIG, gid_generator=hash_gid):
|
||||||
'''
|
'''
|
||||||
Build image structures update images.json in cache.
|
Build image structures update images.json in cache.
|
||||||
'''
|
'''
|
||||||
absolute_path = config['absolute-path']
|
absolute_path = config['absolute-path']
|
||||||
|
|
||||||
for name in os.listdir(path):
|
for name in os.listdir(path):
|
||||||
iid, ext = os.path.splitext(name)
|
fname, ext = os.path.splitext(name)
|
||||||
|
|
||||||
if ext != IMAGE_EXT:
|
if ext != IMAGE_EXT:
|
||||||
continue
|
continue
|
||||||
@ -132,28 +198,146 @@ def build_images(path, config=config, gid_generator=hash_gid):
|
|||||||
|
|
||||||
img = {
|
img = {
|
||||||
'id': gid_generator(source_path),
|
'id': gid_generator(source_path),
|
||||||
|
'name': name,
|
||||||
'type': 'image',
|
'type': 'image',
|
||||||
'state': 'single',
|
'state': 'single',
|
||||||
'path': None,
|
'path': getpath(path, name, absolute_path),
|
||||||
'ctime': os.path.getctime(source_path),
|
'ctime': os.path.getctime(source_path),
|
||||||
'preview': {},
|
'preview': {},
|
||||||
}
|
}
|
||||||
if absolute_path == True:
|
|
||||||
img['path'] = 'file:///' + urllib2.quote(pathjoin(path, name), safe='/:')
|
|
||||||
else:
|
|
||||||
img['path'] = urllib2.quote(name)
|
|
||||||
|
|
||||||
yield img
|
yield img
|
||||||
|
|
||||||
|
|
||||||
def build_previews(image):
|
#------------------------------------------------------build_previews---
|
||||||
|
# NOTE: this will create images in the file system.
|
||||||
|
def build_previews(image, path=None, config=CONFIG, dry_run=True):
|
||||||
|
'''
|
||||||
|
|
||||||
|
NOTE: this needs the cache directory structure present.
|
||||||
|
'''
|
||||||
|
status = []
|
||||||
|
# config...
|
||||||
|
absolute_path = config['absolute-path']
|
||||||
|
dirs = config['cache-structure']
|
||||||
|
sizes = config['sizes']
|
||||||
|
cache_name = config['cache-image-name']
|
||||||
|
|
||||||
|
# data...
|
||||||
|
gid = image['id']
|
||||||
|
img_name = image['name']
|
||||||
|
name = os.path.splitext(img_name)[0]
|
||||||
|
img_path = image['path']
|
||||||
|
|
||||||
|
if absolute_path == False:
|
||||||
|
source_path = os.path.join(path, img_path)
|
||||||
|
else:
|
||||||
|
# XXX is this the best way???
|
||||||
|
o = urllib2.urlopen(img_path)
|
||||||
|
source_path = o.fp.name
|
||||||
|
o.close()
|
||||||
|
|
||||||
|
img = Image.open(source_path, 'r')
|
||||||
|
|
||||||
|
# biggest preview is the original image...
|
||||||
|
image['preview'][str(max(*img.size)) + 'px'] = img_path
|
||||||
|
|
||||||
|
# previews...
|
||||||
|
for k, spec in sizes.items():
|
||||||
|
|
||||||
|
if k in image['preview'].keys():
|
||||||
|
continue
|
||||||
|
|
||||||
|
# build the two paths: relative and full...
|
||||||
|
n = pathjoin(dirs[k], cache_name % {'guid': gid, 'name': img_name})
|
||||||
|
p = pathjoin(path, n)
|
||||||
|
|
||||||
|
# do not upscale images...
|
||||||
|
if max(*img.size) <= spec:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# add image to index...
|
||||||
|
if not os.path.exists(p):
|
||||||
|
scale = spec/float(max(*img.size))
|
||||||
|
preview = img.resize((int(img.size[0]*scale), int(img.size[1]*scale)), Image.ANTIALIAS)
|
||||||
|
|
||||||
|
if not dry_run:
|
||||||
|
preview.save(p)
|
||||||
|
else:
|
||||||
|
preview.close()
|
||||||
|
|
||||||
|
##!!! metadata???
|
||||||
|
|
||||||
|
status += [True]
|
||||||
|
|
||||||
|
# image exists...
|
||||||
|
else:
|
||||||
|
status += [False]
|
||||||
|
|
||||||
|
image['preview'][str(spec) + 'px'] = getpath(path, n, absolute_path)
|
||||||
|
|
||||||
|
return image, status
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------build_data---
|
||||||
|
def build_data(images, path, config=CONFIG):
|
||||||
'''
|
'''
|
||||||
'''
|
'''
|
||||||
|
images_index = {}
|
||||||
|
marked = []
|
||||||
|
data = DATA.copy()
|
||||||
|
ribbon = []
|
||||||
|
|
||||||
|
for image in images:
|
||||||
|
gid = image['id']
|
||||||
|
|
||||||
|
images_index[gid] = image
|
||||||
|
ribbon += [gid]
|
||||||
|
|
||||||
|
ribbon.sort(lambda a, b: cmp(images_index[b]['ctime'], images_index[a]['ctime']))
|
||||||
|
|
||||||
|
data['ribbons'] = [ribbon]
|
||||||
|
data['order'] = ribbon[:]
|
||||||
|
data['current'] = ribbon[0]
|
||||||
|
|
||||||
|
return data, images_index, marked
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
|
# High-level API...
|
||||||
|
|
||||||
|
#---------------------------------------------------------build_cache---
|
||||||
|
##!!! DO NOT OVERWRITE EXISTING DATA...
|
||||||
|
def build_cache(path, config=CONFIG, gid_generator=hash_gid,
|
||||||
|
report_progress=report_progress, dry_run=False):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
absolute_path = config['absolute-path']
|
||||||
|
|
||||||
|
build_cache_dirs(path, config)
|
||||||
|
|
||||||
|
data, images, marked = build_data(
|
||||||
|
(report_progress(*build_previews(img, path, config, dry_run=dry_run))
|
||||||
|
for img in build_images(path, config, gid_generator)),
|
||||||
|
path, config)
|
||||||
|
|
||||||
|
images_file = config['images']
|
||||||
|
data_file = config['data']
|
||||||
|
marked_file = config['marked']
|
||||||
|
|
||||||
|
data['image_file'] = getpath(path, images_file, absolute_path)
|
||||||
|
|
||||||
|
if not dry_run:
|
||||||
|
##!!! DO NOT OVERWRITE EXISTING DATA...
|
||||||
|
with open(os.path.join(path, images_file), 'w') as f:
|
||||||
|
json.dump(images, f, indent=4)
|
||||||
|
with open(os.path.join(path, data_file), 'w') as f:
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
with open(os.path.join(path, marked_file), 'w') as f:
|
||||||
|
json.dump(marked, f, indent=4)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -164,5 +348,6 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#=======================================================================
|
#=======================================================================
|
||||||
# vim:set ts=4 sw=4 nowrap :
|
# vim:set ts=4 sw=4 nowrap :
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user