예제 #1
0
def generate_enums_flags(file):
    all_enums = []
    all_flags = []

    def add_enum(gtype, a, b):
        nickname = type_name(gtype)
        all_enums.append(nickname)

        type_map(gtype, add_enum)

        return ffi.NULL

    # Enums
    type_map(type_from_name('GEnum'), add_enum)

    # Flags
    all_flags.append('VipsForeignPngFilter')

    print(f'Generating {file}...')

    with open(file, 'w') as f:
        f.write('    // Auto-generated enums\n')

        for name in all_enums:
            gtype = type_from_name(name)

            f.write(f'    enum_<{name}>("{remove_prefix(name)}")')

            for value in values_for_enum(gtype):
                js_value = cppize(value)
                prefix = to_snake_case(name).upper()
                if prefix == 'VIPS_BAND_FORMAT':
                    prefix = 'VIPS_FORMAT'
                elif prefix == 'VIPS_IMAGE_TYPE':
                    prefix = 'VIPS_IMAGE'
                cpp_value = prefix + '_' + js_value.upper()
                if cpp_value == 'VIPS_INTERPRETATION_SRGB':
                    cpp_value = 'VIPS_INTERPRETATION_sRGB'
                elif cpp_value == 'VIPS_INTERPRETATION_SCRGB':
                    cpp_value = 'VIPS_INTERPRETATION_scRGB'

                f.write(f'\n        .value("{js_value}", {cpp_value})')

            f.write(';\n\n')

        for name in all_flags:
            gtype = type_from_name(name)

            f.write(f'    enum_<{name}>("{remove_prefix(name)}")')

            for value in values_for_flag(gtype):
                js_value = cppize(value)
                prefix = to_snake_case(name).upper()
                cpp_value = prefix + '_' + js_value.upper()

                f.write(f'\n        .value("{js_value}", {cpp_value})')

            f.write(';\n\n')
예제 #2
0
파일: gen-enums.py 프로젝트: manthey/pyvips
def generate_enums():
    # otherwise we're missing some enums
    vips_lib.vips_token_get_type()
    vips_lib.vips_saveable_get_type()
    vips_lib.vips_image_type_get_type()

    all_enums = []

    def add_enum(gtype, a, b):
        nickname = type_name(gtype)
        all_enums.append(nickname)

        type_map(gtype, add_enum)

        return ffi.NULL

    type_map(type_from_name('GEnum'), add_enum)

    for name in all_enums:
        gtype = type_from_name(name)
        python_name = remove_prefix(name)
        if python_name not in xml_enums:
            continue

        node = xml_enums[python_name]
        enum_doc = node.find("goi:doc", namespace)

        print(f'')
        print(f'')
        print(f'class {python_name}(object):')
        print(f'    """{python_name}.')
        if enum_doc is not None:
            print(f'')
            print(f'{enum_doc.text}')
        print(f'')
        print(f'Attributes:')
        print(f'')
        for value in values_for_enum(gtype):
            python_name = value.replace('-', '_')
            member = node.find(f"goi:member[@name='{python_name}']", namespace)
            member_doc = member.find("goi:doc", namespace)
            if member_doc is not None:
                text = member_doc.text
                print(f'    {python_name.upper()} (str): {text}')
                print(f'')
        print(f'    """')
        print(f'')

        for value in values_for_enum(gtype):
            python_name = value.replace('-', '_').upper()
            print(f'    {python_name} = \'{value}\'')
