added VipsEmbed

added VipsEmbed class, new macros for arg boilerplate, new priority
thing for arg ordering
This commit is contained in:
John Cupitt 2011-10-16 14:48:47 +01:00
parent fba3d000a3
commit 8dfb3056ac
21 changed files with 1039 additions and 426 deletions

View File

@ -22,6 +22,9 @@
- added vips_image_write(), old one becomes vips_image_write_to_file()
- jpeg read/write copies over XMP data
- handle offset correctly in separable convolutions (thanks Nicolas)
- macros for class arg boilerplate
- class arg order set by new 'priority' param
- VipsExtend enum added
12/9/11 started 7.26.4
- fallback vips_init()

52
TODO
View File

@ -1,3 +1,55 @@
- embed args are in the wrong order
$ vips embed
vips_embed_class_init
VipsEmbed (embed), embed an image in a larger image
embed input type x y width height out
where:
input :: VipsImage (input)
type :: gint (input)
x :: gint (input)
y :: gint (input)
width :: gint (input)
height :: gint (input)
out :: VipsImage (output)
how can we fix this?
need to give an extra arg to vips_object_class_install_argument() to
specify 'argument priority' ... show args in priority order
- try some macros for arg specification
pspec = g_param_spec_int( "y", "Y",
_( "Top edge of input in output" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_Y, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, y ) );
could become
VIPS_ARG_INT( class, "y", "Y",
_( "Top edge of input in output" ),
0, 1000000, 0,
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, y ) );
could get rid of PROP_ enums as well
doing binary.c next
- make 'type' field to embed an enum?
- vips_object_set_argument_from_string() needs more arg types
must be some way to make this more automatic

View File

@ -53,15 +53,6 @@
#include "arithmetic.h"
/* Properties.
*/
enum {
PROP_OUTPUT = 1,
PROP_BOOLTEST = 2,
PROP_IMTEST = 3,
PROP_LAST
};
G_DEFINE_ABSTRACT_TYPE( VipsArithmetic, vips_arithmetic, VIPS_TYPE_OPERATION );
static int
@ -96,8 +87,6 @@ vips_arithmetic_class_init( VipsArithmeticClass *class )
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
GParamSpec *pspec;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -105,33 +94,22 @@ vips_arithmetic_class_init( VipsArithmeticClass *class )
vobject_class->description = _( "arithmetic operations" );
vobject_class->build = vips_arithmetic_build;
pspec = g_param_spec_object( "out", "Output",
VIPS_ARG_IMAGE( class, "out", 1,
_( "Output" ),
_( "Output image" ),
VIPS_TYPE_IMAGE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_OUTPUT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsArithmetic, output ) );
pspec = g_param_spec_boolean( "booltest", "Bool test",
VIPS_ARG_BOOL( class, "booltest", 2,
_( "Bool test" ),
_( "Test optional boolean argument" ),
FALSE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_BOOLTEST, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsArithmetic, booltest ) );
G_STRUCT_OFFSET( VipsArithmetic, booltest ),
FALSE );
pspec = g_param_spec_object( "imtest", "Image test",
VIPS_ARG_IMAGE( class, "imtest", 3,
_( "Image test" ),
_( "Test optional image argument" ),
VIPS_TYPE_IMAGE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_IMTEST, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsArithmetic, imtest ) );
}

View File

@ -86,13 +86,6 @@
* See also: im_stats(), im_bandmean(), im_deviate(), im_rank()
*/
/* Properties.
*/
enum {
PROP_OUTPUT = 1,
PROP_LAST
};
typedef struct _VipsAvg {
VipsStatistic parent_instance;
@ -228,8 +221,6 @@ vips_avg_class_init( VipsAvgClass *class )
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsStatisticClass *sclass = VIPS_STATISTIC_CLASS( class );
GParamSpec *pspec;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -241,17 +232,12 @@ vips_avg_class_init( VipsAvgClass *class )
sclass->scan = vips_avg_scan;
sclass->stop = vips_avg_stop;
pspec = g_param_spec_double( "out", "Output",
VIPS_ARG_DOUBLE( class, "out", 2,
_( "Output" ),
_( "Output value" ),
-G_MAXDOUBLE,
G_MAXDOUBLE,
0.0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_OUTPUT, pspec );
vips_object_class_install_argument( object_class, pspec,
VIPS_ARGUMENT_REQUIRED_OUTPUT | VIPS_ARGUMENT_APPEND,
G_STRUCT_OFFSET( VipsAvg, avg ) );
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsAvg, avg ),
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0 );
}
static void

View File

