Merge remote-tracking branch 'origin/rot45'
This commit is contained in:
commit
7dfab19bb0
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
19/10/13 started 7.37.0
|
||||
- redone im_rotate_*mask45(), im_gauss_*mask*(), im_log_*mask(), im_dilate(),
|
||||
im_erode(), im_rank_image(), im_compass(), im_linedet(), im_gradient(),
|
||||
im_convsep(), im_convsep_f() as classes
|
||||
- vips_init() now does some ABI compat checking, though this change requires
|
||||
an ABI break
|
||||
- add "interlace" option to vips_jpegsave()
|
||||
- remove vips_image_copy_fields() and vips_demand_hint() and add
|
||||
vips_image_pipeline() to do both jobs
|
||||
- vipsthumbnail allows non-square bounding boxes, thanks seth
|
||||
- add vips_matrixprint()
|
||||
|
||||
18/10/13 started 7.36.3
|
||||
- fix compiler warnings in ubuntu 13.10
|
||||
- reverse similarity rotation direction to match the convention used
|
||||
|
39
TODO
39
TODO
@ -1,20 +1,9 @@
|
||||
|
||||
Next version
|
||||
============
|
||||
|
||||
- make vips_init() into a macro, check sizes of important structs against size
|
||||
at library compile time
|
||||
|
||||
add a new API call like vips__get_sizeof_image() which returns
|
||||
sizeof(VipsImage) from library compile time, compare that to the application
|
||||
compile-time value
|
||||
|
||||
vips_init() macro then passes control on to vips__init() for real startup
|
||||
|
||||
breaks binary API sadly
|
||||
|
||||
- do conv and morph quickly as simple wrappers over the vips7 operations
|
||||
|
||||
- add vips_gaussian_blur() with approx / int / float precision, maybe
|
||||
vips_resize() as well?
|
||||
|
||||
- do much fancier profiling with timing on all locks saved in memory and
|
||||
dumped on exit
|
||||
|
||||
@ -23,16 +12,6 @@ Next version
|
||||
|
||||
- use g_log() instead of vips_info()
|
||||
|
||||
- do we always call copy_fields and demand_hint with ALL input images? what
|
||||
about the operators in conversion?
|
||||
|
||||
could we add something to check that the two calls agree on the image lists?
|
||||
I think they should
|
||||
|
||||
- support multiscan jpeg write? see
|
||||
|
||||
https://github.com/jcupitt/ruby-vips/issues/41
|
||||
|
||||
- object construction is threadsafe, but class construction is not
|
||||
|
||||
https://github.com/jcupitt/libvips/issues/64
|
||||
@ -157,6 +136,18 @@ convolution
|
||||
|
||||
wait for vipsobject for this
|
||||
|
||||
- we have aconv and aconvsep
|
||||
|
||||
test timing, make sure it;s worth having a separate aconvsep version
|
||||
|
||||
if it is, make im_aconvsep an optimisation: call im_aconvsep_raw() from
|
||||
vips_conv() if mask width or height == 1 and prec == APPROX
|
||||
|
||||
now we can get rid of im_aconvsep() since it's just vips_convsep() with prec
|
||||
set to approx
|
||||
|
||||
aconv needs some more work, get it going at least with gaussian
|
||||
|
||||
|
||||
arithmetic
|
||||
==========
|
||||
|
12
configure.ac
12
configure.ac
@ -2,7 +2,7 @@
|
||||
|
||||
# also update the version number in the m4 macros below
|
||||
|
||||
AC_INIT([vips], [7.36.3], [vipsip@jiscmail.ac.uk])
|
||||
AC_INIT([vips], [7.37.0], [vipsip@jiscmail.ac.uk])
|
||||
# required for gobject-introspection
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
@ -16,8 +16,8 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
# user-visible library versioning
|
||||
m4_define([vips_major_version], [7])
|
||||
m4_define([vips_minor_version], [36])
|
||||
m4_define([vips_micro_version], [3])
|
||||
m4_define([vips_minor_version], [37])
|
||||
m4_define([vips_micro_version], [0])
|
||||
m4_define([vips_version],
|
||||
[vips_major_version.vips_minor_version.vips_micro_version])
|
||||
|
||||
@ -36,9 +36,9 @@ VIPS_VERSION_STRING=$VIPS_VERSION-`date`
|
||||
# binary interface changes backwards compatible?: increment age
|
||||
# binary interface changes not backwards compatible?: reset age to 0
|
||||
|
||||
LIBRARY_CURRENT=35
|
||||
LIBRARY_REVISION=3
|
||||
LIBRARY_AGE=0
|
||||
LIBRARY_CURRENT=36
|
||||
LIBRARY_REVISION=0
|
||||
LIBRARY_AGE=1
|
||||
|
||||
# patched into include/vips/version.h
|
||||
AC_SUBST(VIPS_VERSION)
|
||||
|
@ -545,11 +545,9 @@ vips_arithmetic_build( VipsObject *object )
|
||||
*/
|
||||
arithmetic->ready = size;
|
||||
|
||||
if( vips_image_copy_fields_array( arithmetic->out,
|
||||
arithmetic->ready ) )
|
||||
if( vips_image_pipeline_array( arithmetic->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, arithmetic->ready ) )
|
||||
return( -1 );
|
||||
vips_demand_hint_array( arithmetic->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, arithmetic->ready );
|
||||
|
||||
arithmetic->out->Bands = arithmetic->ready[0]->Bands;
|
||||
arithmetic->out->BandFmt =
|
||||
|
@ -150,7 +150,8 @@ vips_hist_find_build( VipsObject *object )
|
||||
|
||||
/* Make the output image.
|
||||
*/
|
||||
if( vips_image_copy_fields( hist_find->out, statistic->ready ) )
|
||||
if( vips_image_pipelinev( hist_find->out,
|
||||
VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) )
|
||||
return( -1 );
|
||||
vips_image_init_fields( hist_find->out,
|
||||
hist_find->hist->mx + 1, 1, hist_find->hist->bands,
|
||||
|
@ -163,7 +163,8 @@ vips_hist_find_indexed_build( VipsObject *object )
|
||||
|
||||
VIPS_UNREF( indexed->hist->reg );
|
||||
|
||||
if( vips_image_copy_fieldsv( indexed->out,
|
||||
if( vips_image_pipelinev( indexed->out,
|
||||
VIPS_DEMAND_STYLE_ANY,
|
||||
statistic->ready, indexed->index_ready, NULL ) )
|
||||
return( -1 );
|
||||
vips_image_init_fields( indexed->out,
|
||||
|
@ -154,7 +154,8 @@ vips_hist_find_ndim_build( VipsObject *object )
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( ndim->out, statistic->ready ) )
|
||||
if( vips_image_pipelinev( ndim->out,
|
||||
VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) )
|
||||
return( -1 );
|
||||
vips_image_init_fields( ndim->out,
|
||||
ndim->bins,
|
||||
|
@ -136,8 +136,10 @@ vips_profile_build( VipsObject *object )
|
||||
|
||||
/* Make the output image.
|
||||
*/
|
||||
if( vips_image_copy_fields( profile->columns, statistic->ready ) ||
|
||||
vips_image_copy_fields( profile->rows, statistic->ready ) )
|
||||
if( vips_image_pipelinev( profile->columns,
|
||||
VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) ||
|
||||
vips_image_pipelinev( profile->rows,
|
||||
VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) )
|
||||
return( -1 );
|
||||
profile->columns->Ysize = 1;
|
||||
profile->columns->BandFmt = VIPS_FORMAT_INT;
|
||||
|
@ -141,8 +141,10 @@ vips_project_build( VipsObject *object )
|
||||
|
||||
/* Make the output image.
|
||||
*/
|
||||
if( vips_image_copy_fields( project->columns, statistic->ready ) ||
|
||||
vips_image_copy_fields( project->rows, statistic->ready ) )
|
||||
if( vips_image_pipelinev( project->columns,
|
||||
VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) ||
|
||||
vips_image_pipelinev( project->rows,
|
||||
VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL ) )
|
||||
return( -1 );
|
||||
project->columns->Ysize = 1;
|
||||
project->columns->BandFmt =
|
||||
|
@ -320,10 +320,9 @@ vips_colour_build( VipsObject *object )
|
||||
*/
|
||||
g_assert( !colour->in[colour->n] );
|
||||
|
||||
if( vips_image_copy_fields_array( colour->out, colour->in ) )
|
||||
if( vips_image_pipeline_array( colour->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, colour->in ) )
|
||||
return( -1 );
|
||||
vips_demand_hint_array( colour->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, colour->in );
|
||||
colour->out->Coding = colour->coding;
|
||||
colour->out->Type = colour->interpretation;
|
||||
colour->out->BandFmt = colour->format;
|
||||
|
@ -17,12 +17,14 @@ libconversion_la_SOURCES = \
|
||||
replicate.c \
|
||||
cast.c \
|
||||
bandjoin.c \
|
||||
bandrank.c \
|
||||
recomb.c \
|
||||
bandmean.c \
|
||||
bandbool.c \
|
||||
bandary.h \
|
||||
bandary.c \
|
||||
rot.c \
|
||||
rot45.c \
|
||||
ifthenelse.c \
|
||||
falsecolour.c \
|
||||
msb.c \
|
||||
|
@ -147,10 +147,9 @@ vips_bandary_build( VipsObject *object )
|
||||
return( -1 );
|
||||
bandary->ready = size;
|
||||
|
||||
if( vips_image_copy_fields_array( conversion->out, bandary->ready ) )
|
||||
if( vips_image_pipeline_array( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, bandary->ready ) )
|
||||
return( -1 );
|
||||
vips_demand_hint_array( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, bandary->ready );
|
||||
|
||||
conversion->out->Bands = bandary->out_bands;
|
||||
|
||||
|
322
libvips/conversion/bandrank.c
Normal file
322
libvips/conversion/bandrank.c
Normal file
@ -0,0 +1,322 @@
|
||||
/* Sort a set of images, pixelwise, and pick out the index at each point.
|
||||
*
|
||||
* 19/8/03
|
||||
* - from im_maxvalue(), via im_gbandrank()
|
||||
* 10/11/10
|
||||
* - gtkdoc
|
||||
* - cleanups
|
||||
* - any mix of formats and bands
|
||||
* 23/10/13
|
||||
* - redo as a class, from bandrank.c
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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 "bandary.h"
|
||||
|
||||
typedef struct _VipsBandrank {
|
||||
VipsBandary parent_instance;
|
||||
|
||||
/* The input images.
|
||||
*/
|
||||
VipsArea *in;
|
||||
int index; /* Pick out this one */
|
||||
} VipsBandrank;
|
||||
|
||||
typedef VipsBandaryClass VipsBandrankClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsBandrank, vips_bandrank, VIPS_TYPE_BANDARY );
|
||||
|
||||
/* Special-case max and min (rather common).
|
||||
*/
|
||||
#define FIND_MAX( TYPE ) { \
|
||||
for( x = 0; x < sz; x++ ) { \
|
||||
TYPE top = ((TYPE *) p[0])[x]; \
|
||||
\
|
||||
for( i = 1; i < bandary->n; i++ ) { \
|
||||
TYPE v = ((TYPE *) p[i])[x]; \
|
||||
\
|
||||
if( v > top ) \
|
||||
top = v; \
|
||||
} \
|
||||
\
|
||||
((TYPE *) q)[x] = top; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FIND_MIN( TYPE ) { \
|
||||
for( x = 0; x < sz; x++ ) { \
|
||||
TYPE bot = ((TYPE *) p[0])[x]; \
|
||||
\
|
||||
for( i = 1; i < bandary->n; i++ ) { \
|
||||
TYPE v = ((TYPE *) p[i])[x]; \
|
||||
\
|
||||
if( v < bot ) \
|
||||
bot = v; \
|
||||
} \
|
||||
\
|
||||
((TYPE *) q)[x] = bot; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FIND_RANK( TYPE ) { \
|
||||
TYPE *sort = (TYPE *) sort_buffer; \
|
||||
\
|
||||
for( x = 0; x < sz; x++ ) { \
|
||||
for( i = 0; i < bandary->n; i++ ) { \
|
||||
TYPE v = ((TYPE *) p[i])[x]; \
|
||||
\
|
||||
/* Search for element >v.
|
||||
*/\
|
||||
for( j = 0; j < i; j++ ) \
|
||||
if( sort[j] > v ) \
|
||||
break; \
|
||||
\
|
||||
/* Move remaining elements down.
|
||||
*/ \
|
||||
for( k = i; k > j; k-- ) \
|
||||
sort[k] = sort[k - 1]; \
|
||||
\
|
||||
/* Insert this element.
|
||||
*/ \
|
||||
sort[j] = v; \
|
||||
} \
|
||||
\
|
||||
((TYPE *) q)[x] = sort[bandrank->index]; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SWITCH( OPERATION ) \
|
||||
switch( in[0]->BandFmt ) { \
|
||||
case VIPS_FORMAT_UCHAR: OPERATION( unsigned char ); break; \
|
||||
case VIPS_FORMAT_CHAR: OPERATION( signed char ); break; \
|
||||
case VIPS_FORMAT_USHORT: OPERATION( unsigned short ); break; \
|
||||
case VIPS_FORMAT_SHORT: OPERATION( signed short ); break; \
|
||||
case VIPS_FORMAT_UINT: OPERATION( unsigned int ); break; \
|
||||
case VIPS_FORMAT_INT: OPERATION( signed int ); break; \
|
||||
case VIPS_FORMAT_FLOAT: OPERATION( float ); break; \
|
||||
case VIPS_FORMAT_DOUBLE: OPERATION( double ); break; \
|
||||
\
|
||||
default: \
|
||||
g_assert( 0 ); \
|
||||
}
|
||||
|
||||
/* Sort input band elements in the stack. Needs to be big enough for
|
||||
* sizeof(band-element) * number-of-images.
|
||||
*/
|
||||
#define SORT_BUFFER (1024)
|
||||
|
||||
static void
|
||||
vips_bandrank_buffer( VipsBandary *bandary, VipsPel *q, VipsPel **p, int width )
|
||||
{
|
||||
VipsBandrank *bandrank = (VipsBandrank *) bandary;
|
||||
VipsImage **in = bandary->ready;
|
||||
int sz = width * in[0]->Bands;
|
||||
|
||||
int i, j, k;
|
||||
int x;
|
||||
VipsPel sort_buffer[SORT_BUFFER];
|
||||
|
||||
/* Special-case max and min.
|
||||
*/
|
||||
if( bandrank->index == 0 )
|
||||
SWITCH( FIND_MIN )
|
||||
else if( bandrank->index == bandary->n - 1 )
|
||||
SWITCH( FIND_MAX )
|
||||
else
|
||||
SWITCH( FIND_RANK )
|
||||
}
|
||||
|
||||
static int
|
||||
vips_bandrank_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsBandary *bandary = (VipsBandary *) object;
|
||||
VipsBandrank *bandrank = (VipsBandrank *) object;
|
||||
|
||||
if( bandrank->in ) {
|
||||
VipsImage **band = (VipsImage **)
|
||||
vips_object_local_array( object, bandrank->in->n );
|
||||
|
||||
if( bandrank->in->n == 1 )
|
||||
return( vips_bandary_copy( bandary ) );
|
||||
|
||||
/* We need to keep one band element for every input image
|
||||
* on the stack.
|
||||
*/
|
||||
if( sizeof( double ) * bandrank->in->n > SORT_BUFFER ) {
|
||||
vips_error( class->nickname,
|
||||
"%s", _( "too many input images" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips__bandalike_vec( class->nickname,
|
||||
bandrank->in->data, band, bandrank->in->n, 0 ) )
|
||||
return( -1 );
|
||||
|
||||
bandary->in = band;
|
||||
bandary->n = bandrank->in->n;
|
||||
bandary->out_bands = band[0]->Bands;
|
||||
|
||||
if( bandrank->index == -1 )
|
||||
bandrank->index = bandary->n / 2;
|
||||
}
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_bandrank_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_bandrank_class_init( VipsBandrankClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
|
||||
VipsBandaryClass *bandary_class = VIPS_BANDARY_CLASS( class );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_bandrank_class_init\n" );
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
vobject_class->nickname = "bandrank";
|
||||
vobject_class->description = _( "band-wise rank of a set of images" );
|
||||
vobject_class->build = vips_bandrank_build;
|
||||
|
||||
bandary_class->process_line = vips_bandrank_buffer;
|
||||
|
||||
VIPS_ARG_BOXED( class, "in", 0,
|
||||
_( "Input" ),
|
||||
_( "Array of input images" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsBandrank, in ),
|
||||
VIPS_TYPE_ARRAY_IMAGE );
|
||||
|
||||
VIPS_ARG_INT( class, "index", 0,
|
||||
_( "Index" ),
|
||||
_( "Select this band element from sorted list" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsBandrank, index ),
|
||||
-1, 1000000, -1 );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_bandrank_init( VipsBandrank *bandrank )
|
||||
{
|
||||
/* -1 means median.
|
||||
*/
|
||||
bandrank->index = -1;
|
||||
}
|
||||
|
||||
static int
|
||||
vips_bandrankv( VipsImage **in, VipsImage **out, int n, va_list ap )
|
||||
{
|
||||
VipsArea *area;
|
||||
VipsImage **array;
|
||||
int i;
|
||||
int result;
|
||||
|
||||
area = vips_area_new_array_object( n );
|
||||
array = (VipsImage **) area->data;
|
||||
for( i = 0; i < n; i++ ) {
|
||||
array[i] = in[i];
|
||||
g_object_ref( array[i] );
|
||||
}
|
||||
|
||||
result = vips_call_split( "bandrank", ap, area, out );
|
||||
|
||||
vips_area_unref( area );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_bandrank:
|
||||
* @in: array of input images
|
||||
* @out: output image
|
||||
* @n: number of input images
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @index: pick this index from list of sorted values
|
||||
*
|
||||
* Sorts the images @in band-element-wise, then outputs an
|
||||
* image in which each band element is selected from the sorted list by the
|
||||
* @index parameter. For example, if @index
|
||||
* is zero, then each output band element will be the minimum of all the
|
||||
* corresponding input band element.
|
||||
*
|
||||
* By default, @index is -1, meaning pick the median value.
|
||||
*
|
||||
* It works for any uncoded, non-complex image type. Images are cast up to the
|
||||
* smallest common-format.
|
||||
*
|
||||
* Any image can have either 1 band or n bands, where n is the same for all
|
||||
* the non-1-band images. Single band images are then effectively copied to
|
||||
* make n-band images.
|
||||
*
|
||||
* Smaller input images are expanded by adding black pixels.
|
||||
*
|
||||
* See also: vips_rank().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_bandrank( VipsImage **in, VipsImage **out, int n, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, n );
|
||||
result = vips_bandrankv( in, out, n, ap );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
@ -441,10 +441,9 @@ vips_cast_build( VipsObject *object )
|
||||
vips_image_pio_input( cast->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, cast->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, cast->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, cast->in, NULL );
|
||||
|
||||
conversion->out->BandFmt = cast->format;
|
||||
|
||||
|
@ -210,8 +210,10 @@ vips_conversion_operation_init( void )
|
||||
extern GType vips_replicate_get_type( void );
|
||||
extern GType vips_cast_get_type( void );
|
||||
extern GType vips_bandjoin_get_type( void );
|
||||
extern GType vips_bandrank_get_type( void );
|
||||
extern GType vips_black_get_type( void );
|
||||
extern GType vips_rot_get_type( void );
|
||||
extern GType vips_rot45_get_type( void );
|
||||
extern GType vips_ifthenelse_get_type( void );
|
||||
extern GType vips_recomb_get_type( void );
|
||||
extern GType vips_bandmean_get_type( void );
|
||||
@ -245,8 +247,10 @@ vips_conversion_operation_init( void )
|
||||
vips_replicate_get_type();
|
||||
vips_cast_get_type();
|
||||
vips_bandjoin_get_type();
|
||||
vips_bandrank_get_type();
|
||||
vips_black_get_type();
|
||||
vips_rot_get_type();
|
||||
vips_rot45_get_type();
|
||||
vips_ifthenelse_get_type();
|
||||
vips_recomb_get_type();
|
||||
vips_bandmean_get_type();
|
||||
|
@ -250,10 +250,9 @@ vips_copy_build( VipsObject *object )
|
||||
if( vips_image_pio_input( copy->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, copy->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL );
|
||||
|
||||
/* Use props to adjust header fields.
|
||||
*/
|
||||
|
@ -426,14 +426,12 @@ vips_embed_build( VipsObject *object )
|
||||
case VIPS_EXTEND_WHITE:
|
||||
case VIPS_EXTEND_BACKGROUND:
|
||||
case VIPS_EXTEND_COPY:
|
||||
if( vips_image_copy_fields( conversion->out, embed->in ) )
|
||||
return( -1 );
|
||||
|
||||
/* embed is used in many places. We don't really care about
|
||||
* geometry, so use ANY to avoid disturbing all pipelines.
|
||||
*/
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_ANY, embed->in, NULL );
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_ANY, embed->in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
conversion->out->Xsize = embed->width;
|
||||
conversion->out->Ysize = embed->height;
|
||||
|
@ -155,10 +155,9 @@ vips_extract_area_build( VipsObject *object )
|
||||
vips_check_coding_known( class->nickname, extract->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, extract->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, extract->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, extract->in, NULL );
|
||||
|
||||
conversion->out->Xsize = extract->width;
|
||||
conversion->out->Ysize = extract->height;
|
||||
|
@ -316,10 +316,9 @@ vips_flatten_build( VipsObject *object )
|
||||
vips_image_pio_input( flatten->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, flatten->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, flatten->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, flatten->in, NULL );
|
||||
|
||||
conversion->out->Bands -= 1;
|
||||
|
||||
|
@ -198,10 +198,9 @@ vips_flip_build( VipsObject *object )
|
||||
if( vips_image_pio_input( flip->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, flip->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, flip->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, flip->in, NULL );
|
||||
|
||||
if( flip->direction == VIPS_DIRECTION_HORIZONTAL ) {
|
||||
generate_fn = vips_flip_horizontal_gen;
|
||||
|
@ -166,12 +166,11 @@ vips_grid_build( VipsObject *object )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, grid->in ) )
|
||||
return( -1 );
|
||||
/* We can render small tiles with pointer copies.
|
||||
*/
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, grid->in, NULL );
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, grid->in, NULL ) )
|
||||
return( -1 );
|
||||
conversion->out->Xsize = grid->in->Xsize * grid->across;
|
||||
conversion->out->Ysize = grid->tile_height * grid->down;
|
||||
|
||||
|
@ -442,10 +442,9 @@ vips_ifthenelse_build( VipsObject *object )
|
||||
if( vips__formatalike_vec( size, format, 2 ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields_array( conversion->out, format ) )
|
||||
if( vips_image_pipeline_array( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, format ) )
|
||||
return( -1 );
|
||||
vips_demand_hint_array( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, format );
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_many, generate_fn, vips_stop_many,
|
||||
|
@ -284,10 +284,9 @@ vips_insert_build( VipsObject *object )
|
||||
insert->main_processed, insert->sub_processed, NULL )) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields_array( conversion->out, arry ) )
|
||||
if( vips_image_pipeline_array( conversion->out,
|
||||
VIPS_DEMAND_STYLE_ANY, arry ) )
|
||||
return( -1 );
|
||||
vips_demand_hint_array( conversion->out,
|
||||
VIPS_DEMAND_STYLE_ANY, arry );
|
||||
|
||||
/* Calculate geometry.
|
||||
*/
|
||||
|
@ -201,10 +201,9 @@ vips_msb_build( VipsObject *object )
|
||||
msb->in->BandFmt == VIPS_FORMAT_UCHAR )
|
||||
return( vips_image_write( msb->in, conversion->out ) );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, msb->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, msb->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, msb->in, NULL );
|
||||
|
||||
if( msb->band != -1 )
|
||||
conversion->out->Bands = 1;
|
||||
|
@ -164,10 +164,9 @@ vips_recomb_build( VipsObject *object )
|
||||
return( -1 );
|
||||
recomb->coeff = t[0];
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, recomb->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, recomb->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, recomb->in, NULL );
|
||||
|
||||
conversion->out->Bands = recomb->m->Ysize;
|
||||
if( vips_bandfmt_isint( recomb->in->BandFmt ) )
|
||||
|
@ -162,10 +162,9 @@ vips_replicate_build( VipsObject *object )
|
||||
if( vips_image_pio_input( replicate->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, replicate->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, replicate->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, replicate->in, NULL );
|
||||
|
||||
conversion->out->Xsize *= replicate->across;
|
||||
conversion->out->Ysize *= replicate->down;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* im_rot90
|
||||
/* rotate by 0/90/180/270 degrees
|
||||
*
|
||||
* Copyright: 1991, N. Dessipris
|
||||
* Written on: 28/10/91
|
||||
@ -294,13 +294,16 @@ vips_rot_build( VipsObject *object )
|
||||
if( vips_image_pio_input( rot->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, rot->in ) )
|
||||
hint = rot->angle == VIPS_ANGLE_180 ?
|
||||
VIPS_DEMAND_STYLE_THINSTRIP :
|
||||
VIPS_DEMAND_STYLE_SMALLTILE;
|
||||
|
||||
if( vips_image_pipelinev( conversion->out, hint, rot->in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
switch( rot->angle ) {
|
||||
case VIPS_ANGLE_90:
|
||||
generate_fn = vips_rot90_gen;
|
||||
hint = VIPS_DEMAND_STYLE_SMALLTILE;
|
||||
conversion->out->Xsize = rot->in->Ysize;
|
||||
conversion->out->Ysize = rot->in->Xsize;
|
||||
conversion->out->Xoffset = rot->in->Ysize;
|
||||
@ -309,14 +312,12 @@ vips_rot_build( VipsObject *object )
|
||||
|
||||
case VIPS_ANGLE_180:
|
||||
generate_fn = vips_rot180_gen;
|
||||
hint = VIPS_DEMAND_STYLE_THINSTRIP;
|
||||
conversion->out->Xoffset = rot->in->Xsize;
|
||||
conversion->out->Yoffset = rot->in->Ysize;
|
||||
break;
|
||||
|
||||
case VIPS_ANGLE_270:
|
||||
generate_fn = vips_rot270_gen;
|
||||
hint = VIPS_DEMAND_STYLE_SMALLTILE;
|
||||
conversion->out->Xsize = rot->in->Ysize;
|
||||
conversion->out->Ysize = rot->in->Xsize;
|
||||
conversion->out->Xoffset = 0;
|
||||
@ -331,8 +332,6 @@ vips_rot_build( VipsObject *object )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
vips_demand_hint( conversion->out, hint, rot->in, NULL );
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, generate_fn, vips_stop_one,
|
||||
rot->in, rot ) )
|
||||
|
319
libvips/conversion/rot45.c
Normal file
319
libvips/conversion/rot45.c
Normal file
@ -0,0 +1,319 @@
|
||||
/* 'lossless' 45 degree rotate ... odd-sized square images only
|
||||
*
|
||||
* Author: N. Dessipris (Copyright, N. Dessipris 1991)
|
||||
* Written on: 08/05/1991
|
||||
* Modified on: 28/05/1991
|
||||
* 12/10/95 JC
|
||||
* - small revisions, needs rewriting really
|
||||
* 7/8/96 JC
|
||||
* - absolutely foul desp code revised
|
||||
* - many bugs and mem leaks fixed
|
||||
* 1/3/99 JC
|
||||
* - oops, fns were not preserving scale and offset
|
||||
* 1/12/10
|
||||
* - allow any size mask for the 90 degree rot45ates by using im_rot4590().
|
||||
* 12/10/13
|
||||
* - rewritten 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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 <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#include "pconversion.h"
|
||||
|
||||
typedef struct _VipsRot45 {
|
||||
VipsConversion parent_instance;
|
||||
|
||||
/* The input image.
|
||||
*/
|
||||
VipsImage *in;
|
||||
|
||||
/* Rotate by ...
|
||||
*/
|
||||
VipsAngle45 angle;
|
||||
|
||||
} VipsRot45;
|
||||
|
||||
typedef VipsConversionClass VipsRot45Class;
|
||||
|
||||
G_DEFINE_TYPE( VipsRot45, vips_rot45, VIPS_TYPE_CONVERSION );
|
||||
|
||||
#define COPY( Q, P ) { \
|
||||
VipsPel *q = (Q); \
|
||||
VipsPel *p = (P); \
|
||||
int b;\
|
||||
\
|
||||
for( b = 0; b < ps; b++ )\
|
||||
q[b] = p[b];\
|
||||
}
|
||||
|
||||
#define ASSIGN( Xout, Yout, Xin, Yin ) \
|
||||
COPY( VIPS_IMAGE_ADDR( out, Xout, Yout ), \
|
||||
VIPS_IMAGE_ADDR( in, Xin, Yin ) )
|
||||
|
||||
#define POINT_TO_TEMP( q, Xin, Yin ) \
|
||||
COPY( q, VIPS_IMAGE_ADDR( in, Xin, Yin ) )
|
||||
|
||||
#define TEMP_TO_POINT( Xout, Yout, p ) \
|
||||
COPY( VIPS_IMAGE_ADDR( out, Xout, Yout ), p )
|
||||
|
||||
/* This can work inplace, ie. in == out is allowed.
|
||||
*/
|
||||
static void
|
||||
vips_rot45_rot45( VipsImage *out, VipsImage *in )
|
||||
{
|
||||
size_t ps = VIPS_IMAGE_SIZEOF_PEL( in );
|
||||
VipsPel *temp = VIPS_ARRAY( in, ps, VipsPel );
|
||||
int size = in->Xsize;
|
||||
int size_2 = size / 2;
|
||||
|
||||
int x, y;
|
||||
|
||||
g_assert( in->Xsize == in->Ysize );
|
||||
g_assert( out->Xsize == out->Ysize );
|
||||
g_assert( in->Xsize == out->Xsize );
|
||||
g_assert( in->Xsize % 2 == 1 );
|
||||
|
||||
/* Split the square into 8 triangles. Loop over the top-left one,
|
||||
* reflect to index the others.
|
||||
*
|
||||
* 1 1 2 2 3
|
||||
* 8 1 2 3 3
|
||||
* 8 8 x 4 4
|
||||
* 7 7 6 5 4
|
||||
* 7 6 6 5 5
|
||||
*
|
||||
* do the centre separately.
|
||||
*/
|
||||
|
||||
for( y = 0; y < size_2; y++ )
|
||||
for( x = y; x < size_2; x++ ) {
|
||||
/* Save 1, it goes into 2 at the end.
|
||||
*/
|
||||
POINT_TO_TEMP( temp, x, y );
|
||||
|
||||
/* Fill 1 from 8.
|
||||
*/
|
||||
ASSIGN( x, y,
|
||||
y, size_2 - (x - y) );
|
||||
|
||||
/* 8 from 7.
|
||||
*/
|
||||
ASSIGN( y, size_2 - (x - y),
|
||||
y, (size - 1) - x );
|
||||
|
||||
/* 7 from 6.
|
||||
*/
|
||||
ASSIGN( y, (size - 1) - x,
|
||||
size_2 - (x - y), (size - 1) - y );
|
||||
|
||||
/* 6 from 5.
|
||||
*/
|
||||
ASSIGN( size_2 - (x - y), (size - 1) - y,
|
||||
(size - 1) - x, (size - 1) - y );
|
||||
|
||||
/* 5 from 4.
|
||||
*/
|
||||
ASSIGN( (size - 1) - x, (size - 1) - y,
|
||||
(size - 1) - y, (x - y) + size_2 );
|
||||
|
||||
/* 4 from 3.
|
||||
*/
|
||||
ASSIGN( (size - 1) - y, (x - y) + size_2,
|
||||
(size - 1) - y, x );
|
||||
|
||||
/* 3 from 2.
|
||||
*/
|
||||
ASSIGN( (size - 1) - y, x,
|
||||
(x - y) + size_2, y );
|
||||
|
||||
/* 2 from saved 1.
|
||||
*/
|
||||
TEMP_TO_POINT( (x - y) + size_2, y, temp );
|
||||
}
|
||||
|
||||
/* Centre.
|
||||
*/
|
||||
ASSIGN( size_2, size_2, size_2, size_2 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_rot45_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConversion *conversion = VIPS_CONVERSION( object );
|
||||
VipsRot45 *rot45 = (VipsRot45 *) object;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
|
||||
|
||||
VipsImage *from;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_rot45_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_check_oddsquare( class->nickname, rot45->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( rot45->angle == VIPS_ANGLE45_0 )
|
||||
return( vips_image_write( rot45->in, conversion->out ) );
|
||||
|
||||
if( vips_image_wio_input( rot45->in ) )
|
||||
return( -1 );
|
||||
|
||||
t[0] = vips_image_new_buffer();
|
||||
if( vips_image_pipelinev( t[0],
|
||||
VIPS_DEMAND_STYLE_ANY, rot45->in, NULL ) )
|
||||
return( -1 );
|
||||
if( vips_image_write_prepare( t[0] ) )
|
||||
return( -1 );
|
||||
|
||||
from = rot45->in;
|
||||
|
||||
switch( rot45->angle ) {
|
||||
case VIPS_ANGLE45_315:
|
||||
vips_rot45_rot45( t[0], from );
|
||||
from = t[0];
|
||||
|
||||
case VIPS_ANGLE45_270:
|
||||
vips_rot45_rot45( t[0], from );
|
||||
from = t[0];
|
||||
|
||||
case VIPS_ANGLE45_225:
|
||||
vips_rot45_rot45( t[0], from );
|
||||
from = t[0];
|
||||
|
||||
case VIPS_ANGLE45_180:
|
||||
vips_rot45_rot45( t[0], from );
|
||||
from = t[0];
|
||||
|
||||
case VIPS_ANGLE45_135:
|
||||
vips_rot45_rot45( t[0], from );
|
||||
from = t[0];
|
||||
|
||||
case VIPS_ANGLE45_90:
|
||||
vips_rot45_rot45( t[0], from );
|
||||
from = t[0];
|
||||
|
||||
case VIPS_ANGLE45_45:
|
||||
vips_rot45_rot45( t[0], from );
|
||||
from = t[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
|
||||
/* Keep -Wall happy.
|
||||
*/
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( vips_image_write( t[0], conversion->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_rot45_class_init( VipsRot45Class *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_rot45_class_init\n" );
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
vobject_class->nickname = "rot45";
|
||||
vobject_class->description = _( "rotate an image" );
|
||||
vobject_class->build = vips_rot45_build;
|
||||
|
||||
VIPS_ARG_IMAGE( class, "in", 1,
|
||||
_( "Input" ),
|
||||
_( "Input image" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsRot45, in ) );
|
||||
|
||||
VIPS_ARG_ENUM( class, "angle", 6,
|
||||
_( "Angle" ),
|
||||
_( "Angle to rotate image" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsRot45, angle ),
|
||||
VIPS_TYPE_ANGLE45, VIPS_ANGLE45_45 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_rot45_init( VipsRot45 *rot45 )
|
||||
{
|
||||
rot45->angle = VIPS_ANGLE45_45;
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_rot45:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @angle: rotation angle
|
||||
*
|
||||
* Rotate @in by a multiple of 45 degrees. Odd-length sides and square images
|
||||
* only.
|
||||
*
|
||||
* See also: vips_rot().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_rot45( VipsImage *in, VipsImage **out, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, out );
|
||||
result = vips_call_split( "rot45", ap, in, out );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
@ -273,10 +273,9 @@ vips_sequential_build( VipsObject *object )
|
||||
|
||||
vips_object_local( object, t );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, t ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, t, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, t, NULL );
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, vips_sequential_generate, vips_stop_one,
|
||||
t, sequential ) )
|
||||
|
@ -209,10 +209,14 @@ vips_subsample_build( VipsObject *object )
|
||||
vips_check_coding_known( class->nickname, subsample->in ) )
|
||||
return( -1 );
|
||||
|
||||
/* Set demand hints. We want THINSTRIP, as we will be demanding a
|
||||
* large area of input for each output line.
|
||||
*/
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, subsample->in, NULL ) )
|
||||
return( -1 );
|
||||
/* Prepare output. Note: we round the output width down!
|
||||
*/
|
||||
if( vips_image_copy_fields( conversion->out, subsample->in ) )
|
||||
return( -1 );
|
||||
conversion->out->Xsize = subsample->in->Xsize / subsample->xfac;
|
||||
conversion->out->Ysize = subsample->in->Ysize / subsample->yfac;
|
||||
conversion->out->Xres = subsample->in->Xres / subsample->xfac;
|
||||
@ -224,12 +228,6 @@ vips_subsample_build( VipsObject *object )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Set demand hints. We want THINSTRIP, as we will be demanding a
|
||||
* large area of input for each output line.
|
||||
*/
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, subsample->in, NULL );
|
||||
|
||||
/* Generate! If this is a very large shrink, then it's
|
||||
* probably faster to do it a pixel at a time.
|
||||
*/
|
||||
|
@ -740,10 +740,9 @@ vips_tile_cache_build( VipsObject *object )
|
||||
if( vips_image_pio_input( block_cache->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, block_cache->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, block_cache->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_SMALLTILE, block_cache->in, NULL );
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, vips_tile_cache_gen, vips_stop_one,
|
||||
@ -926,10 +925,9 @@ vips_line_cache_build( VipsObject *object )
|
||||
if( vips_image_pio_input( block_cache->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, block_cache->in ) )
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, block_cache->in, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, block_cache->in, NULL );
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, vips_line_cache_gen, vips_stop_one,
|
||||
|
@ -349,13 +349,12 @@ vips_zoom_build( VipsObject *object )
|
||||
vips_check_coding_known( class->nickname, zoom->in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fields( conversion->out, zoom->in ) )
|
||||
return( -1 );
|
||||
/* Set demand hints. THINSTRIP will prevent us from using
|
||||
* vips_zoom_paint_whole() much ... so go for FATSTRIP.
|
||||
*/
|
||||
vips_demand_hint( conversion->out,
|
||||
VIPS_DEMAND_STYLE_FATSTRIP, zoom->in, NULL );
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_FATSTRIP, zoom->in, NULL ) )
|
||||
return( -1 );
|
||||
conversion->out->Xsize = zoom->in->Xsize * zoom->xfac;
|
||||
conversion->out->Ysize = zoom->in->Ysize * zoom->yfac;
|
||||
|
||||
|
@ -4,9 +4,10 @@ libconvolution_la_SOURCES = \
|
||||
convolution.c \
|
||||
pconvolution.h \
|
||||
conv.c \
|
||||
convsep.c \
|
||||
compass.c \
|
||||
morph.c \
|
||||
convol_dispatch.c \
|
||||
im_addgnoise.c \
|
||||
im_compass.c \
|
||||
im_aconv.c \
|
||||
im_aconvsep.c \
|
||||
im_conv.c \
|
||||
|
214
libvips/convolution/compass.c
Normal file
214
libvips/convolution/compass.c
Normal file
@ -0,0 +1,214 @@
|
||||
/* repeatedly convolve with a rotating mask
|
||||
*
|
||||
* 23/10/13
|
||||
* - from vips_conv()
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#include "pconvolution.h"
|
||||
|
||||
typedef struct {
|
||||
VipsConvolution parent_instance;
|
||||
|
||||
int times;
|
||||
VipsAngle45 angle;
|
||||
VipsCombine combine;
|
||||
VipsPrecision precision;
|
||||
int layers;
|
||||
int cluster;
|
||||
} VipsCompass;
|
||||
|
||||
typedef VipsConvolutionClass VipsCompassClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsCompass, vips_compass, VIPS_TYPE_CONVOLUTION );
|
||||
|
||||
static int
|
||||
vips_compass_build( VipsObject *object )
|
||||
{
|
||||
VipsConvolution *convolution = (VipsConvolution *) object;
|
||||
VipsCompass *compass = (VipsCompass *) object;
|
||||
VipsImage **masks;
|
||||
VipsImage *mask;
|
||||
VipsImage **images;
|
||||
int i;
|
||||
VipsImage **abs;
|
||||
VipsImage **combine;
|
||||
VipsImage *x;
|
||||
|
||||
g_object_set( compass, "out", vips_image_new(), NULL );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_compass_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
masks = (VipsImage **)
|
||||
vips_object_local_array( object, compass->times );
|
||||
images = (VipsImage **)
|
||||
vips_object_local_array( object, compass->times );
|
||||
abs = (VipsImage **)
|
||||
vips_object_local_array( object, compass->times );
|
||||
combine = (VipsImage **)
|
||||
vips_object_local_array( object, compass->times );
|
||||
|
||||
mask = convolution->M;
|
||||
for( i = 0; i < compass->times; i++ ) {
|
||||
if( vips_conv( convolution->in, &images[i], mask,
|
||||
"precision", compass->precision,
|
||||
"layers", compass->layers,
|
||||
"cluster", compass->cluster,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( vips_rot45( mask, &masks[i],
|
||||
"angle", compass->angle,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
mask = masks[i];
|
||||
}
|
||||
|
||||
for( i = 0; i < compass->times; i++ )
|
||||
if( vips_abs( images[i], &abs[i], NULL ) )
|
||||
return( -1 );
|
||||
|
||||
switch( compass->combine ) {
|
||||
case VIPS_COMBINE_MAX:
|
||||
if( vips_bandrank( abs, &combine[0], compass->times,
|
||||
"index", compass->times - 1,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
x = combine[0];
|
||||
break;
|
||||
|
||||
case VIPS_COMBINE_SUM:
|
||||
x = abs[0];
|
||||
for( i = 1; i < compass->times; i++ ) {
|
||||
if( vips_add( x, abs[i], &combine[i], NULL ) )
|
||||
return( -1 );
|
||||
x = combine[i];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
|
||||
if( vips_image_write( x, convolution->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_compass_class_init( VipsCompassClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "compass";
|
||||
object_class->description = _( "convolution operation" );
|
||||
object_class->build = vips_compass_build;
|
||||
|
||||
VIPS_ARG_INT( class, "times", 101,
|
||||
_( "Times" ),
|
||||
_( "Rotate and convolve this many times" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsCompass, times ),
|
||||
1, 1000, 2 );
|
||||
|
||||
VIPS_ARG_ENUM( class, "angle", 103,
|
||||
_( "Angle" ),
|
||||
_( "Rotate mask by this much between convolutions" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsCompass, angle ),
|
||||
VIPS_TYPE_ANGLE45, VIPS_ANGLE45_90 );
|
||||
|
||||
VIPS_ARG_ENUM( class, "combine", 104,
|
||||
_( "Combine" ),
|
||||
_( "Combine convolution results like this" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsCompass, combine ),
|
||||
VIPS_TYPE_COMBINE, VIPS_COMBINE_MAX );
|
||||
|
||||
VIPS_ARG_ENUM( class, "precision", 203,
|
||||
_( "Precision" ),
|
||||
_( "Convolve with this precision" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsCompass, precision ),
|
||||
VIPS_TYPE_PRECISION, VIPS_PRECISION_INTEGER );
|
||||
|
||||
VIPS_ARG_INT( class, "layers", 204,
|
||||
_( "Layers" ),
|
||||
_( "Use this many layers in approximation" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsCompass, layers ),
|
||||
1, 1000, 5 );
|
||||
|
||||
VIPS_ARG_INT( class, "cluster", 205,
|
||||
_( "Cluster" ),
|
||||
_( "Cluster lines closer than this in approximation" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsCompass, cluster ),
|
||||
1, 100, 1 );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_compass_init( VipsCompass *compass )
|
||||
{
|
||||
compass->times = 2;
|
||||
compass->angle = VIPS_ANGLE45_90;
|
||||
compass->combine = VIPS_COMBINE_MAX;
|
||||
compass->precision = VIPS_PRECISION_INTEGER;
|
||||
compass->layers = 5;
|
||||
compass->cluster = 1;
|
||||
}
|
||||
|
||||
int
|
||||
vips_compass( VipsImage *in, VipsImage **out, VipsImage *mask, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, mask );
|
||||
result = vips_call_split( "compass", ap, in, out, mask );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
@ -62,6 +62,7 @@ G_DEFINE_TYPE( VipsConv, vips_conv, VIPS_TYPE_CONVOLUTION );
|
||||
static int
|
||||
vips_conv_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConvolution *convolution = (VipsConvolution *) object;
|
||||
VipsConv *conv = (VipsConv *) object;
|
||||
|
||||
@ -73,27 +74,32 @@ vips_conv_build( VipsObject *object )
|
||||
if( VIPS_OBJECT_CLASS( vips_conv_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
/*
|
||||
printf( "vips_conv_build: convolving with:\n" );
|
||||
vips_matrixprint( convolution->M, NULL );
|
||||
*/
|
||||
|
||||
if( !(imsk = im_vips2imask( convolution->M, class->nickname )) ||
|
||||
!im_local_imask( convolution->out, imsk ) )
|
||||
return( -1 );
|
||||
if( !(dmsk = im_vips2mask( convolution->M, class->nickname )) ||
|
||||
!im_local_dmask( convolution->out, dmsk ) )
|
||||
return( -1 );
|
||||
|
||||
switch( conv->precision ) {
|
||||
case VIPS_PRECISION_INTEGER:
|
||||
if( !(imsk = im_vips2imask( convolution->M, "im_stats" )) ||
|
||||
!im_local_imask( convolution->out, imsk ) ||
|
||||
im_conv( convolution->in, convolution->out, imsk ) )
|
||||
if( im_conv( convolution->in, convolution->out, imsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
case VIPS_PRECISION_FLOAT:
|
||||
if( !(dmsk = im_vips2mask( convolution->M, "im_stats" )) ||
|
||||
!im_local_dmask( convolution->out, dmsk ) ||
|
||||
im_conv_f( convolution->in, convolution->out, dmsk ) )
|
||||
if( im_conv_f( convolution->in, convolution->out, dmsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
case VIPS_PRECISION_APPROXIMATE:
|
||||
if( !(dmsk = im_vips2mask( convolution->M, "im_stats" )) ||
|
||||
!im_local_dmask( convolution->out, dmsk ) ||
|
||||
im_aconv( convolution->in, convolution->out, dmsk,
|
||||
conv->layers, conv->cluster ) )
|
||||
if( im_aconv( convolution->in, convolution->out, dmsk,
|
||||
conv->layers, conv->cluster ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
|
@ -78,8 +78,8 @@ G_DEFINE_ABSTRACT_TYPE( VipsConvolution, vips_convolution,
|
||||
static int
|
||||
vips_convolution_build( VipsObject *object )
|
||||
{
|
||||
VipsConvolution *convolution = VIPS_CONVOLUTION( object );
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConvolution *convolution = VIPS_CONVOLUTION( object );
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -127,7 +127,7 @@ vips_convolution_class_init( VipsConvolutionClass *class )
|
||||
VIPS_ARGUMENT_REQUIRED_OUTPUT,
|
||||
G_STRUCT_OFFSET( VipsConvolution, out ) );
|
||||
|
||||
VIPS_ARG_IMAGE( class, "mask", 102,
|
||||
VIPS_ARG_IMAGE( class, "mask", 20,
|
||||
_( "Mask" ),
|
||||
_( "Input matrix image" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
@ -147,6 +147,12 @@ void
|
||||
vips_convolution_operation_init( void )
|
||||
{
|
||||
extern int vips_conv_get_type( void );
|
||||
extern int vips_morph_get_type( void );
|
||||
extern int vips_compass_get_type( void );
|
||||
extern int vips_convsep_get_type( void );
|
||||
|
||||
vips_conv_get_type();
|
||||
vips_morph_get_type();
|
||||
vips_compass_get_type();
|
||||
vips_convsep_get_type();
|
||||
}
|
||||
|
173
libvips/convolution/convsep.c
Normal file
173
libvips/convolution/convsep.c
Normal file
@ -0,0 +1,173 @@
|
||||
/* convolve twice, rotating the mask
|
||||
*
|
||||
* 23/10/13
|
||||
* - from vips_convsep()
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#include "pconvolution.h"
|
||||
|
||||
typedef struct {
|
||||
VipsConvolution parent_instance;
|
||||
|
||||
VipsPrecision precision;
|
||||
int layers;
|
||||
int cluster;
|
||||
} VipsConvsep;
|
||||
|
||||
typedef VipsConvolutionClass VipsConvsepClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsConvsep, vips_convsep, VIPS_TYPE_CONVOLUTION );
|
||||
|
||||
static int
|
||||
vips_convsep_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConvolution *convolution = (VipsConvolution *) object;
|
||||
VipsConvsep *convsep = (VipsConvsep *) object;
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( object, 3 );
|
||||
|
||||
g_object_set( convsep, "out", vips_image_new(), NULL );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_convsep_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_check_separable( class->nickname, convolution->M ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_rot( convolution->M, &t[0], VIPS_ANGLE_90, NULL ) ||
|
||||
vips_conv( convolution->in, &t[1], convolution->M,
|
||||
"precision", convsep->precision,
|
||||
"layers", convsep->layers,
|
||||
"cluster", convsep->cluster,
|
||||
NULL ) ||
|
||||
vips_conv( t[1], &t[2], t[0],
|
||||
"precision", convsep->precision,
|
||||
"layers", convsep->layers,
|
||||
"cluster", convsep->cluster,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_write( t[2], convolution->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_convsep_class_init( VipsConvsepClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "convsep";
|
||||
object_class->description = _( "convolution operation" );
|
||||
object_class->build = vips_convsep_build;
|
||||
|
||||
VIPS_ARG_ENUM( class, "precision", 203,
|
||||
_( "Precision" ),
|
||||
_( "Convolve with this precision" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsConvsep, precision ),
|
||||
VIPS_TYPE_PRECISION, VIPS_PRECISION_INTEGER );
|
||||
|
||||
VIPS_ARG_INT( class, "layers", 204,
|
||||
_( "Layers" ),
|
||||
_( "Use this many layers in approximation" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsConvsep, layers ),
|
||||
1, 1000, 5 );
|
||||
|
||||
VIPS_ARG_INT( class, "cluster", 205,
|
||||
_( "Cluster" ),
|
||||
_( "Cluster lines closer than this in approximation" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsConvsep, cluster ),
|
||||
1, 100, 1 );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_convsep_init( VipsConvsep *convsep )
|
||||
{
|
||||
convsep->precision = VIPS_PRECISION_INTEGER;
|
||||
convsep->layers = 5;
|
||||
convsep->cluster = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_convsep:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: convolution mask
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @precision: calculation accuracy
|
||||
* @layers: number of layers for approximation
|
||||
* @cluster: cluster lines closer than this distance
|
||||
*
|
||||
* Perform a separable convolution of @in with @mask.
|
||||
* See vips_conv() for a detailed description.
|
||||
*
|
||||
* The mask must be 1xn or nx1 elements.
|
||||
*
|
||||
* The image is convolved twice: once with @mask and then again with @mask
|
||||
* rotated by 90 degrees. This is much faster for certain types of mask
|
||||
* (gaussian blur, for example) than doing a full 2D convolution.
|
||||
*
|
||||
* See also: vips_conv(), vips_gaussmat().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_convsep( VipsImage *in, VipsImage **out, VipsImage *mask, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, mask );
|
||||
result = vips_call_split( "convsep", ap, in, out, mask );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/* im_addgnoise
|
||||
*
|
||||
* Copyright 1990, N. Dessipris.
|
||||
*
|
||||
* File written on 2/12/1986
|
||||
* Author : N. Dessipris
|
||||
* Updated : 22/01/1991
|
||||
* 1/2/95 JC
|
||||
* - junked!
|
||||
* - now uses partial im_gaussnoise() and partial im_add() to do the
|
||||
* same job
|
||||
& 1/5/01 JC
|
||||
* - oops, failed for not-1-band images
|
||||
*
|
||||
* 2008-01-28 tcv:
|
||||
* - now works (was broken)
|
||||
* - no limit on bands
|
||||
* 4/2/10
|
||||
* - no need to bandup here now, im_add() does that
|
||||
* - gtkdoc
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
/**
|
||||
* im_addgnoise:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @sigma: standard deviation of noise
|
||||
*
|
||||
* Add gaussian noise with mean 0 and variance sigma to @in.
|
||||
* The noise is generated by averaging 12 random numbers,
|
||||
* see page 78, PIETGEN, 1989.
|
||||
*
|
||||
* See also: im_gaussnoise().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_addgnoise( IMAGE *in, IMAGE *out, double sigma )
|
||||
{
|
||||
IMAGE *t;
|
||||
|
||||
if( !(t = im_open_local( out, "im_addgnoise", "p" )) ||
|
||||
im_gaussnoise( t, in->Xsize, in->Ysize, 0, sigma ) ||
|
||||
im_add( in, t, out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
/* im_compass
|
||||
*
|
||||
* Author: N. Dessipris (Copyright, N. Dessipris 1991)
|
||||
* Written on: 08/05/1991
|
||||
* Modified on:
|
||||
* 11/3/01 JC
|
||||
* - rewritten, calling im_conv() and im_maxvalue()
|
||||
* 3/2/10
|
||||
* - gtkdoc
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
/**
|
||||
* im_compass:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: convolution mask
|
||||
*
|
||||
* @in is convolved 8 times with @mask, each time @mask is rotated by 45
|
||||
* degrees. Each output pixel is the largest absolute value of the 8
|
||||
* convolutions.
|
||||
*
|
||||
* See also: im_lindetect(), im_gradient(), im_conv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_compass( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
IMAGE *filtered[8];
|
||||
IMAGE *absed[8];
|
||||
int i;
|
||||
|
||||
if( im_open_local_array( out, filtered, 8, "im_compass:1", "p" ) ||
|
||||
im_open_local_array( out, absed, 8, "im_compass:2", "p" ) )
|
||||
return( -1 );
|
||||
|
||||
for( i = 0; i < 8; i++ ) {
|
||||
if( im_conv( in, filtered[i], mask ) ||
|
||||
!(mask = im_local_imask( out,
|
||||
im_rotate_imask45( mask, mask->filename ) )) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
if( im_abs( filtered[i], absed[i] ) )
|
||||
return( -1 );
|
||||
|
||||
return( im_maxvalue( absed, out, 8 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_lindetect:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: convolution mask
|
||||
*
|
||||
* @in is convolved four times with @mask, each time @mask is rotated by 45
|
||||
* degrees. Each output pixel is the largest absolute value of the four
|
||||
* convolutions.
|
||||
*
|
||||
* See also: im_compass(), im_gradient(), im_conv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_lindetect( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
IMAGE *filtered[4];
|
||||
IMAGE *absed[4];
|
||||
int i;
|
||||
|
||||
if( im_open_local_array( out, filtered, 4, "im_lindetect:1", "p" ) ||
|
||||
im_open_local_array( out, absed, 4, "im_lindetect:2", "p" ) )
|
||||
return( -1 );
|
||||
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
if( im_conv( in, filtered[i], mask ) ||
|
||||
!(mask = im_local_imask( out,
|
||||
im_rotate_imask45( mask, mask->filename ) )) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
if( im_abs( filtered[i], absed[i] ) )
|
||||
return( -1 );
|
||||
|
||||
return( im_maxvalue( absed, out, 4 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_gradient:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: convolution mask
|
||||
*
|
||||
* @in is convolved with @mask and with @mask after a 90 degree rotation. The
|
||||
* result is the sum of the absolute value of the two convolutions.
|
||||
*
|
||||
* See also: im_lindetect(), im_gradient(), im_conv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_gradient( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
IMAGE *t[4];
|
||||
INTMASK *rmask;
|
||||
|
||||
if( im_open_local_array( out, t, 4, "im_gradient", "p" ) )
|
||||
return( -1 );
|
||||
|
||||
if( !(rmask = im_local_imask( out,
|
||||
im_rotate_imask90( mask, mask->filename ) )) )
|
||||
return( -1 );
|
||||
|
||||
if( im_conv( in, t[0], mask ) ||
|
||||
im_conv( in, t[1], rmask ) ||
|
||||
im_abs( t[0], t[2] ) ||
|
||||
im_abs( t[1], t[3] ) ||
|
||||
im_add( t[2], t[3], out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
@ -1075,28 +1075,6 @@ im_conv_raw( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_conv:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: convolution mask
|
||||
*
|
||||
* Convolve @in with @mask using integer arithmetic. The output image
|
||||
* always has the same #VipsBandFmt as the input image.
|
||||
*
|
||||
* Each output pixel is
|
||||
* calculated as sigma[i]{pixel[i] * mask[i]} / scale + offset, where scale
|
||||
* and offset are part of @mask. For integer @in, the division by scale
|
||||
* includes round-to-nearest.
|
||||
*
|
||||
* Convolutions on unsigned 8-bit images are calculated with the
|
||||
* processor's vector unit,
|
||||
* if possible. Disable this with --vips-novector or IM_NOVECTOR.
|
||||
*
|
||||
* See also: im_conv_f(), im_convsep(), im_create_imaskv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_conv( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
@ -1114,72 +1092,3 @@ im_conv( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_convsep_raw( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
IMAGE *t;
|
||||
INTMASK *rmask;
|
||||
|
||||
if( mask->xsize != 1 && mask->ysize != 1 ) {
|
||||
im_error( "im_convsep",
|
||||
"%s", _( "expect 1xN or Nx1 input mask" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( !(t = im_open_local( out, "im_convsep", "p" )) ||
|
||||
!(rmask = (INTMASK *) im_local( out,
|
||||
(im_construct_fn) im_dup_imask,
|
||||
(im_callback_fn) im_free_imask, mask, mask->filename, NULL )) )
|
||||
return( -1 );
|
||||
|
||||
rmask->xsize = mask->ysize;
|
||||
rmask->ysize = mask->xsize;
|
||||
rmask->offset = 0.;
|
||||
|
||||
if( im_conv_raw( in, t, rmask ) ||
|
||||
im_conv_raw( t, out, mask ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_convsep:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: convolution mask
|
||||
*
|
||||
* Perform a separable convolution of @in with @mask using integer arithmetic.
|
||||
* See im_conv() for a detailed description.
|
||||
*
|
||||
* The mask must be 1xn or nx1 elements.
|
||||
* The output image
|
||||
* always has the same #VipsBandFmt as the input image.
|
||||
*
|
||||
* The image is convolved twice: once with @mask and then again with @mask
|
||||
* rotated by 90 degrees. This is much faster for certain types of mask
|
||||
* (gaussian blur, for example) than doing a full 2D convolution.
|
||||
*
|
||||
* See also: im_convsep_f(), im_conv(), im_create_imaskv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_convsep( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
IMAGE *t1 = im_open_local( out, "im_convsep intermediate", "p" );
|
||||
int n_mask = mask->xsize * mask->ysize;
|
||||
|
||||
if( !t1 ||
|
||||
im_embed( in, t1, 1, n_mask / 2, n_mask / 2,
|
||||
in->Xsize + n_mask - 1,
|
||||
in->Ysize + n_mask - 1 ) ||
|
||||
im_convsep_raw( t1, out, mask ) )
|
||||
return( -1 );
|
||||
|
||||
out->Xoffset = 0;
|
||||
out->Yoffset = 0;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -392,77 +392,3 @@ im_conv_f( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_convsep_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
|
||||
{
|
||||
IMAGE *t;
|
||||
DOUBLEMASK *rmask;
|
||||
|
||||
if( mask->xsize != 1 && mask->ysize != 1 ) {
|
||||
im_error( "im_convsep_f",
|
||||
"%s", _( "expect 1xN or Nx1 input mask" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( !(t = im_open_local( out, "im_convsep_f", "p" )) ||
|
||||
!(rmask = (DOUBLEMASK *) im_local( out,
|
||||
(im_construct_fn) im_dup_dmask,
|
||||
(im_callback_fn) im_free_dmask, mask, mask->filename, NULL )) )
|
||||
return( -1 );
|
||||
|
||||
rmask->xsize = mask->ysize;
|
||||
rmask->ysize = mask->xsize;
|
||||
rmask->offset = 0.;
|
||||
|
||||
if( im_conv_f_raw( in, t, rmask ) ||
|
||||
im_conv_f_raw( t, out, mask ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_convsep_f:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: convolution mask
|
||||
*
|
||||
* Perform a separable convolution of @in with @mask using floating-point
|
||||
* arithmetic.
|
||||
*
|
||||
* The mask must be 1xn or nx1 elements.
|
||||
* The output image
|
||||
* is always %IM_BANDFMT_FLOAT unless @in is %IM_BANDFMT_DOUBLE, in which case
|
||||
* @out is also %IM_BANDFMT_DOUBLE.
|
||||
*
|
||||
* The image is convolved twice: once with @mask and then again with @mask
|
||||
* rotated by 90 degrees. This is much faster for certain types of mask
|
||||
* (gaussian blur, for example) than doing a full 2D convolution.
|
||||
*
|
||||
* Each output pixel is
|
||||
* calculated as sigma[i]{pixel[i] * mask[i]} / scale + offset, where scale
|
||||
* and offset are part of @mask.
|
||||
*
|
||||
* See also: im_convsep(), im_conv(), im_create_dmaskv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
im_convsep_f( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
|
||||
{
|
||||
IMAGE *t1 = im_open_local( out, "im_convsep intermediate", "p" );
|
||||
int size = mask->xsize * mask->ysize;
|
||||
|
||||
if( !t1 ||
|
||||
im_embed( in, t1, 1, size / 2, size / 2,
|
||||
in->Xsize + size - 1,
|
||||
in->Ysize + size - 1 ) ||
|
||||
im_convsep_f_raw( t1, out, mask ) )
|
||||
return( -1 );
|
||||
|
||||
out->Xoffset = 0;
|
||||
out->Yoffset = 0;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
179
libvips/convolution/morph.c
Normal file
179
libvips/convolution/morph.c
Normal file
@ -0,0 +1,179 @@
|
||||
/* morphology
|
||||
*
|
||||
* 23/10/13
|
||||
* - from vips_conv()
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
/* This is a simple wrapper over the old vips7 functions. At some point we
|
||||
* should rewrite this as a pure vips8 class and redo the vips7 functions as
|
||||
* wrappers over this.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#include "pconvolution.h"
|
||||
|
||||
typedef struct {
|
||||
VipsConvolution parent_instance;
|
||||
|
||||
VipsOperationMorphology morph;
|
||||
|
||||
} VipsMorph;
|
||||
|
||||
typedef VipsConvolutionClass VipsMorphClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsMorph, vips_morph, VIPS_TYPE_CONVOLUTION );
|
||||
|
||||
static int
|
||||
vips_morph_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConvolution *convolution = (VipsConvolution *) object;
|
||||
VipsMorph *morph = (VipsMorph *) object;
|
||||
|
||||
INTMASK *imsk;
|
||||
|
||||
g_object_set( morph, "out", vips_image_new(), NULL );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_morph_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( !(imsk = im_vips2imask( convolution->M, class->nickname )) ||
|
||||
!im_local_imask( convolution->out, imsk ) )
|
||||
return( -1 );
|
||||
|
||||
switch( morph->morph ) {
|
||||
case VIPS_OPERATION_MORPHOLOGY_DILATE:
|
||||
if( im_dilate( convolution->in, convolution->out, imsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
case VIPS_OPERATION_MORPHOLOGY_ERODE:
|
||||
if( im_erode( convolution->in, convolution->out, imsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_morph_class_init( VipsMorphClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "morph";
|
||||
object_class->description = _( "convolution operation" );
|
||||
object_class->build = vips_morph_build;
|
||||
|
||||
VIPS_ARG_ENUM( class, "morph", 103,
|
||||
_( "Morphology" ),
|
||||
_( "Morphological operation to perform" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsMorph, morph ),
|
||||
VIPS_TYPE_OPERATION_MORPHOLOGY,
|
||||
VIPS_OPERATION_MORPHOLOGY_ERODE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_morph_init( VipsMorph *morph )
|
||||
{
|
||||
morph->morph = VIPS_OPERATION_MORPHOLOGY_ERODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_morph:
|
||||
* @in: input image
|
||||
* @out: output image
|
||||
* @mask: morphology with this mask
|
||||
* @morph: operation to perform
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Performs a morphological operation on @in using @mask as a
|
||||
* structuring element.
|
||||
*
|
||||
* The image should have 0 (black) for no object and 255
|
||||
* (non-zero) for an object. Note that this is the reverse of the usual
|
||||
* convention for these operations, but more convenient when combined with the
|
||||
* boolean operators. The output image is the same
|
||||
* size as the input image: edge pxels are made by expanding the input image
|
||||
* as necessary.
|
||||
*
|
||||
* Mask coefficients can be either 0 (for object) or 255 (for background)
|
||||
* or 128 (for do not care). The origin of the mask is at location
|
||||
* (m.xsize / 2, m.ysize / 2), integer division. All algorithms have been
|
||||
* based on the book "Fundamentals of Digital Image Processing" by A. Jain,
|
||||
* pp 384-388, Prentice-Hall, 1989.
|
||||
*
|
||||
* For #VIPS_OPERATION_MOPHOLOGY_ERODE,
|
||||
* the whole mask must match for the output pixel to be
|
||||
* set, that is, the result is the logical AND of the selected input pixels.
|
||||
*
|
||||
* For #VIPS_OPERATION_MOPHOLOGY_DILATE,
|
||||
* the output pixel is set if any part of the mask
|
||||
* matches, that is, the result is the logical OR of the selected input pixels.
|
||||
*
|
||||
* See the boolean operations vips_andimage(), vips_orimage() and
|
||||
* vips_eorimage()
|
||||
* for analogues of the usual set difference and set union operations.
|
||||
*
|
||||
* Operations are performed using the processor's vector unit,
|
||||
* if possible. Disable this with --vips-novector or IM_NOVECTOR.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_morph( VipsImage *in, VipsImage **out, VipsImage *mask,
|
||||
VipsOperationMorphology morph, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, morph );
|
||||
result = vips_call_split( "morph", ap, in, out, mask, morph );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
@ -3,6 +3,8 @@ noinst_LTLIBRARIES = libcreate.la
|
||||
libcreate_la_SOURCES = \
|
||||
create.c \
|
||||
pcreate.h \
|
||||
gaussmat.c \
|
||||
logmat.c \
|
||||
buildlut.c \
|
||||
invertlut.c \
|
||||
tonelut.c \
|
||||
|
@ -100,7 +100,7 @@ vips_black_build( VipsObject *object )
|
||||
black->bands == 1 ?
|
||||
VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_MULTIBAND,
|
||||
1.0, 1.0 );
|
||||
vips_demand_hint( create->out,
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
if( vips_image_generate( create->out,
|
||||
|
@ -111,6 +111,8 @@ void
|
||||
vips_create_operation_init( void )
|
||||
{
|
||||
extern GType vips_black_get_type( void );
|
||||
extern GType vips_gaussmat_get_type( void );
|
||||
extern GType vips_logmat_get_type( void );
|
||||
extern GType vips_gaussnoise_get_type( void );
|
||||
#ifdef HAVE_PANGOFT2
|
||||
extern GType vips_text_get_type( void );
|
||||
@ -126,6 +128,8 @@ vips_create_operation_init( void )
|
||||
extern GType vips_identity_get_type( void );
|
||||
|
||||
vips_black_get_type();
|
||||
vips_gaussmat_get_type();
|
||||
vips_logmat_get_type();
|
||||
vips_gaussnoise_get_type();
|
||||
#ifdef HAVE_PANGOFT2
|
||||
vips_text_get_type();
|
||||
|
242
libvips/create/gaussmat.c
Normal file
242
libvips/create/gaussmat.c
Normal file
@ -0,0 +1,242 @@
|
||||
/* generate gaussian images
|
||||
*
|
||||
* Written on: 30/11/1989 by Nicos
|
||||
* Updated on: 6/12/1991
|
||||
* 7/8/96 JC
|
||||
* - ansified, mem leaks plugged
|
||||
* 20/11/98 JC
|
||||
* - mask too large check added
|
||||
* 18/3/09
|
||||
* - bumped max mask size *40
|
||||
* - added _sep variant
|
||||
* 30/3/09
|
||||
* - set scale in _sep variant, why not
|
||||
* 21/10/10
|
||||
* - gtkdoc
|
||||
* 20/10/13
|
||||
* - redone 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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 "pcreate.h"
|
||||
|
||||
typedef struct _VipsGaussmat {
|
||||
VipsCreate parent_instance;
|
||||
|
||||
double sigma;
|
||||
double min_ampl;
|
||||
|
||||
gboolean separable;
|
||||
gboolean integer;
|
||||
|
||||
} VipsGaussmat;
|
||||
|
||||
typedef struct _VipsGaussmatClass {
|
||||
VipsCreateClass parent_class;
|
||||
|
||||
} VipsGaussmatClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsGaussmat, vips_gaussmat, VIPS_TYPE_CREATE );
|
||||
|
||||
static int
|
||||
vips_gaussmat_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsCreate *create = VIPS_CREATE( object );
|
||||
VipsGaussmat *gaussmat = (VipsGaussmat *) object;
|
||||
double sig2 = 2. * gaussmat->sigma * gaussmat->sigma;
|
||||
int max_x = 8 * gaussmat->sigma > 5000 ? 5000 : 8 * gaussmat->sigma ;
|
||||
|
||||
int x, y;
|
||||
int width, height;
|
||||
double sum;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_gaussmat_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
/* Find the size of the mask. Limit the mask size to 10k x 10k for
|
||||
* sanity.
|
||||
*/
|
||||
for( x = 0; x < max_x; x++ ) {
|
||||
double v = exp( - ((double)(x * x)) / sig2 );
|
||||
|
||||
if( v < gaussmat->min_ampl )
|
||||
break;
|
||||
}
|
||||
if( x == max_x ) {
|
||||
vips_error( class->nickname, "%s", _( "mask too large" ) );
|
||||
return( -1 );
|
||||
}
|
||||
width = x * 2 + 1;
|
||||
height = gaussmat->separable ? 1 : width;
|
||||
|
||||
vips_image_init_fields( create->out,
|
||||
width, height, 1,
|
||||
VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
||||
1.0, 1.0 );
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
if( vips_image_write_prepare( create->out ) )
|
||||
return( -1 );
|
||||
|
||||
sum = 0.0;
|
||||
for( y = 0; y < height; y++ ) {
|
||||
for( x = 0; x < width; x++ ) {
|
||||
int xo = x - width / 2;
|
||||
int yo = y - height / 2;
|
||||
double distance = xo * xo + yo * yo;
|
||||
double v = exp( -distance / sig2 );
|
||||
|
||||
if( gaussmat->integer )
|
||||
v = VIPS_RINT( 20 * v );
|
||||
|
||||
*VIPS_MATRIX( create->out, x, y ) = v;
|
||||
sum += v;
|
||||
}
|
||||
}
|
||||
|
||||
vips_image_set_double( create->out, "scale", sum );
|
||||
vips_image_set_double( create->out, "offset", 0.0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_gaussmat_class_init( VipsGaussmatClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
vobject_class->nickname = "gaussmat";
|
||||
vobject_class->description = _( "make a gaussian image" );
|
||||
vobject_class->build = vips_gaussmat_build;
|
||||
|
||||
VIPS_ARG_DOUBLE( class, "sigma", 2,
|
||||
_( "Radius" ),
|
||||
_( "Radius of Gaussian" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsGaussmat, sigma ),
|
||||
0.000001, 10000.0, 1.0 );
|
||||
|
||||
VIPS_ARG_DOUBLE( class, "min_ampl", 3,
|
||||
_( "Width" ),
|
||||
_( "Minimum amplitude of Gaussian" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsGaussmat, min_ampl ),
|
||||
0.000001, 10000.0, 0.1 );
|
||||
|
||||
VIPS_ARG_BOOL( class, "separable", 4,
|
||||
_( "Separable" ),
|
||||
_( "Generate separable Gaussian" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsGaussmat, separable ),
|
||||
FALSE );
|
||||
|
||||
VIPS_ARG_BOOL( class, "integer", 5,
|
||||
_( "Integer" ),
|
||||
_( "Generate integer Gaussian" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsGaussmat, integer ),
|
||||
FALSE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_gaussmat_init( VipsGaussmat *gaussmat )
|
||||
{
|
||||
gaussmat->sigma = 1;
|
||||
gaussmat->min_ampl = 0.1;
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_gaussmat:
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @separable: generate a separable gaussian
|
||||
* @integer: generate an integer gaussian
|
||||
*
|
||||
* Creates a circularly symmetric Gaussian image of radius
|
||||
* @sigma. The size of the mask is determined by the variable @min_ampl;
|
||||
* if for instance the value .1 is entered this means that the produced mask
|
||||
* is clipped at values less than 10 percent of the maximum amplitude.
|
||||
*
|
||||
* The program uses the following equation:
|
||||
*
|
||||
* H(r) = exp( -(r * r) / (2 * @sigma * @sigma) )
|
||||
*
|
||||
* The generated image has odd size and its maximum value is normalised to
|
||||
* 1.0, unless @integer is set.
|
||||
*
|
||||
* If @separable is set, only the centre horizontal is generated. This is
|
||||
* useful for separable convolutions.
|
||||
*
|
||||
* If @integer is set, an integer gaussian is generated. This is useful for
|
||||
* integer convolutions.
|
||||
*
|
||||
* "scale" is set to the sum of all the mask elements.
|
||||
*
|
||||
* See also: im_log_dmask(), vips_conv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_gaussmat( VipsImage **out, double sigma, double min_ampl, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, min_ampl );
|
||||
result = vips_call_split( "gaussmat", ap, out, sigma, min_ampl );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
@ -131,7 +131,7 @@ vips_gaussnoise_build( VipsObject *object )
|
||||
gaussnoise->width, gaussnoise->height, 1,
|
||||
VIPS_FORMAT_FLOAT, VIPS_CODING_NONE,
|
||||
VIPS_INTERPRETATION_B_W, 1.0, 1.0 );
|
||||
vips_demand_hint( create->out,
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
if( vips_image_generate( create->out,
|
||||
|
@ -116,7 +116,7 @@ vips_identity_build( VipsObject *object )
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_HISTOGRAM,
|
||||
1.0, 1.0 );
|
||||
|
||||
vips_demand_hint( create->out,
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
if( vips_image_generate( create->out,
|
||||
|
273
libvips/create/logmat.c
Normal file
273
libvips/create/logmat.c
Normal file
@ -0,0 +1,273 @@
|
||||
/* laplacian of logmatian
|
||||
*
|
||||
* Written on: 30/11/1989
|
||||
* Updated on: 6/12/1991
|
||||
* 7/8/96 JC
|
||||
* - ansified, mem leaks plugged
|
||||
* 20/11/98 JC
|
||||
* - mask too large check added
|
||||
* 26/3/02 JC
|
||||
* - ahem, was broken since '96, thanks matt
|
||||
* 16/7/03 JC
|
||||
* - makes mask out to zero, not out to minimum, thanks again matt
|
||||
* 22/10/10
|
||||
* - gtkdoc
|
||||
* 20/10/13
|
||||
* - redone as a class from logmat.c
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 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 "pcreate.h"
|
||||
|
||||
typedef struct _VipsLogmat {
|
||||
VipsCreate parent_instance;
|
||||
|
||||
double sigma;
|
||||
double min_ampl;
|
||||
|
||||
gboolean separable;
|
||||
gboolean integer;
|
||||
|
||||
} VipsLogmat;
|
||||
|
||||
typedef struct _VipsLogmatClass {
|
||||
VipsCreateClass parent_class;
|
||||
|
||||
} VipsLogmatClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsLogmat, vips_logmat, VIPS_TYPE_CREATE );
|
||||
|
||||
static int
|
||||
vips_logmat_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsCreate *create = VIPS_CREATE( object );
|
||||
VipsLogmat *logmat = (VipsLogmat *) object;
|
||||
double sig2 = logmat->sigma * logmat->sigma;
|
||||
|
||||
double last;
|
||||
int x, y;
|
||||
int width, height;
|
||||
double sum;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_logmat_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
/* Find the size of the mask. We want to eval the mask out to the
|
||||
* flat zero part, ie. beyond the minimum and to the point where it
|
||||
* comes back up towards zero.
|
||||
*/
|
||||
last = 0.0;
|
||||
for( x = 0; x < 5000; x++ ) {
|
||||
const double distance = x * x;
|
||||
double val;
|
||||
|
||||
/* Handbook of Pattern Recognition and image processing
|
||||
* by Young and Fu AP 1986 pp 220-221
|
||||
* temp = (1.0 / (2.0 * IM_PI * sig4)) *
|
||||
(2.0 - (distance / sig2)) *
|
||||
exp( (-1.0) * distance / (2.0 * sig2) )
|
||||
|
||||
.. use 0.5 to normalise
|
||||
*/
|
||||
val = 0.5 *
|
||||
(2.0 - (distance / sig2)) *
|
||||
exp( -distance / (2.0 * sig2) );
|
||||
|
||||
/* Stop when change in value (ie. difference from the last
|
||||
* point) is positive (ie. we are going up) and absolute value
|
||||
* is less than the min.
|
||||
*/
|
||||
if( val - last >= 0 &&
|
||||
fabs( val ) < logmat->min_ampl )
|
||||
break;
|
||||
|
||||
last = val;
|
||||
}
|
||||
if( x == 5000 ) {
|
||||
vips_error( class->nickname, "%s", _( "mask too large" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
width = x * 2 + 1;
|
||||
height = logmat->separable ? 1 : width;
|
||||
|
||||
vips_image_init_fields( create->out,
|
||||
width, height, 1,
|
||||
VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
||||
1.0, 1.0 );
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
if( vips_image_write_prepare( create->out ) )
|
||||
return( -1 );
|
||||
|
||||
sum = 0.0;
|
||||
for( y = 0; y < height; y++ ) {
|
||||
for( x = 0; x < width; x++ ) {
|
||||
int xo = x - width / 2;
|
||||
int yo = y - height / 2;
|
||||
double distance = xo * xo + yo * yo;
|
||||
double v = 0.5 *
|
||||
(2.0 - (distance / sig2)) *
|
||||
exp( -distance / (2.0 * sig2) );
|
||||
|
||||
if( logmat->integer )
|
||||
v = VIPS_RINT( 20 * v );
|
||||
|
||||
*VIPS_MATRIX( create->out, x, y ) = v;
|
||||
sum += v;
|
||||
}
|
||||
}
|
||||
|
||||
vips_image_set_double( create->out, "scale", sum );
|
||||
vips_image_set_double( create->out, "offset", 0.0 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_logmat_class_init( VipsLogmatClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
vobject_class->nickname = "logmat";
|
||||
vobject_class->description = _( "make a laplacian of gaussian image" );
|
||||
vobject_class->build = vips_logmat_build;
|
||||
|
||||
VIPS_ARG_DOUBLE( class, "sigma", 2,
|
||||
_( "Radius" ),
|
||||
_( "Radius of Logmatian" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsLogmat, sigma ),
|
||||
0.000001, 10000.0, 1.0 );
|
||||
|
||||
VIPS_ARG_DOUBLE( class, "min_ampl", 3,
|
||||
_( "Width" ),
|
||||
_( "Minimum amplitude of Logmatian" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsLogmat, min_ampl ),
|
||||
0.000001, 10000.0, 0.1 );
|
||||
|
||||
VIPS_ARG_BOOL( class, "separable", 4,
|
||||
_( "Separable" ),
|
||||
_( "Generate separable Logmatian" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsLogmat, separable ),
|
||||
FALSE );
|
||||
|
||||
VIPS_ARG_BOOL( class, "integer", 5,
|
||||
_( "Integer" ),
|
||||
_( "Generate integer Logmatian" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsLogmat, integer ),
|
||||
FALSE );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_logmat_init( VipsLogmat *logmat )
|
||||
{
|
||||
logmat->sigma = 1;
|
||||
logmat->min_ampl = 0.1;
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_logmat:
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @separable: generate a separable logmatian
|
||||
* @integer: generate an integer logmatian
|
||||
*
|
||||
* Creates a circularly symmetric Laplacian of Gaussian mask
|
||||
* of radius
|
||||
* @sigma. The size of the mask is determined by the variable @min_ampl;
|
||||
* if for instance the value .1 is entered this means that the produced mask
|
||||
* is clipped at values within 10 persent of zero, and where the change
|
||||
* between mask elements is less than 10%.
|
||||
*
|
||||
* The program uses the following equation: (from Handbook of Pattern
|
||||
* Recognition and image processing by Young and Fu, AP 1986 pages 220-221):
|
||||
*
|
||||
* H(r) = (1 / (2 * M_PI * s4)) *
|
||||
* (2 - (r2 / s2)) *
|
||||
* exp(-r2 / (2 * s2))
|
||||
*
|
||||
* where s2 = @sigma * @sigma, s4 = s2 * s2, r2 = r * r.
|
||||
*
|
||||
* The generated mask has odd size and its maximum value is normalised to
|
||||
* 1.0, unless @integer is set.
|
||||
*
|
||||
* If @separable is set, only the centre horizontal is generated. This is
|
||||
* useful for separable convolutions.
|
||||
*
|
||||
* If @integer is set, an integer logmatian is generated. This is useful for
|
||||
* integer convolutions.
|
||||
*
|
||||
* "scale" is set to the sum of all the mask elements.
|
||||
*
|
||||
* See also: vips_gauss(), vips_conv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_logmat( VipsImage **out, double sigma, double min_ampl, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, min_ampl );
|
||||
result = vips_call_split( "logmat", ap, out, sigma, min_ampl );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
@ -103,7 +103,7 @@ vips_point_build( VipsObject *object )
|
||||
point->width, point->height, 1,
|
||||
VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
||||
1.0, 1.0 );
|
||||
vips_demand_hint( t[0],
|
||||
vips_image_pipelinev( t[0],
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
if( vips_image_generate( t[0],
|
||||
NULL, vips_point_gen, NULL, point, NULL ) )
|
||||
|
@ -233,7 +233,7 @@ vips_text_build( VipsObject *object )
|
||||
text->bitmap.width, text->bitmap.rows, 1,
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
||||
1.0, 1.0 );
|
||||
vips_demand_hint( create->out,
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
for( y = 0; y < text->bitmap.rows; y++ )
|
||||
|
@ -163,7 +163,7 @@ vips_xyz_build( VipsObject *object )
|
||||
VIPS_FORMAT_UINT, VIPS_CODING_NONE,
|
||||
VIPS_INTERPRETATION_MULTIBAND,
|
||||
1.0, 1.0 );
|
||||
vips_demand_hint( create->out,
|
||||
vips_image_pipelinev( create->out,
|
||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
if( vips_image_generate( create->out,
|
||||
|
@ -45,8 +45,6 @@ libdeprecated_la_SOURCES = \
|
||||
im_mask2vips.c \
|
||||
im_vips2mask.c \
|
||||
rotmask.c \
|
||||
im_gaussmasks.c \
|
||||
im_logmasks.c \
|
||||
rw_mask.c \
|
||||
im_matcat.c \
|
||||
im_matinv.c \
|
||||
|
@ -1,280 +0,0 @@
|
||||
/* generate gaussian masks
|
||||
*
|
||||
* Written on: 30/11/1989 by Nicos
|
||||
* Updated on: 6/12/1991
|
||||
* 7/8/96 JC
|
||||
* - ansified, mem leaks plugged
|
||||
* 20/11/98 JC
|
||||
* - mask too large check added
|
||||
* 18/3/09
|
||||
* - bumped max mask size *40
|
||||
* - added _sep variant
|
||||
* 30/3/09
|
||||
* - set scale in _sep variant, why not
|
||||
* 21/10/10
|
||||
* - gtkdoc
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#define IM_MAXMASK 5000
|
||||
|
||||
/**
|
||||
* im_gauss_dmask:
|
||||
* @filename: the returned mask has this set as the filename
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
*
|
||||
* im_gauss_dmask() creates a circularly symmetric Gaussian mask of radius
|
||||
* @sigma. The size of the mask is determined by the variable @min_ampl;
|
||||
* if for instance the value .1 is entered this means that the produced mask
|
||||
* is clipped at values less than 10 percent of the maximum amplitude.
|
||||
*
|
||||
* The program uses the following equation:
|
||||
*
|
||||
* H(r) = exp( -(r * r) / (2 * sigma * sigma) )
|
||||
*
|
||||
* The generated mask has odd size and its maximum value is normalised to
|
||||
* 1.0.
|
||||
*
|
||||
* See also: im_gauss_imask(), im_gauss_imask_sep(), im_log_dmask(), im_conv().
|
||||
*
|
||||
* Returns: the calculated mask on success, or NULL on error.
|
||||
*/
|
||||
DOUBLEMASK *
|
||||
im_gauss_dmask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
int x, y, k;
|
||||
double distance;
|
||||
double temp;
|
||||
double *pt1, *pt2, *pt3, *pt4;
|
||||
int max_x;
|
||||
int xm, ym;
|
||||
int xm2, ym2; /* xm2 = xm/2 */
|
||||
int offset;
|
||||
double *cf, *cfs, *mc;
|
||||
DOUBLEMASK *m;
|
||||
double sig2, sum; /* sig2 = 2. * sigma * sigma */
|
||||
|
||||
/* Find the size of the mask depending on the entered data
|
||||
*/
|
||||
sig2 = 2. * sigma * sigma;
|
||||
max_x = 8 * sigma > IM_MAXMASK ? IM_MAXMASK : 8 * sigma ;
|
||||
for( x = 0; x < max_x; x++ ) {
|
||||
temp = exp( - ((double)(x * x))/sig2 );
|
||||
if( temp < min_ampl )
|
||||
break;
|
||||
}
|
||||
if( x == max_x ) {
|
||||
im_error( "im_gauss_dmask", "%s", _( "mask too large" ) );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
xm2 = x;
|
||||
ym2 = x;
|
||||
xm = xm2 * 2 + 1;
|
||||
ym = ym2 * 2 + 1;
|
||||
|
||||
if( !(cfs = IM_ARRAY( NULL, (xm2+1)*(ym2+1), double )) )
|
||||
return( NULL );
|
||||
|
||||
for( k = 0, y = 0; y <= ym2; y++ ) {
|
||||
for( x = 0; x <= xm2; x++, k++ ) {
|
||||
distance = x*x + y*y;
|
||||
cfs[k] = exp( -distance / sig2 );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PIM_RINT
|
||||
for( k = 0, y = 0; y <= ymask_2; y++ ) {
|
||||
for( x = 0; x <= xmask_2; x++, k++ )
|
||||
fprintf(stderr, "%3.2f ", cfs[k] );
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if( !(m = im_create_dmask( filename, xm, ym )) ) {
|
||||
im_free( cfs );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* copy the 1/4 cfs into the m
|
||||
*/
|
||||
cf = cfs;
|
||||
offset = xm2 * (xm + 1);
|
||||
mc = m->coeff + offset;
|
||||
for( y = 0; y <= ym2; y++ ) {
|
||||
for( x = 0; x <= xm2; x++ ) {
|
||||
pt1 = mc + (y * xm) + x;
|
||||
pt2 = mc - (y * xm) + x;
|
||||
pt3 = mc + (y * xm) - x;
|
||||
pt4 = mc - (y * xm) - x;
|
||||
|
||||
*pt1 = cf[x];
|
||||
*pt2 = cf[x];
|
||||
*pt3 = cf[x];
|
||||
*pt4 = cf[x];
|
||||
}
|
||||
|
||||
cf += (xm2 + 1);
|
||||
}
|
||||
im_free( cfs );
|
||||
|
||||
sum = 0.0;
|
||||
for( k = 0, y = 0; y < m->ysize; y++ )
|
||||
for( x = 0; x < m->xsize; x++, k++ )
|
||||
sum += m->coeff[k];
|
||||
m->scale = sum;
|
||||
m->offset = 0.0;
|
||||
|
||||
#ifdef PIM_RINT
|
||||
im_print_dmask( m );
|
||||
#endif
|
||||
return( m );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_gauss_dmask_sep:
|
||||
* @filename: the returned mask has this set as the filename
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
*
|
||||
* im_gauss_dmask_sep() works exactly as im_gauss_dmask(), but returns only
|
||||
* the central line of the mask. This is useful with im_convsepf().
|
||||
*
|
||||
* See also: im_gauss_dmask(), im_convsepf().
|
||||
*
|
||||
* Returns: the calculated mask on success, or NULL on error.
|
||||
*/
|
||||
DOUBLEMASK *
|
||||
im_gauss_dmask_sep( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
DOUBLEMASK *im;
|
||||
DOUBLEMASK *im2;
|
||||
int i;
|
||||
double sum;
|
||||
|
||||
if( !(im = im_gauss_dmask( filename, sigma, min_ampl )) )
|
||||
return( NULL );
|
||||
if( !(im2 = im_create_dmask( filename, im->xsize, 1 )) ) {
|
||||
im_free_dmask( im );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
sum = 0;
|
||||
for( i = 0; i < im->xsize; i++ ) {
|
||||
im2->coeff[i] = im->coeff[i + im->xsize * (im->ysize / 2)];
|
||||
sum += im2->coeff[i];
|
||||
}
|
||||
im2->scale = sum;
|
||||
|
||||
im_free_dmask( im );
|
||||
|
||||
return( im2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_gauss_imask:
|
||||
* @filename: the returned mask has this set as the filename
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
*
|
||||
* im_gauss_imask() works exactly as im_gauss_dmask(), but the returned mask
|
||||
* is scaled so that it's maximum value it set to 100.
|
||||
*
|
||||
* See also: im_gauss_dmask(), im_gauss_imask_sep(), im_conv(), im_convsep().
|
||||
*
|
||||
* Returns: the calculated mask on success, or NULL on error.
|
||||
*/
|
||||
INTMASK *
|
||||
im_gauss_imask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
DOUBLEMASK *dm;
|
||||
INTMASK *im;
|
||||
|
||||
if( !(dm = im_gauss_dmask( filename, sigma, min_ampl )) )
|
||||
return( NULL );
|
||||
|
||||
if( !(im = im_scale_dmask( dm, dm->filename )) ) {
|
||||
im_free_dmask( dm );
|
||||
return( NULL );
|
||||
}
|
||||
im_free_dmask( dm );
|
||||
|
||||
return( im ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* im_gauss_imask_sep:
|
||||
* @filename: the returned mask has this set as the filename
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
*
|
||||
* im_gauss_imask_sep() works exactly as im_gauss_imask(), but returns only
|
||||
* the central line of the mask. This is useful with im_convsep().
|
||||
*
|
||||
* See also: im_gauss_dmask(), im_convsep().
|
||||
*
|
||||
* Returns: the calculated mask on success, or NULL on error.
|
||||
*/
|
||||
INTMASK *
|
||||
im_gauss_imask_sep( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
INTMASK *im;
|
||||
INTMASK *im2;
|
||||
int i;
|
||||
int sum;
|
||||
|
||||
if( !(im = im_gauss_imask( filename, sigma, min_ampl )) )
|
||||
return( NULL );
|
||||
if( !(im2 = im_create_imask( filename, im->xsize, 1 )) ) {
|
||||
im_free_imask( im );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
sum = 0;
|
||||
for( i = 0; i < im->xsize; i++ ) {
|
||||
im2->coeff[i] = im->coeff[i + im->xsize * (im->ysize / 2)];
|
||||
sum += im2->coeff[i];
|
||||
}
|
||||
im2->scale = sum;
|
||||
|
||||
im_free_imask( im );
|
||||
|
||||
return( im2 );
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
/* laplacian of gaussian
|
||||
*
|
||||
* Written on: 30/11/1989
|
||||
* Updated on: 6/12/1991
|
||||
* 7/8/96 JC
|
||||
* - ansified, mem leaks plugged
|
||||
* 20/11/98 JC
|
||||
* - mask too large check added
|
||||
* 26/3/02 JC
|
||||
* - ahem, was broken since '96, thanks matt
|
||||
* 16/7/03 JC
|
||||
* - makes mask out to zero, not out to minimum, thanks again matt
|
||||
* 22/10/10
|
||||
* - gtkdoc
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
#define PIM_RINT 1
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/util.h>
|
||||
|
||||
#define IM_MAXMASK 256
|
||||
|
||||
/**
|
||||
* im_log_dmask:
|
||||
* @filename: the returned mask has this set as the filename
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
*
|
||||
* im_log_dmask() creates a circularly symmetric Laplacian of Gaussian mask
|
||||
* of radius
|
||||
* @sigma. The size of the mask is determined by the variable @min_ampl;
|
||||
* if for instance the value .1 is entered this means that the produced mask
|
||||
* is clipped at values within 10 persent of zero, and where the change
|
||||
* between mask elements is less than 10%.
|
||||
*
|
||||
* The program uses the following equation: (from Handbook of Pattern
|
||||
* Recognition and image processing by Young and Fu, AP 1986 pages 220-221):
|
||||
*
|
||||
* H(r) = (1 / (2 * M_PI * s4)) *
|
||||
* (2 - (r2 / s2)) *
|
||||
* exp(-r2 / (2 * s2))
|
||||
*
|
||||
* where s2 = sigma * sigma, s4 = s2 * s2, r2 = r * r.
|
||||
*
|
||||
* The generated mask has odd size and its maximum value is normalised to 1.0.
|
||||
*
|
||||
* See also: im_log_imask(), im_gauss_dmask(), im_conv().
|
||||
*
|
||||
* Returns: the calculated mask on success, or NULL on error.
|
||||
*/
|
||||
DOUBLEMASK *
|
||||
im_log_dmask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
const double sig2 = sigma * sigma;
|
||||
|
||||
double last;
|
||||
int x, y, k;
|
||||
|
||||
double *pt1, *pt2, *pt3, *pt4;
|
||||
int xm, ym;
|
||||
int xm2, ym2; /* xm2 = xm/2 */
|
||||
int offset;
|
||||
double *cf, *cfs, *mc;
|
||||
DOUBLEMASK *m;
|
||||
double sum;
|
||||
|
||||
/* Find the size of the mask depending on the entered data. We want to
|
||||
* eval the mask out to the flat zero part, ie. beyond the minimum and
|
||||
* to the point where it comes back up towards zero.
|
||||
*/
|
||||
last = 0.0;
|
||||
for( x = 0; x < IM_MAXMASK; x++ ) {
|
||||
const double distance = x * x;
|
||||
double val;
|
||||
|
||||
/* Handbook of Pattern Recognition and image processing
|
||||
* by Young and Fu AP 1986 pp 220-221
|
||||
* temp = (1.0 / (2.0 * IM_PI * sig4)) *
|
||||
(2.0 - (distance / sig2)) *
|
||||
exp( (-1.0) * distance / (2.0 * sig2) )
|
||||
|
||||
.. use 0.5 to normalise
|
||||
*/
|
||||
val = 0.5 *
|
||||
(2.0 - (distance / sig2)) *
|
||||
exp( -distance / (2.0 * sig2) );
|
||||
|
||||
/* Stop when change in value (ie. difference from the last
|
||||
* point) is positive (ie. we are going up) and absolute value
|
||||
* is less than the min.
|
||||
*/
|
||||
if( val - last >= 0 &&
|
||||
fabs( val ) < min_ampl )
|
||||
break;
|
||||
|
||||
last = val;
|
||||
}
|
||||
if( x == IM_MAXMASK ) {
|
||||
im_error( "im_log_dmask", "%s", _( "mask too large" ) );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
xm2 = x;
|
||||
ym2 = x;
|
||||
xm = xm2 * 2 + 1;
|
||||
ym = ym2 * 2 + 1;
|
||||
|
||||
if( !(cfs = IM_ARRAY( NULL, (xm2 + 1) * (ym2 + 1), double )) )
|
||||
return( NULL );
|
||||
|
||||
/* Make 1/4 of the mask.
|
||||
*/
|
||||
for( k = 0, y = 0; y <= ym2; y++ )
|
||||
for( x = 0; x <= xm2; x++, k++ ) {
|
||||
const double distance = x * x + y * y;
|
||||
|
||||
cfs[k] = 0.5 *
|
||||
(2.0 - (distance / sig2)) *
|
||||
exp( -distance / (2.0 * sig2) );
|
||||
}
|
||||
|
||||
#ifdef PIM_RINT
|
||||
for( k = 0, y = 0; y <= ym2; y++ ) {
|
||||
for( x = 0; x <= xm2; x++, k++ )
|
||||
fprintf( stderr, "%3.2f ", cfs[k] );
|
||||
fprintf( stderr, "\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( !(m = im_create_dmask( filename, xm, ym )) ) {
|
||||
im_free( cfs );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* Copy the 1/4 cfs into the m
|
||||
*/
|
||||
cf = cfs;
|
||||
offset = xm2 * (xm + 1);
|
||||
mc = m->coeff + offset;
|
||||
for( y = 0; y <= ym2; y++ ) {
|
||||
for( x = 0; x <= xm2; x++ ) {
|
||||
pt1 = mc + (y * xm) + x;
|
||||
pt2 = mc - (y * xm) + x;
|
||||
pt3 = mc + (y * xm) - x;
|
||||
pt4 = mc - (y * xm) - x;
|
||||
|
||||
*pt1 = cf[x];
|
||||
*pt2 = cf[x];
|
||||
*pt3 = cf[x];
|
||||
*pt4 = cf[x];
|
||||
}
|
||||
|
||||
cf += (xm2 + 1);
|
||||
}
|
||||
im_free( cfs );
|
||||
|
||||
sum = 0.0;
|
||||
for( k = 0, y = 0; y < m->ysize; y++ )
|
||||
for( x = 0; x < m->xsize; x++, k++ )
|
||||
sum += m->coeff[k];
|
||||
m->scale = sum;
|
||||
m->offset = 0.0;
|
||||
|
||||
#ifdef PIM_RINT
|
||||
im_print_dmask( m );
|
||||
#endif
|
||||
|
||||
return( m );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_log_imask:
|
||||
* @filename: the returned mask has this set as the filename
|
||||
* @sigma: standard deviation of mask
|
||||
* @min_ampl: minimum amplitude
|
||||
*
|
||||
* im_log_imask() works exactly as im_log_dmask(), but the returned mask
|
||||
* is scaled so that it's maximum value it set to 100.
|
||||
*
|
||||
* See also: im_log_dmask(), im_gauss_imask(), im_conv().
|
||||
*
|
||||
* Returns: the calculated mask on success, or NULL on error.
|
||||
*/
|
||||
INTMASK *
|
||||
im_log_imask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
DOUBLEMASK *dm;
|
||||
INTMASK *im;
|
||||
|
||||
if( !(dm = im_log_dmask( filename, sigma, min_ampl )) )
|
||||
return( NULL );
|
||||
|
||||
if( !(im = im_scale_dmask( dm, dm->filename )) ) {
|
||||
im_free_dmask( dm );
|
||||
return( NULL );
|
||||
}
|
||||
im_free_dmask( dm );
|
||||
|
||||
return( im ) ;
|
||||
}
|
@ -101,3 +101,17 @@ im_mask2vips( DOUBLEMASK *in, IMAGE *out )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_imask2vips( INTMASK *in, IMAGE *out )
|
||||
{
|
||||
DOUBLEMASK *d;
|
||||
int result;
|
||||
|
||||
if( !(d = im_imask2dmask( in, in->filename )) )
|
||||
return( -1 );
|
||||
result = im_mask2vips( d, out );
|
||||
im_free_dmask( d );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,7 @@ vips_image_open_lazy( VipsImage *image,
|
||||
/* Then 'start' creates the real image and 'gen' paints 'image'
|
||||
* with pixels from the real image on demand.
|
||||
*/
|
||||
vips_demand_hint( image, image->dhint, NULL );
|
||||
vips_image_pipelinev( image, image->dhint, NULL );
|
||||
if( vips_image_generate( image,
|
||||
open_lazy_start, open_lazy_generate, vips_stop_one,
|
||||
lazy, NULL ) )
|
||||
|
@ -56,166 +56,6 @@
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
/* Creates the offsets to rotate by 45 degrees an odd size square mask
|
||||
*/
|
||||
int *
|
||||
im_offsets45( int size )
|
||||
{
|
||||
int temp;
|
||||
int x, y;
|
||||
int size2 = size * size;
|
||||
int size_2 = size / 2;
|
||||
int *pnt, *cpnt1, *cpnt2;
|
||||
|
||||
if( size%2 == 0 ) {
|
||||
im_error( "im_offsets45", "%s", _( "size not odd" ) );
|
||||
return( NULL );
|
||||
}
|
||||
if( !(pnt = IM_ARRAY( NULL, size2, int )) )
|
||||
return( NULL );
|
||||
|
||||
/* point at the beginning and end of the buffer
|
||||
*/
|
||||
cpnt1 = pnt; cpnt2 = pnt + size2 - 1;
|
||||
|
||||
for( y = 0; y < size_2; y++ ) {
|
||||
temp = (size_2 + y) * size;
|
||||
*cpnt1++ = temp;
|
||||
*cpnt2-- = size2 - 1 - temp;
|
||||
|
||||
for( x = 0; x < y; x++ ) {
|
||||
temp -= (size-1);
|
||||
*cpnt1++ = temp;
|
||||
*cpnt2-- = size2 - 1 - temp;
|
||||
}
|
||||
|
||||
for( x = 0; x < size_2 - y; x++ ) {
|
||||
temp -= size;
|
||||
*cpnt1++ = temp;
|
||||
*cpnt2-- = size2 - 1 - temp;
|
||||
}
|
||||
|
||||
for( x = 0; x < size_2 - y; x++ ) {
|
||||
temp++;
|
||||
*cpnt1++ = temp;
|
||||
*cpnt2-- = size2 - 1 - temp;
|
||||
}
|
||||
|
||||
for( x = 0; x < y; x++ ) {
|
||||
temp -= ( size - 1 );
|
||||
*cpnt1++ = temp;
|
||||
*cpnt2-- = size2 - 1 - temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* the diagonal now
|
||||
*/
|
||||
temp = size * (size - 1);
|
||||
cpnt1 = pnt + size_2 * size;
|
||||
for( x = 0; x < size; x++ ) {
|
||||
*cpnt1++ = temp;
|
||||
temp -= (size-1);
|
||||
}
|
||||
|
||||
#ifdef PIM_RINT
|
||||
temp = 0;
|
||||
for( y = 0; y < size; y++ ) {
|
||||
for( x = 0; x < size; x++ ) {
|
||||
fprintf( stderr, "%4d", *(pnt+temp) );
|
||||
temp++;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
|
||||
return( pnt );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_rotate_dmask45:
|
||||
* @in: input matrix
|
||||
* @filename: name for output matrix
|
||||
*
|
||||
* Returns a mask which is the argument mask rotated by 45 degrees.
|
||||
* Pass the filename to set for the output.
|
||||
*
|
||||
* See also: im_rotate_dmask90().
|
||||
*
|
||||
* Returns: the result matrix on success, or %NULL on error.
|
||||
*/
|
||||
DOUBLEMASK *
|
||||
im_rotate_dmask45( DOUBLEMASK *in, const char *filename )
|
||||
{
|
||||
DOUBLEMASK *out;
|
||||
int size = in->xsize * in->ysize;
|
||||
int *offsets;
|
||||
int i;
|
||||
|
||||
if( in->xsize != in->ysize || (in->xsize % 2) == 0 ) {
|
||||
im_error( "im_rotate_dmask45", "%s",
|
||||
_( "mask should be square of odd size" ) );
|
||||
return( NULL );
|
||||
}
|
||||
if( !(offsets = im_offsets45( in->xsize )) )
|
||||
return( NULL );
|
||||
if( !(out = im_create_dmask( filename, in->xsize, in->ysize )) ) {
|
||||
im_free( offsets );
|
||||
return( NULL );
|
||||
}
|
||||
out->scale = in->scale;
|
||||
out->offset = in->offset;
|
||||
|
||||
for( i = 0; i < size; i++ )
|
||||
out->coeff[i] = in->coeff[offsets[i]];
|
||||
|
||||
im_free( offsets );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_rotate_imask45:
|
||||
* @in: input matrix
|
||||
* @filename: name for output matrix
|
||||
*
|
||||
* Returns a mask which is the argument mask rotated by 45 degrees.
|
||||
* Pass the filename to set for the output.
|
||||
*
|
||||
* See also: im_rotate_imask90().
|
||||
*
|
||||
* Returns: the result matrix on success, or %NULL on error.
|
||||
*/
|
||||
INTMASK *
|
||||
im_rotate_imask45( INTMASK *in, const char *filename )
|
||||
{
|
||||
INTMASK *out;
|
||||
int size = in->xsize * in->ysize;
|
||||
int *offsets;
|
||||
int i;
|
||||
|
||||
if( in->xsize != in->ysize || (in->xsize % 2) == 0 ) {
|
||||
im_error( "im_rotate_imask45", "%s",
|
||||
_( "mask should be square of odd size" ) );
|
||||
return( NULL );
|
||||
}
|
||||
if( !(offsets = im_offsets45( in->xsize )) )
|
||||
return( NULL );
|
||||
if( !(out = im_create_imask( filename, in->xsize, in->ysize )) ) {
|
||||
im_free( offsets );
|
||||
return( NULL );
|
||||
}
|
||||
out->scale = in->scale;
|
||||
out->offset = in->offset;
|
||||
|
||||
for( i = 0; i < size; i++ )
|
||||
out->coeff[i] = in->coeff[offsets[i]];
|
||||
|
||||
im_free( offsets );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
/* The type of the vips operations we support.
|
||||
*/
|
||||
typedef int (*vips_fn)( IMAGE *in, IMAGE *out );
|
||||
@ -273,38 +113,42 @@ vapplydmask( DOUBLEMASK *in, const char *name, vips_fn fn )
|
||||
return( out );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_rotate_imask90:
|
||||
* @in: input matrix
|
||||
* @filename: name for output matrix
|
||||
*
|
||||
* Returns a mask which is the argument mask rotated by 90 degrees.
|
||||
* Pass the filename to set for the output.
|
||||
*
|
||||
* See also: im_rotate_imask45().
|
||||
*
|
||||
* Returns: the result matrix on success, or %NULL on error.
|
||||
*/
|
||||
INTMASK *
|
||||
im_rotate_imask90( INTMASK *in, const char *filename )
|
||||
{
|
||||
return( vapplyimask( in, filename, im_rot90 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* im_rotate_dmask90:
|
||||
* @in: input matrix
|
||||
* @filename: name for output matrix
|
||||
*
|
||||
* Returns a mask which is the argument mask rotated by 90 degrees.
|
||||
* Pass the filename to set for the output.
|
||||
*
|
||||
* See also: im_rotate_dmask45().
|
||||
*
|
||||
* Returns: the result matrix on success, or %NULL on error.
|
||||
*/
|
||||
DOUBLEMASK *
|
||||
im_rotate_dmask90( DOUBLEMASK *in, const char *filename )
|
||||
{
|
||||
return( vapplydmask( in, filename, im_rot90 ) );
|
||||
}
|
||||
|
||||
static int
|
||||
im_rot45( IMAGE *in, IMAGE *out )
|
||||
{
|
||||
VipsImage *t;
|
||||
|
||||
if( vips_rot45( in, &t, NULL ) )
|
||||
return( -1 );
|
||||
if( vips_image_write( t, out ) ) {
|
||||
g_object_unref( t );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
INTMASK *
|
||||
im_rotate_imask45( INTMASK *in, const char *filename )
|
||||
{
|
||||
return( vapplyimask( in, filename, im_rot45 ) );
|
||||
}
|
||||
|
||||
DOUBLEMASK *
|
||||
im_rotate_dmask45( DOUBLEMASK *in, const char *filename )
|
||||
{
|
||||
return( vapplydmask( in, filename, im_rot45 ) );
|
||||
}
|
||||
|
@ -50,6 +50,12 @@
|
||||
#include <vips/vector.h>
|
||||
#include <vips/transform.h>
|
||||
|
||||
int
|
||||
im_init_world( const char *argv0 )
|
||||
{
|
||||
return( vips_init( argv0 ) );
|
||||
}
|
||||
|
||||
VipsImage *
|
||||
im_open( const char *filename, const char *mode )
|
||||
{
|
||||
@ -480,7 +486,7 @@ im_wrapmany( IMAGE **in, IMAGE *out, im_wrapmany_fn fn, void *a, void *b )
|
||||
if( vips_image_pio_input( in[i] ) )
|
||||
return( -1 );
|
||||
}
|
||||
vips_demand_hint_array( out, VIPS_DEMAND_STYLE_THINSTRIP, in );
|
||||
vips_image_pipeline_array( out, VIPS_DEMAND_STYLE_THINSTRIP, in );
|
||||
|
||||
/* Generate!
|
||||
*/
|
||||
@ -953,7 +959,35 @@ im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (im_demand_hint_array (im, hint, ar));
|
||||
vips__demand_hint_array (im, hint, ar);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
im_cp_descv (IMAGE * im, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
IMAGE *ar[MAX_IMAGES];
|
||||
|
||||
va_start (ap, im);
|
||||
for (i = 0; i < MAX_IMAGES && (ar[i] = va_arg (ap, IMAGE *)); i++)
|
||||
;
|
||||
va_end (ap);
|
||||
if (i == MAX_IMAGES)
|
||||
{
|
||||
im_error ("im_cp_descv", "%s", _("too many images"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (vips__image_copy_fields_array (im, ar));
|
||||
}
|
||||
|
||||
int
|
||||
im_cp_desc(IMAGE *out, IMAGE *in )
|
||||
{
|
||||
return( im_cp_descv( out, in, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
@ -1356,6 +1390,30 @@ im_gbandjoin( VipsImage **in, VipsImage *out, int n )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_rank_image( VipsImage **in, VipsImage *out, int n, int index )
|
||||
{
|
||||
VipsImage *t;
|
||||
|
||||
if( vips_bandrank( in, &t, n,
|
||||
"index", index,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
if( vips_image_write( t, out ) ) {
|
||||
g_object_unref( t );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_maxvalue( IMAGE **in, IMAGE *out, int n )
|
||||
{
|
||||
return( im_rank_image( in, out, n, n - 1 ) );
|
||||
}
|
||||
|
||||
int
|
||||
im_invert( IMAGE *in, IMAGE *out )
|
||||
{
|
||||
@ -1894,6 +1952,119 @@ im_stats( VipsImage *in )
|
||||
return( msk );
|
||||
}
|
||||
|
||||
DOUBLEMASK *
|
||||
im_gauss_dmask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
VipsImage *t;
|
||||
DOUBLEMASK *msk;
|
||||
|
||||
if( vips_gaussmat( &t, sigma, min_ampl,
|
||||
NULL ) )
|
||||
return( NULL );
|
||||
if( !(msk = im_vips2mask( t, filename )) ) {
|
||||
g_object_unref( t );
|
||||
return( NULL );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( msk );
|
||||
}
|
||||
|
||||
DOUBLEMASK *
|
||||
im_gauss_dmask_sep( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
VipsImage *t;
|
||||
DOUBLEMASK *msk;
|
||||
|
||||
if( vips_gaussmat( &t, sigma, min_ampl,
|
||||
"separable", TRUE,
|
||||
NULL ) )
|
||||
return( NULL );
|
||||
if( !(msk = im_vips2mask( t, filename )) ) {
|
||||
g_object_unref( t );
|
||||
return( NULL );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( msk );
|
||||
}
|
||||
|
||||
INTMASK *
|
||||
im_gauss_imask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
VipsImage *t;
|
||||
INTMASK *msk;
|
||||
|
||||
if( vips_gaussmat( &t, sigma, min_ampl,
|
||||
"integer", TRUE,
|
||||
NULL ) )
|
||||
return( NULL );
|
||||
if( !(msk = im_vips2imask( t, filename )) ) {
|
||||
g_object_unref( t );
|
||||
return( NULL );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( msk );
|
||||
}
|
||||
|
||||
INTMASK *
|
||||
im_gauss_imask_sep( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
VipsImage *t;
|
||||
INTMASK *msk;
|
||||
|
||||
if( vips_gaussmat( &t, sigma, min_ampl,
|
||||
"integer", TRUE,
|
||||
"separable", TRUE,
|
||||
NULL ) )
|
||||
return( NULL );
|
||||
if( !(msk = im_vips2imask( t, filename )) ) {
|
||||
g_object_unref( t );
|
||||
return( NULL );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( msk );
|
||||
}
|
||||
|
||||
INTMASK *
|
||||
im_log_imask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
VipsImage *t;
|
||||
INTMASK *msk;
|
||||
|
||||
if( vips_logmat( &t, sigma, min_ampl,
|
||||
"integer", TRUE,
|
||||
NULL ) )
|
||||
return( NULL );
|
||||
if( !(msk = im_vips2imask( t, filename )) ) {
|
||||
g_object_unref( t );
|
||||
return( NULL );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( msk );
|
||||
}
|
||||
|
||||
DOUBLEMASK *
|
||||
im_log_dmask( const char *filename, double sigma, double min_ampl )
|
||||
{
|
||||
VipsImage *t;
|
||||
DOUBLEMASK *msk;
|
||||
|
||||
if( vips_logmat( &t, sigma, min_ampl,
|
||||
NULL ) )
|
||||
return( NULL );
|
||||
if( !(msk = im_vips2mask( t, filename )) ) {
|
||||
g_object_unref( t );
|
||||
return( NULL );
|
||||
}
|
||||
g_object_unref( t );
|
||||
|
||||
return( msk );
|
||||
}
|
||||
|
||||
int
|
||||
im_recomb( IMAGE *in, IMAGE *out, DOUBLEMASK *recomb )
|
||||
{
|
||||
@ -1917,6 +2088,154 @@ im_recomb( IMAGE *in, IMAGE *out, DOUBLEMASK *recomb )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_compass( VipsImage *in, VipsImage *out, INTMASK *mask )
|
||||
{
|
||||
VipsImage *t1, *t2;
|
||||
|
||||
if( !(t1 = vips_image_new()) ||
|
||||
im_imask2vips( mask, t1 ) )
|
||||
return( -1 );
|
||||
if( vips_compass( in, &t2, t1,
|
||||
"times", 8,
|
||||
NULL ) ) {
|
||||
g_object_unref( t1 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t1 );
|
||||
if( vips_image_write( t2, out ) ) {
|
||||
g_object_unref( t2 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t2 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_lindetect( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
VipsImage *t1, *t2;
|
||||
|
||||
if( !(t1 = vips_image_new()) ||
|
||||
im_imask2vips( mask, t1 ) )
|
||||
return( -1 );
|
||||
if( vips_compass( in, &t2, t1,
|
||||
"times", 4,
|
||||
NULL ) ) {
|
||||
g_object_unref( t1 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t1 );
|
||||
if( vips_image_write( t2, out ) ) {
|
||||
g_object_unref( t2 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t2 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_gradient( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
VipsImage *t1, *t2;
|
||||
|
||||
if( !(t1 = vips_image_new()) ||
|
||||
im_imask2vips( mask, t1 ) )
|
||||
return( -1 );
|
||||
if( vips_compass( in, &t2, t1,
|
||||
"times", 2,
|
||||
"angle", VIPS_ANGLE45_90,
|
||||
"combine", VIPS_COMBINE_SUM,
|
||||
NULL ) ) {
|
||||
g_object_unref( t1 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t1 );
|
||||
if( vips_image_write( t2, out ) ) {
|
||||
g_object_unref( t2 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t2 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_convsep_raw( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
im_error( "im_convsep_raw", "no compat function" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
int
|
||||
im_convsep( IMAGE *in, IMAGE *out, INTMASK *mask )
|
||||
{
|
||||
VipsImage *t1, *t2;
|
||||
|
||||
if( !(t1 = vips_image_new()) ||
|
||||
im_imask2vips( mask, t1 ) )
|
||||
return( -1 );
|
||||
if( vips_convsep( in, &t2, t1,
|
||||
NULL ) ) {
|
||||
g_object_unref( t1 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t1 );
|
||||
if( vips_image_write( t2, out ) ) {
|
||||
g_object_unref( t2 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t2 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_convsep_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
|
||||
{
|
||||
im_error( "im_convsep_raw", "no compat function" );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
int
|
||||
im_convsep_f( IMAGE *in, IMAGE *out, DOUBLEMASK *mask )
|
||||
{
|
||||
VipsImage *t1, *t2;
|
||||
|
||||
if( !(t1 = vips_image_new()) ||
|
||||
im_mask2vips( mask, t1 ) )
|
||||
return( -1 );
|
||||
if( vips_convsep( in, &t2, t1,
|
||||
"precision", VIPS_PRECISION_FLOAT,
|
||||
NULL ) ) {
|
||||
g_object_unref( t1 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t1 );
|
||||
if( vips_image_write( t2, out ) ) {
|
||||
g_object_unref( t2 );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( t2 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_addgnoise( IMAGE *in, IMAGE *out, double sigma )
|
||||
{
|
||||
IMAGE *t;
|
||||
|
||||
if( !(t = im_open_local( out, "im_addgnoise", "p" )) ||
|
||||
im_gaussnoise( t, in->Xsize, in->Ysize, 0, sigma ) ||
|
||||
im_add( in, t, out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips__round( VipsImage *in, VipsImage *out, VipsOperationRound round )
|
||||
{
|
||||
|
@ -280,11 +280,11 @@ read_csv( FILE *fp, VipsImage *out,
|
||||
fsetpos( fp, &pos );
|
||||
}
|
||||
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
vips_image_init_fields( out,
|
||||
columns, lines, 1,
|
||||
VIPS_FORMAT_DOUBLE,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, 1.0, 1.0 );
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
/* Just reading the header? We are done.
|
||||
*/
|
||||
@ -663,12 +663,11 @@ vips__matrix_body( char *whitemap, VipsImage *out, FILE *fp )
|
||||
}
|
||||
|
||||
VipsImage *
|
||||
vips__matrix_read( const char *filename )
|
||||
vips__matrix_read_file( FILE *fp )
|
||||
{
|
||||
char whitemap[256];
|
||||
int i;
|
||||
char *p;
|
||||
FILE *fp;
|
||||
int width;
|
||||
int height;
|
||||
double scale;
|
||||
@ -680,13 +679,9 @@ vips__matrix_read( const char *filename )
|
||||
for( p = WHITESPACE; *p; p++ )
|
||||
whitemap[(int) *p] = 1;
|
||||
|
||||
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
|
||||
return( NULL );
|
||||
if( vips__matrix_header( whitemap, fp,
|
||||
&width, &height, &scale, &offset ) ) {
|
||||
fclose( fp );
|
||||
&width, &height, &scale, &offset ) )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if( !(out = vips_image_new_matrix( width, height )) )
|
||||
return( NULL );
|
||||
@ -695,28 +690,35 @@ vips__matrix_read( const char *filename )
|
||||
|
||||
if( vips__matrix_body( whitemap, out, fp ) ) {
|
||||
g_object_unref( out );
|
||||
fclose( fp );
|
||||
return( NULL );
|
||||
}
|
||||
fclose( fp );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
VipsImage *
|
||||
vips__matrix_read( const char *filename )
|
||||
{
|
||||
FILE *fp;
|
||||
VipsImage *out;
|
||||
|
||||
if( !(fp = vips__file_open_read( filename, NULL, TRUE )) )
|
||||
return( NULL );
|
||||
out = vips__matrix_read_file( fp );
|
||||
fclose( fp );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
int
|
||||
vips__matrix_write( VipsImage *in, const char *filename )
|
||||
vips__matrix_write_file( VipsImage *in, FILE *fp )
|
||||
{
|
||||
VipsImage *mask;
|
||||
FILE *fp;
|
||||
int x, y;
|
||||
|
||||
if( vips_check_matrix( "vips2mask", in, &mask ) )
|
||||
return( -1 );
|
||||
|
||||
if( !(fp = vips__file_open_write( filename, TRUE )) ) {
|
||||
g_object_unref( mask );
|
||||
return( -1 );
|
||||
}
|
||||
fprintf( fp, "%d %d ", mask->Xsize, mask->Ysize );
|
||||
if( vips_image_get_typeof( mask, "scale" ) &&
|
||||
vips_image_get_typeof( mask, "offset" ) )
|
||||
@ -733,10 +735,23 @@ vips__matrix_write( VipsImage *in, const char *filename )
|
||||
}
|
||||
|
||||
g_object_unref( mask );
|
||||
fclose( fp );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
vips__matrix_write( VipsImage *in, const char *filename )
|
||||
{
|
||||
FILE *fp;
|
||||
int result;
|
||||
|
||||
if( !(fp = vips__file_open_write( filename, TRUE )) )
|
||||
return( -1 );
|
||||
result = vips__matrix_write_file( in, fp );
|
||||
fclose( fp );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
const char *vips__foreign_matrix_suffs[] = { ".mat", NULL };
|
||||
|
||||
|
@ -48,8 +48,10 @@ int vips__csv_write( VipsImage *in, const char *filename,
|
||||
int vips__matrix_read_header( const char *filename,
|
||||
int *width, int *height, double *scale, double *offset );
|
||||
int vips__matrix_ismatrix( const char *filename );
|
||||
VipsImage *vips__matrix_read_file( FILE *fp );
|
||||
VipsImage *vips__matrix_read( const char *filename );
|
||||
int vips__matrix_write( VipsImage *in, const char *filename );
|
||||
int vips__matrix_write_file( VipsImage *in, FILE *fp );
|
||||
|
||||
extern const char *vips__foreign_matrix_suffs[];
|
||||
|
||||
|
@ -263,7 +263,8 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above,
|
||||
* easy.
|
||||
*/
|
||||
layer->image = vips_image_new();
|
||||
if( vips_image_copy_fields( layer->image, save->ready ) ) {
|
||||
if( vips_image_pipelinev( layer->image,
|
||||
VIPS_DEMAND_STYLE_ANY, save->ready, NULL ) ) {
|
||||
layer_free( layer );
|
||||
return( NULL );
|
||||
}
|
||||
|
@ -296,11 +296,11 @@ vips_fits_get_header( VipsFits *fits, VipsImage *out )
|
||||
else
|
||||
type = VIPS_INTERPRETATION_MULTIBAND;
|
||||
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
vips_image_init_fields( out,
|
||||
width, height, bands,
|
||||
format,
|
||||
VIPS_CODING_NONE, type, 1.0, 1.0 );
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
|
||||
/* Read all keys into meta.
|
||||
*/
|
||||
|
@ -776,7 +776,7 @@ vips_foreign_load_start( VipsImage *out, void *a, void *b )
|
||||
/* We have to tell vips that out depends on real. We've set
|
||||
* the demand hint below, but not given an input there.
|
||||
*/
|
||||
vips_demand_hint( load->out, load->out->dhint,
|
||||
vips_image_pipelinev( load->out, load->out->dhint,
|
||||
load->real, NULL );
|
||||
}
|
||||
|
||||
@ -874,7 +874,7 @@ vips_foreign_load_build( VipsObject *object )
|
||||
/* ->header() should set the dhint. It'll default to the safe
|
||||
* SMALLTILE if header() did not set it.
|
||||
*/
|
||||
vips_demand_hint( load->out, load->out->dhint, NULL );
|
||||
vips_image_pipelinev( load->out, load->out->dhint, NULL );
|
||||
|
||||
/* Then 'start' creates the real image and 'gen' fetches
|
||||
* pixels for @out from @real on demand.
|
||||
@ -1611,6 +1611,7 @@ vips_foreign_operation_init( void )
|
||||
extern GType vips_foreign_save_csv_get_type( void );
|
||||
extern GType vips_foreign_load_matrix_get_type( void );
|
||||
extern GType vips_foreign_save_matrix_get_type( void );
|
||||
extern GType vips_foreign_print_matrix_get_type( void );
|
||||
extern GType vips_foreign_load_fits_get_type( void );
|
||||
extern GType vips_foreign_save_fits_get_type( void );
|
||||
extern GType vips_foreign_load_analyze_get_type( void );
|
||||
@ -1643,6 +1644,7 @@ vips_foreign_operation_init( void )
|
||||
vips_foreign_save_csv_get_type();
|
||||
vips_foreign_load_matrix_get_type();
|
||||
vips_foreign_save_matrix_get_type();
|
||||
vips_foreign_print_matrix_get_type();
|
||||
vips_foreign_load_analyze_get_type();
|
||||
vips_foreign_load_raw_get_type();
|
||||
vips_foreign_save_raw_get_type();
|
||||
@ -1988,6 +1990,7 @@ vips_jpegload( const char *filename, VipsImage **out, ... )
|
||||
* @Q: quality factor
|
||||
* @profile: attach this ICC profile
|
||||
* @optimize_coding: compute optimal Huffman coding tables
|
||||
* @interlace: write an interlaced (progressive) jpeg
|
||||
*
|
||||
* Write a VIPS image to a file as JPEG.
|
||||
*
|
||||
@ -2012,6 +2015,13 @@ vips_jpegload( const char *filename, VipsImage **out, ... )
|
||||
* IPCT as @VIPS_META_IPCT_NAME ("ipct-data") and XMP as VIPS_META_XMP_NAME
|
||||
* ("xmp-data") are coded and attached.
|
||||
*
|
||||
* If @optimize_coding is set, the Huffman tables are optimised. This is
|
||||
* sllightly slower and produces slightly smaller files.
|
||||
*
|
||||
* If @interlace is set, the jpeg files will be interlaced (progressive jpeg,
|
||||
* in jpg parlance). These files may be better for display over a slow network
|
||||
* conection, but need much more memory to encode and decode.
|
||||
*
|
||||
* See also: vips_jpegsave_buffer(), vips_image_write_file().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
@ -2041,6 +2051,7 @@ vips_jpegsave( VipsImage *in, const char *filename, ... )
|
||||
* @Q: JPEG quality factor
|
||||
* @profile: attach this ICC profile
|
||||
* @optimize_coding: compute optimal Huffman coding tables
|
||||
* @interlace: write an interlaced (progressive) jpeg
|
||||
*
|
||||
* As vips_jpegsave(), but save to a memory buffer.
|
||||
*
|
||||
|
@ -764,7 +764,7 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out )
|
||||
interpretation,
|
||||
xres, yres );
|
||||
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
/* Interlaced jpegs need lots of memory to read, so our caller needs
|
||||
* to know.
|
||||
|
@ -83,6 +83,10 @@ typedef struct _VipsForeignSaveJpeg {
|
||||
*/
|
||||
gboolean optimize_coding;
|
||||
|
||||
/* Generate an interlaced (progressive, in jpg terminology) file.
|
||||
*/
|
||||
gboolean interlace;
|
||||
|
||||
} VipsForeignSaveJpeg;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignSaveJpegClass;
|
||||
@ -135,6 +139,13 @@ vips_foreign_save_jpeg_class_init( VipsForeignSaveJpegClass *class )
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveJpeg, optimize_coding ),
|
||||
FALSE );
|
||||
|
||||
VIPS_ARG_BOOL( class, "interlace", 13,
|
||||
_( "interlace" ),
|
||||
_( "Generate an interlaced (progressive) jpeg" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveJpeg, interlace ),
|
||||
FALSE );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -169,7 +180,8 @@ vips_foreign_save_jpeg_file_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__jpeg_write_file( save->ready, file->filename,
|
||||
jpeg->Q, jpeg->profile, jpeg->optimize_coding ) )
|
||||
jpeg->Q, jpeg->profile, jpeg->optimize_coding,
|
||||
jpeg->interlace ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -234,7 +246,8 @@ vips_foreign_save_jpeg_buffer_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__jpeg_write_buffer( save->ready,
|
||||
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding ) )
|
||||
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding,
|
||||
jpeg->interlace ) )
|
||||
return( -1 );
|
||||
|
||||
area = vips_area_new_blob( (VipsCallbackFn) vips_free, obuf, olen );
|
||||
@ -295,7 +308,8 @@ vips_foreign_save_jpeg_mime_build( VipsObject *object )
|
||||
return( -1 );
|
||||
|
||||
if( vips__jpeg_write_buffer( save->ready,
|
||||
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding ) )
|
||||
&obuf, &olen, jpeg->Q, jpeg->profile, jpeg->optimize_coding,
|
||||
jpeg->interlace ) )
|
||||
return( -1 );
|
||||
|
||||
printf( "Content-length: %zd\r\n", olen );
|
||||
|
@ -337,7 +337,7 @@ parse_header( Read *read )
|
||||
*/
|
||||
im->Coding = VIPS_CODING_NONE;
|
||||
|
||||
vips_demand_hint( im, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
vips_image_pipelinev( im, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
|
||||
/* Three ways to loop over attributes / properties :-(
|
||||
*/
|
||||
|
@ -155,3 +155,75 @@ vips_matrixsave( VipsImage *in, const char *filename, ... )
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignPrintMatrix {
|
||||
VipsForeignSave parent_object;
|
||||
|
||||
} VipsForeignPrintMatrix;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignPrintMatrixClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignPrintMatrix, vips_foreign_print_matrix,
|
||||
VIPS_TYPE_FOREIGN_SAVE );
|
||||
|
||||
static int
|
||||
vips_foreign_print_matrix_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_print_matrix_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__matrix_write_file( save->ready, stdout ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_print_matrix_class_init( VipsForeignPrintMatrixClass *class )
|
||||
{
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||
|
||||
object_class->nickname = "matrixprint";
|
||||
object_class->description = _( "print matrix" );
|
||||
object_class->build = vips_foreign_print_matrix_build;
|
||||
|
||||
foreign_class->suffs = vips__foreign_matrix_suffs;
|
||||
|
||||
save_class->saveable = VIPS_SAVEABLE_MONO;
|
||||
save_class->format_table = bandfmt_matrix;
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_print_matrix_init( VipsForeignPrintMatrix *matrix )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_matrixprint:
|
||||
* @in: image to print
|
||||
* @...: %NULL-terminated list of optional named arguments
|
||||
*
|
||||
* Print @in to %stdout in matrix format. See vips_matrixload() for a
|
||||
* description of the format.
|
||||
*
|
||||
* See also: vips_matrixload().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_matrixprint( VipsImage *in, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, in );
|
||||
result = vips_call_split( "matrixprint", ap, in );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
||||
|
@ -212,9 +212,9 @@ read_header( Read *read, VipsImage *out )
|
||||
VIPS_FORMAT_FLOAT,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
if( read->tiles )
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
else
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -220,7 +220,7 @@ readslide_new( const char *filename, VipsImage *out,
|
||||
associated, &w, &h );
|
||||
vips_image_set_string( out, "slide-associated-image",
|
||||
associated );
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
}
|
||||
else {
|
||||
char buf[256];
|
||||
@ -231,7 +231,7 @@ readslide_new( const char *filename, VipsImage *out,
|
||||
rslide->downsample = openslide_get_level_downsample(
|
||||
rslide->osr, level );
|
||||
vips_image_set_int( out, "slide-level", level );
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL );
|
||||
|
||||
/* Try to get tile width/height. An undocumented, experimental
|
||||
* feature.
|
||||
|
@ -1236,7 +1236,7 @@ read_tilewise( ReadTiff *rtiff, VipsImage *out )
|
||||
* the cache we are quite happy serving that if anything downstream
|
||||
* would like it.
|
||||
*/
|
||||
vips_demand_hint( raw, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
vips_image_pipelinev( raw, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
if( vips_image_generate( raw,
|
||||
tiff_seq_start, tiff_fill_region, tiff_seq_stop,
|
||||
@ -1413,7 +1413,7 @@ read_stripwise( ReadTiff *rtiff, VipsImage *out )
|
||||
if( parse_header( rtiff, t[0] ) )
|
||||
return( -1 );
|
||||
|
||||
vips_demand_hint( t[0], VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
vips_image_pipelinev( t[0], VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
if( !tfget32( rtiff->tiff,
|
||||
TIFFTAG_ROWSPERSTRIP, &rtiff->rows_per_strip ) )
|
||||
|
@ -841,7 +841,7 @@ write_jpeg_block( REGION *region, Rect *area, void *a )
|
||||
*/
|
||||
static int
|
||||
write_vips( Write *write, int qfac, const char *profile,
|
||||
gboolean optimize_coding )
|
||||
gboolean optimize_coding, gboolean progressive )
|
||||
{
|
||||
VipsImage *in;
|
||||
J_COLOR_SPACE space;
|
||||
@ -898,6 +898,11 @@ write_vips( Write *write, int qfac, const char *profile,
|
||||
*/
|
||||
write->cinfo.optimize_coding = optimize_coding;
|
||||
|
||||
/* Enable progressive write.
|
||||
*/
|
||||
if( progressive )
|
||||
jpeg_simple_progression( &write->cinfo );
|
||||
|
||||
/* Build compress tables.
|
||||
*/
|
||||
jpeg_start_compress( &write->cinfo, TRUE );
|
||||
@ -941,7 +946,7 @@ write_vips( Write *write, int qfac, const char *profile,
|
||||
int
|
||||
vips__jpeg_write_file( VipsImage *in,
|
||||
const char *filename, int Q, const char *profile,
|
||||
gboolean optimize_coding )
|
||||
gboolean optimize_coding, gboolean progressive )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
@ -971,7 +976,7 @@ vips__jpeg_write_file( VipsImage *in,
|
||||
|
||||
/* Convert!
|
||||
*/
|
||||
if( write_vips( write, Q, profile, optimize_coding ) ) {
|
||||
if( write_vips( write, Q, profile, optimize_coding, progressive ) ) {
|
||||
write_destroy( write );
|
||||
return( -1 );
|
||||
}
|
||||
@ -1218,7 +1223,7 @@ buf_dest( j_compress_ptr cinfo, void **obuf, size_t *olen )
|
||||
int
|
||||
vips__jpeg_write_buffer( VipsImage *in,
|
||||
void **obuf, size_t *olen, int Q, const char *profile,
|
||||
gboolean optimize_coding )
|
||||
gboolean optimize_coding, gboolean progressive )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
@ -1247,7 +1252,7 @@ vips__jpeg_write_buffer( VipsImage *in,
|
||||
|
||||
/* Convert!
|
||||
*/
|
||||
if( write_vips( write, Q, profile, optimize_coding ) ) {
|
||||
if( write_vips( write, Q, profile, optimize_coding, progressive ) ) {
|
||||
write_destroy( write );
|
||||
|
||||
return( -1 );
|
||||
|
@ -39,10 +39,10 @@ extern const char *vips__jpeg_suffs[];
|
||||
|
||||
int vips__jpeg_write_file( VipsImage *in,
|
||||
const char *filename, int Q, const char *profile,
|
||||
gboolean optimize_coding );
|
||||
gboolean optimize_coding, gboolean progressive );
|
||||
int vips__jpeg_write_buffer( VipsImage *in,
|
||||
void **obuf, size_t *olen, int Q, const char *profile,
|
||||
gboolean optimize_coding );
|
||||
gboolean optimize_coding, gboolean progressive );
|
||||
|
||||
int vips__isjpeg( const char *filename );
|
||||
int vips__jpeg_read_file( const char *name, VipsImage *out,
|
||||
|
@ -351,7 +351,7 @@ png2vips_header( Read *read, VipsImage *out )
|
||||
/* Sequential mode needs thinstrip to work with things like
|
||||
* vips_shrink().
|
||||
*/
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
/* Fetch the ICC profile. @name is useless, something like "icc" or
|
||||
* "ICC Profile" etc. Ignore it.
|
||||
|
@ -153,7 +153,7 @@ read_header( Read *read, VipsImage *out )
|
||||
VIPS_INTERPRETATION_sRGB,
|
||||
1.0, 1.0 );
|
||||
|
||||
vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -256,16 +256,14 @@ vips_hist_local_build( VipsObject *object )
|
||||
|
||||
g_object_set( object, "out", vips_image_new(), NULL );
|
||||
|
||||
if( vips_image_copy_fields( local->out, in ) )
|
||||
return( -1 );
|
||||
local->out->Xsize -= local->width - 1;
|
||||
local->out->Ysize -= local->height - 1;
|
||||
|
||||
/* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause
|
||||
* too many recalculations on overlaps.
|
||||
*/
|
||||
vips_demand_hint( local->out,
|
||||
VIPS_DEMAND_STYLE_FATSTRIP, in, NULL );
|
||||
if( vips_image_pipelinev( local->out,
|
||||
VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
local->out->Xsize -= local->width - 1;
|
||||
local->out->Ysize -= local->height - 1;
|
||||
|
||||
if( vips_image_generate( local->out,
|
||||
vips_hist_local_start,
|
||||
|
@ -157,10 +157,9 @@ vips_histogram_build( VipsObject *object )
|
||||
*/
|
||||
histogram->ready = size;
|
||||
|
||||
if( vips_image_copy_fields_array( histogram->out, histogram->ready ) )
|
||||
if( vips_image_pipeline_array( histogram->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, histogram->ready ) )
|
||||
return( -1 );
|
||||
vips_demand_hint_array( histogram->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, histogram->ready );
|
||||
|
||||
histogram->out->Xsize = VIPS_IMAGE_N_PELS( histogram->ready[0] );
|
||||
histogram->out->Ysize = 1;
|
||||
|
@ -564,10 +564,9 @@ vips_maplut_build( VipsObject *object )
|
||||
vips_image_pio_input( in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_copy_fieldsv( maplut->out, in, lut, NULL ) )
|
||||
if( vips_image_pipelinev( maplut->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, lut, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( maplut->out, VIPS_DEMAND_STYLE_THINSTRIP,
|
||||
in, lut, NULL );
|
||||
maplut->out->BandFmt = lut->BandFmt;
|
||||
|
||||
/* Output has same number of bands as LUT, unless LUT has 1 band, in
|
||||
|
@ -249,16 +249,14 @@ vips_stdif_build( VipsObject *object )
|
||||
|
||||
g_object_set( object, "out", vips_image_new(), NULL );
|
||||
|
||||
if( vips_image_copy_fields( stdif->out, in ) )
|
||||
return( -1 );
|
||||
stdif->out->Xsize -= stdif->width - 1;
|
||||
stdif->out->Ysize -= stdif->height - 1;
|
||||
|
||||
/* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause
|
||||
* too many recalculations on overlaps.
|
||||
*/
|
||||
vips_demand_hint( stdif->out,
|
||||
VIPS_DEMAND_STYLE_FATSTRIP, in, NULL );
|
||||
if( vips_image_pipelinev( stdif->out,
|
||||
VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
stdif->out->Xsize -= stdif->width - 1;
|
||||
stdif->out->Ysize -= stdif->height - 1;
|
||||
|
||||
if( vips_image_generate( stdif->out,
|
||||
vips_start_one,
|
||||
|
@ -65,6 +65,7 @@ vips_scan_headers = \
|
||||
${top_srcdir}/libvips/include/vips/colour.h \
|
||||
${top_srcdir}/libvips/include/vips/operation.h \
|
||||
${top_srcdir}/libvips/include/vips/convolution.h \
|
||||
${top_srcdir}/libvips/include/vips/morphology.h \
|
||||
${top_srcdir}/libvips/include/vips/object.h
|
||||
|
||||
enumtypes.h: $(vips_scan_headers) Makefile
|
||||
|
@ -69,6 +69,18 @@ typedef enum {
|
||||
VIPS_ANGLE_LAST
|
||||
} VipsAngle;
|
||||
|
||||
typedef enum {
|
||||
VIPS_ANGLE45_0,
|
||||
VIPS_ANGLE45_45,
|
||||
VIPS_ANGLE45_90,
|
||||
VIPS_ANGLE45_135,
|
||||
VIPS_ANGLE45_180,
|
||||
VIPS_ANGLE45_225,
|
||||
VIPS_ANGLE45_270,
|
||||
VIPS_ANGLE45_315,
|
||||
VIPS_ANGLE45_LAST
|
||||
} VipsAngle45;
|
||||
|
||||
int vips_copy( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_tilecache( VipsImage *in, VipsImage **out, ... )
|
||||
@ -107,6 +119,8 @@ int vips_wrap( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_rot( VipsImage *in, VipsImage **out, VipsAngle angle, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_rot45( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_zoom( VipsImage *in, VipsImage **out, int xfac, int yfac, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_subsample( VipsImage *in, VipsImage **out, int xfac, int yfac, ... )
|
||||
@ -143,7 +157,7 @@ int vips_bandjoin( VipsImage **in, VipsImage **out, int n, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_bandjoin2( VipsImage *in1, VipsImage *in2, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_bandmean( VipsImage *in, VipsImage **out, ... )
|
||||
int vips_bandrank( VipsImage **in, VipsImage **out, int n, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_bandbool( VipsImage *in, VipsImage **out,
|
||||
@ -155,6 +169,8 @@ int vips_bandor( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_bandeor( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_bandmean( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_recomb( VipsImage *in, VipsImage **out, VipsImage *m, ... )
|
||||
__attribute__((sentinel));
|
||||
|
@ -41,31 +41,48 @@ extern "C" {
|
||||
typedef enum {
|
||||
VIPS_PRECISION_INTEGER,
|
||||
VIPS_PRECISION_FLOAT,
|
||||
VIPS_PRECISION_APPROXIMATE
|
||||
VIPS_PRECISION_APPROXIMATE,
|
||||
VIPS_PRECISION_LAST
|
||||
} VipsPrecision;
|
||||
|
||||
typedef enum {
|
||||
VIPS_COMBINE_MAX,
|
||||
VIPS_COMBINE_SUM,
|
||||
VIPS_COMBINE_LAST
|
||||
} VipsCombine;
|
||||
|
||||
/**
|
||||
* VipsOperationMorphology:
|
||||
* @VIPS_OPERATION_MORPHOLOGY_ERODE: true if all set
|
||||
* @VIPS_OPERATION_MORPHOLOGY_DILATE: true if one set
|
||||
*
|
||||
* More like hit-miss, really.
|
||||
*
|
||||
* See also: vips_morph().
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
VIPS_OPERATION_MORPHOLOGY_ERODE,
|
||||
VIPS_OPERATION_MORPHOLOGY_DILATE,
|
||||
VIPS_OPERATION_MORPHOLOGY_LAST
|
||||
} VipsOperationMorphology;
|
||||
|
||||
int vips_conv( VipsImage *in, VipsImage **out, VipsImage *mask, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_compass( VipsImage *in, VipsImage **out, VipsImage *mask, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_convsep( VipsImage *in, VipsImage **out, VipsImage *mask, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_morph( VipsImage *in, VipsImage **out, VipsImage *mask,
|
||||
VipsOperationMorphology morph, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
void vips_convolution_operation_init( void );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int im_aconvsep( VipsImage *in, VipsImage *out,
|
||||
DOUBLEMASK *mask, int n_layers );
|
||||
int im_aconv( VipsImage *in, VipsImage *out,
|
||||
DOUBLEMASK *mask, int n_layers, int cluster );
|
||||
int im_conv( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_conv_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask );
|
||||
int im_convsep( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_convsep_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask );
|
||||
|
||||
int im_compass( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_gradient( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_lindetect( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
|
||||
int im_sharpen( VipsImage *in, VipsImage *out,
|
||||
int mask_size,
|
||||
double x1, double y2, double y3,
|
||||
@ -80,8 +97,6 @@ int im_gradcor( VipsImage *in, VipsImage *ref, VipsImage *out );
|
||||
int im_contrast_surface( VipsImage *in, VipsImage *out,
|
||||
int half_win_size, int spacing );
|
||||
|
||||
int im_addgnoise( VipsImage *in, VipsImage *out, double sigma );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -47,6 +47,10 @@ int vips_xyz( VipsImage **out, int width, int height, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_grey( VipsImage **out, int width, int height, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_gaussmat( VipsImage **out, double sigma, double min_ampl, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_logmat( VipsImage **out, double sigma, double min_ampl, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_text( VipsImage **out, const char *text, ... )
|
||||
__attribute__((sentinel));
|
||||
|
@ -47,6 +47,8 @@ GType vips_align_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_ALIGN (vips_align_get_type())
|
||||
GType vips_angle_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_ANGLE (vips_angle_get_type())
|
||||
GType vips_angle45_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_ANGLE45 (vips_angle45_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())
|
||||
@ -72,6 +74,10 @@ GType vips_operation_flags_get_type (void) G_GNUC_CONST;
|
||||
/* enumerations from "../../../libvips/include/vips/convolution.h" */
|
||||
GType vips_precision_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_PRECISION (vips_precision_get_type())
|
||||
GType vips_combine_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_COMBINE (vips_combine_get_type())
|
||||
GType vips_operation_morphology_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_OPERATION_MORPHOLOGY (vips_operation_morphology_get_type())
|
||||
/* enumerations from "../../../libvips/include/vips/object.h" */
|
||||
GType vips_argument_flags_get_type (void) G_GNUC_CONST;
|
||||
#define VIPS_TYPE_ARGUMENT_FLAGS (vips_argument_flags_get_type())
|
||||
|
@ -83,10 +83,12 @@ int vips_check_8or16( const char *domain, VipsImage *im );
|
||||
int vips_check_u8or16orf( const char *domain, VipsImage *im );
|
||||
int vips_check_format_same( const char *domain, VipsImage *im1, VipsImage *im2 );
|
||||
int vips_check_size_same( const char *domain, VipsImage *im1, VipsImage *im2 );
|
||||
int vips_check_oddsquare( const char *domain, VipsImage *im );
|
||||
int vips_check_vector_length( const char *domain, int n, int len );
|
||||
int vips_check_vector( const char *domain, int n, VipsImage *im );
|
||||
int vips_check_hist( const char *domain, VipsImage *im );
|
||||
int vips_check_matrix( const char *domain, VipsImage *im, VipsImage **out );
|
||||
int vips_check_separable( const char *domain, VipsImage *im );
|
||||
|
||||
int vips_check_imask( const char *domain, INTMASK *mask );
|
||||
int vips_check_dmask( const char *domain, DOUBLEMASK *mask );
|
||||
|
@ -421,6 +421,8 @@ int vips_matrixload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_matrixsave( VipsImage *in, const char *filename, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_matrixprint( VipsImage *in, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_magickload( const char *filename, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
@ -73,9 +73,9 @@ int vips_image_generate( VipsImage *im,
|
||||
void *a, void *b
|
||||
);
|
||||
|
||||
void vips_demand_hint_array( VipsImage *image,
|
||||
int vips_image_pipeline_array( VipsImage *image,
|
||||
VipsDemandStyle hint, VipsImage **in );
|
||||
void vips_demand_hint( VipsImage *image, VipsDemandStyle hint, ... )
|
||||
int vips_image_pipelinev( VipsImage *image, VipsDemandStyle hint, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -118,11 +118,6 @@ void vips_image_init_fields( VipsImage *image,
|
||||
VipsInterpretation interpretation,
|
||||
double xres, double yres );
|
||||
|
||||
int vips_image_copy_fields_array( VipsImage *out, VipsImage *in[] );
|
||||
int vips_image_copy_fieldsv( VipsImage *out, VipsImage *in1, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_image_copy_fields( VipsImage *out, VipsImage *in );
|
||||
|
||||
void vips_image_set( VipsImage *image, const char *field, GValue *value );
|
||||
int vips_image_get( const VipsImage *image,
|
||||
const char *field, GValue *value_copy );
|
||||
|
@ -4,6 +4,9 @@
|
||||
* - from proto.h
|
||||
*/
|
||||
|
||||
/* All deprecated.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file is part of VIPS.
|
||||
|
@ -31,19 +31,18 @@
|
||||
|
||||
*/
|
||||
|
||||
#ifndef IM_MORPHOLOGY_H
|
||||
#define IM_MORPHOLOGY_H
|
||||
#ifndef VIPS_MORPHOLOGY_H
|
||||
#define VIPS_MORPHOLOGY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
int im_dilate( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_erode( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
|
||||
|
||||
|
||||
|
||||
int im_rank( VipsImage *in, VipsImage *out, int width, int height, int index );
|
||||
int im_rank_image( VipsImage **in, VipsImage *out, int n, int index );
|
||||
int im_maxvalue( VipsImage **in, VipsImage *out, int n );
|
||||
|
||||
int im_cntlines( VipsImage *im, double *nolines, int flag );
|
||||
int im_zerox( VipsImage *in, VipsImage *out, int sign );
|
||||
@ -53,4 +52,4 @@ int im_label_regions( VipsImage *test, VipsImage *mask, int *segments );
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#endif /*IM_MORPHOLOGY_H*/
|
||||
#endif /*VIPS_MORPHOLOGY_H*/
|
||||
|
@ -56,6 +56,11 @@ extern "C" {
|
||||
*/
|
||||
#define VIPS_SIZEOF_HEADER (64)
|
||||
|
||||
/* Startup plus ABI check.
|
||||
*/
|
||||
int vips__init( const char *argv0 );
|
||||
size_t vips__get_sizeof_vipsobject( void );
|
||||
|
||||
/* What we track for each mmap window. Have a list of these on an openin
|
||||
* VipsImage.
|
||||
*/
|
||||
@ -165,6 +170,11 @@ VipsArgumentInstance *vips__argument_get_instance(
|
||||
VipsArgument *vips__argument_table_lookup( VipsArgumentTable *table,
|
||||
GParamSpec *pspec);
|
||||
|
||||
void vips__demand_hint_array( struct _VipsImage *image,
|
||||
int hint, struct _VipsImage **in );
|
||||
int vips__image_copy_fields_array( struct _VipsImage *out,
|
||||
struct _VipsImage *in[] );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -149,8 +149,20 @@ extern "C" {
|
||||
#include <vips/almostdeprecated.h>
|
||||
#include <vips/dispatch.h>
|
||||
|
||||
#define vips_init( ARGV0 ) \
|
||||
(sizeof( VipsObject ) != vips__get_sizeof_vipsobject() ? ( \
|
||||
vips_info( "vips_init", "%s", _( "ABI mismatch" ) ), \
|
||||
vips_info( "vips_init", \
|
||||
_( "library has sizeof(VipsObject) == %zd" ), \
|
||||
vips__get_sizeof_vipsobject() ), \
|
||||
vips_info( "vips_init", \
|
||||
_( "application has sizeof(VipsObject) == %zd" ), \
|
||||
sizeof( VipsObject() ) ), \
|
||||
vips_error( "vips_init", "%s", _( "ABI mismatch" ) ), \
|
||||
-1 ) : \
|
||||
vips__init( ARGV0 ))
|
||||
|
||||
const char *vips_get_argv0( void );
|
||||
int vips_init( const char *argv0 );
|
||||
void vips_check_init( void );
|
||||
void vips_shutdown( void );
|
||||
GOptionGroup *vips_get_option_group( void );
|
||||
|
@ -203,15 +203,17 @@ extern "C" {
|
||||
#define im_get_argv0 vips_get_argv0
|
||||
#define im_version_string vips_version_string
|
||||
#define im_version vips_version
|
||||
#define im_init_world vips_init
|
||||
#define im_get_option_group vips_get_option_group
|
||||
#define im_guess_prefix vips_guess_prefix
|
||||
#define im_guess_libdir vips_guess_libdir
|
||||
#define im__global_lock vips__global_lock
|
||||
|
||||
#define im_cp_desc vips_image_copy_fields
|
||||
#define im_cp_descv vips_image_copy_fieldsv
|
||||
#define im_cp_desc_array vips_image_copy_fields_array
|
||||
int im_cp_desc(IMAGE *out, IMAGE *in );
|
||||
int im_cp_descv (IMAGE * im, ...);
|
||||
#define im_cp_desc_array(I, A) vips__image_copy_fields_array(I, A)
|
||||
int im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...);
|
||||
#define im_demand_hint_array( A, B, C ) (vips__demand_hint_array( A, B, C ), 0)
|
||||
|
||||
#define im_image vips_image_new_from_memory
|
||||
#define im_binfile vips_image_new_from_file_raw
|
||||
#define im__open_temp vips_image_new_temp_file
|
||||
@ -325,9 +327,6 @@ VipsDemandStyle im_char2dhint( const char *str );
|
||||
#define im_rect_dup vips_rect_dup
|
||||
#define im_rect_normalise vips_rect_normalise
|
||||
|
||||
int im_demand_hint (IMAGE * im, VipsDemandStyle hint, ...);
|
||||
#define im_demand_hint_array( A, B, C ) (vips_demand_hint_array( A, B, C ), 0)
|
||||
|
||||
#define im_start_one vips_start_one
|
||||
#define im_stop_one vips_stop_one
|
||||
#define im_start_many vips_start_many
|
||||
@ -586,6 +585,8 @@ size_t im_ref_string_get_length( const GValue *value );
|
||||
#define im_concurrency_set vips_concurrency_set
|
||||
#define im_concurrency_get vips_concurrency_get
|
||||
|
||||
int im_init_world( const char *argv0 );
|
||||
|
||||
int im_add( VipsImage *in1, VipsImage *in2, VipsImage *out );
|
||||
int im_subtract( VipsImage *in1, VipsImage *in2, VipsImage *out );
|
||||
int im_multiply( VipsImage *in1, VipsImage *in2, VipsImage *out );
|
||||
@ -711,6 +712,8 @@ int im_rotquad( VipsImage *in, VipsImage *out );
|
||||
int im_clip2fmt( VipsImage *in, VipsImage *out, VipsBandFormat fmt );
|
||||
int im_bandjoin( VipsImage *in1, VipsImage *in2, VipsImage *out );
|
||||
int im_gbandjoin( VipsImage **in, VipsImage *out, int n );
|
||||
int im_rank_image( VipsImage **in, VipsImage *out, int n, int index );
|
||||
int im_maxvalue( VipsImage **in, VipsImage *out, int n );
|
||||
int im_grid( VipsImage *in, VipsImage *out, int tile_height, int across, int down );
|
||||
int im_scale( VipsImage *in, VipsImage *out );
|
||||
int im_scaleps( VipsImage *in, VipsImage *out );
|
||||
@ -768,6 +771,7 @@ int im_blend( VipsImage *c, VipsImage *a, VipsImage *b, VipsImage *out );
|
||||
DOUBLEMASK *im_vips2mask( VipsImage *in, const char *filename );
|
||||
INTMASK *im_vips2imask( IMAGE *in, const char *filename );
|
||||
int im_mask2vips( DOUBLEMASK *in, VipsImage *out );
|
||||
int im_imask2vips( INTMASK *in, VipsImage *out );
|
||||
|
||||
int im_bandmean( VipsImage *in, VipsImage *out );
|
||||
int im_recomb( VipsImage *in, VipsImage *out, DOUBLEMASK *recomb );
|
||||
@ -894,6 +898,26 @@ int im_tone_map( VipsImage *in, VipsImage *out, VipsImage *lut );
|
||||
*/
|
||||
#define vips_class_map_concrete_all vips_class_map_all
|
||||
|
||||
int im_dilate( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_erode( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
|
||||
int im_aconv( VipsImage *in, VipsImage *out,
|
||||
DOUBLEMASK *mask, int n_layers, int cluster );
|
||||
int im_conv( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_conv_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask );
|
||||
|
||||
int im_aconvsep( VipsImage *in, VipsImage *out,
|
||||
DOUBLEMASK *mask, int n_layers );
|
||||
|
||||
int im_convsep( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_convsep_f( VipsImage *in, VipsImage *out, DOUBLEMASK *mask );
|
||||
|
||||
int im_compass( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_gradient( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
int im_lindetect( VipsImage *in, VipsImage *out, INTMASK *mask );
|
||||
|
||||
int im_addgnoise( VipsImage *in, VipsImage *out, double sigma );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -50,6 +50,7 @@ vips_scan_headers = \
|
||||
${top_srcdir}/libvips/include/vips/colour.h \
|
||||
${top_srcdir}/libvips/include/vips/operation.h \
|
||||
${top_srcdir}/libvips/include/vips/convolution.h \
|
||||
${top_srcdir}/libvips/include/vips/morphology.h \
|
||||
${top_srcdir}/libvips/include/vips/object.h
|
||||
|
||||
enumtypes.c: $(vips_scan_headers) Makefile
|
||||
|
@ -223,6 +223,30 @@ vips_angle_get_type( void )
|
||||
|
||||
return( etype );
|
||||
}
|
||||
GType
|
||||
vips_angle45_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if( etype == 0 ) {
|
||||
static const GEnumValue values[] = {
|
||||
{VIPS_ANGLE45_0, "VIPS_ANGLE45_0", "0"},
|
||||
{VIPS_ANGLE45_45, "VIPS_ANGLE45_45", "45"},
|
||||
{VIPS_ANGLE45_90, "VIPS_ANGLE45_90", "90"},
|
||||
{VIPS_ANGLE45_135, "VIPS_ANGLE45_135", "135"},
|
||||
{VIPS_ANGLE45_180, "VIPS_ANGLE45_180", "180"},
|
||||
{VIPS_ANGLE45_225, "VIPS_ANGLE45_225", "225"},
|
||||
{VIPS_ANGLE45_270, "VIPS_ANGLE45_270", "270"},
|
||||
{VIPS_ANGLE45_315, "VIPS_ANGLE45_315", "315"},
|
||||
{VIPS_ANGLE45_LAST, "VIPS_ANGLE45_LAST", "last"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
etype = g_enum_register_static( "VipsAngle45", values );
|
||||
}
|
||||
|
||||
return( etype );
|
||||
}
|
||||
/* enumerations from "../../libvips/include/vips/arithmetic.h" */
|
||||
GType
|
||||
vips_operation_math_get_type( void )
|
||||
@ -601,6 +625,7 @@ vips_precision_get_type( void )
|
||||
{VIPS_PRECISION_INTEGER, "VIPS_PRECISION_INTEGER", "integer"},
|
||||
{VIPS_PRECISION_FLOAT, "VIPS_PRECISION_FLOAT", "float"},
|
||||
{VIPS_PRECISION_APPROXIMATE, "VIPS_PRECISION_APPROXIMATE", "approximate"},
|
||||
{VIPS_PRECISION_LAST, "VIPS_PRECISION_LAST", "last"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -609,6 +634,42 @@ vips_precision_get_type( void )
|
||||
|
||||
return( etype );
|
||||
}
|
||||
GType
|
||||
vips_combine_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if( etype == 0 ) {
|
||||
static const GEnumValue values[] = {
|
||||
{VIPS_COMBINE_MAX, "VIPS_COMBINE_MAX", "max"},
|
||||
{VIPS_COMBINE_SUM, "VIPS_COMBINE_SUM", "sum"},
|
||||
{VIPS_COMBINE_LAST, "VIPS_COMBINE_LAST", "last"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
etype = g_enum_register_static( "VipsCombine", values );
|
||||
}
|
||||
|
||||
return( etype );
|
||||
}
|
||||
GType
|
||||
vips_operation_morphology_get_type( void )
|
||||
{
|
||||
static GType etype = 0;
|
||||
|
||||
if( etype == 0 ) {
|
||||
static const GEnumValue values[] = {
|
||||
{VIPS_OPERATION_MORPHOLOGY_ERODE, "VIPS_OPERATION_MORPHOLOGY_ERODE", "erode"},
|
||||
{VIPS_OPERATION_MORPHOLOGY_DILATE, "VIPS_OPERATION_MORPHOLOGY_DILATE", "dilate"},
|
||||
{VIPS_OPERATION_MORPHOLOGY_LAST, "VIPS_OPERATION_MORPHOLOGY_LAST", "last"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
etype = g_enum_register_static( "VipsOperationMorphology", values );
|
||||
}
|
||||
|
||||
return( etype );
|
||||
}
|
||||
/* enumerations from "../../libvips/include/vips/object.h" */
|
||||
GType
|
||||
vips_argument_flags_get_type( void )
|
||||
|
@ -1012,6 +1012,32 @@ vips_check_size_same( const char *domain, VipsImage *im1, VipsImage *im2 )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_check_oddsquare:
|
||||
* @domain: the originating domain for the error message
|
||||
* @im: image to check
|
||||
*
|
||||
* Check that the image is square and that the sides are odd.
|
||||
* If not, set an error message
|
||||
* and return non-zero.
|
||||
*
|
||||
* See also: vips_error().
|
||||
*
|
||||
* Returns: 0 if OK, -1 otherwise.
|
||||
*/
|
||||
int
|
||||
vips_check_oddsquare( const char *domain, VipsImage *im )
|
||||
{
|
||||
if( im->Xsize != im->Ysize ||
|
||||
im->Xsize % 2 == 0 ) {
|
||||
vips_error( domain,
|
||||
"%s", _( "images must be odd and square" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_check_bands_same:
|
||||
* @domain: the originating domain for the error message
|
||||
@ -1240,6 +1266,33 @@ vips_check_matrix( const char *domain, VipsImage *im, VipsImage **out )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_check_separable:
|
||||
* @domain: the originating domain for the error message
|
||||
* @im: image to check
|
||||
*
|
||||
* Separable matrix images must have width or height 1.
|
||||
* Return 0 if the image will pass, or -1 and
|
||||
* set an error message otherwise.
|
||||
*
|
||||
* See also: vips_error().
|
||||
*
|
||||
* Returns: 0 if OK, -1 otherwise.
|
||||
*/
|
||||
int
|
||||
vips_check_separable( const char *domain, VipsImage *im )
|
||||
{
|
||||
if( im->Xsize != 1 &&
|
||||
im->Ysize != 1 ) {
|
||||
vips_error( domain,
|
||||
"%s", _( "separable matrix images must have "
|
||||
"width or height 1" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_check_imask: (skip)
|
||||
* @domain: the originating domain for the error message
|
||||
|
@ -274,26 +274,12 @@ vips__link_map( VipsImage *image, gboolean upstream,
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_demand_hint_array:
|
||||
* @image: image to set hint for
|
||||
* @hint: hint for this image
|
||||
* @in: array of input images to this operation
|
||||
*
|
||||
* Operations can set demand hints, that is, hints to the VIPS IO system about
|
||||
* the type of region geometry this operation works best with. For example,
|
||||
* operations which transform coordinates will usually work best with
|
||||
* %VIPS_DEMAND_STYLE_SMALLTILE, operations which work on local windows of
|
||||
* pixels will like %VIPS_DEMAND_STYLE_FATSTRIP.
|
||||
*
|
||||
* VIPS uses the list of input images to build the tree of operations it needs
|
||||
* for the cache invalidation system. You have to call this function, or its
|
||||
* varargs friend vips_demand_hint().
|
||||
*
|
||||
* See also: vips_demand_hint(), vips_image_generate().
|
||||
/* We have to have this as a separate entry point so we can support the old
|
||||
* vips7 API.
|
||||
*/
|
||||
void
|
||||
vips_demand_hint_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in )
|
||||
vips__demand_hint_array( VipsImage *image,
|
||||
VipsDemandStyle hint, VipsImage **in )
|
||||
{
|
||||
int i, len, nany;
|
||||
VipsDemandStyle set_hint;
|
||||
@ -327,7 +313,7 @@ vips_demand_hint_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in )
|
||||
image->dhint = set_hint;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_demand_hint_array: set dhint for \"%s\" to %s\n",
|
||||
printf( "vips_image_pipeline_array: set dhint for \"%s\" to %s\n",
|
||||
image->filename,
|
||||
vips_enum_nick( VIPS_TYPE_DEMAND_STYLE, image->dhint ) );
|
||||
printf( "\toperation requested %s\n",
|
||||
@ -354,17 +340,62 @@ vips_demand_hint_array( VipsImage *image, VipsDemandStyle hint, VipsImage **in )
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_demand_hint:
|
||||
* @image: image to set hint for
|
||||
* @hint: hint for this image
|
||||
* @Varargs: %NULL-terminated list of input images to this operation
|
||||
* vips_image_pipeline_array:
|
||||
* @image: output image
|
||||
* @hint: demand hint for @image
|
||||
* @in: %NULL-terminated array of input images
|
||||
*
|
||||
* Build an array and call vips_demand_hint_array().
|
||||
* Add an image to a pipeline. @image depends on all of the images in @in,
|
||||
* @image prefers to supply pixels according to @hint.
|
||||
*
|
||||
* See also: vips_demand_hint(), vips_image_generate().
|
||||
* Operations can set demand hints, that is, hints to the VIPS IO system about
|
||||
* the type of region geometry this operation works best with. For example,
|
||||
* operations which transform coordinates will usually work best with
|
||||
* %VIPS_DEMAND_STYLE_SMALLTILE, operations which work on local windows of
|
||||
* pixels will like %VIPS_DEMAND_STYLE_FATSTRIP.
|
||||
*
|
||||
* Header fields in @image are set from the fields in @in, with lower-numbered
|
||||
* images in @in taking priority.
|
||||
* For example, if @in[0] and @in[1] both have an item
|
||||
* called "icc-profile", it's the profile attached to @in[0] that will end up
|
||||
* on @image.
|
||||
* Image history is completely copied from all @in. @image will have the history
|
||||
* of all the input images.
|
||||
* The array of input images can be empty, meaning @image is at the start of a
|
||||
* pipeline.
|
||||
*
|
||||
* VIPS uses the list of input images to build the tree of operations it needs
|
||||
* for the cache invalidation system.
|
||||
*
|
||||
* See also: vips_image_pipelinev(), vips_image_generate().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
void
|
||||
vips_demand_hint( VipsImage *image, VipsDemandStyle hint, ... )
|
||||
int
|
||||
vips_image_pipeline_array( VipsImage *image,
|
||||
VipsDemandStyle hint, VipsImage **in )
|
||||
{
|
||||
vips__demand_hint_array( image, hint, in );
|
||||
|
||||
if( in[0] &&
|
||||
vips__image_copy_fields_array( image, in ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_pipelinev:
|
||||
* @image: output image of pipeline
|
||||
* @hint: hint for this image
|
||||
* @...: %NULL-terminated list of input images
|
||||
*
|
||||
* Build an array and call vips_image_pipeline_array().
|
||||
*
|
||||
* See also: vips_image_generate().
|
||||
*/
|
||||
int
|
||||
vips_image_pipelinev( VipsImage *image, VipsDemandStyle hint, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
@ -376,14 +407,14 @@ vips_demand_hint( VipsImage *image, VipsDemandStyle hint, ... )
|
||||
;
|
||||
va_end( ap );
|
||||
if( i == MAX_IMAGES ) {
|
||||
vips_warn( "vips_demand_hint", "%s", _( "too many images" ) );
|
||||
vips_warn( "vips_image_pipeline", "%s", _( "too many images" ) );
|
||||
|
||||
/* Make sure we have a sentinel there.
|
||||
*/
|
||||
ar[i - 1] = NULL;
|
||||
}
|
||||
|
||||
vips_demand_hint_array( image, hint, ar );
|
||||
return( vips_image_pipeline_array( image, hint, ar ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -604,13 +604,13 @@ vips_image_get_data( VipsImage *image )
|
||||
* @yres: vertical resolution, pixels per millimetre
|
||||
*
|
||||
* A convenience function to set the header fields after creating an image.
|
||||
* Normally you copy the fields from one of your input images with
|
||||
* vips_image_copy_fields() and then make
|
||||
* Normally you copy the fields from your input images with
|
||||
* vips_image_pipelinev() and then make
|
||||
* any adjustments you need, but if you are creating an image from scratch,
|
||||
* for example im_black() or im_jpeg2vips(), you do need to set all the
|
||||
* fields yourself.
|
||||
*
|
||||
* See also: vips_image_copy_fields().
|
||||
* See also: vips_image_pipelinev().
|
||||
*/
|
||||
void
|
||||
vips_image_init_fields( VipsImage *image,
|
||||
@ -655,7 +655,7 @@ meta_cp_field( VipsMeta *meta, VipsImage *dst )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* Copy meta on to dst. Called from vips_cp_desc().
|
||||
/* Copy meta on to dst.
|
||||
*/
|
||||
static int
|
||||
meta_cp( VipsImage *dst, const VipsImage *src )
|
||||
@ -671,31 +671,11 @@ meta_cp( VipsImage *dst, const VipsImage *src )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_copy_fields_array:
|
||||
* @out: image to copy to
|
||||
* @in: %NULL-terminated array of images to copy from
|
||||
*
|
||||
* Copy fields from all the input images to the output image. There must be at
|
||||
* least one input image.
|
||||
*
|
||||
* The first input image is used to set the main fields of @out (@width,
|
||||
* @coding and so on).
|
||||
*
|
||||
* Metadata from all the images is merged on to @out, with lower-numbered items
|
||||
* overriding higher. So for example, if @in[0] and @in[1] both have an item
|
||||
* called "icc-profile", it's the profile attached to @in[0] that will end up
|
||||
* on @out.
|
||||
*
|
||||
* Image history is completely copied from all @in. @out will have the history
|
||||
* of all the input images.
|
||||
*
|
||||
* See also: vips_image_copy_fieldsv(), vips_image_copy_fields().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
/* We have to have this as a separate entry point so we can support the old
|
||||
* vips7 API.
|
||||
*/
|
||||
int
|
||||
vips_image_copy_fields_array( VipsImage *out, VipsImage *in[] )
|
||||
vips__image_copy_fields_array( VipsImage *out, VipsImage *in[] )
|
||||
{
|
||||
int i;
|
||||
int ni;
|
||||
@ -740,63 +720,6 @@ vips_image_copy_fields_array( VipsImage *out, VipsImage *in[] )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Max number of images we can handle.
|
||||
*/
|
||||
#define MAX_IMAGES (1000)
|
||||
|
||||
/**
|
||||
* vips_image_copy_fieldsv:
|
||||
* @out: image to copy to
|
||||
* @in1: first image to copy from
|
||||
* @Varargs: %NULL-terminated list of images to copy from
|
||||
*
|
||||
* Copy fields from all the input images to the output image. A convenience
|
||||
* function over vips_image_copy_fields_array().
|
||||
*
|
||||
* See also: vips_image_copy_fields_array(), vips_image_copy_fields().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_image_copy_fieldsv( VipsImage *out, VipsImage *in1, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
VipsImage *in[MAX_IMAGES];
|
||||
|
||||
in[0] = in1;
|
||||
va_start( ap, in1 );
|
||||
for( i = 1; i < MAX_IMAGES &&
|
||||
(in[i] = va_arg( ap, VipsImage * )); i++ )
|
||||
;
|
||||
va_end( ap );
|
||||
if( i == MAX_IMAGES ) {
|
||||
vips_error( "vips_image_copy_fieldsv",
|
||||
"%s", _( "too many images" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( vips_image_copy_fields_array( out, in ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_copy_fields:
|
||||
* @out: image to copy to
|
||||
* @in: image to copy from
|
||||
*
|
||||
* Copy fields from @in to @out. A convenience
|
||||
* function over vips_image_copy_fields_array().
|
||||
*
|
||||
* See also: vips_image_copy_fields_array(), vips_image_copy_fieldsv().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_image_copy_fields( VipsImage *out, VipsImage *in )
|
||||
{
|
||||
return( vips_image_copy_fieldsv( out, in, NULL ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_set:
|
||||
* @image: image to set the metadata on
|
||||
|
@ -105,7 +105,7 @@
|
||||
* @VIPS_DEMAND_STYLE_THINSTRIP: demand in thin (typically 1 pixel high) strips
|
||||
* @VIPS_DEMAND_STYLE_ANY: demand geometry does not matter
|
||||
*
|
||||
* See vips_demand_hint(). Operations can hint to the VIPS image IO system about
|
||||
* See vips_image_pipelinev(). Operations can hint to the VIPS image IO system about
|
||||
* the kind of demand geometry they prefer.
|
||||
*
|
||||
* These demand styles are given below in order of increasing
|
||||
@ -134,7 +134,7 @@
|
||||
* file (even indirectly) so any demand style is OK. It's used for things like
|
||||
* im_black() where the pixels are calculated.
|
||||
*
|
||||
* See also: vips_demand_hint().
|
||||
* See also: vips_image_pipelinev().
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -1939,10 +1939,9 @@ int
|
||||
vips_image_write( VipsImage *image, VipsImage *out )
|
||||
{
|
||||
if( vips_image_pio_input( image ) ||
|
||||
vips_image_copy_fields( out, image ) )
|
||||
vips_image_pipelinev( out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, image, NULL ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, image, NULL );
|
||||
|
||||
/* We generate from @image partially, so we need to keep it about as
|
||||
* long as @out is about.
|
||||
@ -2358,7 +2357,7 @@ int
|
||||
vips__image_wio_output( VipsImage *image )
|
||||
{
|
||||
#ifdef DEBUG_IO
|
||||
printf( "vips_image_wio_output: WIO output for %s\n",
|
||||
printf( "vips__image_wio_output: WIO output for %s\n",
|
||||
image->filename );
|
||||
#endif/*DEBUG_IO*/
|
||||
|
||||
@ -2367,7 +2366,7 @@ vips__image_wio_output( VipsImage *image )
|
||||
/* Make sure nothing is attached.
|
||||
*/
|
||||
if( image->generate_fn ) {
|
||||
vips_error( "vips_image_wio_output",
|
||||
vips_error( "vips__image_wio_output",
|
||||
"%s", _( "image already written" ) );
|
||||
return( -1 );
|
||||
}
|
||||
@ -2391,7 +2390,7 @@ vips__image_wio_output( VipsImage *image )
|
||||
break;
|
||||
|
||||
default:
|
||||
vips_error( "vips_image_wio_output",
|
||||
vips_error( "vips__image_wio_output",
|
||||
"%s", _( "image not writeable" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ vips_get_argv0( void )
|
||||
* </para>
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* <para>loads any plugins from $libdir/vips-x.y, where x and y are the
|
||||
* <para>loads any plugins from $libdir/vips-x.y/, where x and y are the
|
||||
* major and minor version numbers for this VIPS.
|
||||
* </para>
|
||||
* </listitem>
|
||||
@ -165,8 +165,13 @@ vips_get_argv0( void )
|
||||
*
|
||||
* Returns: 0 on success, -1 otherwise
|
||||
*/
|
||||
|
||||
/* vips_init() is actually a macro which checks library and application
|
||||
* compatibility before calling vips__init().
|
||||
*/
|
||||
|
||||
int
|
||||
vips_init( const char *argv0 )
|
||||
vips__init( const char *argv0 )
|
||||
{
|
||||
extern GType vips_system_get_type( void );
|
||||
|
||||
@ -299,6 +304,20 @@ vips_init( const char *argv0 )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Return the sizeof() various important data structures. These are checked
|
||||
* against the headers used to build our caller by vips_init().
|
||||
*
|
||||
* We allow direct access to members of VipsImage and VipsRegion (mostly for
|
||||
* reasons of history), so any change to a superclass of either of these
|
||||
* objects will break our ABI.
|
||||
*/
|
||||
|
||||
size_t
|
||||
vips__get_sizeof_vipsobject( void )
|
||||
{
|
||||
return( sizeof( VipsObject ) );
|
||||
}
|
||||
|
||||
/* Call this before vips stuff that uses stuff we need to have inited.
|
||||
*/
|
||||
void
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user