Merge branch 'master' into add-magick7

This commit is contained in:
John Cupitt 2016-07-25 12:40:43 +01:00
commit 12a32b23f1
40 changed files with 1077 additions and 158 deletions

View File

@ -28,9 +28,11 @@
- pyvips8 can create new metadata
- better upsizing with vips_resize()
- add imagemagick v7 support, thanks sachinwalia2k8
- added vips_worley(), vips_perlin() noise generators
18/5/16 started 8.3.2
- more robust vips image reading
- more robust tiff read [Matt Richards]
15/4/16 started 8.3.1
- rename vips wrapper script, it was still vips-8.2, thanks Benjamin

View File

@ -112,6 +112,7 @@ headers="\
draw.h \
morphology.h \
type.h \
rect.h \
memory.h \
region.h"

View File

@ -22,6 +22,8 @@ import re
import logging
#logging.basicConfig(level = logging.DEBUG)
import gi
gi.require_version('Vips', '8.0')
from gi.repository import Vips, GObject
vips_type_image = GObject.GType.from_name("VipsImage")

View File

@ -12,6 +12,8 @@ import re
import logging
#logging.basicConfig(level = logging.DEBUG)
import gi
gi.require_version('Vips', '8.0')
from gi.repository import Vips, GObject
vips_type_image = GObject.GType.from_name("VipsImage")

View File

@ -1,7 +1,3 @@
// headers for vips operations
// Fri Feb 12 20:04:03 GMT 2016
// this file is generated automatically, do not edit!
static void system( char * cmd_format , VOption *options = 0 );
VImage add( VImage right , VOption *options = 0 );
VImage subtract( VImage right , VOption *options = 0 );
@ -103,13 +99,15 @@ VImage invertlut( VOption *options = 0 );
static VImage tonelut( VOption *options = 0 );
static VImage identity( VOption *options = 0 );
static VImage fractsurf( int width , int height , double fractal_dimension , VOption *options = 0 );
static VImage radload( char * filename , VOption *options = 0 );
static VImage ppmload( char * filename , VOption *options = 0 );
static VImage worley( int width , int height , VOption *options = 0 );
static VImage perlin( int width , int height , VOption *options = 0 );
static VImage csvload( char * filename , VOption *options = 0 );
static VImage matrixload( char * filename , VOption *options = 0 );
static VImage analyzeload( char * filename , VOption *options = 0 );
static VImage rawload( char * filename , int width , int height , int bands , VOption *options = 0 );
static VImage vipsload( char * filename , VOption *options = 0 );
static VImage analyzeload( char * filename , VOption *options = 0 );
static VImage ppmload( char * filename , VOption *options = 0 );
static VImage radload( char * filename , VOption *options = 0 );
static VImage pdfload( char * filename , VOption *options = 0 );
static VImage pdfload_buffer( VipsBlob * buffer , VOption *options = 0 );
static VImage svgload( char * filename , VOption *options = 0 );
@ -130,15 +128,15 @@ static VImage magickload( char * filename , VOption *options = 0 );
static VImage magickload_buffer( VipsBlob * buffer , VOption *options = 0 );
static VImage fitsload( char * filename , VOption *options = 0 );
static VImage openexrload( char * filename , VOption *options = 0 );
void radsave( char * filename , VOption *options = 0 );
VipsBlob * radsave_buffer( VOption *options = 0 );
void ppmsave( char * filename , VOption *options = 0 );
void csvsave( char * filename , VOption *options = 0 );
void matrixsave( char * filename , VOption *options = 0 );
void matrixprint( VOption *options = 0 );
void rawsave( char * filename , VOption *options = 0 );
void rawsave_fd( int fd , VOption *options = 0 );
void vipssave( char * filename , VOption *options = 0 );
void ppmsave( char * filename , VOption *options = 0 );
void radsave( char * filename , VOption *options = 0 );
VipsBlob * radsave_buffer( VOption *options = 0 );
void dzsave( char * filename , VOption *options = 0 );
void pngsave( char * filename , VOption *options = 0 );
VipsBlob * pngsave_buffer( VOption *options = 0 );

View File

