def mk_caption(config, pkgid, build=True): """ Create JPEG from gallery TIFF with photoid added as caption. """ work_dir = get_work_dir(config, build) package = Package(config, pkgid, build) pkg_dir = os.path.join(work_dir, pkgid) gallery_tiff_directory = config.get('album', 'gallery_tiff_directory') gallery_caption_directory = config.get('album', 'gallery_caption_directory') source_dir = os.path.join(pkg_dir, gallery_tiff_directory) target_dir = os.path.join(pkg_dir, gallery_caption_directory) if not os.path.exists(pkg_dir): logger.error("Invalid package directory: {}".format(pkg_dir)) sys.exit(1) pathlib.Path(target_dir).mkdir(parents=True, exist_ok=True) for photoid in package.keys(): source = os.path.join(source_dir, '{}.tif'.format(photoid)) target = os.path.join(target_dir, '{}.jpg'.format(photoid)) logger.info("Processing {}".format(source)) logger.debug("Target is {}".format(target)) caption = GalleryImage(config, source, target) caption.captioned_jpeg(photoid)
def mk_gallery_jpeg(config, pkgid, build=True): """ Convert cropped TIFF images to JPEG with gallery size. """ work_dir = get_work_dir(config, build) package = Package(config, pkgid, build) pkg_dir = os.path.join(work_dir, pkgid) gallery_tiff_dir = config.get('album', 'gallery_tiff_directory') gallery_jpeg_dir = config.get('album', 'gallery_jpeg_directory') gallery_thumb_dir = config.get('album', 'gallery_thumb_directory') gallery_tiff_path = os.path.join(pkg_dir, gallery_tiff_dir) gallery_jpeg_path = os.path.join(pkg_dir, gallery_jpeg_dir) gallery_thumb_path = os.path.join(pkg_dir, gallery_thumb_dir) if not os.path.exists(pkg_dir): logger.error("Invalid package directory: {}".format(pkg_dir)) sys.exit(1) # Create both directories as needed. pathlib.Path(gallery_jpeg_path).mkdir(parents=True, exist_ok=True) pathlib.Path(gallery_thumb_path).mkdir(parents=True, exist_ok=True) for photoid in package.keys(): source_photo = os.path.join(gallery_tiff_path, '{}.tif'.format(photoid)) gallery_jpeg_photo = os.path.join(gallery_jpeg_path, '{}.jpg'.format(photoid)) gallery_thumb_photo = os.path.join(gallery_thumb_path, '{}.jpg'.format(photoid)) im = Image.open(source_photo) gallery_thumb_height = int(config.get('album', 'gallery_thumb_height')) thumb_scale_factor = compute_scale_factor(gallery_thumb_height, im.size) # Normalize the TIFF image if necessary. norm_img = GalleryImage(config, source_photo, source_photo) norm_img.normalize_tiff() jpeg_cmd = [ 'convert', '{source}'.format(source=source_photo), '{target}'.format(target=gallery_jpeg_photo) ] thumb_cmd = [ 'convert', '-resize', '{scale}%'.format(scale=thumb_scale_factor), '{source}'.format(source=source_photo), '{target}'.format(target=gallery_thumb_photo) ] logger.debug("{}".format(jpeg_cmd)) logger.info("Creating gallery JPEG {}.jpg".format(photoid)) # XXX: Intentionally not handling exception if subprocess fails. run = subprocess.run(jpeg_cmd, stdout=subprocess.PIPE, check=True) logger.debug("{}".format(thumb_cmd)) logger.info( "Creating gallery thumbnail JPEG {}.jpg with scaling {:3.2f}%". format(photoid, thumb_scale_factor)) # XXX: Intentionally not handling exception if subprocess fails. run = subprocess.run(thumb_cmd, stdout=subprocess.PIPE, check=True)
def mk_db_template(config, pkgid, build=True): """ Build a package database template. Update existing if it already exists. Warning: The update mechanism is a one-shot update. It will do nothing if the SQL is already current. """ work_dir = get_work_dir(config, build) db_dir = config.get('album', 'database_directory') tiff_src_dir = config.get('album', 'tiff_source_directory') gallery_tiff_dir = config.get('album', 'gallery_tiff_directory') package = Package(config, pkgid, build) mapfile = os.path.join(work_dir, pkgid, tiff_src_dir, 'rename_map.txt') map = read_alt_file_map(mapfile) newpkg = collections.OrderedDict() for photoid in sorted(package.keys()): newpkg[map.get(photoid, photoid)] = {} for photoid in sorted(newpkg.keys()): photo = os.path.join(work_dir, pkgid, gallery_tiff_dir, '{}.tif'.format(photoid)) logger.debug("Identifying photograph {}".format(photo)) if os.path.isfile(photo): run = subprocess.run(['identify', photo], stdout=subprocess.PIPE, check=True) match = re.search(r'\d+x\d+\+\d+\+\d+', run.stdout.decode("utf-8")) if match: crop = match.group() logger.debug("Found crop marks: {}".format(crop)) newpkg[photoid]['crop'] = crop env = Environment(loader=PackageLoader("photo_album", package_path="templates"), autoescape=select_autoescape(['sql'])) template_vars = { "pkgid": pkgid, "photographs": newpkg, "package": newpkg, } sql_template = env.get_template('PKG-template.sql') dbfile = os.path.join(db_dir, 'PKG-{}.sql'.format(pkgid)) if os.path.isfile(dbfile): logger.warn("PKG-{}.sql exists. Performing update.".format(pkgid)) update(pkgid, newpkg, dbfile) else: logger.info("Writing package {}.sql".format(pkgid)) with open(dbfile, 'w') as f: f.write(sql_template.render(template_vars))
def mk_package_contents(config): packages = Album(config, False) build_dir = config.get('album', 'build_directory') album_dir = config.get('album', 'album_directory') template_dir = "{}/templates".format(build_dir) for pkgid in packages.keys(): package = Package(config, pkgid, build=False) env = Environment(loader=PackageLoader("photo_album", package_path="templates"), autoescape=select_autoescape(['html'])) template_vars = { "pkgid": pkgid, "photographs": package, "package": packages[pkgid], } detail_template = env.get_template('detail.html') gallery_template = env.get_template('gallery.html') logger.info("Writing package {}/detail.html".format(pkgid)) with open(os.path.join(album_dir, pkgid, 'detail.html'), 'w') as f: f.write(detail_template.render(template_vars)) logger.info("Writing package {}/gallery.html".format(pkgid)) with open(os.path.join(album_dir, pkgid, 'gallery.html'), 'w') as f: f.write(gallery_template.render(template_vars))
def mk_gallery_tiff(config, pkgid, build=True): """ Convert TIFF images to gallery size. """ work_dir = get_work_dir(config, build) package = Package(config, pkgid, build) pkg_dir = os.path.join(work_dir, pkgid) tiff_source_dir = config.get('album', 'tiff_source_directory') gallery_tiff_dir = config.get('album', 'gallery_tiff_directory') source_dir = os.path.join(pkg_dir, tiff_source_dir) gallery_dir = os.path.join(pkg_dir, gallery_tiff_dir) if not os.path.exists(pkg_dir): logger.error("Invalid package directory: {}".format(pkg_dir)) sys.exit(1) pathlib.Path(gallery_dir).mkdir(parents=True, exist_ok=True) for photoid in package.keys(): source_photo = os.path.join(source_dir, '{}.tif'.format(photoid)) target_photo = os.path.join(gallery_dir, '{}.tif'.format(photoid)) # Necessary for large format photographs. Image.MAX_IMAGE_PIXELS = int(1024 * 1024 * 1024) im = Image.open(source_photo) crop = get_crop(package, photoid) scale_factor = None if crop: # Crop marks recorded from previous processing. logger.debug( "Crop marks already recorded. Checking for proper scaling.") gallery_height = int(config.get('album', 'gallery_height')) gallery_width = gallery_height # Yes, we are committing to square. if crop[0] != gallery_height: logger.warn("Scaling not correct. Rescaling and cropping...") scale_factor = compute_scale_factor( config, (int(crop[0]), int(crop[1], ))) logger.debug( "Computed new scale factor {:3.2f}".format(scale_factor)) new_crop = ( gallery_width, gallery_height, int((crop[2] * scale_factor) / 100), int((crop[3] * scale_factor) / 100), ) new_crop_str = "{}x{}+{}+{}".format(*new_crop) set_crop(package, photoid, new_crop_str) if scale_factor is None: # Crop marks not previously recorded. scale_factor = compute_scale_factor(config, im.size) logger.debug("({}x{}) [{}] {}".format(im.size[0], im.size[1], scale_factor, photoid)) resize_cmd = [ 'convert', '-resize', '{scale}%'.format(scale=scale_factor), '{source}'.format(source=source_photo), '{target}'.format(target=target_photo) ] if os.path.exists(target_photo): logger.info( "Target photograph exists. Skipping: {}".format(target_photo)) else: logger.info( "Creating gallery TIFF {}.tif with scaling {:3.2f}%".format( photoid, scale_factor)) run = subprocess.run(resize_cmd, stdout=subprocess.PIPE, check=True) # Resize complete. Crop if previously recorded. if crop: logger.warn("Scaling as expected. Cropping...") crop_str = "{}x{}+{}+{}".format(*crop) crop_cmd = [ 'convert', '-crop', '{}'.format(crop_str), '{source}'.format(source=target_photo), '{target}'.format(target=target_photo) ] logger.debug(crop_cmd) # XXX: Intentionally not handling exception if subprocess # fails. run = subprocess.run(crop_cmd, stdout=subprocess.PIPE, check=True)