Ejemplo n.º 1
0
def get_cache_info(path, boundary):
    """For an image at `path` return (cache_path, thumb_size)

    cache_path points to a potential cache file
    thumb size is either 128 or 256
    """

    assert is_fsnative(path)

    width, height = boundary

    if width <= ThumbSize.NORMAL and height <= ThumbSize.NORMAL:
        size_name = "normal"
        thumb_size = ThumbSize.NORMAL
    else:
        size_name = "large"
        thumb_size = ThumbSize.LARGE

    thumb_folder = get_thumbnail_folder()
    cache_dir = os.path.join(thumb_folder, size_name)

    uri = "file://" + pathname2url(path)
    thumb_name = hashlib.md5(uri).hexdigest() + ".png"
    thumb_path = os.path.join(cache_dir, thumb_name)

    return (thumb_path, thumb_size)
Ejemplo n.º 2
0
    def test_thumb(s):
        thumb = thumbnails.get_thumbnail(s.filename, (50, 60))

        #check for right scaling
        s.failUnless(thumb)
        s.failUnlessEqual((thumb.get_width(), thumb.get_height()), (50, 3))

        #test the thumbnail filename
        uri = "file://" + pathname2url(s.filename)
        name = hash.md5(uri).hexdigest() + ".png"

        path = thumbnails.get_thumbnail_folder()
        path = os.path.join(path, "normal", name)

        s.failUnless(os.path.isfile(path))

        #check for metadata
        thumb_pb = GdkPixbuf.Pixbuf.new_from_file(path)
        meta_mtime = thumb_pb.get_option("tEXt::Thumb::MTime")
        meta_uri = thumb_pb.get_option("tEXt::Thumb::URI")

        s.failUnlessEqual(int(meta_mtime), int(mtime(s.filename)))
        s.failUnlessEqual(meta_uri, uri)

        #check rights
        if os.name != "nt":
            s.failUnlessEqual(os.stat(path).st_mode, 33152)
Ejemplo n.º 3
0
    def test_thumb(s):
        thumb = thumbnails.get_thumbnail(s.filename, (50, 60))

        #check for right scaling
        s.failUnless(thumb)
        s.failUnlessEqual((thumb.get_width(), thumb.get_height()), (50, 3))

        #test the thumbnail filename
        uri = "file://" + pathname2url(s.filename)
        name = hash.md5(uri).hexdigest() + ".png"

        path = thumbnails.get_thumbnail_folder()
        path = os.path.join(path, "normal", name)

        s.failUnless(os.path.isfile(path))

        #check for metadata
        thumb_pb = GdkPixbuf.Pixbuf.new_from_file(path)
        meta_mtime = thumb_pb.get_option("tEXt::Thumb::MTime")
        meta_uri = thumb_pb.get_option("tEXt::Thumb::URI")

        s.failUnlessEqual(int(meta_mtime), int(mtime(s.filename)))
        s.failUnlessEqual(meta_uri, uri)

        #check rights
        if os.name != "nt":
            s.failUnlessEqual(os.stat(path).st_mode, 33152)
Ejemplo n.º 4
0
def get_thumbnail(path, boundary):
    """Get a thumbnail pixbuf of an image at `path`.

    Will create/use a thumbnail in the user's thumbnail directory if possible.
    Follows the Free Desktop specification:

    http://specifications.freedesktop.org/thumbnail-spec/

    Can raise GLib.GError. Thread-safe.
    """

    width, height = boundary
    new_from_file_at_size = GdkPixbuf.Pixbuf.new_from_file_at_size

    # larger than thumbnails, load directly
    if width > ThumbSize.LARGEST or height > ThumbSize.LARGEST:
        return new_from_file_at_size(path, width, height)

    path_mtime = mtime(path)
    if path_mtime == 0:
        return new_from_file_at_size(path, width, height)

    # embedded thumbnails come from /tmp/
    # FIXME: move this to another layer
    if path.startswith(tempfile.gettempdir()):
        return new_from_file_at_size(path, width, height)

    thumb_path, thumb_size = get_cache_info(path, boundary)
    cache_dir = os.path.dirname(thumb_path)
    try:
        mkdir(cache_dir, 0o700)
    except OSError:
        return new_from_file_at_size(path, width, height)

    try:
        pb = new_from_file_at_size(thumb_path, width, height)
    except GLib.GError:
        # in case it fails to load, we recreate it
        pass
    else:
        meta_mtime = pb.get_option("tEXt::Thumb::MTime")
        if meta_mtime is not None:
            try:
                meta_mtime = int(meta_mtime)
            except ValueError:
                pass
            else:
                if meta_mtime == int(path_mtime):
                    return pb

    info, pw, ph = GdkPixbuf.Pixbuf.get_file_info(path)

    # Too small picture, no thumbnail needed
    if pw < thumb_size and ph < thumb_size:
        return new_from_file_at_size(path, width, height)

    thumb_pb = new_from_file_at_size(path, thumb_size, thumb_size)

    uri = "file://" + pathname2url(path)
    mime = info.get_mime_types()[0]
    options = {
        "tEXt::Thumb::Image::Width": str(pw),
        "tEXt::Thumb::Image::Height": str(ph),
        "tEXt::Thumb::URI": uri,
        "tEXt::Thumb::MTime": str(int(path_mtime)),
        "tEXt::Thumb::Size": str(os.path.getsize(path)),
        "tEXt::Thumb::Mimetype": mime,
        "tEXt::Software": "QuodLibet"
    }

    thumb_pb.savev(thumb_path, "png", options.keys(), options.values())
    try:
        os.chmod(thumb_path, 0o600)
    except OSError:
        pass

    return scale(thumb_pb, boundary)
