예제 #1
0
def thumbnail(filename, thumb_path, width, height):
    _, tmp_thumb_path = tempfile.mkstemp(prefix="ojo_thumbnail_")

    def use_pil():
        pil = get_pil(filename, width, height)
        try:
            pil.save(tmp_thumb_path, "JPEG")
        except Exception:
            logging.exception("Could not save thumbnail in format %s:" %
                              format)
            raise

    def use_pixbuf():
        pixbuf = get_pixbuf(filename, width, height)
        pixbuf.savev(tmp_thumb_path, "png", [], [])

    cache_dir = os.path.dirname(thumb_path)
    if not os.path.exists(cache_dir):
        os.makedirs(cache_dir)

    if ext(filename) in {".gif", ".png", ".svg", ".xpm"}.union(RAW_FORMATS):
        try:
            use_pixbuf()
        except Exception:
            use_pil()
    else:
        try:
            use_pil()
        except Exception:
            use_pixbuf()

    os.rename(tmp_thumb_path, thumb_path)

    return filename, thumb_path
예제 #2
0
def is_image(filename):
    """Decide if something might be a supported image based on extension"""
    try:
        return os.path.isfile(filename) and ext(
            filename) in get_supported_image_extensions()
    except Exception:
        return False
예제 #3
0
파일: metadata.py 프로젝트: peterlevi/ojo
    def read(self, filename):
        try:
            if imaging.exiftool is None or not imaging.exiftool.running:
                return None

            meta = imaging.exiftool.get_metadata(filename)

            meta["SourceFile"] = {
                "desc": "Source File",
                "val": meta["SourceFile"]
            }

            # also cache the most important part
            needs_rot = needs_rotation(meta)
            stat = os.stat(filename)

            result = {
                "filename":
                os.path.basename(filename),
                "needs_rotation":
                needs_rot,
                "width":
                meta["ImageWidth" if not needs_rot else "ImageHeight"]["val"],
                "height":
                meta["ImageHeight" if not needs_rot else "ImageWidth"]["val"],
                "orientation":
                meta.get("Orientation", {"val": None})["val"],
                "file_date":
                stat.st_mtime,
                "file_size":
                stat.st_size,
                "exif":
                meta,
            }

            if ext(filename) == ".svg":
                # svg sizing is special, exiftool could return things like "270mm" which causes
                # exceptions downstream, as width and height are expected to be numbers.
                # So use size from pixbuf, it works OK for svgs.
                meta_svg = self.read_via_pixbuf(filename)
                result["width"] = meta_svg["width"]
                result["height"] = meta_svg["height"]

            return result

        except Exception:
            logging.exception("Could not parse meta-info for %s" % filename)
            return None
예제 #4
0
    def get_cached_thumbnail_path(filename,
                                  force_cache=False,
                                  thumb_height=None):
        # Use gifs directly - webkit will handle transparency, animation, etc.
        if not force_cache and ext(filename) == ".gif":
            return filename

        if thumb_height is None:
            thumb_height = options["thumb_height"]

        # we append modification time to ensure we're not using outdated cached images
        mtime = os.path.getmtime(filename)
        hash = hashlib.md5(_bytes(filename +
                                  "{0:.2f}".format(mtime))).hexdigest()
        # we use .2 precision to keep the same behavior of getmtime as under Python 2
        folder = os.path.dirname(filename)
        if folder.startswith(os.sep):
            folder = folder[1:]
        return os.path.join(
            Thumbs.get_thumbs_cache_dir(thumb_height),  # cache folder root
            folder,  # mirror the original directory structure
            os.path.basename(filename) + "_" + hash + ".jpg",
        )  # filename + hash of the name & time
예제 #5
0
def get_pixbuf(filename, width=None, height=None):
    meta = metadata.get(filename)
    orientation = meta["orientation"]
    image_width, image_height = meta["width"], meta["height"]

    def _from_preview():
        try:
            with tempfile.TemporaryDirectory(prefix="ojo") as to_folder:
                optimal_preview = get_optimal_preview(filename, to_folder,
                                                      width, height)
                pixbuf = pixbuf_from_file(optimal_preview)
            pixbuf = auto_rotate_pixbuf(orientation, pixbuf)
            logging.debug("Loaded from preview")
            return pixbuf
        except Exception:
            return None  # below we'll use another method

    def _from_gdk_pixbuf():
        try:
            pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
            pixbuf = auto_rotate_pixbuf(orientation, pixbuf)
            logging.debug("Loaded directly")
            return pixbuf
        except GObject.GError:
            return None  # below we'll use another method

    def _from_pil():
        try:
            pixbuf = pil_to_pixbuf(get_pil(filename))
            logging.debug("Loaded with PIL")
            return pixbuf
        except:
            return None

    if ext(filename) in RAW_FORMATS:
        # raw file, prefer preview with max size
        pixbuf = _from_preview()
        if not pixbuf:
            pixbuf = _from_gdk_pixbuf()
    else:
        # ordinary image, prefer loading with GdkPixbuf directly
        # (previews here might be present, but wrong)
        pixbuf = _from_gdk_pixbuf()
        if not pixbuf:
            pixbuf = _from_preview()

    if not pixbuf:
        pixbuf = _from_pil()

    if not pixbuf:
        raise Exception("Could not load %s" % filename)

    if width is not None and (width < image_width or height < image_height):
        # scale it
        if float(width) / height < float(image_width) / image_height:
            pixbuf = pixbuf.scale_simple(
                width, int(float(width) * image_height / image_width),
                GdkPixbuf.InterpType.BILINEAR)
        else:
            pixbuf = pixbuf.scale_simple(
                int(float(height) * image_width / image_height),
                height,
                GdkPixbuf.InterpType.BILINEAR,
            )

    return pixbuf