@ -50,14 +50,6 @@
#include "arithmetic.h"
#include "binary.h"
/* Properties.
*/
enum {
PROP_LEFT = 1,
PROP_RIGHT,
PROP_LAST
};
G_DEFINE_ABSTRACT_TYPE( VipsBinary, vips_binary, VIPS_TYPE_ARITHMETIC );
/* Save a bit of typing.
@ -348,8 +340,6 @@ vips_binary_class_init( VipsBinaryClass *class )
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
GParamSpec *pspec;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -359,23 +349,15 @@ vips_binary_class_init( VipsBinaryClass *class )
/* Create properties.
*/
pspec = g_param_spec_object( "right",
"Right", "Right-hand image argument",
VIPS_TYPE_IMAGE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_RIGHT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARG_IMAGE( class, "right", 1,
_( "Right" ),
_( "Right-hand image argument" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsBinary, right ) );
pspec = g_param_spec_object( "left",
"Left", "Left-hand image argument",
VIPS_TYPE_IMAGE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_LEFT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARG_IMAGE( class, "left", 2,
_( "Left" ),
_( "Left-hand image argument" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsBinary, left ) );
}

View File

@ -83,15 +83,6 @@
* See also: #VipsAvg, im_stats(), im_bandmean(), im_deviate(), im_rank()
*/
/* Properties.
*/
enum {
PROP_OUTPUT = 1,
PROP_X, /* Position of minimum */
PROP_Y,
PROP_LAST
};
typedef struct _VipsMin {
VipsStatistic parent_instance;
@ -291,8 +282,6 @@ vips_min_class_init( VipsMinClass *class )
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsStatisticClass *sclass = VIPS_STATISTIC_CLASS( class );
GParamSpec *pspec;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -304,37 +293,26 @@ vips_min_class_init( VipsMinClass *class )
sclass->scan = vips_min_scan;
sclass->stop = vips_min_stop;
pspec = g_param_spec_double( "out", "Output",
VIPS_ARG_DOUBLE( class, "out", 1,
_( "Output" ),
_( "Output value" ),
-G_MAXDOUBLE,
G_MAXDOUBLE,
0.0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_OUTPUT, pspec );
vips_object_class_install_argument( object_class, pspec,
VIPS_ARGUMENT_REQUIRED_OUTPUT | VIPS_ARGUMENT_APPEND,
G_STRUCT_OFFSET( VipsMin, min ) );
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsMin, min ),
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0 );
pspec = g_param_spec_int( "x", "x",
VIPS_ARG_INT( class, "x", 2,
_( "x" ),
_( "Horizontal position of minimum" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_X, pspec );
vips_object_class_install_argument( object_class, pspec,
VIPS_ARGUMENT_OPTIONAL_OUTPUT,
G_STRUCT_OFFSET( VipsMin, x ) );
G_STRUCT_OFFSET( VipsMin, x ),
0, 1000000, 0 );
pspec = g_param_spec_int( "y", "y",
VIPS_ARG_INT( class, "y", 2,
_( "y" ),
_( "Vertical position of minimum" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_Y, pspec );
vips_object_class_install_argument( object_class, pspec,
VIPS_ARGUMENT_OPTIONAL_OUTPUT,
G_STRUCT_OFFSET( VipsMin, y ) );
G_STRUCT_OFFSET( VipsMin, y ),
0, 1000000, 0 );
}
static void

View File

@ -52,13 +52,6 @@
#include "statistic.h"
/* Properties.
*/
enum {
PROP_INPUT = 1,
PROP_LAST
};
G_DEFINE_ABSTRACT_TYPE( VipsStatistic, vips_statistic, VIPS_TYPE_OPERATION );
static void *
@ -147,8 +140,6 @@ vips_statistic_class_init( VipsStatisticClass *class )
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
GParamSpec *pspec;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -156,14 +147,10 @@ vips_statistic_class_init( VipsStatisticClass *class )
vobject_class->description = _( "VIPS statistic operations" );
vobject_class->build = vips_statistic_build;
pspec = g_param_spec_object( "in", "Input",
VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ),
_( "Input image" ),
VIPS_TYPE_IMAGE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_INPUT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_REQUIRED_INPUT,
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsStatistic, input ) );
}

View File

@ -4,6 +4,7 @@ libconversion_la_SOURCES = \
conversion.c \
conversion.h \
copy.c \
embed.c \
conver_dispatch.c \
im_black.c \
im_c2amph.c \

View File

@ -50,13 +50,6 @@
#include "conversion.h"
/* Properties.
*/
enum {
PROP_OUTPUT = 1,
PROP_LAST
};
G_DEFINE_ABSTRACT_TYPE( VipsConversion, vips_conversion, VIPS_TYPE_OPERATION );
static int
@ -84,8 +77,6 @@ vips_conversion_class_init( VipsConversionClass *class )
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
GParamSpec *pspec;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
@ -93,13 +84,9 @@ vips_conversion_class_init( VipsConversionClass *class )
vobject_class->description = _( "conversion operations" );
vobject_class->build = vips_conversion_build;
pspec = g_param_spec_object( "out", "Output",
VIPS_ARG_IMAGE( class, "out", 1,
_( "Output" ),
_( "Output image" ),
VIPS_TYPE_IMAGE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_OUTPUT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsConversion, output ) );
}
@ -116,7 +103,9 @@ void
vips_conversion_operation_init( void )
{
extern GType vips_copy_get_type( void );
extern GType vips_embed_get_type( void );
vips_copy_get_type();
vips_embed_get_type();
}

View File