Ejemplo n.º 5
0
    def frompath(klass, value):
        """Construct a URI from an unescaped filename."""

        return klass("file://" + pathname2url(value), escaped=True)
Ejemplo n.º 6
0
def get_thumbnail(path, boundary):
    """Get a thumbnail pixbuf of an image at `path`.

    Will create/use a thumbnail in the user's thumbnail directory if possible.
    Follows the Free Desktop specification:

    http://specifications.freedesktop.org/thumbnail-spec/

    Can raise GLib.GError.
    """

    width, height = boundary

    # embedded thumbnails come from /tmp/
    # and too big thumbnails make no sense
    if path.startswith(tempfile.gettempdir()) or \
            width > 256 or height > 256 or mtime(path) == 0:
        return GdkPixbuf.Pixbuf.new_from_file_at_size(path, width, height)

    if width <= 128 and height <= 128:
        size_name = "normal"
        thumb_size = 128
    else:
        size_name = "large"
        thumb_size = 256

    thumb_folder = get_thumbnail_folder()
    cache_dir = os.path.join(thumb_folder, size_name)
    try:
        mkdir(cache_dir, 0700)
    except OSError:
        return GdkPixbuf.Pixbuf.new_from_file_at_size(path, width, height)

    bytes_ = path
    if isinstance(path, unicode):
        bytes_ = path.encode("utf-8")
    uri = "file://" + pathname2url(bytes_)
    thumb_name = hashlib.md5(uri).hexdigest() + ".png"

    thumb_path = os.path.join(cache_dir, thumb_name)

    pb = meta_mtime = None
    if os.path.exists(thumb_path):
        pb = GdkPixbuf.Pixbuf.new_from_file(thumb_path)
        meta_mtime = pb.get_option("tEXt::Thumb::MTime")
        meta_mtime = meta_mtime and int(meta_mtime)

    if not pb or meta_mtime != int(mtime(path)):
        pb = GdkPixbuf.Pixbuf.new_from_file(path)

        #Too small picture, no thumbnail needed
        if pb.get_width() < thumb_size and pb.get_height() < thumb_size:
            return scale(pb, boundary)

        info = GdkPixbuf.Pixbuf.get_file_info(path)[0]
        mime = info.get_mime_types()[0]
        options = {
            "tEXt::Thumb::Image::Width": str(pb.get_width()),
            "tEXt::Thumb::Image::Height": str(pb.get_height()),
            "tEXt::Thumb::URI": uri,
            "tEXt::Thumb::MTime": str(int(mtime(path))),
            "tEXt::Thumb::Size": str(os.path.getsize(fsnative(path))),
            "tEXt::Thumb::Mimetype": mime,
            "tEXt::Software": "QuodLibet"
        }

        pb = scale(pb, (thumb_size, thumb_size))
        pb.savev(thumb_path, "png", options.keys(), options.values())
        try:
            os.chmod(thumb_path, 0600)
        except OSError:
            pass

    return scale(pb, boundary)
Ejemplo n.º 7
0
    def frompath(klass, value):
        """Construct a URI from an unescaped filename."""

        return klass("file://" + pathname2url(value), escaped=True)