예제 #3
0
def generate_operators(declarations_only=False):
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            op = Operation.new_from_name(nickname)

            # we are only interested in non-deprecated operations
            if (op.get_flags() & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # add 'missing' synonyms by hand
    all_nicknames.append('crop')

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort()

    for nickname in all_nicknames:
        print(generate_operation(nickname, declarations_only))
예제 #4
0
def generate_operators(declarations_only=False):
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            intro = Introspect.get(nickname)

            # we are only interested in non-deprecated operations
            if (intro.flags & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # add 'missing' synonyms by hand
    all_nicknames.append('crop')

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort()

    for nickname in all_nicknames:
        print(generate_operation(nickname, declarations_only))
예제 #5
0
def gen_function_list():
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            op = Operation.new_from_name(nickname)

            # we are only interested in non-deprecated operations
            if (op.get_flags() & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # add 'missing' synonyms by hand
    all_nicknames.append('crop')

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort()

    for nickname in all_nicknames:
        gen_function(nickname)
예제 #6
0
def generate_enums():
    # otherwise we're missing some enums
    vips_lib.vips_token_get_type()
    vips_lib.vips_saveable_get_type()
    vips_lib.vips_image_type_get_type()

    all_enums = []

    def add_enum(gtype, a, b):
        nickname = type_name(gtype)
        all_enums.append(nickname)

        type_map(gtype, add_enum)

        return ffi.NULL

    type_map(type_from_name('GEnum'), add_enum)

    for name in all_enums:
        gtype = type_from_name(name)
        php_name = remove_prefix(name)

        print('Generating {0}.php ...'.format(php_name))

        with open('{0}.php'.format(php_name), 'w') as f:
            f.write(preamble)
            f.write('\n')
            f.write('namespace Jcupitt\\Vips;\n')
            f.write('\n')
            f.write('/**\n')
            f.write(' * The {0} enum.\n'.format(php_name))
            f.write(class_header)
            f.write(' */\n')
            f.write('abstract class {0}\n'.format(php_name))
            f.write('{\n')

            for value in values_for_enum(gtype):
                php_name = value.replace('-', '_').upper()
                if php_name in reserved_php_names:
                    php_name = reserved_php_names[php_name]
                f.write('    const {0} = \'{1}\';\n'.format(php_name, value))

            f.write('}\n')
예제 #7
0
    def generate_sphinx_all():
        """Generate sphinx documentation.

        This generates a .rst file for all auto-generated image methods. Use it
        to regenerate the docs with something like::

            $ python -c \
"import pyvips; pyvips.Operation.generate_sphinx_all()" > x

        And copy-paste the file contents into doc/vimage.rst in the appropriate
        place.

        """

        # generate list of all nicknames we can generate docstrings for

        all_nicknames = []

        def add_nickname(gtype, a, b):
            nickname = nickname_find(gtype)
            try:
                Operation.generate_sphinx(nickname)
                all_nicknames.append(nickname)
            except Error:
                pass

            type_map(gtype, add_nickname)

            return ffi.NULL

        type_map(type_from_name('VipsOperation'), add_nickname)

        all_nicknames.sort()

        # remove operations we have to wrap by hand

        exclude = ['scale', 'ifthenelse', 'bandjoin', 'bandrank']
        all_nicknames = [x for x in all_nicknames if x not in exclude]

        # Output summary table
        print('.. class:: pyvips.Image\n')
        print('   .. rubric:: Methods\n')
        print('   .. autosummary::')
        print('      :nosignatures:\n')
        for nickname in all_nicknames:
            print('      ~{0}'.format(nickname))
        print()

        # Output docs
        print()
        for nickname in all_nicknames:
            docstr = Operation.generate_sphinx(nickname)
            docstr = docstr.replace('\n', '\n      ')
            print('   ' + docstr)
예제 #8
0
def generate_functions(file):
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            intro = Introspect.get(nickname)

            # we are only interested in non-deprecated operations
            if (intro.flags & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # add 'missing' synonyms by hand
    all_nicknames.append('crop')

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort(key=lambda x: (bool(Introspect.get(x).member_x), x))

    # enum, _const and multiple output functions are wrapped by hand
    filter = [
        'add', 'bandbool', 'bandjoin_const', 'boolean', 'boolean_const',
        'complex', 'complexget', 'composite', 'divide', 'find_trim', 'flip',
        'linear', 'math', 'math2', 'math2_const', 'morph', 'multiply',
        'profile', 'project', 'relational', 'relational_const', 'remainder',
        'remainder_const', 'rot', 'round', 'subtract'
    ]
    all_nicknames = [name for name in all_nicknames if name not in filter]

    print(f'Generating {file}...')

    with open(file, 'w') as f:
        f.write('        // Auto-generated (class-)functions\n')

        for nickname in all_nicknames:
            f.write(generate_operation(nickname) + '\n')
예제 #9
0
def generate_type_declarations(filename):
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            intro = Introspect.get(nickname)

            # we are only interested in non-deprecated operations
            if (intro.flags & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # add 'missing' synonyms by hand
    all_nicknames.append('crop')

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort(key=lambda x: (bool(Introspect.get(x).member_x), x))

    # filter functions we document by hand
    filter = [
        'composite', 'find_trim', 'profile', 'project', 'bandjoin_const',
        'boolean_const', 'math2_const', 'relational_const', 'remainder_const'
    ]
    all_nicknames = [name for name in all_nicknames if name not in filter]

    with open(filename, 'a') as f:
        f.write('    class ImageAutoGen {\n')
        f.write(
            '        // THIS IS A GENERATED CLASS. DO NOT EDIT DIRECTLY.\n')

        for nickname in all_nicknames:
            f.write(generate_operation(nickname) + '\n')

        f.write('    }\n')
        f.write('}')
예제 #10
0
def generate_operators(declarations_only=False):
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            intro = Introspect.get(nickname)

            # we are only interested in non-deprecated operations
            if (intro.flags & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # add 'missing' synonyms by hand
    all_nicknames.append('crop')

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort(key=lambda x: (bool(Introspect.get(x).member_x), x))

    # some functions are wrapped by hand
    filter = [
        'add', 'bandjoin_const', 'boolean', 'composite', 'divide',
        'ifthenelse', 'math2', 'multiply', 'relational', 'remainder',
        'subtract'
    ]
    all_nicknames = [name for name in all_nicknames if name not in filter]

    print(preamble)

    for nickname in all_nicknames:
        print(generate_operation(nickname, declarations_only))
예제 #11
0
def generate_auto_doc(filename):
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            op = Operation.new_from_name(nickname)

            # we are only interested in non-deprecated operations
            if (op.get_flags() & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # add 'missing' synonyms by hand
    all_nicknames.append('crop')

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort()

    # these have hand-written methods, don't autodoc them
    no_generate = [
        'bandjoin', 'bandrank', 'ifthenelse', 'add', 'subtract', 'multiply',
        'divide', 'remainder'
    ]
    all_nicknames = [x for x in all_nicknames if x not in no_generate]

    print('Generating {0} ...'.format(filename))

    with open(filename, 'w') as f:
        f.write(preamble)
        f.write('\n')
        f.write('namespace Jcupitt\\Vips;\n')
        f.write('\n')
        f.write('/**\n')
        f.write(' * Autodocs for the Image class.\n')
        f.write(class_header)
        f.write(' *\n')

        for nickname in all_nicknames:
            f.write(generate_operation(nickname))

        f.write(' *\n')

        # all magic properties
        tmp_file = Image.new_temp_file('%s.v')
        all_properties = tmp_file.get_fields()
        for name in all_properties:
            php_name = name.replace('-', '_')
            gtype = tmp_file.get_typeof(name)
            fundamental = gobject_lib.g_type_fundamental(gtype)

            f.write(' * @property {0} ${1} {2}\n'.format(
                gtype_to_php(gtype), php_name, tmp_file.get_blurb(name)))

            if fundamental == GValue.genum_type:
                f.write(' *     @see {0} for possible values\n'.format(
                    remove_prefix(type_name(gtype))))

        f.write(' */\n')
        f.write('abstract class ImageAutodoc\n')
        f.write('{\n')
        f.write('}\n')
예제 #12
0
def generate_enums_flags(gir_file, out_file):
    root = ET.parse(gir_file).getroot()
    namespace = {'goi': 'http://www.gtk.org/introspection/core/1.0'}

    # find all the enumerations/flags and make a dict for them
    xml_enums = {}
    for node in root.findall('goi:namespace/goi:enumeration', namespace):
        xml_enums[node.get('name')] = node

    xml_flags = {}
    for node in root.findall('goi:namespace/goi:bitfield', namespace):
        xml_flags[node.get('name')] = node

    all_nicknames = []

    def add_enum(gtype, a, b):
        nickname = type_name(gtype)
        all_nicknames.append(nickname)
        gtype_to_js_param[gtype] = f'{remove_prefix(nickname)} | Enum'

        type_map(gtype, add_enum)

        return ffi.NULL

    # Enums
    type_map(type_from_name('GEnum'), add_enum)

    # Flags
    all_nicknames.append('VipsForeignPngFilter')
    gtype_to_js_param[
        type_from_name('VipsForeignPngFilter'
                       )] = f'{remove_prefix("VipsForeignPngFilter")} | Flag'

    with open('preamble_vips.d.ts', 'r') as f:
        preamble = f.read()

    with open(out_file, 'w') as f:
        f.write(preamble)

        for name in all_nicknames:
            gtype = type_from_name(name)
            name = remove_prefix(name)
            if name in xml_enums:
                is_enum = True
                node = xml_enums[name]
            elif name in xml_flags:
                is_enum = False
                node = xml_flags[name]
            else:
                continue

            enum_doc = node.find('goi:doc', namespace)

            if enum_doc is not None:
                text = enum_doc.text.replace('\n', '\n     * ')
                f.write('    /**\n')
                f.write(f"     * {text}\n")
                f.write('     */\n')

            f.write(f'    export enum {name} {{\n')

            values = values_for_enum(gtype) if is_enum else values_for_flag(
                gtype)
            for i, value in enumerate(values):
                js_value = value.replace('-', '_')
                if i == 0 and (js_value == 'error' or js_value == 'notset'):
                    continue

                member = node.find(f"goi:member[@name='{js_value}']",
                                   namespace)
                member_doc = member.find('goi:doc', namespace)
                if member_doc is not None:
                    text = member_doc.text[:1].upper() + member_doc.text[1:]
                    f.write('        /**\n')
                    f.write(f'         * {text}\n')
                    f.write('         */\n')

                f.write(f"        {js_value} = '{value}'")

                if i != len(values) - 1:
                    f.write(',\n')

            f.write('\n    }\n\n')
예제 #13
0
def gen_function_list():
    all_nicknames = []

    def add_nickname(gtype, a, b):
        nickname = nickname_find(gtype)
        try:
            # can fail for abstract types
            intro = Introspect.get(nickname)

            # we are only interested in non-deprecated operations
            if (intro.flags & _OPERATION_DEPRECATED) == 0:
                all_nicknames.append(nickname)
        except Error:
            pass

        type_map(gtype, add_nickname)

        return ffi.NULL

    type_map(type_from_name('VipsOperation'), add_nickname)

    # make list unique and sort
    all_nicknames = list(set(all_nicknames))
    all_nicknames.sort()

    # make dict with overloads
    overloads = {
        'bandbool': ['bandand', 'bandor', 'bandeor', 'bandmean'],
        'bandjoin': ['bandjoin2'],
        'bandjoin_const': ['bandjoin_const1'],
        'boolean': ['andimage', 'orimage', 'eorimage', 'lshift', 'rshift'],
        'cast': ['cast_uchar', 'cast_char', 'cast_ushort', 'cast_short' 'cast_uint', 'cast_int', 'cast_float',
                 'cast_double', 'cast_complex', 'cast_dpcomplex'],
        'complex': ['polar', 'rect', 'conj'],
        'complex2': ['cross_phase'],
        'complexget': ['real', 'imag'],
        'draw_circle': ['draw_circle1'],
        'draw_flood': ['draw_flood1'],
        'draw_line': ['draw_line1'],
        'draw_mask': ['draw_mask1'],
        'draw_rect': ['draw_rect1', 'draw_point', 'draw_point1'],
        'extract_area': ['crop'],
        'linear': ['linear1'],
        'math': ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'exp', 'exp10', 'log', 'log10'],
        'math2': ['pow', 'wop'],
        'rank': ['median'],
        'relational': ['equal', 'notequal', 'less', 'lesseq', 'more', 'moreeq'],
        'remainder_const': ['remainder_const1'],
        'round': ['floor', 'ceil', 'rint'],
    }

    overloads['boolean_const'] = [o + '_const' for o in overloads['boolean']] + ['boolean_const1'] + \
                                 [o + '_const1' for o in overloads['boolean']]

    overloads['math2_const'] = [o + '_const' for o in overloads['boolean']] + ['math2_const1'] + \
                               [o + '_const1' for o in overloads['boolean']]

    overloads['relational_const'] = [o + '_const' for o in overloads['relational']] + ['relational_const1'] + \
                                    [o + '_const1' for o in overloads['relational']]

    for nickname in all_nicknames:
        result = gen_function(nickname, overloads[nickname] if nickname in overloads else None)
        print(result)
예제 #14
0
#
#     call( "invert",
#         (options ? options : VImage::option())->
#             set( "in", *this )->
#             set( "out", &out ) );
#
#     return( out );
# }

import argparse

from pyvips import Introspect, Operation, GValue, Error, \
    ffi, gobject_lib, type_map, type_from_name, nickname_find, type_name

# TODO Move to pyvips.GValue
stream_input_type = type_from_name('VipsStreami')
stream_output_type = type_from_name('VipsStreamo')

# turn a GType into a C++ type
gtype_to_cpp = {
    GValue.gbool_type: 'bool',
    GValue.gint_type: 'int',
    GValue.gdouble_type: 'double',
    GValue.gstr_type: 'const char *',
    GValue.refstr_type: 'char *',
    GValue.gflags_type: 'int',
    GValue.image_type: 'VImage',
    stream_input_type: 'VStreamI',
    stream_output_type: 'VStreamO',
    GValue.array_int_type: 'std::vector<int>',
    GValue.array_double_type: 'std::vector<double>',
예제 #15
0
gtype_to_js_param = {
    GValue.gbool_type: 'boolean',
    GValue.gint_type: 'number',
    GValue.guint64_type: 'number',
    GValue.gdouble_type: 'number',
    GValue.gstr_type: 'string',
    GValue.refstr_type: 'string',
    GValue.gflags_type: 'Flag',
    GValue.image_type: 'Image',
    GValue.source_type: 'Source',
    GValue.target_type: 'Target',
    GValue.array_int_type: 'ArrayConstant',
    GValue.array_double_type: 'ArrayConstant',
    GValue.array_image_type: 'ArrayImage',
    GValue.blob_type: 'Blob',
    type_from_name('VipsInterpolate'): 'Interpolate'
}

gtype_to_js_return = {
    GValue.gbool_type: 'boolean',
    GValue.gint_type: 'number',
    GValue.guint64_type: 'number',
    GValue.gdouble_type: 'number',
    GValue.gstr_type: 'string',
    GValue.refstr_type: 'string',
    GValue.gflags_type: 'number',
    GValue.image_type: 'Image',
    GValue.array_int_type: 'number[]',
    GValue.array_double_type: 'number[]',
    GValue.array_image_type: 'Vector<Image>',
    GValue.blob_type: 'Uint8Array',
예제 #16
0
class GValue(object):
    """Wrap GValue in a Python class.

    This class wraps :class:`.GValue` in a convenient interface. You can use
    instances of this class to get and set :class:`.GObject` properties.

    On construction, :class:`.GValue` is all zero (empty). You can pass it to
    a get function to have it filled by :class:`.GObject`, or use init to
    set a type, set to set a value, then use it to set an object property.

    GValue lifetime is managed automatically.

    """

    # look up some common gtypes at init for speed
    gbool_type = type_from_name('gboolean')
    gint_type = type_from_name('gint')
    gdouble_type = type_from_name('gdouble')
    gstr_type = type_from_name('gchararray')
    genum_type = type_from_name('GEnum')
    gflags_type = type_from_name('GFlags')
    gobject_type = type_from_name('GObject')
    image_type = type_from_name('VipsImage')
    array_int_type = type_from_name('VipsArrayInt')
    array_double_type = type_from_name('VipsArrayDouble')
    array_image_type = type_from_name('VipsArrayImage')
    refstr_type = type_from_name('VipsRefString')
    blob_type = type_from_name('VipsBlob')

    pyvips.vips_lib.vips_band_format_get_type()
    format_type = type_from_name('VipsBandFormat')

    if at_least_libvips(8, 6):
        pyvips.vips_lib.vips_blend_mode_get_type()
    blend_mode_type = type_from_name('VipsBlendMode')

    # map a gtype to the name of the corresponding Python type
    _gtype_to_python = {
        gbool_type: 'bool',
        gint_type: 'int',
        gdouble_type: 'float',
        gstr_type: 'str',
        refstr_type: 'str',
        genum_type: 'str',
        gflags_type: 'int',
        gobject_type: 'GObject',
        image_type: 'Image',
        array_int_type: 'list[int]',
        array_double_type: 'list[float]',
        array_image_type: 'list[Image]',
        blob_type: 'str'
    }

    @staticmethod
    def gtype_to_python(gtype):
        """Map a gtype to the name of the Python type we use to represent it.

        """

        fundamental = gobject_lib.g_type_fundamental(gtype)

        if gtype in GValue._gtype_to_python:
            return GValue._gtype_to_python[gtype]
        if fundamental in GValue._gtype_to_python:
            return GValue._gtype_to_python[fundamental]
        return '<unknown type>'

    @staticmethod
    def to_enum(gtype, value):
        """Turn a string into an enum value ready to be passed into libvips.

        """

        if isinstance(value, basestring if _is_PY2 else str):
            enum_value = vips_lib.vips_enum_from_nick(b'pyvips', gtype,
                                                      _to_bytes(value))
            if enum_value < 0:
                raise Error('no value {0} in gtype {1} ({2})'.format(
                    value, type_name(gtype), gtype))
        else:
            enum_value = value

        return enum_value

    @staticmethod
    def from_enum(gtype, enum_value):
        """Turn an int back into an enum string.

        """

        pointer = vips_lib.vips_enum_nick(gtype, enum_value)
        if pointer == ffi.NULL:
            raise Error('value not in enum')

        return _to_string(pointer)

    def __init__(self):
        # allocate memory for the gvalue which will be freed on GC
        self.pointer = ffi.new('GValue *')
        # logger.debug('GValue.__init__: pointer = %s', self.pointer)

        # and tag it to be unset on GC as well
        self.gvalue = ffi.gc(self.pointer, gobject_lib.g_value_unset)
        # logger.debug('GValue.__init__: gvalue = %s', self.gvalue)

    def set_type(self, gtype):
        """Set the type of a GValue.

        GValues have a set type, fixed at creation time. Use set_type to set
        the type of a GValue before assigning to it.

        GTypes are 32 or 64-bit integers (depending on the platform). See
        type_find.

        """

        gobject_lib.g_value_init(self.gvalue, gtype)

    def set(self, value):
        """Set a GValue.

        The value is converted to the type of the GValue, if possible, and
        assigned.

        """

        # logger.debug('GValue.set: value = %s', value)

        gtype = self.gvalue.g_type
        fundamental = gobject_lib.g_type_fundamental(gtype)

        if gtype == GValue.gbool_type:
            gobject_lib.g_value_set_boolean(self.gvalue, value)
        elif gtype == GValue.gint_type:
            gobject_lib.g_value_set_int(self.gvalue, int(value))
        elif gtype == GValue.gdouble_type:
            gobject_lib.g_value_set_double(self.gvalue, value)
        elif fundamental == GValue.genum_type:
            gobject_lib.g_value_set_enum(self.gvalue,
                                         GValue.to_enum(gtype, value))
        elif fundamental == GValue.gflags_type:
            gobject_lib.g_value_set_flags(self.gvalue, value)
        elif gtype == GValue.gstr_type:
            gobject_lib.g_value_set_string(self.gvalue, _to_bytes(value))
        elif gtype == GValue.refstr_type:
            vips_lib.vips_value_set_ref_string(self.gvalue, _to_bytes(value))
        elif fundamental == GValue.gobject_type:
            gobject_lib.g_value_set_object(self.gvalue, value.pointer)
        elif gtype == GValue.array_int_type:
            if isinstance(value, numbers.Number):
                value = [value]

            array = ffi.new('int[]', value)
            vips_lib.vips_value_set_array_int(self.gvalue, array, len(value))
        elif gtype == GValue.array_double_type:
            if isinstance(value, numbers.Number):
                value = [value]

            array = ffi.new('double[]', value)
            vips_lib.vips_value_set_array_double(self.gvalue, array,
                                                 len(value))
        elif gtype == GValue.array_image_type:
            if isinstance(value, pyvips.Image):
                value = [value]

            vips_lib.vips_value_set_array_image(self.gvalue, len(value))
            array = vips_lib.vips_value_get_array_image(self.gvalue, ffi.NULL)
            for i, image in enumerate(value):
                gobject_lib.g_object_ref(image.pointer)
                array[i] = image.pointer
        elif gtype == GValue.blob_type:
            # we need to set the blob to a copy of the string that vips_lib
            # can own
            memory = glib_lib.g_malloc(len(value))
            ffi.memmove(memory, value, len(value))

            # this is horrible!
            #
            # * in API mode, we must have 8.6+ and use set_blob_free to
            #   attach the metadata to avoid leaks
            # * pre-8.6, we just pass a NULL free pointer and live with the
            #   leak
            #
            # this is because in API mode you can't pass a builtin (what
            # vips_lib.g_free() becomes) as a parameter to ffi.callback(), and
            # vips_value_set_blob() needs a callback for arg 2
            #
            # additionally, you can't make a py def which calls g_free() and
            # then use the py def in the callback, since libvips will trigger
            # these functions during cleanup, and py will have shut down by
            # then and you'll get a segv

            if at_least_libvips(8, 6):
                vips_lib.vips_value_set_blob_free(self.gvalue, memory,
                                                  len(value))
            else:
                if pyvips.API_mode:
                    vips_lib.vips_value_set_blob(self.gvalue, ffi.NULL, memory,
                                                 len(value))
                else:
                    vips_lib.vips_value_set_blob(self.gvalue, glib_lib.g_free,
                                                 memory, len(value))
        else:
            raise Error(
                'unsupported gtype for set {0}, fundamental {1}'.format(
                    type_name(gtype), type_name(fundamental)))

    def get(self):
        """Get the contents of a GValue.

        The contents of the GValue are read out as a Python type.
        """

        # logger.debug('GValue.get: self = %s', self)

        gtype = self.gvalue.g_type
        fundamental = gobject_lib.g_type_fundamental(gtype)

        result = None

        if gtype == GValue.gbool_type:
            result = bool(gobject_lib.g_value_get_boolean(self.gvalue))
        elif gtype == GValue.gint_type:
            result = gobject_lib.g_value_get_int(self.gvalue)
        elif gtype == GValue.gdouble_type:
            result = gobject_lib.g_value_get_double(self.gvalue)
        elif fundamental == GValue.genum_type:
            return GValue.from_enum(gtype,
                                    gobject_lib.g_value_get_enum(self.gvalue))
        elif fundamental == GValue.gflags_type:
            result = gobject_lib.g_value_get_flags(self.gvalue)
        elif gtype == GValue.gstr_type:
            pointer = gobject_lib.g_value_get_string(self.gvalue)

            if pointer != ffi.NULL:
                result = _to_string(pointer)
        elif gtype == GValue.refstr_type:
            psize = ffi.new('size_t *')
            pointer = vips_lib.vips_value_get_ref_string(self.gvalue, psize)

            # psize[0] will be number of bytes in string, but just assume it's
            # NULL-terminated
            result = _to_string(pointer)
        elif gtype == GValue.image_type:
            # g_value_get_object() will not add a ref ... that is
            # held by the gvalue
            go = gobject_lib.g_value_get_object(self.gvalue)
            vi = ffi.cast('VipsImage *', go)

            # we want a ref that will last with the life of the vimage:
            # this ref is matched by the unref that's attached to finalize
            # by Image()
            gobject_lib.g_object_ref(go)

            result = pyvips.Image(vi)
        elif gtype == GValue.array_int_type:
            pint = ffi.new('int *')
            array = vips_lib.vips_value_get_array_int(self.gvalue, pint)

            result = []
            for i in range(0, pint[0]):
                result.append(array[i])
        elif gtype == GValue.array_double_type:
            pint = ffi.new('int *')
            array = vips_lib.vips_value_get_array_double(self.gvalue, pint)

            result = []
            for i in range(0, pint[0]):
                result.append(array[i])
        elif gtype == GValue.array_image_type:
            pint = ffi.new('int *')
            array = vips_lib.vips_value_get_array_image(self.gvalue, pint)

            result = []
            for i in range(0, pint[0]):
                vi = array[i]
                gobject_lib.g_object_ref(vi)
                image = pyvips.Image(vi)
                result.append(image)
        elif gtype == GValue.blob_type:
            psize = ffi.new('size_t *')
            array = vips_lib.vips_value_get_blob(self.gvalue, psize)
            buf = ffi.cast('char*', array)

            result = ffi.unpack(buf, psize[0])
        else:
            raise Error('unsupported gtype for get {0}'.format(
                type_name(gtype)))

        return result
예제 #17
0
from pyvips import Introspect, Operation, GValue, Error, \
    ffi, gobject_lib, type_map, type_from_name, nickname_find, type_name

# turn a GType into a C++ type
gtype_to_cpp = {
    GValue.gbool_type: 'bool',
    GValue.gint_type: 'int',
    GValue.gdouble_type: 'double',
    GValue.gstr_type: 'const char *',
    GValue.refstr_type: 'char *',
    GValue.gflags_type: 'int',
    GValue.image_type: 'VImage',
    GValue.source_type: 'VSource',
    GValue.target_type: 'VTarget',
    GValue.guint64_type: 'guint64',
    type_from_name('VipsInterpolate'): 'VInterpolate',
    GValue.array_int_type: 'std::vector<int>',
    GValue.array_double_type: 'std::vector<double>',
    GValue.array_image_type: 'std::vector<VImage>',
    GValue.blob_type: 'VipsBlob *'
}

cplusplus_suffixes = ('*', '&')
cplusplus_keywords = ('case', 'switch')

# values for VipsArgumentFlags
_REQUIRED = 1
_INPUT = 16
_OUTPUT = 32
_DEPRECATED = 64
_MODIFY = 128
예제 #18
0
#
#     call( "invert",
#         (options ? options : VImage::option())->
#             set( "in", *this )->
#             set( "out", &out ) );
#
#     return( out );
# }

import argparse

from pyvips import Introspect, Operation, GValue, Error, \
    ffi, gobject_lib, type_map, type_from_name, nickname_find, type_name

# TODO Move to pyvips.GValue
source_type = type_from_name('VipsSource')
target_type = type_from_name('VipsTarget')

# turn a GType into a C++ type
gtype_to_cpp = {
    GValue.gbool_type: 'bool',
    GValue.gint_type: 'int',
    GValue.gdouble_type: 'double',
    GValue.gstr_type: 'const char *',
    GValue.refstr_type: 'char *',
    GValue.gflags_type: 'int',
    GValue.image_type: 'VImage',
    source_type: 'VSource',
    target_type: 'VTarget',
    GValue.array_int_type: 'std::vector<int>',
    GValue.array_double_type: 'std::vector<double>',