@ -74,8 +74,8 @@
*/
/*
*/
#define VIPS_DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
@ -108,24 +108,6 @@
* Returns: 0 on success, -1 on error.
*/
/* Properties.
*/
enum {
PROP_INPUT = 1,
PROP_SWAP,
PROP_WIDTH,
PROP_HEIGHT,
PROP_BANDS,
PROP_FORMAT,
PROP_CODING,
PROP_INTERPRETATION,
PROP_XRES,
PROP_YRES,
PROP_XOFFSET,
PROP_YOFFSET,
PROP_LAST
};
typedef struct _VipsCopy {
VipsConversion parent_instance;
@ -344,8 +326,6 @@ vips_copy_class_init( VipsCopyClass *class )
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
GParamSpec *pspec;
VIPS_DEBUG_MSG( "vips_copy_class_init\n" );
gobject_class->set_property = vips_object_set_property;
@ -355,116 +335,88 @@ vips_copy_class_init( VipsCopyClass *class )
vobject_class->description = _( "copy an image" );
vobject_class->build = vips_copy_build;
pspec = g_param_spec_object( "input",
"Input", "Input image argument",
VIPS_TYPE_IMAGE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_INPUT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCopy, input ) );
pspec = g_param_spec_boolean( "swap", "Swap",
VIPS_ARG_BOOL( class, "swap", 2,
_( "Swap" ),
_( "Swap bytes in image between little and big-endian" ),
FALSE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_SWAP, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, swap ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, swap ),
FALSE );
pspec = g_param_spec_int( "width", "Width",
VIPS_ARG_INT( class, "width", 2,
_( "Width" ),
_( "Image width in pixels" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_WIDTH, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, width ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, width ),
0, 1000000, 0 );
pspec = g_param_spec_int( "height", "Height",
VIPS_ARG_INT( class, "height", 3,
_( "Height" ),
_( "Image height in pixels" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_HEIGHT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, height ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, height ),
0, 1000000, 0 );
pspec = g_param_spec_int( "bands", "Bands",
VIPS_ARG_INT( class, "bands", 4,
_( "Bands" ),
_( "Number of bands in image" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_BANDS, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, bands ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, bands ),
0, 1000000, 0 );
pspec = g_param_spec_enum( "format", "Format",
VIPS_ARG_ENUM( class, "format", 5,
_( "Format" ),
_( "Pixel format in image" ),
VIPS_TYPE_BAND_FORMAT, VIPS_FORMAT_UCHAR,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_FORMAT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, format ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, format ),
VIPS_TYPE_BAND_FORMAT, VIPS_FORMAT_UCHAR );
pspec = g_param_spec_enum( "coding", "Coding",
VIPS_ARG_ENUM( class, "coding", 6,
_( "Coding" ),
_( "Pixel coding" ),
VIPS_TYPE_CODING, VIPS_CODING_NONE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_CODING, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, coding ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, coding ),
VIPS_TYPE_CODING, VIPS_CODING_NONE );
pspec = g_param_spec_enum( "interpretation", "Interpretation",
VIPS_ARG_ENUM( class, "interpretation", 7,
_( "Interpretation" ),
_( "Pixel interpretation" ),
VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_MULTIBAND,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_INTERPRETATION, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, interpretation ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, interpretation ),
VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_MULTIBAND );
pspec = g_param_spec_double( "xres", "XRes",
VIPS_ARG_DOUBLE( class, "xres", 8,
_( "Xres" ),
_( "Horizontal resolution in pixels/mm" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_XRES, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, xres ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, xres ),
0, 1000000, 0 );
pspec = g_param_spec_double( "yres", "YRes",
VIPS_ARG_DOUBLE( class, "yres", 9,
_( "Yres" ),
_( "Vertical resolution in pixels/mm" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_YRES, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, yres ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, yres ),
0, 1000000, 0 );
pspec = g_param_spec_int( "xoffset", "XOffset",
VIPS_ARG_INT( class, "xoffset", 10,
_( "Xoffset" ),
_( "Horizontal offset of origin" ),
-10000000, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_XOFFSET, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, xoffset ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, xoffset ),
-1000000, 1000000, 0 );
pspec = g_param_spec_int( "yoffset", "YOffset",
VIPS_ARG_INT( class, "yoffset", 11,
_( "Yoffset" ),
_( "Vertical offset of origin" ),
-10000000, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_YOFFSET, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, yoffset ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCopy, yoffset ),
-1000000, 1000000, 0 );
}
static void

617
libvips/conversion/embed.c Normal file
View File

@ -0,0 +1,617 @@
/* im_embed
*
* Author: J. Cupitt
* Written on: 21/2/95
* Modified on:
* 6/4/04
* - added extend pixels from edge mode
* - sets Xoffset / Yoffset to x / y
* 15/4/04
* - added replicate and mirror modes
* 4/3/05
* - added solid white mode
* 4/1/07
* - degenerate to im_copy() for 0/0/w/h
* 1/8/07
* - more general ... x and y can be negative
* 24/3/09
* - added IM_CODING_RAD support
* 5/11/09
* - gtkdoc
* 27/1/10
* - use im_region_paint()
* - cleanups
* 15/10/11
* - rewrite as a class
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
*/
#define VIPS_DEBUG
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#include <vips/debug.h>
#include "conversion.h"
/**
* VipsEmbed:
* @in: input image
* @out: output image
* @type: how to generate the edge pixels
* @x: place @in at this x position in @out
* @y: place @in at this y position in @out
* @width: @out should be this many pixels across
* @height: @out should be this many pixels down
*
* The opposite of im_extract(): embed an image within a larger image. @type
* controls what appears in the new pels, see #VipsExtend.
*
* See also: im_extract_area(), im_insert().
*
* Returns: 0 on success, -1 on error.
*/
typedef struct _VipsEmbed {
VipsConversion parent_instance;
/* The input image.
*/
VipsImage *input;
VipsExtend type;
int x;
int y;
int width;
int height;
/* Geometry calculations.
*/
Rect rout; /* Whole output area */
Rect rsub; /* Rect occupied by image */
/* The 8 border pieces. The 4 borders strictly up/down/left/right of
* the main image, and the 4 corner pieces.
*/
Rect border[8];
} VipsEmbed;
typedef VipsConversionClass VipsEmbedClass;
G_DEFINE_TYPE( VipsEmbed, vips_embed, VIPS_TYPE_CONVERSION );
/* r is the bit we are trying to paint, guaranteed to be entirely within
* border area i. Set out to be the edge of the image we need to paint the
* pixels in r.
*/
static void
vips_embed_find_edge( VipsEmbed *embed, VipsRect *r, int i, VipsRect *out )
{
/* Expand the border by 1 pixel, intersect with the image area, and we
* get the edge. Usually too much though: eg. we could make the entire
* right edge.
*/
*out = embed->border[i];
vips_rect_marginadjust( out, 1 );
vips_rect_intersectrect( out, &embed->rsub, out );
/* Usually too much though: eg. we could make the entire
* right edge. If we're strictly up/down/left/right of the image, we
* can trim.
*/
if( i == 0 || i == 2 ) {
VipsRect extend;
/* Above or below.
*/
extend = *r;
extend.top = 0;
extend.height = embed->height;
vips_rect_intersectrect( out, &extend, out );
}
if( i == 1 || i == 3 ) {
VipsRect extend;
/* Left or right.
*/
extend = *r;
extend.left = 0;
extend.width = embed->width;
vips_rect_intersectrect( out, &extend, out );
}
}
/* Copy a single pixel sideways into a line of pixels.
*/
static void
vips_embed_copy_pixel( VipsEmbed *embed, PEL *q, PEL *p, int n )
{
const int bs = VIPS_IMAGE_SIZEOF_PEL( embed->input );
int x, b;
for( x = 0; x < n; x++ )
for( b = 0; b < bs; b++ )
*q++ = p[b];
}
/* Paint r of region or. It's a border area, lying entirely within
* embed->border[i]. p points to the top-left source pixel to fill with.
* plsk is the line stride.
*/
static void
vips_embed_paint_edge( VipsEmbed *embed,
VipsRegion *or, int i, VipsRect *r, PEL *p, int plsk )
{
const int bs = VIPS_IMAGE_SIZEOF_PEL( embed->input );
VipsRect todo;
PEL *q;
int y;
/* Pixels left to paint.
*/
todo = *r;
/* Corner pieces ... copy the single pixel to paint the top line of
* todo, then use the line copier below to paint the rest of it.
*/
if( i > 3 ) {
q = (PEL *) VIPS_REGION_ADDR( or, todo.left, todo.top );
vips_embed_copy_pixel( embed, q, p, todo.width );
p = q;
todo.top += 1;
todo.height -= 1;
}
if( i == 1 || i == 3 ) {
/* Vertical line of pixels to copy.
*/
for( y = 0; y < todo.height; y++ ) {
q = (PEL *) VIPS_REGION_ADDR( or,
todo.left, todo.top + y );
vips_embed_copy_pixel( embed, q, p, todo.width );
p += plsk;
}
}
else {
/* Horizontal line of pixels to copy.
*/
for( y = 0; y < todo.height; y++ ) {
q = (PEL *) VIPS_REGION_ADDR( or,
todo.left, todo.top + y );
memcpy( q, p, bs * todo.width );
}
}
}
static int
vips_embed_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
VipsRegion *ir = (VipsRegion *) seq;
VipsEmbed *embed = (VipsEmbed *) b;
VipsRect *r = &or->valid;
Rect ovl;
int i;
PEL *p;
int plsk;
/* Entirely within the input image? Generate the subimage and copy
* pointers.
*/
if( vips_rect_includesrect( &embed->rsub, r ) ) {
VipsRect need;
need = *r;
need.left -= embed->x;
need.top -= embed->y;
if( vips_region_prepare( ir, &need ) ||
vips_region_region( or, ir, r, need.left, need.top ) )
return( -1 );
return( 0 );
}
/* Does any of the input image appear in the area we have been asked
* to make? Paste it in.
*/
vips_rect_intersectrect( r, &embed->rsub, &ovl );
if( !vips_rect_isempty( &ovl ) ) {
/* Paint the bits coming from the input image.
*/
ovl.left -= embed->x;
ovl.top -= embed->y;
if( vips_region_prepare_to( ir, or, &ovl,
ovl.left + embed->x, ovl.top + embed->y ) )
return( -1 );
ovl.left += embed->x;
ovl.top += embed->y;
}
switch( embed->type ) {
case 0:
case 4:
/* Paint the borders a solid value.
*/
for( i = 0; i < 8; i++ )
vips_region_paint( or, &embed->border[i],
embed->type == 0 ? 0 : 255 );
break;
case 1:
/* Extend the borders.
*/
for( i = 0; i < 8; i++ ) {
VipsRect todo;
VipsRect edge;
vips_rect_intersectrect( r, &embed->border[i], &todo );
if( !vips_rect_isempty( &todo ) ) {
vips_embed_find_edge( embed, &todo, i, &edge );
/* Did we paint any of the input image? If we
* did, we can fetch the edge pixels from
* that.
*/
if( !vips_rect_isempty( &ovl ) ) {
p = (PEL *) VIPS_REGION_ADDR( or,
edge.left, edge.top );
plsk = VIPS_REGION_LSKIP( or );
}
else {
/* No pixels painted ... fetch
* directly from the input image.
*/
edge.left -= embed->x;
edge.top -= embed->y;
if( vips_region_prepare( ir, &edge ) )
return( -1 );
p = (PEL *) VIPS_REGION_ADDR( ir,
edge.left, edge.top );
plsk = VIPS_REGION_LSKIP( ir );
}
vips_embed_paint_edge( embed,
or, i, &todo, p, plsk );
}
}
break;
default:
g_assert( 0 );
}
return( 0 );
}
static int
vips_embed_build( VipsObject *object )
{
VipsConversion *conversion = VIPS_CONVERSION( object );
VipsEmbed *embed = (VipsEmbed *) object;
VipsRect want;
if( VIPS_OBJECT_CLASS( vips_embed_parent_class )->build( object ) )
return( -1 );
if( vips_image_pio_input( embed->input ) ||
vips_image_pio_output( conversion->output ) )
return( -1 );
if( embed->type < 0 || embed->type > 4 ) {
vips_error( "VipsEmbed", "%s", _( "unknown type" ) );
return( -1 );
}
/* nip can generate this quite often ... just copy.
*/
if( embed->x == 0 &&
embed->y == 0 &&
embed->width == embed->input->Xsize &&
embed->height == embed->input->Ysize )
return( vips_image_write( embed->input, conversion->output ) );
switch( embed->type ) {
case 2:
{
/* Clock arithmetic: we want negative x/y to wrap around
* nicely.
*/
const int nx = embed->x < 0 ?
-embed->x % embed->input->Xsize :
embed->input->Xsize - embed->x % embed->input->Xsize;
const int ny = embed->y < 0 ?
-embed->y % embed->input->Ysize :
embed->input->Ysize - embed->y % embed->input->Ysize;
VipsImage *t[1];
if( im_open_local_array( conversion->output,
t, 1, "embed-type2", "p" ) ||
im_replicate( embed->input, t[0],
embed->width / embed->input->Xsize + 2,
embed->height / embed->input->Ysize + 2 ) ||
im_extract_area( t[0], conversion->output,
nx, ny, embed->width, embed->height ) )
return( -1 );
}
break;
case 3:
{
/* As case 2, but the tiles are twice the size because of
* mirroring.
*/
const int w2 = embed->input->Xsize * 2;
const int h2 = embed->input->Ysize * 2;
const int nx = embed->x < 0 ?
-embed->x % w2 : w2 - embed->x % w2;
const int ny = embed->y < 0 ?
-embed->y % h2 : h2 - embed->y % h2;
VipsImage *t[7];
if( im_open_local_array( conversion->output,
t, 7, "embed-type3", "p" ) ||
/* Cache the edges of in, since we may well be reusing
* them repeatedly. Will only help for tiny borders
* (up to 20 pixels?), but that's our typical case
* with im_conv() etc.
im_cache( in, t[0], IM__TILE_WIDTH, IM__TILE_HEIGHT,
3 * (in->Xsize / IM__TILE_WIDTH + 1) +
3 * (in->Ysize / IM__TILE_HEIGHT + 1) ) ||
*/
/*
FIXME ... alternatively, don't cache, hmm,
need to time this for typical cases
*/
im_copy( embed->input, t[0] ) ||
/* Make a 2x2 mirror tile.
*/
im_fliphor( t[0], t[1] ) ||
im_lrjoin( t[0], t[1], t[2] ) ||
im_flipver( t[2], t[3] ) ||
im_tbjoin( t[2], t[3], t[4] ) ||
/* Repeat, then cut out the centre.
*/
im_replicate( t[4], t[5],
embed->width / t[4]->Xsize + 2,
embed->height / t[4]->Ysize + 2 ) ||
im_extract_area( t[5], t[6], nx, ny,
embed->width, embed->height ) ||
/* Overwrite the centre with the input, much faster
* for centre pixels.
*/
im_insert_noexpand( t[6], embed->input,
conversion->output, embed->x, embed->y ) )
return( -1 );
}
break;
case 0:
case 1:
case 4:
if( vips_image_copy_fields( conversion->output, embed->input ) )
return( -1 );
conversion->output->Xsize = embed->width;
conversion->output->Ysize = embed->height;
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_SMALLTILE, embed->input, NULL );
/* Whole output area.
*/
embed->rout.left = 0;
embed->rout.top = 0;
embed->rout.width = conversion->output->Xsize;
embed->rout.height = conversion->output->Ysize;
/* Rect occupied by image (can be clipped to nothing).
*/
want.left = embed->x;
want.top = embed->y;
want.width = embed->input->Xsize;
want.height = embed->input->Ysize;
im_rect_intersectrect( &want, &embed->rout, &embed->rsub );
/* FIXME ... actually, it can't. embed_find_edge() will fail
* if rsub is empty. Make this more general at some point
* and remove this test.
*/
if( vips_rect_isempty( &embed->rsub ) ) {
vips_error( "VipsEmbed", "%s", _( "bad dimensions" ) );
return( -1 );
}
/* Edge rects of new pixels ... top, right, bottom, left. Order
* important. Can be empty.
*/
embed->border[0].left = embed->rsub.left;
embed->border[0].top = 0;
embed->border[0].width = embed->rsub.width;
embed->border[0].height = embed->rsub.top;
embed->border[1].left = VIPS_RECT_RIGHT( &embed->rsub );
embed->border[1].top = embed->rsub.top;
embed->border[1].width = conversion->output->Xsize -
VIPS_RECT_RIGHT( &embed->rsub );
embed->border[1].height = embed->rsub.height;
embed->border[2].left = embed->rsub.left;
embed->border[2].top = VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[2].width = embed->rsub.width;
embed->border[2].height = conversion->output->Ysize -
VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[3].left = 0;
embed->border[3].top = embed->rsub.top;
embed->border[3].width = embed->rsub.left;
embed->border[3].height = embed->rsub.height;
/* Corner rects. Top-left, top-right, bottom-right,
* bottom-left. Order important.
*/
embed->border[4].left = 0;
embed->border[4].top = 0;
embed->border[4].width = embed->rsub.left;
embed->border[4].height = embed->rsub.top;
embed->border[5].left = VIPS_RECT_RIGHT( &embed->rsub );
embed->border[5].top = 0;
embed->border[5].width = conversion->output->Xsize -
VIPS_RECT_RIGHT( &embed->rsub );
embed->border[5].height = embed->rsub.top;
embed->border[6].left = VIPS_RECT_RIGHT( &embed->rsub );
embed->border[6].top = VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[6].width = conversion->output->Xsize -
VIPS_RECT_RIGHT( &embed->rsub );
embed->border[6].height = conversion->output->Ysize -
VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[7].left = 0;
embed->border[7].top = VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[7].width = embed->rsub.left;
embed->border[7].height = conversion->output->Ysize -
VIPS_RECT_BOTTOM( &embed->rsub );
if( vips_image_generate( conversion->output,
vips_start_one, vips_embed_gen, vips_stop_one,
embed->input, embed ) )
return( -1 );
break;
default:
g_assert( 0 );
}
return( 0 );
}
static void
vips_embed_class_init( VipsEmbedClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VIPS_DEBUG_MSG( "vips_embed_class_init\n" );
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
vobject_class->nickname = "embed";
vobject_class->description = _( "embed an image in a larger image" );
vobject_class->build = vips_embed_build;
VIPS_ARG_IMAGE( class, "in", -1,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, input ) );
VIPS_ARG_INT( class, "width", 2,
_( "Width" ),
_( "Image width in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, width ),
0, 1000000, 0 );
VIPS_ARG_INT( class, "height", 3,
_( "Height" ),
_( "Image height in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, height ),
0, 1000000, 0 );
VIPS_ARG_INT( class, "x", 4,
_( "x" ),
_( "Left edge of input in output" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, x ),
-1000000, 1000000, 0 );
VIPS_ARG_INT( class, "y", 5,
_( "y" ),
_( "Top edge of input in output" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, y ),
-1000000, 1000000, 0 );
VIPS_ARG_ENUM( class, "type", 6,
_( "type" ),
_( "How to generate the extra pixels" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsEmbed, type ),
VIPS_TYPE_EXTEND, VIPS_EXTEND_BLACK );
}
static void
vips_embed_init( VipsEmbed *embed )
{
/* Init our instance fields.
*/
}
int
vips_embed( VipsImage *in, VipsImage **out,
int x, int y, int width, int height, ... )
{
va_list ap;
int result;
va_start( ap, height );
result = vips_call_split( "embed", ap,
in, out, x, y, width, height );
va_end( ap );
return( result );
}

View File

@ -775,7 +775,7 @@ vips_wrap7_subclass_class_init( VipsWrap7Class *class )
(type->flags & IM_TYPE_OUTPUT) ?
VIPS_ARGUMENT_REQUIRED_OUTPUT :
VIPS_ARGUMENT_REQUIRED_INPUT,
i );
i, i );
break;
default:

View File

@ -57,6 +57,7 @@ EXTRA_DIST = version.h.in internal.h enumtemplate
# well
vips_scan_headers = \
${top_srcdir}/libvips/include/vips/memory.h \
${top_srcdir}/libvips/include/vips/conversion.h \
${top_srcdir}/libvips/include/vips/util.h \
${top_srcdir}/libvips/include/vips/buf.h \
${top_srcdir}/libvips/include/vips/image.h \

View File

@ -37,7 +37,49 @@
extern "C" {
#endif /*__cplusplus*/
int vips_copy( VipsImage *in, VipsImage **out, ... );
/**
* VipsExtend:
* @VIPS_EXTEND_BLACK; extend with black (all 0) pixels
* @VIPS_EXTEND_COPY; copy the image edges
* @VIPS_EXTEND_REPEAT; repeat the whole image
* @VIPS_EXTEND_MIRROR; mirror the whole image
* @VIPS_EXTEND_WHITE; extend with white (all bits set) pixels
*
* See vips_embed(), vips_conv(), vips_affine() and so on.
*
* When the edges of an image are extended, you can specify
* how you want the extension done.
*
* #VIPS_EXTEND_BLACK --- new pixels are black, ie. all bits are zero.
*
* #VIPS_EXTEND_COPY --- each new pixel takes the value of the nearest edge
* pixel
*
* #VIPS_EXTEND_REPEAT --- the image is tiled to fill the new area
*
* #VIPS_EXTEND_MIRROR --- the image is reflected and tiled to reduce hash
* edges
*
* #VIPS_EXTEND_WHITE --- new pixels are white, ie. all bits are set
*
* We have to specify the exact value of each enum member since we have to
* keep these frozen for back compat with vips7.
*
* See also: vips_embed().
*/
typedef enum {
VIPS_EXTEND_BLACK = 0,
VIPS_EXTEND_COPY = 1,
VIPS_EXTEND_REPEAT = 2,
VIPS_EXTEND_MIRROR = 3,
VIPS_EXTEND_WHITE = 4
} VipsExtend;
int vips_copy( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_embed( VipsImage *in, VipsImage **out,
int x, int y, int width, int height, ... )
__attribute__((sentinel));

View File

@ -6,6 +6,9 @@
G_BEGIN_DECLS
/* enumerations from "../../../libvips/include/vips/conversion.h" */
GType vips_extend_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_EXTEND (vips_extend_get_type())
/* enumerations from "../../../libvips/include/vips/util.h" */
GType vips_token_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_TOKEN (vips_token_get_type())

View File

@ -62,23 +62,23 @@ extern "C" {
* will use the most restrictive of the styles requested by the operations
* in the pipeline.
*
* VIPS_DEMAND_STYLE_THINSTRIP --- This operation would like to output strips
* #VIPS_DEMAND_STYLE_THINSTRIP --- This operation would like to output strips
* the width of the image and a few pels high. This is option suitable for
* point-to-point operations, such as those in the arithmetic package.
*
* This option is only efficient for cases where each output pel depends
* upon the pel in the corresponding position in the input image.
*
* VIPS_DEMAND_STYLE_FATSTRIP --- This operation would like to output strips
* #VIPS_DEMAND_STYLE_FATSTRIP --- This operation would like to output strips
* the width of the image and as high as possible. This option is suitable
* for area operations which do not violently transform coordinates, such
* as im_conv().
*
* VIPS_DEMAND_STYLE_SMALLTILE --- This is the most general demand format.
* #VIPS_DEMAND_STYLE_SMALLTILE --- This is the most general demand format.
* Output is demanded in small (around 100x100 pel) sections. This style works
* reasonably efficiently, even for bizzare operations like 45 degree rotate.
*
* VIPS_DEMAND_STYLE_ANY --- This image is not being demand-read from a disc
* #VIPS_DEMAND_STYLE_ANY --- This image is not being demand-read from a disc
* file (even indirectly) so any demand style is OK. It's used for things like
* im_black() where the pixels are calculated.
*

View File

@ -52,7 +52,6 @@ typedef struct _VipsObjectClass VipsObjectClass;
* @VIPS_ARGUMENT_SET_ONCE: can only be set once
* @VIPS_ARGUMENT_INPUT: is an input argument (one we depend on)
* @VIPS_ARGUMENT_OUTPUT: is an output argument (depends on us)
* @VIPS_ARGUMENT_APPEND: add to end of arg list (default is prepend)
*
* Flags we associate with each object argument.
*
@ -67,8 +66,7 @@ typedef enum {
VIPS_ARGUMENT_CONSTRUCT = 2,
VIPS_ARGUMENT_SET_ONCE = 4,
VIPS_ARGUMENT_INPUT = 8,
VIPS_ARGUMENT_OUTPUT = 16,
VIPS_ARGUMENT_APPEND = 32
VIPS_ARGUMENT_OUTPUT = 16
} VipsArgumentFlags;
/* Useful flag combinations. User-visible ones are:
@ -108,6 +106,96 @@ VIPS_ARGUMENT_OPTIONAL_OUTPUT Eg. the x pos of the image minimum
VIPS_ARGUMENT_CONSTRUCT | \
VIPS_ARGUMENT_SET_ONCE)
extern int _vips__argument_id;
#define VIPS_ARG_IMAGE( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_object( (NAME), (LONG), (DESC), \
VIPS_TYPE_IMAGE, \
G_PARAM_READWRITE ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
}
#define VIPS_ARG_BOOL( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_boolean( (NAME), (LONG), (DESC), \
(VALUE), \
G_PARAM_READWRITE ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
}
#define VIPS_ARG_DOUBLE( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
MIN, MAX, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_double( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \
G_PARAM_READWRITE );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
}
#define VIPS_ARG_INT( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
MIN, MAX, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_int( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \
G_PARAM_READWRITE );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
}
#define VIPS_ARG_ENUM( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
TYPE, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_enum( (NAME), (LONG), (DESC), \
(TYPE), (VALUE), \
G_PARAM_READWRITE );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
}
#define VIPS_ARG_STRING( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_string( (NAME), (LONG), (DESC), \
(VALUE), \
G_PARAM_READWRITE ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
}
#define VIPS_ARG_POINTER( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_pointer( (NAME), (LONG), (DESC), \
G_PARAM_READWRITE ); \
g_object_class_install_property( gobject_class, \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
}
/* Keep one of these for every argument.
*/
typedef struct _VipsArgument {
@ -126,6 +214,7 @@ typedef struct _VipsArgumentClass {
VipsObjectClass *object_class;
VipsArgumentFlags flags;
int priority; /* Order args by this */
guint offset; /* G_STRUCT_OFFSET of member in object */
} VipsArgumentClass;
@ -332,8 +421,8 @@ gboolean vips_object_sanity( VipsObject *object );
GType vips_object_get_type( void );
void vips_object_class_install_argument( VipsObjectClass *,
GParamSpec *pspec, VipsArgumentFlags flags, guint offset );
void vips_object_class_install_argument( VipsObjectClass *, GParamSpec *pspec,
VipsArgumentFlags flags, int priority, guint offset );
int vips_object_set_argument_from_string( VipsObject *object,
const char *name, const char *value );
gboolean vips_object_get_argument_needs_string( VipsObject *object,

View File

@ -41,6 +41,7 @@ INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
# well
vips_scan_headers = \
${top_srcdir}/libvips/include/vips/memory.h \
${top_srcdir}/libvips/include/vips/conversion.h \
${top_srcdir}/libvips/include/vips/util.h \
${top_srcdir}/libvips/include/vips/buf.h \
${top_srcdir}/libvips/include/vips/image.h \

View File

@ -4,6 +4,27 @@
/* auto-generated enums for vips introspection */
#include <vips/vips.h>
/* enumerations from "../../libvips/include/vips/conversion.h" */
GType
vips_extend_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GEnumValue values[] = {
{VIPS_EXTEND_BLACK, "VIPS_EXTEND_BLACK", "black"},
{VIPS_EXTEND_COPY, "VIPS_EXTEND_COPY", "copy"},
{VIPS_EXTEND_REPEAT, "VIPS_EXTEND_REPEAT", "repeat"},
{VIPS_EXTEND_MIRROR, "VIPS_EXTEND_MIRROR", "mirror"},
{VIPS_EXTEND_WHITE, "VIPS_EXTEND_WHITE", "white"},
{0, NULL, NULL}
};
etype = g_enum_register_static( "VipsExtend", values );
}
return( etype );
}
/* enumerations from "../../libvips/include/vips/util.h" */
GType
vips_token_get_type( void )
@ -158,7 +179,6 @@ vips_argument_flags_get_type( void )
{VIPS_ARGUMENT_SET_ONCE, "VIPS_ARGUMENT_SET_ONCE", "set-once"},
{VIPS_ARGUMENT_INPUT, "VIPS_ARGUMENT_INPUT", "input"},
{VIPS_ARGUMENT_OUTPUT, "VIPS_ARGUMENT_OUTPUT", "output"},
{VIPS_ARGUMENT_APPEND, "VIPS_ARGUMENT_APPEND", "append"},
{0, NULL, NULL}
};

View File

@ -143,28 +143,6 @@
* Returns: The address of pixel (x,y) in the image.
*/
/* Properties.
*/
enum {
PROP_WIDTH = 1,
PROP_HEIGHT,
PROP_BANDS,
PROP_FORMAT,
PROP_CODING,
PROP_INTERPRETATION,
PROP_XRES,
PROP_YRES,
PROP_XOFFSET,
PROP_YOFFSET,
PROP_FILENAME,
PROP_KILL,
PROP_MODE,
PROP_DEMAND,
PROP_SIZEOF_HEADER,
PROP_FOREIGN_BUFFER,
PROP_LAST
};
/* Our signals.
*/
enum {
@ -938,12 +916,11 @@ vips_image_class_init( VipsImageClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
GParamSpec *pspec;
VIPS_DEBUG_MSG( "vips_image_class_init:\n" );
/* Pass in a nonsense name for argv0 ... this init world is only here
* for old programs which are missing an vips_init() call. We must
* for old programs which are missing a vips_init() call. We must
* have threads set up before we can process.
*/
if( vips_init( "vips" ) )
@ -972,149 +949,114 @@ vips_image_class_init( VipsImageClass *class )
/* Create properties.
*/
/* Width / height / bands can be zero for unintialised.
*/
pspec = g_param_spec_int( "width", "Width",
VIPS_ARG_INT( class, "width", 2,
_( "Width" ),
_( "Image width in pixels" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_WIDTH, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Xsize ) );
pspec = g_param_spec_int( "height", "Height",
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Xsize ),
0, 1000000, 0 );
VIPS_ARG_INT( class, "height", 3,
_( "Height" ),
_( "Image height in pixels" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_HEIGHT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Ysize ) );
pspec = g_param_spec_int( "bands", "Bands",
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Ysize ),
0, 1000000, 0 );
VIPS_ARG_INT( class, "bands", 4,
_( "Bands" ),
_( "Number of bands in image" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_BANDS, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Bands ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Bands ),
0, 1000000, 0 );
pspec = g_param_spec_enum( "format", "Format",
VIPS_ARG_ENUM( class, "format", 5,
_( "Format" ),
_( "Pixel format in image" ),
VIPS_TYPE_BAND_FORMAT, VIPS_FORMAT_UCHAR,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_FORMAT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, BandFmt ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, BandFmt ),
VIPS_TYPE_BAND_FORMAT, VIPS_FORMAT_UCHAR );
pspec = g_param_spec_enum( "coding", "Coding",
VIPS_ARG_ENUM( class, "coding", 6,
_( "Coding" ),
_( "Pixel coding" ),
VIPS_TYPE_CODING, VIPS_CODING_NONE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_CODING, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Coding ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Coding ),
VIPS_TYPE_CODING, VIPS_CODING_NONE );
pspec = g_param_spec_enum( "interpretation", "Interpretation",
VIPS_ARG_ENUM( class, "interpretation", 7,
_( "Interpretation" ),
_( "Pixel interpretation" ),
VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_MULTIBAND,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_INTERPRETATION, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Type ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Type ),
VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_MULTIBAND );
pspec = g_param_spec_double( "xres", "XRes",
VIPS_ARG_DOUBLE( class, "xres", 8,
_( "Xres" ),
_( "Horizontal resolution in pixels/mm" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_XRES, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Xres ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Xres ),
0, 1000000, 0 );
pspec = g_param_spec_double( "yres", "YRes",
VIPS_ARG_DOUBLE( class, "yres", 9,
_( "Yres" ),
_( "Vertical resolution in pixels/mm" ),
0, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_YRES, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Yres ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Yres ),
0, 1000000, 0 );
pspec = g_param_spec_int( "xoffset", "XOffset",
VIPS_ARG_INT( class, "xoffset", 10,
_( "Xoffset" ),
_( "Horizontal offset of origin" ),
-10000000, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_XOFFSET, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Xoffset ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Xoffset ),
-1000000, 1000000, 0 );
pspec = g_param_spec_int( "yoffset", "YOffset",
VIPS_ARG_INT( class, "yoffset", 11,
_( "Yoffset" ),
_( "Vertical offset of origin" ),
-10000000, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_YOFFSET, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsImage, Yoffset ) );
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsImage, Yoffset ),
-1000000, 1000000, 0 );
pspec = g_param_spec_string( "filename", "Filename",
VIPS_ARG_STRING( class, "filename", 12,
_( "Filename" ),
_( "Image filename" ),
NULL,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_FILENAME, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_CONSTRUCT,
G_STRUCT_OFFSET( VipsImage, filename ) );
G_STRUCT_OFFSET( VipsImage, filename ),
NULL );
pspec = g_param_spec_string( "mode", "Mode",
VIPS_ARG_STRING( class, "mode", 13,
_( "Mode" ),
_( "Open mode" ),
"p", /* Default to partial */
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_MODE, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_CONSTRUCT,
G_STRUCT_OFFSET( VipsImage, mode ) );
G_STRUCT_OFFSET( VipsImage, filename ),
"p" );
pspec = g_param_spec_boolean( "kill", "Kill",
VIPS_ARG_BOOL( class, "kill", 14,
_( "Kill" ),
_( "Block evaluation on this image" ),
FALSE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_KILL, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_NONE,
G_STRUCT_OFFSET( VipsImage, kill ) );
G_STRUCT_OFFSET( VipsImage, kill ),
FALSE );
pspec = g_param_spec_enum( "demand", "Demand",
VIPS_ARG_ENUM( class, "demand", 15,
_( "Demand style" ),
_( "Preferred demand style for this image" ),
VIPS_TYPE_DEMAND_STYLE, VIPS_DEMAND_STYLE_SMALLTILE,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_DEMAND, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_NONE,
G_STRUCT_OFFSET( VipsImage, dhint ) );
VIPS_ARGUMENT_NONE,
G_STRUCT_OFFSET( VipsImage, dhint ),
VIPS_TYPE_DEMAND_STYLE, VIPS_DEMAND_STYLE_SMALLTILE );
pspec = g_param_spec_int( "sizeof_header", "Size of header",
VIPS_ARG_INT( class, "sizeof_header", 16,
_( "Size of header" ),
_( "Offset in bytes from start of file" ),
0, 1000000, VIPS_SIZEOF_HEADER,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_SIZEOF_HEADER, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE | VIPS_ARGUMENT_CONSTRUCT,
G_STRUCT_OFFSET( VipsImage, sizeof_header ) );
G_STRUCT_OFFSET( VipsImage, sizeof_header ),
0, 1000000, VIPS_SIZEOF_HEADER );
pspec = g_param_spec_pointer( "foreign_buffer", "Foreign buffer",
"Pointer to foreign pixels",
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_FOREIGN_BUFFER, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARG_POINTER( class, "foreign_buffer", 17,
_( "Foreign buffer" ),
_( "Pointer to foreign pixels" ),
VIPS_ARGUMENT_SET_ONCE | VIPS_ARGUMENT_CONSTRUCT,
G_STRUCT_OFFSET( VipsImage, data ) );

View File

@ -48,14 +48,6 @@
#include <vips/internal.h>
#include <vips/debug.h>
/* Properties.
*/
enum {
PROP_NICKNAME = 1,/* Class properties as object props */
PROP_DESCRIPTION,
PROP_LAST
};
/* Our signals.
*/
enum {
@ -72,6 +64,8 @@ static GMutex *vips__object_all_lock = NULL;
static guint vips_object_signals[SIG_LAST] = { 0 };
int _vips__argument_id = 0;
G_DEFINE_ABSTRACT_TYPE( VipsObject, vips_object, G_TYPE_OBJECT );
void
@ -1058,8 +1052,6 @@ vips_object_class_init( VipsObjectClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
GParamSpec *pspec;
if( !vips__object_all ) {
vips__object_all = g_hash_table_new(
g_direct_hash, g_direct_equal );
@ -1092,29 +1084,19 @@ vips_object_class_init( VipsObjectClass *class )
g_value_register_transform_func( G_TYPE_STRING, G_TYPE_DOUBLE,
transform_string_double );
/* Create properties.
*/
pspec = g_param_spec_string( "nickname",
VIPS_ARG_STRING( class, "nickname", 1,
_( "Nickname" ),
_( "Class nickname" ),
"",
(GParamFlags) G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_NICKNAME, pspec );
vips_object_class_install_argument( class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsObject, nickname ) );
G_STRUCT_OFFSET( VipsObject, nickname ),
"" );
pspec = g_param_spec_string( "description",
VIPS_ARG_STRING( class, "description", 2,
_( "Description" ),
_( "Class description" ),
"",
(GParamFlags) G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_DESCRIPTION, pspec );
vips_object_class_install_argument( class, pspec,
VIPS_ARGUMENT_SET_ONCE,
G_STRUCT_OFFSET( VipsObject, description ) );
G_STRUCT_OFFSET( VipsObject, description ),
"" );
vips_object_signals[SIG_PRECLOSE] = g_signal_new( "preclose",
G_TYPE_FROM_CLASS( class ),
@ -1154,11 +1136,20 @@ vips_object_init( VipsObject *object )
g_mutex_unlock( vips__object_all_lock );
}
static gint
traverse_sort( gconstpointer a, gconstpointer b )
{
VipsArgumentClass *class1 = (VipsArgumentClass *) a;
VipsArgumentClass *class2 = (VipsArgumentClass *) b;
return( class1->priority - class2->priority );
}
/* Add a vipsargument ... automate some stuff with this.
*/
void
vips_object_class_install_argument( VipsObjectClass *object_class,
GParamSpec *pspec, VipsArgumentFlags flags, guint offset )
GParamSpec *pspec, VipsArgumentFlags flags, int priority, guint offset )
{
VipsArgumentClass *argument_class = g_new( VipsArgumentClass, 1 );
@ -1181,16 +1172,15 @@ vips_object_class_install_argument( VipsObjectClass *object_class,
((VipsArgument *) argument_class)->pspec = pspec;
argument_class->object_class = object_class;
argument_class->flags = flags;
argument_class->priority = priority;
argument_class->offset = offset;
vips_argument_table_replace( object_class->argument_table,
(VipsArgument *) argument_class );
if( flags & VIPS_ARGUMENT_APPEND )
object_class->argument_table_traverse = g_slist_append(
object_class->argument_table_traverse, argument_class );
else
object_class->argument_table_traverse = g_slist_prepend(
object_class->argument_table_traverse, argument_class );
object_class->argument_table_traverse = g_slist_prepend(
object_class->argument_table_traverse, argument_class );
object_class->argument_table_traverse = g_slist_sort(
object_class->argument_table_traverse, traverse_sort );
}
/* Set a named arg from a string.