Merge branch 'master' into add-magick7
This commit is contained in:
commit
12a32b23f1
@ -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
|
||||
|
@ -112,6 +112,7 @@ headers="\
|
||||
draw.h \
|
||||
morphology.h \
|
||||
type.h \
|
||||
rect.h \
|
||||
memory.h \
|
||||
region.h"
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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 );
|
||||
|
@ -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" ,
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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().
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,8 @@
|
||||
noinst_LTLIBRARIES = libcreate.la
|
||||
|
||||
libcreate_la_SOURCES = \
|
||||
perlin.c \
|
||||
worley.c \
|
||||
create.c \
|
||||
pcreate.h \
|
||||
gaussmat.c \
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
394
libvips/create/perlin.c
Normal 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
393
libvips/create/worley.c
Normal 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 );
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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 );
|
||||
|
@ -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*/
|
||||
|
@ -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 );
|
||||
|
@ -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.
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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 )
|
||||
|
@ -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 );
|
||||
|
@ -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 )
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -1093,6 +1093,8 @@ class_methods = [
|
||||
"mask_fractal",
|
||||
"tonelut",
|
||||
"identity",
|
||||
"perlin",
|
||||
"worley",
|
||||
"fractsurf",
|
||||
"radload",
|
||||
"ppmload",
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user