1from __future__ import division
2
3import logging
4
5import pyvips
6from pyvips import ffi, vips_lib, Error, _to_bytes
7
8logger = logging.getLogger(__name__)
9
10
11class Source(pyvips.Connection):
12    """An input connection.
13
14    """
15
16    def __init__(self, pointer):
17        # logger.debug('Operation.__init__: pointer = %s', pointer)
18        super(Source, self).__init__(pointer)
19
20    @staticmethod
21    def new_from_descriptor(descriptor):
22        """Make a new source from a file descriptor (a small integer).
23
24        Make a new source that is attached to the descriptor. For example::
25
26            source = pyvips.Source.new_from_descriptor(0)
27
28        Makes a descriptor attached to stdin.
29
30        You can pass this source to (for example) :meth:`new_from_source`.
31
32        """
33
34        # logger.debug('VipsSource.new_from_descriptor: descriptor = %d',
35        #   descriptor)
36
37        # sources are mutable, so we can't use the cache
38        pointer = vips_lib.vips_source_new_from_descriptor(descriptor)
39        if pointer == ffi.NULL:
40            raise Error("can't create source from descriptor {0}"
41                        .format(descriptor))
42
43        return Source(pointer)
44
45    @staticmethod
46    def new_from_file(filename):
47        """Make a new source from a filename.
48
49        Make a new source that is attached to the named file. For example::
50
51            source = pyvips.Source.new_from_file("myfile.jpg")
52
53        You can pass this source to (for example) :meth:`new_from_source`.
54
55        """
56
57        # logger.debug('VipsSource.new_from_file: filename = %s',
58        #              filename)
59
60        pointer = vips_lib.vips_source_new_from_file(_to_bytes(filename))
61        if pointer == ffi.NULL:
62            raise Error("can't create source from filename {0}"
63                        .format(filename))
64
65        return Source(pointer)
66
67    @staticmethod
68    def new_from_memory(data):
69        """Make a new source from a memory object.
70
71        Make a new source that is attached to the memory object. For example::
72
73            source = pyvips.Source.new_from_memory("myfile.jpg")
74
75        You can pass this source to (for example) :meth:`new_from_source`.
76
77        The memory object can be anything that supports the Python buffer or
78        memoryview protocol.
79
80        """
81
82        # logger.debug('VipsSource.new_from_memory:')
83
84        # py3:
85        #   - memoryview has .nbytes for number of bytes in object
86        #   - len() returns number of elements in top array
87        # py2:
88        #   - buffer has no nbytes member
89        #   - but len() gives number of bytes in object
90        start = ffi.from_buffer(data)
91        nbytes = data.nbytes if hasattr(data, 'nbytes') else len(data)
92
93        pointer = vips_lib.vips_source_new_from_memory(start, nbytes)
94        if pointer == ffi.NULL:
95            raise Error("can't create input source from memory")
96
97        source = Source(pointer)
98
99        # keep a secret reference to the input data to make sure it's not GCed
100        source._references = [data]
101
102        return source
103
104
105__all__ = ['Source']
106