@ -1,7 +1,3 @@
// bodies for vips operations
// Fri Feb 12 20:03:53 GMT 2016
// this file is generated automatically, do not edit!
void VImage::system( char * cmd_format , VOption *options )
{
call( "system" ,
@ -1321,26 +1317,28 @@ VImage VImage::fractsurf( int width , int height , double fractal_dimension , VO
return( out );
}
VImage VImage::radload( char * filename , VOption *options )
VImage VImage::worley( int width , int height , VOption *options )
{
VImage out;
call( "radload" ,
call( "worley" ,
(options ? options : VImage::option()) ->
set( "filename", filename ) ->
set( "out", &out ) );
set( "out", &out ) ->
set( "width", width ) ->
set( "height", height ) );
return( out );
}
VImage VImage::ppmload( char * filename , VOption *options )
VImage VImage::perlin( int width , int height , VOption *options )
{
VImage out;
call( "ppmload" ,
call( "perlin" ,
(options ? options : VImage::option()) ->
set( "filename", filename ) ->
set( "out", &out ) );
set( "out", &out ) ->
set( "width", width ) ->
set( "height", height ) );
return( out );
}
@ -1369,18 +1367,6 @@ VImage VImage::matrixload( char * filename , VOption *options )
return( out );
}
VImage VImage::analyzeload( char * filename , VOption *options )
{
VImage out;
call( "analyzeload" ,
(options ? options : VImage::option()) ->
set( "filename", filename ) ->
set( "out", &out ) );
return( out );
}
VImage VImage::rawload( char * filename , int width , int height , int bands , VOption *options )
{
VImage out;
@ -1408,6 +1394,42 @@ VImage VImage::vipsload( char * filename , VOption *options )
return( out );
}
VImage VImage::analyzeload( char * filename , VOption *options )
{
VImage out;
call( "analyzeload" ,
(options ? options : VImage::option()) ->
set( "filename", filename ) ->
set( "out", &out ) );
return( out );
}
VImage VImage::ppmload( char * filename , VOption *options )
{
VImage out;
call( "ppmload" ,
(options ? options : VImage::option()) ->
set( "filename", filename ) ->
set( "out", &out ) );
return( out );
}
VImage VImage::radload( char * filename , VOption *options )
{
VImage out;
call( "radload" ,
(options ? options : VImage::option()) ->
set( "filename", filename ) ->
set( "out", &out ) );
return( out );
}
VImage VImage::pdfload( char * filename , VOption *options )
{
VImage out;
@ -1648,34 +1670,6 @@ VImage VImage::openexrload( char * filename , VOption *options )
return( out );
}
void VImage::radsave( char * filename , VOption *options )
{
call( "radsave" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "filename", filename ) );
}
VipsBlob * VImage::radsave_buffer( VOption *options )
{
VipsBlob * buffer;
call( "radsave_buffer" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "buffer", &buffer ) );
return( buffer );
}
void VImage::ppmsave( char * filename , VOption *options )
{
call( "ppmsave" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "filename", filename ) );
}
void VImage::csvsave( char * filename , VOption *options )
{
call( "csvsave" ,
@ -1723,6 +1717,34 @@ void VImage::vipssave( char * filename , VOption *options )
set( "filename", filename ) );
}
void VImage::ppmsave( char * filename , VOption *options )
{
call( "ppmsave" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "filename", filename ) );
}
void VImage::radsave( char * filename , VOption *options )
{
call( "radsave" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "filename", filename ) );
}
VipsBlob * VImage::radsave_buffer( VOption *options )
{
VipsBlob * buffer;
call( "radsave_buffer" ,
(options ? options : VImage::option()) ->
set( "in", *this ) ->
set( "buffer", &buffer ) );
return( buffer );
}
void VImage::dzsave( char * filename , VOption *options )
{
call( "dzsave" ,

View File

@ -98,14 +98,14 @@ Vips_8_0_gir_LIBS = libvips.la
Vips_8_0_gir_FILES = $(introspection_sources)
INTROSPECTION_GIRS += Vips-8.0.gir
# don't use --warn-all --verbose
# we have an unusual markup with optional args and we don't want to see all
# those warnings
# don't use
# --warn-all --verbose
# too annoying
Vips_8_0_gir_SCANNERFLAGS = \
--program=./introspect \
--identifier-prefix=Vips \
--identifier-prefix=vips \
--symbol-prefix=vips
--program=./introspect \
--identifier-prefix=Vips \
--identifier-prefix=vips \
--symbol-prefix=vips
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)

View File

@ -197,9 +197,9 @@ vips_Lab2XYZ_init( VipsLab2XYZ *Lab2XYZ )
* @out: output image
* @...: %NULL-terminated list of optional named arguments
*
* optional arguments:
* Optional arguments:
*
* @temp: colour temperature
* * @temp: #VipsArrayDouble, colour temperature
*
* Turn Lab to XYZ. The colour temperature defaults to D65, but can be
* specified with @temp.

View File

@ -250,9 +250,9 @@ vips_XYZ2Lab_init( VipsXYZ2Lab *XYZ2Lab )
* @out: output image
* @...: %NULL-terminated list of optional named arguments
*
* optional arguments:
* Optional arguments:
*
* @temp: colour temperature
* * @temp: #VipsArrayDouble, colour temperature
*
* Turn XYZ to Lab, optionally specifying the colour temperature. @temp
* defaults to D65.

View File

@ -394,16 +394,17 @@ vips_arrayjoinv( VipsImage **in, VipsImage **out, int n, va_list ap )
* @in: (array length=n) (transfer none): array of input images
* @out: output image
* @n: number of input images
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @across: number of images per row
* * @shim: space between images, in pixels
* * @background: background ink colour
* * @halign: low, centre or high alignment
* * @valign: low, centre or high alignment
* * @hspacing: horizontal distance between images
* * @vspacing: vertical distance between images
* * @across: %gint, number of images per row
* * @shim: %gint, space between images, in pixels
* * @background: #VipsArrayDouble, background ink colour
* * @halign: #VipsAlign, low, centre or high alignment
* * @valign: #VipsAlign, low, centre or high alignment
* * @hspacing: %gint, horizontal distance between images
* * @vspacing: %gint, vertical distance between images
*
* Lay out the images in @in in a grid. The grid is @across images across and
* however high is necessary to use up all of @in. Images are set down

View File

@ -126,9 +126,9 @@ vips_autorot_remove_angle_sub( VipsImage *image,
/**
* vips_autorot_remove_angle:
* @im: image to remove orientation from
* @image: image to remove orientation from
*
* Remove the orientation tag on @im. Also remove any exif orientation tags.
* Remove the orientation tag on @image. Also remove any exif orientation tags.
*
* See also: vips_autorot_get_angle().
*/

View File

@ -31,6 +31,8 @@
* - cache minimisation is optional, see "persistent" flag
* 26/8/14 Lovell
* - free the hash table in _dispose()
* 11/7/16
* - terminate on tile calc error
*/
/*
@ -609,6 +611,9 @@ vips_tile_cache_gen( VipsRegion *or,
VipsTile *tile;
GSList *work;
GSList *p;
int result;
result = 0;
VIPS_GATE_START( "vips_tile_cache_gen: wait1" );
@ -658,8 +663,6 @@ vips_tile_cache_gen( VipsRegion *or,
tile = (VipsTile *) p->data;
if( tile->state == VIPS_TILE_STATE_PEND ) {
int result;
tile->state = VIPS_TILE_STATE_CALC;
VIPS_DEBUG_MSG_RED( "vips_tile_cache_gen: "
@ -688,11 +691,11 @@ vips_tile_cache_gen( VipsRegion *or,
}
/* If there was an error calculating this
* tile, just warn and carry on.
* tile, black it out and terminate
* calculation. We have to stop so we can
* support things like --fail on jpegload.
*
* This can happen with things like reading
* .scn files via openslide. We don't want the
* read to fail because of one broken tile.
* Don't return early, we'd deadlock.
*/
if( result ) {
VIPS_DEBUG_MSG_RED(
@ -707,6 +710,8 @@ vips_tile_cache_gen( VipsRegion *or,
vips_error_clear();
vips_region_black( tile->region );
*stop = TRUE;
}
tile->state = VIPS_TILE_STATE_DATA;
@ -749,7 +754,7 @@ vips_tile_cache_gen( VipsRegion *or,
g_mutex_unlock( cache->lock );
return( 0 );
return( result );
}
static int

View File

@ -1,6 +1,8 @@
noinst_LTLIBRARIES = libcreate.la
libcreate_la_SOURCES = \
perlin.c \
worley.c \
create.c \
pcreate.h \
gaussmat.c \

View File

@ -278,7 +278,8 @@ vips_buildlut_init( VipsBuildlut *lut )
*
* This operation builds a lookup table from a set of points. Intermediate
* values are generated by piecewise linear interpolation. The lookup table is
* always of type %gdouble, use vips_cast() to change it to the type you need.
* always of type #VIPS_FORMAT_DOUBLE, use vips_cast() to change it to the
* type you need.
*
* For example, consider this 2 x 2 matrix of (x, y) coordinates:
*
@ -331,7 +332,7 @@ vips_buildlut_init( VipsBuildlut *lut )
* several Ys, each becomes a band in the output LUT. You don't need to
* start at zero, any integer will do, including negatives.
*
* See also: vips_identity(), vips_invertlut().
* See also: vips_identity(), vips_invertlut(), vips_cast(), vips_maplut().
*
* Returns: 0 on success, -1 on error
*/

View File

@ -139,6 +139,8 @@ vips_create_operation_init( void )
extern GType vips_mask_ideal_band_get_type( void );
extern GType vips_mask_fractal_get_type( void );
extern GType vips_fractsurf_get_type( void );
extern GType vips_worley_get_type( void );
extern GType vips_perlin_get_type( void );
vips_black_get_type();
vips_gaussmat_get_type();
@ -167,5 +169,7 @@ vips_create_operation_init( void )
vips_mask_gaussian_band_get_type();
vips_mask_fractal_get_type();
vips_fractsurf_get_type();
vips_worley_get_type();
vips_perlin_get_type();
}

394
libvips/create/perlin.c Normal file
View File

@ -0,0 +1,394 @@
/* Perlin noise generator.
*
* 24/7/16
*/
/*
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 _VipsPerlin {
VipsCreate parent_instance;
int width;
int height;
int cell_size;
gboolean uchar;
int cells_across;
int cells_down;
/* Use this to seed this call of our rng.
*/
guint32 seed;
} VipsPerlin;
typedef struct _VipsPerlinClass {
VipsCreateClass parent_class;
} VipsPerlinClass;
G_DEFINE_TYPE( VipsPerlin, vips_perlin, VIPS_TYPE_CREATE );
/* Round N down to P boundary.
*/
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
/* Round N up to P boundary.
*/
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
/* cos and sin from an angle in 0 - 255.
*/
float vips_perlin_cos[256];
float vips_perlin_sin[256];
typedef struct _Sequence {
VipsPerlin *perlin;
/* The position of the last cell we were in. Use this to avoid
* regenerating vectors on every pixel lookup.
*/
int cell_x;
int cell_y;
/* The 2 x 2 grid of unit vectors, with cell_x/cell_y as the top left.
*/
float gx[4];
float gy[4];
} Sequence;
/* A very simple random number generator. See:
* http://isthe.com/chongo/tech/comp/fnv/#FNV-source
*/
static guint32
vips_perlin_random( guint32 seed )
{
return( 1103515245u * seed + 12345 );
}
static guint32
vips_perlin_seed_add( guint32 seed, int value )
{
return( ((2166136261u ^ seed) * 16777619u) ^ value );
}
/* Generate a 3 x 3 grid of cells around a point.
*/
static void
vips_perlin_create_cells( VipsPerlin *perlin,
float gx[4], float gy[4], int cell_x, int cell_y )
{
int x, y;
for( y = 0; y < 2; y++ )
for( x = 0; x < 2; x++ ) {
int ci = x + y * 2;
guint32 seed;
int cx;
int cy;
int angle;
seed = perlin->seed;
cx = cell_x + x;
cy = cell_y + y;
/* When we calculate the seed for this cell, we wrap
* around so that our output will tesselate.
*/
if( cy >= perlin->cells_down )
cy = 0;
seed = vips_perlin_seed_add( seed, cy );
if( cx >= perlin->cells_across )
cx = 0;
seed = vips_perlin_seed_add( seed, cx );
seed = vips_perlin_random( seed );
angle = (seed ^ (seed >> 8) ^ (seed >> 16)) & 0xff;
gx[ci] = vips_perlin_cos[angle];
gy[ci] = vips_perlin_sin[angle];
}
}
static int
vips_perlin_stop( void *vseq, void *a, void *b )
{
Sequence *seq = (Sequence *) vseq;
VIPS_FREE( seq );
return( 0 );
}
static void *
vips_perlin_start( VipsImage *out, void *a, void *b )
{
VipsPerlin *perlin = (VipsPerlin *) b;
Sequence *seq;
if( !(seq = VIPS_NEW( NULL, Sequence )) )
return( NULL );
seq->perlin = perlin;
seq->cell_x = -1;
seq->cell_y = -1;
return( seq );
}
/* Smooth linear interpolation, 0 <= x <= 1.
*
* https://en.wikipedia.org/wiki/Smoothstep
*/
static float
smootherstep( float x )
{
return( x * x * x * (x * (x * 6 - 15) + 10) );
}
static int
vips_perlin_gen( VipsRegion *or, void *vseq, void *a, void *b,
gboolean *stop )
{
VipsPerlin *perlin = (VipsPerlin *) a;
VipsRect *r = &or->valid;
Sequence *seq = (Sequence *) vseq;
int x, y;
for( y = 0; y < r->height; y++ ) {
float *fq = (float *)
VIPS_REGION_ADDR( or, r->left, r->top + y );
VipsPel *q = (VipsPel *) fq;
for( x = 0; x < r->width; x++ ) {
int cs = perlin->cell_size;
int cell_x = (r->left + x) / cs;
int cell_y = (r->top + y) / cs;
float dx = (x + r->left - cell_x * cs) / (float) cs;
float dy = (y + r->top - cell_y * cs) / (float) cs;
float sx = smootherstep( dx );
float sy = smootherstep( dy );
float n0, n1;
float ix0, ix1;
float p;
if( cell_x != seq->cell_x ||
cell_y != seq->cell_y ) {
vips_perlin_create_cells( perlin,
seq->gx, seq->gy, cell_x, cell_y );
seq->cell_x = cell_x;
seq->cell_y = cell_y;
}
n0 = -dx * seq->gx[0] + -dy * seq->gy[0];
n1 = (1 - dx) * seq->gx[1] + -dy * seq->gy[1];
ix0 = n0 + sx * (n1 - n0);
n0 = -dx * seq->gx[2] + (1 - dy) * seq->gy[2];
n1 = (1 - dx) * seq->gx[3] + (1 - dy) * seq->gy[3];
ix1 = n0 + sx * (n1 - n0);
p = ix0 + sy * (ix1 - ix0);
if( perlin->uchar )
q[x] = 128 * p + 128;
else
fq[x] = p;
}
}
return( 0 );
}
static int
vips_perlin_build( VipsObject *object )
{
VipsCreate *create = VIPS_CREATE( object );
VipsPerlin *perlin = (VipsPerlin *) object;
if( VIPS_OBJECT_CLASS( vips_perlin_parent_class )->build( object ) )
return( -1 );
/* Be careful if width is a multiple of cell_size.
*/
perlin->cells_across = ROUND_UP( perlin->width, perlin->cell_size ) /
perlin->cell_size;
perlin->cells_down = ROUND_UP( perlin->height, perlin->cell_size ) /
perlin->cell_size;
perlin->seed = g_random_double() * 0xffffffffu;
vips_image_init_fields( create->out,
perlin->width, perlin->height, 1,
perlin->uchar ? VIPS_FORMAT_UCHAR : VIPS_FORMAT_FLOAT,
VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
1.0, 1.0 );
vips_image_pipelinev( create->out,
VIPS_DEMAND_STYLE_ANY, NULL );
if( vips_image_generate( create->out,
vips_perlin_start, vips_perlin_gen, vips_perlin_stop,
perlin, NULL ) )
return( -1 );
return( 0 );
}
static void *
vips_perlin_make_tables( void *client )
{
int i;
for( i = 0; i < 256; i++ ) {
double angle = 2 * M_PI * i / 256.0;
vips_perlin_cos[i] = cos( angle );
vips_perlin_sin[i] = sin( angle );
}
return( NULL );
}
static void
vips_perlin_class_init( VipsPerlinClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
static GOnce once = G_ONCE_INIT;
(void) g_once( &once, vips_perlin_make_tables, NULL );
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
vobject_class->nickname = "perlin";
vobject_class->description = _( "make a perlin noise image" );
vobject_class->build = vips_perlin_build;
VIPS_ARG_INT( class, "width", 2,
_( "Width" ),
_( "Image width in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsPerlin, width ),
1, VIPS_MAX_COORD, 1 );
VIPS_ARG_INT( class, "height", 3,
_( "Height" ),
_( "Image height in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsPerlin, height ),
1, VIPS_MAX_COORD, 1 );
VIPS_ARG_INT( class, "cell_size", 3,
_( "Cell size" ),
_( "Size of Perlin cells" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsPerlin, cell_size ),
1, VIPS_MAX_COORD, 256 );
VIPS_ARG_BOOL( class, "uchar", 4,
_( "Uchar" ),
_( "Output an unsigned char image" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsPerlin, uchar ),
FALSE );
}
static void
vips_perlin_init( VipsPerlin *perlin )
{
perlin->cell_size = 256;
}
/**
* vips_perlin:
* @out: output image
* @width: horizontal size
* @height: vertical size
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @cell_size: %gint, size of Perlin cells
* * @uchar: output a uchar image
*
* Create a one-band float image of Perlin noise. See:
*
* https://en.wikipedia.org/wiki/Perlin_noise
*
* Use @cell_size to set the size of the cells from which the image is
* constructed. The default is 256 x 256.
*
* If @width and @height are multiples of @cell_size, the image will tessellate.
*
* Normally, output pixels are #VIPS_FORMAT_FLOAT in the range [-1, +1]. Set
* @uchar to output a uchar image with pixels in [0, 255].
*
* See also: vips_worley(), vips_fractsurf(), vips_gaussnoise().
*
* Returns: 0 on success, -1 on error
*/
int
vips_perlin( VipsImage **out, int width, int height, ... )
{
va_list ap;
int result;
va_start( ap, height );
result = vips_call_split( "perlin", ap, out, width, height );
va_end( ap );
return( result );
}

393
libvips/create/worley.c Normal file
View File

@ -0,0 +1,393 @@
/* Worley noise generator.
*
* 19/7/16
*/
/*
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 _VipsWorley {
VipsCreate parent_instance;
int width;
int height;
int cell_size;
int cells_across;
int cells_down;
/* Use this to seed this call of our rng.
*/
guint32 seed;
} VipsWorley;
typedef struct _VipsWorleyClass {
VipsCreateClass parent_class;
} VipsWorleyClass;
G_DEFINE_TYPE( VipsWorley, vips_worley, VIPS_TYPE_CREATE );
#define MAX_FEATURES (10)
/* Round N down to P boundary.
*/
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
/* Round N up to P boundary.
*/
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
typedef struct _Cell {
/* Cell position, in number of cells. Scale by cell_size to get
* absolute image cods.
*/
int cell_x;
int cell_y;
/* A cell contains 1 to n features.
*/
int n_features;
/* Feature coordinates, in absolute image space.
*/
int feature_x[MAX_FEATURES];
int feature_y[MAX_FEATURES];
} Cell;
typedef struct _Sequence {
VipsWorley *worley;
/* The position of the last cell we were in. Use this to avoid
* regenerating cells on every pixel lookup.
*/
int cell_x;
int cell_y;
/* The 3 x 3 grid of cells around the current point.
*/
Cell cells[9];
} Sequence;
/* A very simple random number generator. See:
* http://isthe.com/chongo/tech/comp/fnv/#FNV-source
*/
static guint32
vips_worley_random( guint32 seed )
{
return( 1103515245u * seed + 12345 );
}
static guint32
vips_worley_seed_add( guint32 seed, int value )
{
return( ((2166136261u ^ seed) * 16777619u) ^ value );
}
/* Generate a 3 x 3 grid of cells around a point.
*/
static void
vips_worley_create_cells( VipsWorley *worley,
Cell cells[9], int cell_x, int cell_y )
{
int x, y;
for( y = 0; y < 3; y++ )
for( x = 0; x < 3; x++ ) {
Cell *cell = &cells[x + y * 3];
guint32 seed;
int value;
int j;
/* Can go <0 and >width for edges.
*/
cell->cell_x = cell_x + x - 1;
cell->cell_y = cell_y + y - 1;
seed = worley->seed;
/* When we calculate the seed for this cell, we wrap
* around so that our output will tesselate.
*/
if( cell->cell_x >= worley->cells_across )
value = 0;
else if( cell->cell_x < 0 )
value = worley->cells_across - 1;
else
value = cell->cell_x;
seed = vips_worley_seed_add( seed, value );
if( cell->cell_y >= worley->cells_down )
value = 0;
else if( cell->cell_y < 0 )
value = worley->cells_down - 1;
else
value = cell->cell_y;
seed = vips_worley_seed_add( seed, value );
/* [1, MAX_FEATURES)
*/
seed = vips_worley_random( seed );
cell->n_features = (seed % (MAX_FEATURES - 1)) + 1;
for( j = 0; j < cell->n_features; j++ ) {
seed = vips_worley_random( seed );
cell->feature_x[j] =
cell->cell_x * worley->cell_size +
seed % worley->cell_size;
seed = vips_worley_random( seed );
cell->feature_y[j] =
cell->cell_y * worley->cell_size +
seed % worley->cell_size;
}
}
}
static int
vips_worley_stop( void *vseq, void *a, void *b )
{
Sequence *seq = (Sequence *) vseq;
VIPS_FREE( seq );
return( 0 );
}
static void *
vips_worley_start( VipsImage *out, void *a, void *b )
{
VipsWorley *worley = (VipsWorley *) b;
Sequence *seq;
if( !(seq = VIPS_NEW( NULL, Sequence )) )
return( NULL );
seq->worley = worley;
seq->cell_x = -1;
seq->cell_y = -1;
return( seq );
}
static int
vips_hypot( int x, int y )
{
/* Faster than hypot() for int args.
*/
return( sqrt( x * x + y * y ) );
}
static int
vips_worley_distance( VipsWorley *worley, Cell cells[9], int x, int y )
{
int distance;
int i, j;
distance = worley->cell_size * 1.5;
for( i = 0; i < 9; i++ ) {
Cell *cell = &cells[i];
for( j = 0; j < cell->n_features; j++ ) {
int d = vips_hypot(
x - cell->feature_x[j],
y - cell->feature_y[j] );
distance = VIPS_MIN( distance, d );
}
}
return( distance );
}
static int
vips_worley_gen( VipsRegion *or, void *vseq, void *a, void *b,
gboolean *stop )
{
VipsWorley *worley = (VipsWorley *) a;
VipsRect *r = &or->valid;
Sequence *seq = (Sequence *) vseq;
int x, y;
for( y = 0; y < r->height; y++ ) {
int *q = (int *) VIPS_REGION_ADDR( or, r->left, r->top + y );
for( x = 0; x < r->width; x++ ) {
int cell_x = (r->left + x) / worley->cell_size;
int cell_y = (r->top + y) / worley->cell_size;
if( cell_x != seq->cell_x ||
cell_y != seq->cell_y ) {
vips_worley_create_cells( worley,
seq->cells, cell_x, cell_y );
seq->cell_x = cell_x;
seq->cell_y = cell_y;
}
q[x] = vips_worley_distance( worley, seq->cells,
r->left + x, r->top + y );
}
}
return( 0 );
}
static int
vips_worley_build( VipsObject *object )
{
VipsCreate *create = VIPS_CREATE( object );
VipsWorley *worley = (VipsWorley *) object;
if( VIPS_OBJECT_CLASS( vips_worley_parent_class )->build( object ) )
return( -1 );
/* Be careful if width is a multiple of cell_size.
*/
worley->cells_across = ROUND_UP( worley->width, worley->cell_size ) /
worley->cell_size;
worley->cells_down = ROUND_UP( worley->height, worley->cell_size ) /
worley->cell_size;
worley->seed = g_random_double() * 0xffffffffu;
vips_image_init_fields( create->out,
worley->width, worley->height, 1,
VIPS_FORMAT_INT, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
1.0, 1.0 );
vips_image_pipelinev( create->out,
VIPS_DEMAND_STYLE_ANY, NULL );
if( vips_image_generate( create->out,
vips_worley_start, vips_worley_gen, vips_worley_stop,
worley, NULL ) )
return( -1 );
return( 0 );
}
static void
vips_worley_class_init( VipsWorleyClass *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 = "worley";
vobject_class->description = _( "make a worley noise image" );
vobject_class->build = vips_worley_build;
VIPS_ARG_INT( class, "width", 2,
_( "Width" ),
_( "Image width in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsWorley, width ),
1, VIPS_MAX_COORD, 1 );
VIPS_ARG_INT( class, "height", 3,
_( "Height" ),
_( "Image height in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsWorley, height ),
1, VIPS_MAX_COORD, 1 );
VIPS_ARG_INT( class, "cell_size", 3,
_( "Cell size" ),
_( "Size of Worley cells" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsWorley, cell_size ),
1, VIPS_MAX_COORD, 256 );
}
static void
vips_worley_init( VipsWorley *worley )
{
worley->cell_size = 256;
}
/**
* vips_worley:
* @out: output image
* @width: horizontal size
* @height: vertical size
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @cell_size: %gint, size of Worley cells
*
* Create a one-band int image of Worley noise. See:
*
* https://en.wikipedia.org/wiki/Worley_noise
*
* Use @cell_size to set the size of the cells from which the image is
* constructed. The default is 256 x 256.
*
* If @width and @height are multiples of @cell_size, the image will tessellate.
*
* See also: vips_perlin(), vips_fractsurf(), vips_gaussnoise().
*
* Returns: 0 on success, -1 on error
*/
int
vips_worley( VipsImage **out, int width, int height, ... )
{
va_list ap;
int result;
va_start( ap, height );
result = vips_call_split( "worley", ap, out, width, height );
va_end( ap );
return( result );
}

View File

@ -609,7 +609,7 @@ vips_foreign_find_load_buffer( const void *data, size_t size )
gboolean
vips_foreign_is_a( const char *loader, const char *filename )
{
VipsObjectClass *class;
const VipsObjectClass *class;
VipsForeignLoadClass *load_class;
if( !(class = vips_class_find( "VipsForeignLoad", loader )) )
@ -636,7 +636,7 @@ vips_foreign_is_a( const char *loader, const char *filename )
gboolean
vips_foreign_is_a_buffer( const char *loader, const void *data, size_t size )
{
VipsObjectClass *class;
const VipsObjectClass *class;
VipsForeignLoadClass *load_class;
if( !(class = vips_class_find( "VipsForeignLoad", loader )) )
@ -662,7 +662,7 @@ vips_foreign_is_a_buffer( const char *loader, const void *data, size_t size )
VipsForeignFlags
vips_foreign_flags( const char *loader, const char *filename )
{
VipsObjectClass *class;
const VipsObjectClass *class;
if( (class = vips_class_find( "VipsForeignLoad", loader )) ) {
VipsForeignLoadClass *load_class =

View File

@ -74,6 +74,8 @@
* memory for progressive jpg files
* 26/5/16
* - switch to new orientation tag
* 11/7/16
* - new --fail handling
*/
/*
@ -186,16 +188,10 @@ readjpeg_free( ReadJpeg *jpeg )
result = 0;
if( jpeg->eman.pub.num_warnings != 0 ) {
if( jpeg->fail ) {
vips_error( "VipsJpeg", "%s", vips_error_buffer() );
result = -1;
}
else {
vips_warn( "VipsJpeg",
_( "read gave %ld warnings" ),
jpeg->eman.pub.num_warnings );
vips_warn( NULL, "%s", vips_error_buffer() );
}
vips_warn( "VipsJpeg",
_( "read gave %ld warnings" ),
jpeg->eman.pub.num_warnings );
vips_warn( NULL, "%s", vips_error_buffer() );
/* Make the message only appear once.
*/
@ -991,6 +987,25 @@ read_jpeg_generate( VipsRegion *or,
if( setjmp( jpeg->eman.jmp ) )
return( -1 );
/* If --fail is set, we make read fail on any warnings. This will stop
* on any errors from the previous jpeg_read_scanlines().
*/
if( jpeg->eman.pub.num_warnings > 0 &&
jpeg->fail ) {
vips_error( "VipsJpeg",
_( "read gave %ld warnings" ),
jpeg->eman.pub.num_warnings );
vips_error( NULL, "%s", vips_error_buffer() );
/* Make the message only appear once.
*/
jpeg->eman.pub.num_warnings = 0;
*stop = TRUE;
return( -1 );
}
for( y = 0; y < r->height; y++ ) {
JSAMPROW row_pointer[1];

View File

@ -95,7 +95,8 @@ typedef struct _VipsForeignSaveJpeg {
*/
gboolean trellis_quant;
/* Apply overshooting to samples with extreme values e.g. 0 & 255 for 8-bit.
/* Apply overshooting to samples with extreme values e.g. 0 & 255
* for 8-bit.
*/
gboolean overshoot_deringing;

View File

@ -47,6 +47,8 @@
* - do argb -> rgba for associated as well
* 27/1/15
* - unpremultiplication speedups for fully opaque/transparent pixels
* 11/7/16
* - just warn on tile read error
*/
/*
@ -471,14 +473,16 @@ vips__openslide_generate( VipsRegion *out,
rslide->level,
r->width, r->height );
/* Only warn on error: we don't want to make the whole image unreadable
* because of one broken tile.
*
* FIXME ... add a --fail option like jpegload
*/
error = openslide_get_error( rslide->osr );
if( error ) {
vips_error( "openslide2vips",
if( error )
vips_warn( "openslide2vips",
_( "reading region: %s" ), error );
return( -1 );
}
/* Since we are inside a cache, we know buf must be continuous.
*/
argb2rgba( buf, n, bg );

View File

@ -1895,9 +1895,17 @@ my_tiff_read( thandle_t st, tdata_t buffer, tsize_t size )
{
ReadTiff *rtiff = (ReadTiff *) st;
size_t available = rtiff->len - rtiff->pos;
size_t copy = VIPS_MIN( size, available );
size_t available;
size_t copy;
if( rtiff->pos > rtiff->len ) {
vips_error( "tiff2vips",
"%s", _( "read beyond end of buffer" ) );
return( 0 );
}
available = rtiff->len - rtiff->pos;
copy = VIPS_MIN( size, available );
memcpy( buffer, (unsigned char *) rtiff->buf + rtiff->pos, copy );
rtiff->pos += copy;
@ -1918,6 +1926,9 @@ my_tiff_close( thandle_t st )
return 0;
}
/* After calling this, ->pos is not bound by the size of the buffer, it can
* have any positive value.
*/
static toff_t
my_tiff_seek( thandle_t st, toff_t pos, int whence )
{

View File

@ -78,6 +78,8 @@
* - add quant_table
* 26/5/16
* - switch to new orientation tag
* 9/7/16
* - turn off chroma subsample for Q > 90
*/
/*
@ -225,7 +227,6 @@ write_new( VipsImage *in )
write->cinfo.err = jpeg_std_error( &write->eman.pub );
write->eman.pub.error_exit = vips__new_error_exit;
write->eman.pub.output_message = vips__new_output_message;
write->eman.pub.output_message = vips__new_output_message;
write->eman.fp = NULL;
write->profile_bytes = NULL;
write->profile_length = 0;
@ -1020,7 +1021,9 @@ write_vips( Write *write, int qfac, const char *profile,
*/
g_assert( in->BandFmt == VIPS_FORMAT_UCHAR );
g_assert( in->Coding == VIPS_CODING_NONE );
g_assert( in->Bands == 1 || in->Bands == 3 || in->Bands == 4 );
g_assert( in->Bands == 1 ||
in->Bands == 3 ||
in->Bands == 4 );
/* Check input image.
*/
@ -1032,7 +1035,8 @@ write_vips( Write *write, int qfac, const char *profile,
write->cinfo.image_width = in->Xsize;
write->cinfo.image_height = in->Ysize;
write->cinfo.input_components = in->Bands;
if( in->Bands == 4 && in->Type == VIPS_INTERPRETATION_CMYK ) {
if( in->Bands == 4 &&
in->Type == VIPS_INTERPRETATION_CMYK ) {
space = JCS_CMYK;
/* IJG always sets an Adobe marker, so we should invert CMYK.
*/
@ -1153,9 +1157,11 @@ write_vips( Write *write, int qfac, const char *profile,
if( progressive )
jpeg_simple_progression( &write->cinfo );
/* Turn off chroma subsampling.
/* Turn off chroma subsampling. Follow IM and do it automatically for
* high Q.
*/
if( no_subsample ) {
if( no_subsample ||
qfac > 90 ) {
int i;
for( i = 0; i < in->Bands; i++ ) {
@ -1250,7 +1256,8 @@ vips__jpeg_write_file( VipsImage *in,
*/
if( write_vips( write,
Q, profile, optimize_coding, progressive, strip, no_subsample,
trellis_quant, overshoot_deringing, optimize_scans, quant_table ) ) {
trellis_quant, overshoot_deringing, optimize_scans,
quant_table ) ) {
write_destroy( write );
return( -1 );
}
@ -1535,7 +1542,8 @@ vips__jpeg_write_buffer( VipsImage *in,
*/
if( write_vips( write,
Q, profile, optimize_coding, progressive, strip, no_subsample,
trellis_quant, overshoot_deringing, optimize_scans, quant_table ) ) {
trellis_quant, overshoot_deringing, optimize_scans,
quant_table ) ) {
write_destroy( write );
return( -1 );

View File

@ -114,6 +114,11 @@ int vips_fractsurf( VipsImage **out,
int width, int height, double fractal_dimension, ... )
__attribute__((sentinel));
int vips_worley( VipsImage **out, int width, int height, ... )
__attribute__((sentinel));
int vips_perlin( VipsImage **out, int width, int height, ... )
__attribute__((sentinel));
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -77,7 +77,9 @@ typedef struct _VipsForeignClass {
} VipsForeignClass;
GType vips_foreign_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_foreign_get_type(void);
/* Map over and find formats. This uses type introspection to loop over
* subclasses of VipsForeign.
@ -211,7 +213,9 @@ typedef struct _VipsForeignLoadClass {
int (*load)( VipsForeignLoad *load );
} VipsForeignLoadClass;
GType vips_foreign_load_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_foreign_load_get_type(void);
const char *vips_foreign_find_load( const char *filename );
const char *vips_foreign_find_load_buffer( const void *data, size_t size );
@ -313,7 +317,9 @@ typedef struct _VipsForeignSaveClass {
gboolean coding[VIPS_CODING_LAST];
} VipsForeignSaveClass;
GType vips_foreign_save_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_foreign_save_get_type(void);
const char *vips_foreign_find_save( const char *filename );
const char *vips_foreign_find_save_buffer( const char *suffix );

View File

@ -173,7 +173,7 @@ typedef struct _VipsProgress {
VIPS_TYPE_IMAGE, VipsImageClass ))
typedef struct _VipsImage {
VipsObject parent_object;
VipsObject parent_instance;
/*< private >*/
@ -356,7 +356,9 @@ typedef struct _VipsImageClass {
} VipsImageClass;
GType vips_image_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_image_get_type(void);
/* Has to be guint64 and not size_t/off_t since we have to be able to address
* huge images on platforms with 32-bit files.

View File

@ -87,7 +87,9 @@ typedef struct _VipsInterpolateClass {
int window_offset;
} VipsInterpolateClass;
GType vips_interpolate_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_interpolate_get_type(void);
void vips_interpolate( VipsInterpolate *interpolate,
void *out, VipsRegion *in, double x, double y );
VipsInterpolateMethod vips_interpolate_get_method( VipsInterpolate *interpolate );

View File

@ -296,11 +296,6 @@ typedef struct _VipsArgumentInstance {
*/
typedef GHashTable VipsArgumentTable;
VipsArgumentInstance *vips__argument_get_instance(
VipsArgumentClass *argument_class,
VipsObject *object );
VipsArgument *vips__argument_table_lookup( VipsArgumentTable *argument_class,
GParamSpec *pspec );
void vips__object_set_member( VipsObject *object, GParamSpec *pspec,
GObject **member, GObject *argument );
typedef void *(*VipsArgumentMapFn)( VipsObject *object, GParamSpec *pspec,
@ -411,7 +406,7 @@ int vips_object_get_argument_priority( VipsObject *object, const char *name );
(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_OBJECT, VipsObjectClass ))
struct _VipsObject {
GObject parent_object;
GObject parent_instance;
/* Set after ->build() has run succesfully: construct is fully done
* and checked.
@ -584,7 +579,9 @@ void vips_object_print_name( VipsObject *object );
gboolean vips_object_sanity( VipsObject *object );
GType vips_object_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_object_get_type(void);
void vips_object_class_install_argument( VipsObjectClass *cls,
GParamSpec *pspec, VipsArgumentFlags flags,
@ -622,7 +619,8 @@ GType vips_type_find( const char *basename, const char *nickname );
const char *vips_nickname_find( GType type );
void *vips_class_map_all( GType type, VipsClassMapFn fn, void *a );
VipsObjectClass *vips_class_find( const char *basename, const char *nickname );
const VipsObjectClass *vips_class_find( const char *basename,
const char *nickname );
VipsObject **vips_object_local_array( VipsObject *parent, int n );

View File

@ -92,7 +92,9 @@ typedef struct _VipsOperationClass {
void (*invalidate)( VipsOperation *operation );
} VipsOperationClass;
GType vips_operation_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_operation_get_type(void);
VipsOperationFlags vips_operation_get_flags( VipsOperation *operation );
void vips_operation_class_print_usage( VipsOperationClass *operation_class );

View File

@ -98,7 +98,9 @@ typedef struct _VipsRegionClass {
} VipsRegionClass;
GType vips_region_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_region_get_type(void);
VipsRegion *vips_region_new( VipsImage *image );

View File

@ -97,7 +97,10 @@ typedef struct _VipsThreadStateClass {
} VipsThreadStateClass;
void *vips_thread_state_set( VipsObject *object, void *a, void *b );
GType vips_thread_state_get_type( void );
/* Don't put spaces around void here, it breaks gtk-doc.
*/
GType vips_thread_state_get_type(void);
VipsThreadState *vips_thread_state_new( VipsImage *im, void *a );

View File

@ -50,7 +50,7 @@ typedef struct _VipsThing {
* The #GType for a #VipsThing.
*/
#define VIPS_TYPE_THING (vips_thing_get_type())
GType vips_thing_get_type( void );
GType vips_thing_get_type(void);
VipsThing *vips_thing_new( int i );
/* A ref-counted area of memory. Can hold arrays of things as well.
@ -119,7 +119,7 @@ void *vips_area_get_data( VipsArea *area,
*/
#define VIPS_TYPE_AREA (vips_area_get_type())
#define VIPS_AREA( X ) ((VipsArea *) (X))
GType vips_area_get_type( void );
GType vips_area_get_type(void);
/**
* VIPS_TYPE_SAVE_STRING:
@ -127,7 +127,7 @@ GType vips_area_get_type( void );
* The #GType for a #VipsSaveString.
*/
#define VIPS_TYPE_SAVE_STRING (vips_save_string_get_type())
GType vips_save_string_get_type( void );
GType vips_save_string_get_type(void);
/**
* VIPS_TYPE_REF_STRING:
@ -142,7 +142,7 @@ typedef struct _VipsRefString {
VipsRefString *vips_ref_string_new( const char *str );
const char *vips_ref_string_get( VipsRefString *refstr, size_t *length );
GType vips_ref_string_get_type( void );
GType vips_ref_string_get_type(void);
/**
* VIPS_TYPE_BLOB:
@ -159,7 +159,7 @@ VipsBlob *vips_blob_new( VipsCallbackFn free_fn,
const void *data, size_t size );
VipsBlob *vips_blob_copy( const void *data, size_t size );
const void *vips_blob_get( VipsBlob *blob, size_t *size );
GType vips_blob_get_type( void );
GType vips_blob_get_type(void);
/**
* VIPS_TYPE_ARRAY_DOUBLE:
@ -175,7 +175,7 @@ typedef struct _VipsArrayDouble {
VipsArrayDouble *vips_array_double_new( const double *array, int n );
VipsArrayDouble *vips_array_double_newv( int n, ... );
double *vips_array_double_get( VipsArrayDouble *array, int *n );
GType vips_array_double_get_type( void );
GType vips_array_double_get_type(void);
/**
* VIPS_TYPE_ARRAY_INT:
@ -191,7 +191,7 @@ typedef struct _VipsArrayInt {
VipsArrayInt *vips_array_int_new( const int *array, int n );
VipsArrayInt *vips_array_int_newv( int n, ... );
int *vips_array_int_get( VipsArrayInt *array, int *n );
GType vips_array_int_get_type( void );
GType vips_array_int_get_type(void);
/**
* VIPS_TYPE_ARRAY_IMAGE:
@ -207,7 +207,7 @@ typedef struct _VipsArrayImage {
/* See image.h for vips_array_image_new() etc., they need to be declared after
* VipsImage.
*/
GType vips_array_image_get_type( void );
GType vips_array_image_get_type(void);
void vips_value_set_area( GValue *value, VipsCallbackFn free_fn, void *data );
void *vips_value_get_area( const GValue *value, size_t *length );

View File

@ -2997,6 +2997,8 @@ vips_image_rewind_output( VipsImage *image )
* have made it yourself), use vips_image_wio_input() instead.
*
* See also: vips_image_wio_input().
*
* Returns: (transfer full): the new #VipsImage, or %NULL on error.
*/
VipsImage *
vips_image_copy_memory( VipsImage *image )

View File

@ -2691,9 +2691,9 @@ test_name( VipsObjectClass *class, const char *nickname )
*
* See also: vips_type_find()
*
* Returns: the found class.
* Returns: (transfer none): the found class.
*/
VipsObjectClass *
const VipsObjectClass *
vips_class_find( const char *basename, const char *nickname )
{
const char *classname = basename ? basename : "VipsObject";
@ -2802,7 +2802,7 @@ vips_type_find( const char *basename, const char *nickname )
g_type_is_a( hit->type, base ) )
type = hit->type;
else {
VipsObjectClass *class;
const VipsObjectClass *class;
if( !(class = vips_class_find( basename, nickname )) )
return( 0 );

View File

@ -203,12 +203,12 @@ vips_rect_unionrect( const VipsRect *r1, const VipsRect *r2, VipsRect *out )
}
/**
* vips_rect_dup:
* vips_rect_dup: (skip)
* @r: rectangle to duplicate
*
* Duplicate a rect to the heap. You need to free the result with vips_free().
*
* Returns: a pointer to copy of @r allocated on the heap.
* Returns: (transfer full): a pointer to copy of @r allocated on the heap.
*/
VipsRect *
vips_rect_dup( const VipsRect *r )

View File

@ -623,12 +623,12 @@ vips_affine_init( VipsAffine *affine )
*
* Optional arguments:
*
* * @interpolate: interpolate pixels with this
* * @oarea: output rectangle
* * @idx: input horizontal offset
* * @idy: input vertical offset
* * @odx: output horizontal offset
* * @ody: output vertical offset
* * @interpolate: #VipsInterpolate, interpolate pixels with this
* * @oarea: #VipsArrayInt, output rectangle
* * @idx: %gdouble, input horizontal offset
* * @idy: %gdouble, input vertical offset
* * @odx: %gdouble, output horizontal offset
* * @ody: %gdouble, output vertical offset
*
* This operator performs an affine transform on an image using @interpolate.
*

View File

@ -50,6 +50,19 @@
#include "presample.h"
/**
* VipsKernel:
* @VIPS_KERNEL_NEAREST: The nearest pixel to the point.
* @VIPS_KERNEL_LINEAR: Calculate a pixel value using linear interpolation.
* @VIPS_KERNEL_CUBIC: Calculate using a 4-element cubic kernel.
* @VIPS_KERNEL_LANCZOS2: Calculate with a two-lobe Lanczos kernel.
* @VIPS_KERNEL_LANCZOS3: Calculate with a three-lobe Lanczos kernel.
*
* The resampling kernels vips supports. See vips_reduce(), for example.
*
* The Lanczos kernels vary in size with the downsampling ratio.
*/
typedef struct _VipsReduce {
VipsResample parent_instance;
@ -141,15 +154,15 @@ vips_reduce_init( VipsReduce *reduce )
* @in: input image
* @out: output image
* @xshrink: horizontal shrink
* @shrinke: vertical shrink
* @yshrink: vertical shrink
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @kernel: #VipsKernel to use to interpolate (default: lanczos3)
*
* Reduce @in by a pair of factors with a pair of 1D interpolators. This
* will not work well for shrink factors greater than two.
* Reduce @in by a pair of factors with a pair of 1D kernels. This
* will not work well for shrink factors greater than three.
*
* This is a very low-level operation: see vips_resize() for a more
* convenient way to resize images.

View File

@ -5,6 +5,8 @@ import sys
import logging
#logging.basicConfig(level = logging.DEBUG)
import gi
gi.require_version('Vips', '8.0')
from gi.repository import Vips, GObject
# Search for all VipsOperation which don't have an input image object ... these

View File

@ -1093,6 +1093,8 @@ class_methods = [
"mask_fractal",
"tonelut",
"identity",
"perlin",
"worley",
"fractsurf",
"radload",
"ppmload",

View File

@ -441,5 +441,19 @@ class TestCreate(unittest.TestCase):
self.assertEqual(im.bands, 1)
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
def test_worley(self):
im = Vips.Image.worley(512, 512)
self.assertEqual(im.width, 512)
self.assertEqual(im.height, 512)
self.assertEqual(im.bands, 1)
self.assertEqual(im.format, Vips.BandFormat.INT)
def test_perlin(self):
im = Vips.Image.perlin(512, 512)
self.assertEqual(im.width, 512)
self.assertEqual(im.height, 512)
self.assertEqual(im.bands, 1)
self.assertEqual(im.format, Vips.BandFormat.FLOAT)
if __name__ == '__main__':
unittest.main()