예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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))
예제 #4
0
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))
예제 #5
0
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)