Merge remote-tracking branch 'origin/master' into draw
This commit is contained in:
commit
87ab32d422
12
ChangeLog
12
ChangeLog
@ -1,4 +1,16 @@
|
|||||||
21/1/14 started 7.39.0
|
21/1/14 started 7.39.0
|
||||||
|
- auto-decode for (almost) all operations
|
||||||
|
- background render thread cleans up and quits neatly
|
||||||
|
- colourspace has a source_space option
|
||||||
|
- operations can be tagged as "deprecated"
|
||||||
|
|
||||||
|
22/1/14 started 7.38.2
|
||||||
|
- auto RAD decode for affine
|
||||||
|
- falsecolour was not working for some image types
|
||||||
|
- foreign memory buffer images did not have the right dhint, broke
|
||||||
|
command-line falsecolour on sequential images
|
||||||
|
- support many Radiance readers active at once
|
||||||
|
- add secret "rgbjpeg" flag to vips_tiffsave() to help IIP
|
||||||
|
|
||||||
19/1/14 started 7.38.1
|
19/1/14 started 7.38.1
|
||||||
- bump soname, thanks benjamin
|
- bump soname, thanks benjamin
|
||||||
|
@ -189,7 +189,7 @@ OpenEXR images.
|
|||||||
## OpenSlide
|
## OpenSlide
|
||||||
|
|
||||||
If available, libvips can load OpenSlide-supported virtual slide
|
If available, libvips can load OpenSlide-supported virtual slide
|
||||||
files: Aperio, Hamamatsu VMS and VMU, Leica, MIRAX, and Trestle.
|
files: Aperio, Hamamatsu, Leica, MIRAX, Sakura, Trestle, and Ventana.
|
||||||
|
|
||||||
## swig, python, python-dev
|
## swig, python, python-dev
|
||||||
|
|
||||||
|
22
TODO
22
TODO
@ -1,3 +1,21 @@
|
|||||||
|
|
||||||
|
- check_uncoded() left to do:
|
||||||
|
|
||||||
|
resample/quadratic.c
|
||||||
|
|
||||||
|
- move vips__image_decode() into the public API
|
||||||
|
|
||||||
|
- we vips_image_write() a lot, could we do this by
|
||||||
|
|
||||||
|
int
|
||||||
|
vips_image_write( in, out )
|
||||||
|
{
|
||||||
|
g_object_ref( in)
|
||||||
|
vips_object_local( out,in )
|
||||||
|
}
|
||||||
|
|
||||||
|
i.e. do everything at pipe build time
|
||||||
|
|
||||||
- inplace
|
- inplace
|
||||||
|
|
||||||
can we set a region for the pixels we will modify?
|
can we set a region for the pixels we will modify?
|
||||||
@ -5,7 +23,6 @@
|
|||||||
is there any point doing this? only useful on 32-bit machines, which
|
is there any point doing this? only useful on 32-bit machines, which
|
||||||
don't really exist any more
|
don't really exist any more
|
||||||
|
|
||||||
|
|
||||||
- need to do mosaicing and inplace, plus im_label_regions in morph
|
- need to do mosaicing and inplace, plus im_label_regions in morph
|
||||||
|
|
||||||
- now vips_linear() has uchar output, can we do something with orc?
|
- now vips_linear() has uchar output, can we do something with orc?
|
||||||
@ -22,8 +39,7 @@
|
|||||||
interpolator would need to be built for the bands / stride / type of the
|
interpolator would need to be built for the bands / stride / type of the
|
||||||
image
|
image
|
||||||
|
|
||||||
need new API For this, since interpolators currently work for any image
|
need new API For this since interpolators currently work for any image
|
||||||
|
|
||||||
|
|
||||||
- vips_gaussblur() should switch to float prec if given a float image?
|
- vips_gaussblur() should switch to float prec if given a float image?
|
||||||
|
|
||||||
|
15
configure.ac
15
configure.ac
@ -497,12 +497,19 @@ AC_ARG_WITH([openslide],
|
|||||||
AS_HELP_STRING([--without-openslide], [build without OpenSlide (default: test)]))
|
AS_HELP_STRING([--without-openslide], [build without OpenSlide (default: test)]))
|
||||||
|
|
||||||
if test x"$with_openslide" != x"no"; then
|
if test x"$with_openslide" != x"no"; then
|
||||||
PKG_CHECK_MODULES(OPENSLIDE, openslide >= 3.3.0,
|
PKG_CHECK_MODULES(OPENSLIDE, [openslide >= 3.4.0],
|
||||||
[AC_DEFINE(HAVE_OPENSLIDE,1,[define if you have OpenSlide >= 3.3.0 installed.])
|
[AC_DEFINE(HAVE_OPENSLIDE_3_4,1,[define if you have OpenSlide >= 3.4.0 installed.])
|
||||||
|
AC_DEFINE(HAVE_OPENSLIDE,1,[define if you have OpenSlide >= 3.3.0 installed.])
|
||||||
with_openslide=yes
|
with_openslide=yes
|
||||||
PACKAGES_USED="$PACKAGES_USED openslide"],
|
PACKAGES_USED="$PACKAGES_USED openslide"],
|
||||||
[AC_MSG_WARN([OpenSlide >= 3.3.0 not found; disabling virtual slide support])
|
[AC_MSG_NOTICE([OpenSlide >= 3.4.0 not found; checking for >= 3.3.0])
|
||||||
with_openslide=no
|
PKG_CHECK_MODULES(OPENSLIDE, [openslide >= 3.3.0],
|
||||||
|
[AC_DEFINE(HAVE_OPENSLIDE,1,[define if you have OpenSlide >= 3.3.0 installed.])
|
||||||
|
with_openslide=yes
|
||||||
|
PACKAGES_USED="$PACKAGES_USED openslide"],
|
||||||
|
[AC_MSG_WARN([OpenSlide >= 3.3.0 not found; disabling virtual slide support])
|
||||||
|
with_openslide=no
|
||||||
|
])
|
||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
80
libvips.supp
80
libvips.supp
@ -45,7 +45,7 @@
|
|||||||
init7
|
init7
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
...
|
...
|
||||||
fun:g_malloc0
|
fun:*alloc*
|
||||||
...
|
...
|
||||||
fun:_dl_init
|
fun:_dl_init
|
||||||
}
|
}
|
||||||
@ -85,13 +85,29 @@
|
|||||||
fun:XInitExtension
|
fun:XInitExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
gio
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
...
|
||||||
|
fun:g_simple_async_result_complete
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
pthread
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
fun:_dl_allocate_tls
|
||||||
|
fun:pthread_create@@GLIBC_*
|
||||||
|
}
|
||||||
|
|
||||||
# hide all dbus reports, not the app's problem
|
# hide all dbus reports, not the app's problem
|
||||||
{
|
{
|
||||||
dbus
|
dbus
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
fun:*alloc
|
fun:*alloc
|
||||||
...
|
...
|
||||||
obj:/lib/libdbus-1.so.*
|
obj:*/libdbus-1.so.*
|
||||||
}
|
}
|
||||||
|
|
||||||
# hide all orbit leaks, not our problem
|
# hide all orbit leaks, not our problem
|
||||||
@ -112,6 +128,31 @@
|
|||||||
fun:FcConfigParseAndLoad
|
fun:FcConfigParseAndLoad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fontconfig2
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:strdup
|
||||||
|
fun:FcValueSave
|
||||||
|
obj:*/libfontconfig.so.*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fontconfig3
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:realloc
|
||||||
|
...
|
||||||
|
fun:FcFontMatch
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
fontconfig4
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:realloc
|
||||||
|
...
|
||||||
|
fun:FcPatternAddInteger
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
freetype_init
|
freetype_init
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
@ -120,6 +161,14 @@
|
|||||||
fun:FT_Open_Face
|
fun:FT_Open_Face
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
harfbuzz
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
...
|
||||||
|
fun:hb_shape_plan_execute
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
goffice_init
|
goffice_init
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
@ -257,8 +306,6 @@
|
|||||||
fun:write_vips
|
fun:write_vips
|
||||||
}
|
}
|
||||||
|
|
||||||
# ubuntu 13.04 suppressions
|
|
||||||
|
|
||||||
{
|
{
|
||||||
pixman1
|
pixman1
|
||||||
Memcheck:Cond
|
Memcheck:Cond
|
||||||
@ -272,6 +319,30 @@
|
|||||||
fun:rsvg_cairo_surface_to_pixbuf
|
fun:rsvg_cairo_surface_to_pixbuf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
rsvg
|
||||||
|
Memcheck:Cond
|
||||||
|
obj:*/librsvg-2.so.*
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
murrine
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
fun:g_malloc0
|
||||||
|
fun:raico_blur_create
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
signal_connect
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
fun:g_malloc0
|
||||||
|
fun:g_closure_new_simple
|
||||||
|
fun:g_cclosure_new
|
||||||
|
fun:g_signal_connect_data
|
||||||
|
}
|
||||||
|
|
||||||
# ruby has some annoying ones too
|
# ruby has some annoying ones too
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -304,3 +375,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "parithmetic.h"
|
#include "parithmetic.h"
|
||||||
|
|
||||||
@ -500,6 +501,7 @@ vips_arithmetic_build( VipsObject *object )
|
|||||||
VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
|
VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
|
||||||
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
|
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
|
||||||
|
|
||||||
|
VipsImage **decode;
|
||||||
VipsImage **format;
|
VipsImage **format;
|
||||||
VipsImage **band;
|
VipsImage **band;
|
||||||
VipsImage **size;
|
VipsImage **size;
|
||||||
@ -524,12 +526,9 @@ vips_arithmetic_build( VipsObject *object )
|
|||||||
"%s", _( "too many input images" ) );
|
"%s", _( "too many input images" ) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
for( i = 0; i < arithmetic->n; i++ )
|
|
||||||
if( vips_image_pio_input( arithmetic->in[i] ) ||
|
|
||||||
vips_check_uncoded( class->nickname,
|
|
||||||
arithmetic->in[i] ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
|
decode = (VipsImage **)
|
||||||
|
vips_object_local_array( object, arithmetic->n );
|
||||||
format = (VipsImage **)
|
format = (VipsImage **)
|
||||||
vips_object_local_array( object, arithmetic->n );
|
vips_object_local_array( object, arithmetic->n );
|
||||||
band = (VipsImage **)
|
band = (VipsImage **)
|
||||||
@ -537,9 +536,15 @@ vips_arithmetic_build( VipsObject *object )
|
|||||||
size = (VipsImage **)
|
size = (VipsImage **)
|
||||||
vips_object_local_array( object, arithmetic->n );
|
vips_object_local_array( object, arithmetic->n );
|
||||||
|
|
||||||
|
/* Decode RAD/LABQ etc.
|
||||||
|
*/
|
||||||
|
for( i = 0; i < arithmetic->n; i++ )
|
||||||
|
if( vips__image_decode( arithmetic->in[i], &decode[i] ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
/* Cast our input images up to a common format, bands and size.
|
/* Cast our input images up to a common format, bands and size.
|
||||||
*/
|
*/
|
||||||
if( vips__formatalike_vec( arithmetic->in, format, arithmetic->n ) ||
|
if( vips__formatalike_vec( decode, format, arithmetic->n ) ||
|
||||||
vips__bandalike_vec( class->nickname,
|
vips__bandalike_vec( class->nickname,
|
||||||
format, band, arithmetic->n, arithmetic->base_bands ) ||
|
format, band, arithmetic->n, arithmetic->base_bands ) ||
|
||||||
vips__sizealike_vec( band, size, arithmetic->n ) )
|
vips__sizealike_vec( band, size, arithmetic->n ) )
|
||||||
|
@ -492,7 +492,7 @@ vips_complex2_class_init( VipsComplex2Class *class )
|
|||||||
|
|
||||||
object_class->nickname = "complex2";
|
object_class->nickname = "complex2";
|
||||||
object_class->description =
|
object_class->description =
|
||||||
_( "perform a binary complex operation on two images" );
|
_( "complex binary operations on two images" );
|
||||||
|
|
||||||
aclass->process_line = vips_complex2_buffer;
|
aclass->process_line = vips_complex2_buffer;
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ vips_deviate_class_init( VipsDeviateClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "deviate";
|
object_class->nickname = "deviate";
|
||||||
object_class->description = _( "find image average" );
|
object_class->description = _( "find image standard deviation" );
|
||||||
object_class->build = vips_deviate_build;
|
object_class->build = vips_deviate_build;
|
||||||
|
|
||||||
sclass->start = vips_deviate_start;
|
sclass->start = vips_deviate_start;
|
||||||
|
@ -130,7 +130,7 @@ vips_hist_find_indexed_build( VipsObject *object )
|
|||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsStatistic *statistic = VIPS_STATISTIC( object );
|
VipsStatistic *statistic = VIPS_STATISTIC( object );
|
||||||
VipsHistFindIndexed *indexed = (VipsHistFindIndexed *) object;
|
VipsHistFindIndexed *indexed = (VipsHistFindIndexed *) object;
|
||||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||||
|
|
||||||
g_object_set( object,
|
g_object_set( object,
|
||||||
"out", vips_image_new(),
|
"out", vips_image_new(),
|
||||||
|
@ -286,7 +286,7 @@ vips_hist_find_ndim_class_init( VipsHistFindNDimClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "hist_find_ndim";
|
object_class->nickname = "hist_find_ndim";
|
||||||
object_class->description = _( "find image histogram" );
|
object_class->description = _( "find n-dimensional image histogram" );
|
||||||
object_class->build = vips_hist_find_ndim_build;
|
object_class->build = vips_hist_find_ndim_build;
|
||||||
|
|
||||||
sclass->start = vips_hist_find_ndim_start;
|
sclass->start = vips_hist_find_ndim_start;
|
||||||
|
@ -122,8 +122,22 @@ vips_linear_build( VipsObject *object )
|
|||||||
VipsUnary *unary = (VipsUnary *) object;
|
VipsUnary *unary = (VipsUnary *) object;
|
||||||
VipsLinear *linear = (VipsLinear *) object;
|
VipsLinear *linear = (VipsLinear *) object;
|
||||||
|
|
||||||
|
int bands;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* How many bands will our input image have after decoding?
|
||||||
|
*/
|
||||||
|
switch( unary->in->Coding ) {
|
||||||
|
case VIPS_CODING_RAD:
|
||||||
|
case VIPS_CODING_LABQ:
|
||||||
|
bands = 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
bands = unary->in->Bands;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we have a three-element vector we need to bandup the image to
|
/* If we have a three-element vector we need to bandup the image to
|
||||||
* match.
|
* match.
|
||||||
*/
|
*/
|
||||||
@ -133,7 +147,7 @@ vips_linear_build( VipsObject *object )
|
|||||||
if( linear->b )
|
if( linear->b )
|
||||||
linear->n = VIPS_MAX( linear->n, linear->b->n );
|
linear->n = VIPS_MAX( linear->n, linear->b->n );
|
||||||
if( unary->in )
|
if( unary->in )
|
||||||
linear->n = VIPS_MAX( linear->n, unary->in->Bands );
|
linear->n = VIPS_MAX( linear->n, bands );
|
||||||
arithmetic->base_bands = linear->n;
|
arithmetic->base_bands = linear->n;
|
||||||
|
|
||||||
if( unary->in && linear->a && linear->b ) {
|
if( unary->in && linear->a && linear->b ) {
|
||||||
|
@ -196,7 +196,7 @@ vips_math_class_init( VipsMathClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "math";
|
object_class->nickname = "math";
|
||||||
object_class->description = _( "perform a math function on an image" );
|
object_class->description = _( "apply a math operation to an image" );
|
||||||
object_class->build = vips_math_build;
|
object_class->build = vips_math_build;
|
||||||
|
|
||||||
aclass->process_line = vips_math_buffer;
|
aclass->process_line = vips_math_buffer;
|
||||||
|
@ -216,8 +216,7 @@ vips_relational_class_init( VipsRelationalClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "relational";
|
object_class->nickname = "relational";
|
||||||
object_class->description =
|
object_class->description = _( "relational operation on two images" );
|
||||||
_( "a relational operation on a pair of images" );
|
|
||||||
object_class->build = vips_relational_build;
|
object_class->build = vips_relational_build;
|
||||||
|
|
||||||
aclass->process_line = vips_relational_buffer;
|
aclass->process_line = vips_relational_buffer;
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
#include <vips/debug.h>
|
#include <vips/debug.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "statistic.h"
|
#include "statistic.h"
|
||||||
|
|
||||||
@ -109,9 +110,7 @@ vips_statistic_build( VipsObject *object )
|
|||||||
{
|
{
|
||||||
VipsStatistic *statistic = VIPS_STATISTIC( object );
|
VipsStatistic *statistic = VIPS_STATISTIC( object );
|
||||||
VipsStatisticClass *sclass = VIPS_STATISTIC_GET_CLASS( statistic );
|
VipsStatisticClass *sclass = VIPS_STATISTIC_GET_CLASS( statistic );
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||||
const char *domain = class->nickname;
|
|
||||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "vips_statistic_build: " );
|
printf( "vips_statistic_build: " );
|
||||||
@ -122,20 +121,20 @@ vips_statistic_build( VipsObject *object )
|
|||||||
if( VIPS_OBJECT_CLASS( vips_statistic_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_statistic_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
statistic->ready = statistic->in;
|
||||||
|
|
||||||
|
if( vips__image_decode( statistic->ready, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
statistic->ready = t[0];
|
||||||
|
|
||||||
/* If there's a format table, cast the input.
|
/* If there's a format table, cast the input.
|
||||||
*/
|
*/
|
||||||
if( sclass->format_table ) {
|
if( sclass->format_table ) {
|
||||||
if( vips_cast( statistic->in, &t[0],
|
if( vips_cast( statistic->ready, &t[1],
|
||||||
sclass->format_table[statistic->in->BandFmt], NULL ) )
|
sclass->format_table[statistic->in->BandFmt], NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
statistic->ready = t[0];
|
statistic->ready = t[1];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
statistic->ready = statistic->in;
|
|
||||||
|
|
||||||
if( vips_image_pio_input( statistic->ready ) ||
|
|
||||||
vips_check_uncoded( domain, statistic->ready ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( vips_sink( statistic->ready,
|
if( vips_sink( statistic->ready,
|
||||||
vips_statistic_scan_start,
|
vips_statistic_scan_start,
|
||||||
|
@ -627,30 +627,18 @@ vips_colour_difference_build( VipsObject *object )
|
|||||||
right = difference->right;
|
right = difference->right;
|
||||||
extra = NULL;
|
extra = NULL;
|
||||||
|
|
||||||
/* Unpack LABQ images,
|
if( left ) {
|
||||||
*/
|
if( vips__image_decode( left, &t[0] ) )
|
||||||
if( left &&
|
|
||||||
left->Coding == VIPS_CODING_LABQ ) {
|
|
||||||
if( vips_LabQ2Lab( left, &t[0], NULL ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
left = t[0];
|
left = t[0];
|
||||||
}
|
}
|
||||||
if( right &&
|
|
||||||
right->Coding == VIPS_CODING_LABQ ) {
|
if( right ) {
|
||||||
if( vips_LabQ2Lab( right, &t[1], NULL ) )
|
if( vips__image_decode( right, &t[1] ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
right = t[1];
|
right = t[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if( left &&
|
|
||||||
vips_check_uncoded( VIPS_OBJECT_CLASS( class )->nickname,
|
|
||||||
left ) )
|
|
||||||
return( -1 );
|
|
||||||
if( right &&
|
|
||||||
vips_check_uncoded( VIPS_OBJECT_CLASS( class )->nickname,
|
|
||||||
right ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
/* Detach and reattach extra bands, if any. If both left and right
|
/* Detach and reattach extra bands, if any. If both left and right
|
||||||
* have extra bands, give up.
|
* have extra bands, give up.
|
||||||
*/
|
*/
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
* - add RGB16 as a source
|
* - add RGB16 as a source
|
||||||
* 19/1/14
|
* 19/1/14
|
||||||
* - auto-decode RAD images
|
* - auto-decode RAD images
|
||||||
|
* 3/2/14
|
||||||
|
* - add "source_space", overrides source space guess
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -388,6 +390,7 @@ typedef struct _VipsColourspace {
|
|||||||
VipsImage *in;
|
VipsImage *in;
|
||||||
VipsImage *out;
|
VipsImage *out;
|
||||||
VipsInterpretation space;
|
VipsInterpretation space;
|
||||||
|
VipsInterpretation source_space;
|
||||||
} VipsColourspace;
|
} VipsColourspace;
|
||||||
|
|
||||||
typedef VipsOperationClass VipsColourspaceClass;
|
typedef VipsOperationClass VipsColourspaceClass;
|
||||||
@ -408,7 +411,6 @@ vips_colourspace_build( VipsObject *object )
|
|||||||
|
|
||||||
VipsInterpretation interpretation;
|
VipsInterpretation interpretation;
|
||||||
|
|
||||||
|
|
||||||
/* Verify that all input args have been set.
|
/* Verify that all input args have been set.
|
||||||
*/
|
*/
|
||||||
if( VIPS_OBJECT_CLASS( vips_colourspace_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_colourspace_parent_class )->
|
||||||
@ -426,7 +428,10 @@ vips_colourspace_build( VipsObject *object )
|
|||||||
x = t[0];
|
x = t[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
interpretation = vips_image_guess_interpretation( x );
|
if( vips_object_argument_isset( object, "source_space" ) )
|
||||||
|
interpretation = colourspace->source_space;
|
||||||
|
else
|
||||||
|
interpretation = vips_image_guess_interpretation( x );
|
||||||
|
|
||||||
/* Treat RGB and RGB16 as sRGB. If you want some other treatment,
|
/* Treat RGB and RGB16 as sRGB. If you want some other treatment,
|
||||||
* you'll need to use the icc funcs.
|
* you'll need to use the icc funcs.
|
||||||
@ -506,11 +511,20 @@ vips_colourspace_class_init( VipsColourspaceClass *class )
|
|||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsColourspace, space ),
|
G_STRUCT_OFFSET( VipsColourspace, space ),
|
||||||
VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_sRGB );
|
VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_sRGB );
|
||||||
|
|
||||||
|
VIPS_ARG_ENUM( class, "source-space", 6,
|
||||||
|
_( "Source space" ),
|
||||||
|
_( "Source colour space" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsColourspace, source_space ),
|
||||||
|
VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_sRGB );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_colourspace_init( VipsColourspace *colourspace )
|
vips_colourspace_init( VipsColourspace *colourspace )
|
||||||
{
|
{
|
||||||
|
colourspace->source_space = VIPS_INTERPRETATION_sRGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -519,7 +533,12 @@ vips_colourspace_init( VipsColourspace *colourspace )
|
|||||||
* @out: output image
|
* @out: output image
|
||||||
* @space: convert to this colour space
|
* @space: convert to this colour space
|
||||||
*
|
*
|
||||||
* This operation looks at the interpretation field of @in and runs
|
* Optional arguments:
|
||||||
|
*
|
||||||
|
* @source_space: input colour space
|
||||||
|
*
|
||||||
|
* This operation looks at the interpretation field of @in (or uses
|
||||||
|
* @source_space, if set) and runs
|
||||||
* a set of colourspace conversion functions to move it to @space.
|
* a set of colourspace conversion functions to move it to @space.
|
||||||
*
|
*
|
||||||
* For example, given an image tagged as #VIPS_INTERPRETATION_YXY, running
|
* For example, given an image tagged as #VIPS_INTERPRETATION_YXY, running
|
||||||
|
@ -123,6 +123,7 @@ vips_bandary_build( VipsObject *object )
|
|||||||
VipsBandary *bandary = (VipsBandary *) object;
|
VipsBandary *bandary = (VipsBandary *) object;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
VipsImage **decode;
|
||||||
VipsImage **format;
|
VipsImage **format;
|
||||||
VipsImage **size;
|
VipsImage **size;
|
||||||
|
|
||||||
@ -139,14 +140,15 @@ vips_bandary_build( VipsObject *object )
|
|||||||
"%s", _( "too many input images" ) );
|
"%s", _( "too many input images" ) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
for( i = 0; i < bandary->n; i++ )
|
|
||||||
if( vips_image_pio_input( bandary->in[i] ) ||
|
|
||||||
vips_check_uncoded( class->nickname, bandary->in[i] ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
|
decode = (VipsImage **) vips_object_local_array( object, bandary->n );
|
||||||
format = (VipsImage **) vips_object_local_array( object, bandary->n );
|
format = (VipsImage **) vips_object_local_array( object, bandary->n );
|
||||||
size = (VipsImage **) vips_object_local_array( object, bandary->n );
|
size = (VipsImage **) vips_object_local_array( object, bandary->n );
|
||||||
if( vips__formatalike_vec( bandary->in, format, bandary->n ) ||
|
|
||||||
|
for( i = 0; i < bandary->n; i++ )
|
||||||
|
if( vips__image_decode( bandary->in[i], &decode[i] ) )
|
||||||
|
return( -1 );
|
||||||
|
if( vips__formatalike_vec( decode, format, bandary->n ) ||
|
||||||
vips__sizealike_vec( format, size, bandary->n ) )
|
vips__sizealike_vec( format, size, bandary->n ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
bandary->ready = size;
|
bandary->ready = size;
|
||||||
|
@ -429,36 +429,41 @@ vips_cast_gen( VipsRegion *or, void *vseq, void *a, void *b,
|
|||||||
static int
|
static int
|
||||||
vips_cast_build( VipsObject *object )
|
vips_cast_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
|
||||||
VipsConversion *conversion = VIPS_CONVERSION( object );
|
VipsConversion *conversion = VIPS_CONVERSION( object );
|
||||||
VipsCast *cast = (VipsCast *) object;
|
VipsCast *cast = (VipsCast *) object;
|
||||||
|
VipsImage **t = (VipsImage **)
|
||||||
|
vips_object_local_array( object, 2 );
|
||||||
|
|
||||||
|
VipsImage *in;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_cast_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_cast_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
in = cast->in;
|
||||||
|
|
||||||
/* Trivial case: fall back to copy().
|
/* Trivial case: fall back to copy().
|
||||||
*/
|
*/
|
||||||
if( cast->in->BandFmt == cast->format )
|
if( in->BandFmt == cast->format )
|
||||||
return( vips_image_write( cast->in, conversion->out ) );
|
return( vips_image_write( in, conversion->out ) );
|
||||||
|
|
||||||
if( vips_check_uncoded( class->nickname, cast->in ) ||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
vips_image_pio_input( cast->in ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
if( vips_image_pipelinev( conversion->out,
|
if( vips_image_pipelinev( conversion->out,
|
||||||
VIPS_DEMAND_STYLE_THINSTRIP, cast->in, NULL ) )
|
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
conversion->out->BandFmt = cast->format;
|
conversion->out->BandFmt = cast->format;
|
||||||
|
|
||||||
g_signal_connect( cast->in, "preeval",
|
g_signal_connect( in, "preeval",
|
||||||
G_CALLBACK( vips_cast_preeval ), cast );
|
G_CALLBACK( vips_cast_preeval ), cast );
|
||||||
g_signal_connect( cast->in, "posteval",
|
g_signal_connect( in, "posteval",
|
||||||
G_CALLBACK( vips_cast_posteval ), cast );
|
G_CALLBACK( vips_cast_posteval ), cast );
|
||||||
|
|
||||||
if( vips_image_generate( conversion->out,
|
if( vips_image_generate( conversion->out,
|
||||||
vips_cast_start, vips_cast_gen, vips_cast_stop,
|
vips_cast_start, vips_cast_gen, vips_cast_stop,
|
||||||
cast->in, cast ) )
|
in, cast ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
* - force input to mono 8-bit for the user
|
* - force input to mono 8-bit for the user
|
||||||
* 1/8/13
|
* 1/8/13
|
||||||
* - redone as a class
|
* - redone as a class
|
||||||
|
* 23/1/14
|
||||||
|
* - oops, was not auto-getting and casting the first band
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -52,6 +54,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "pconversion.h"
|
#include "pconversion.h"
|
||||||
|
|
||||||
@ -329,10 +332,9 @@ static unsigned char vips_falsecolour_pet[][3] = {
|
|||||||
static int
|
static int
|
||||||
vips_falsecolour_build( VipsObject *object )
|
vips_falsecolour_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
|
||||||
VipsConversion *conversion = VIPS_CONVERSION( object );
|
VipsConversion *conversion = VIPS_CONVERSION( object );
|
||||||
VipsFalsecolour *falsecolour = (VipsFalsecolour *) object;
|
VipsFalsecolour *falsecolour = (VipsFalsecolour *) object;
|
||||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 );
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 5 );
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_falsecolour_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_falsecolour_parent_class )->
|
||||||
build( object ) )
|
build( object ) )
|
||||||
@ -343,13 +345,15 @@ vips_falsecolour_build( VipsObject *object )
|
|||||||
VIPS_FORMAT_UCHAR )) )
|
VIPS_FORMAT_UCHAR )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Force to mono 8-bit.
|
/* Force to mono 8-bit. Don't use vips_colourspace() to go to B_W, we
|
||||||
|
* want to work for images which aren't in a recognised space, like
|
||||||
|
* MULTIBAND.
|
||||||
*/
|
*/
|
||||||
if( vips_check_uncoded( class->nickname, falsecolour->in ) ||
|
if( vips__image_decode( falsecolour->in, &t[1] ) ||
|
||||||
vips_extract_band( falsecolour->in, &t[1], 0, NULL ) ||
|
vips_extract_band( t[1], &t[2], 0, NULL ) ||
|
||||||
vips_cast( t[1], &t[2], VIPS_FORMAT_UCHAR, NULL ) ||
|
vips_cast( t[2], &t[3], VIPS_FORMAT_UCHAR, NULL ) ||
|
||||||
vips_maplut( falsecolour->in, &t[3], t[0], NULL ) ||
|
vips_maplut( t[3], &t[4], t[0], NULL ) ||
|
||||||
vips_image_write( t[3], conversion->out ) )
|
vips_image_write( t[4], conversion->out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -300,24 +300,31 @@ vips_flatten_build( VipsObject *object )
|
|||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsConversion *conversion = VIPS_CONVERSION( object );
|
VipsConversion *conversion = VIPS_CONVERSION( object );
|
||||||
VipsFlatten *flatten = (VipsFlatten *) object;
|
VipsFlatten *flatten = (VipsFlatten *) object;
|
||||||
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
|
||||||
|
|
||||||
|
VipsImage *in;
|
||||||
int i;
|
int i;
|
||||||
gboolean black;
|
gboolean black;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_flatten_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_flatten_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
in = flatten->in;
|
||||||
|
|
||||||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
/* Trivial case: fall back to copy().
|
/* Trivial case: fall back to copy().
|
||||||
*/
|
*/
|
||||||
if( flatten->in->Bands == 1 )
|
if( flatten->in->Bands == 1 )
|
||||||
return( vips_image_write( flatten->in, conversion->out ) );
|
return( vips_image_write( in, conversion->out ) );
|
||||||
|
|
||||||
if( vips_check_uncoded( class->nickname, flatten->in ) ||
|
if( vips_check_noncomplex( class->nickname, in ) )
|
||||||
vips_check_noncomplex( class->nickname, flatten->in ) ||
|
|
||||||
vips_image_pio_input( flatten->in ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_image_pipelinev( conversion->out,
|
if( vips_image_pipelinev( conversion->out,
|
||||||
VIPS_DEMAND_STYLE_THINSTRIP, flatten->in, NULL ) )
|
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
conversion->out->Bands -= 1;
|
conversion->out->Bands -= 1;
|
||||||
@ -334,7 +341,7 @@ vips_flatten_build( VipsObject *object )
|
|||||||
if( black ) {
|
if( black ) {
|
||||||
if( vips_image_generate( conversion->out,
|
if( vips_image_generate( conversion->out,
|
||||||
vips_start_one, vips_flatten_black_gen, vips_stop_one,
|
vips_start_one, vips_flatten_black_gen, vips_stop_one,
|
||||||
flatten->in, flatten ) )
|
in, flatten ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -347,7 +354,7 @@ vips_flatten_build( VipsObject *object )
|
|||||||
|
|
||||||
if( vips_image_generate( conversion->out,
|
if( vips_image_generate( conversion->out,
|
||||||
vips_start_one, vips_flatten_gen, vips_stop_one,
|
vips_start_one, vips_flatten_gen, vips_stop_one,
|
||||||
flatten->in, flatten ) )
|
in, flatten ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "pconversion.h"
|
#include "pconversion.h"
|
||||||
|
|
||||||
@ -142,19 +143,25 @@ vips_recomb_build( VipsObject *object )
|
|||||||
VipsRecomb *recomb = (VipsRecomb *) object;
|
VipsRecomb *recomb = (VipsRecomb *) object;
|
||||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||||
|
|
||||||
|
VipsImage *in;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_recomb_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_recomb_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_image_pio_input( recomb->in ) ||
|
in = recomb->in;
|
||||||
vips_check_uncoded( class->nickname, recomb->in ) ||
|
|
||||||
vips_check_noncomplex( class->nickname, recomb->in ) )
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
|
if( vips_check_noncomplex( class->nickname, in ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( vips_image_pio_input( recomb->m ) ||
|
if( vips_image_pio_input( recomb->m ) ||
|
||||||
vips_check_uncoded( class->nickname, recomb->m ) ||
|
vips_check_uncoded( class->nickname, recomb->m ) ||
|
||||||
vips_check_noncomplex( class->nickname, recomb->m ) ||
|
vips_check_noncomplex( class->nickname, recomb->m ) ||
|
||||||
vips_check_mono( class->nickname, recomb->m ) )
|
vips_check_mono( class->nickname, recomb->m ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( recomb->in->Bands != recomb->m->Xsize ) {
|
if( in->Bands != recomb->m->Xsize ) {
|
||||||
vips_error( class->nickname,
|
vips_error( class->nickname,
|
||||||
"%s", _( "bands in must equal matrix width" ) );
|
"%s", _( "bands in must equal matrix width" ) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -165,16 +172,16 @@ vips_recomb_build( VipsObject *object )
|
|||||||
recomb->coeff = t[0];
|
recomb->coeff = t[0];
|
||||||
|
|
||||||
if( vips_image_pipelinev( conversion->out,
|
if( vips_image_pipelinev( conversion->out,
|
||||||
VIPS_DEMAND_STYLE_THINSTRIP, recomb->in, NULL ) )
|
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
conversion->out->Bands = recomb->m->Ysize;
|
conversion->out->Bands = recomb->m->Ysize;
|
||||||
if( vips_bandfmt_isint( recomb->in->BandFmt ) )
|
if( vips_bandfmt_isint( in->BandFmt ) )
|
||||||
conversion->out->BandFmt = VIPS_FORMAT_FLOAT;
|
conversion->out->BandFmt = VIPS_FORMAT_FLOAT;
|
||||||
|
|
||||||
if( vips_image_generate( conversion->out,
|
if( vips_image_generate( conversion->out,
|
||||||
vips_start_one, vips_recomb_gen, vips_stop_one,
|
vips_start_one, vips_recomb_gen, vips_stop_one,
|
||||||
recomb->in, recomb ) )
|
in, recomb ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -142,7 +142,7 @@ vips_compass_class_init( VipsCompassClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "compass";
|
object_class->nickname = "compass";
|
||||||
object_class->description = _( "convolution operation" );
|
object_class->description = _( "convolve with rotaing mask" );
|
||||||
object_class->build = vips_compass_build;
|
object_class->build = vips_compass_build;
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "times", 101,
|
VIPS_ARG_INT( class, "times", 101,
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "pconvolution.h"
|
#include "pconvolution.h"
|
||||||
|
|
||||||
@ -65,7 +66,10 @@ vips_conv_build( VipsObject *object )
|
|||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsConvolution *convolution = (VipsConvolution *) object;
|
VipsConvolution *convolution = (VipsConvolution *) object;
|
||||||
VipsConv *conv = (VipsConv *) object;
|
VipsConv *conv = (VipsConv *) object;
|
||||||
|
VipsImage **t = (VipsImage **)
|
||||||
|
vips_object_local_array( object, 4 );
|
||||||
|
|
||||||
|
VipsImage *in;
|
||||||
INTMASK *imsk;
|
INTMASK *imsk;
|
||||||
DOUBLEMASK *dmsk;
|
DOUBLEMASK *dmsk;
|
||||||
|
|
||||||
@ -74,6 +78,8 @@ vips_conv_build( VipsObject *object )
|
|||||||
if( VIPS_OBJECT_CLASS( vips_conv_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_conv_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
in = convolution->in;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
printf( "vips_conv_build: convolving with:\n" );
|
printf( "vips_conv_build: convolving with:\n" );
|
||||||
vips_matrixprint( convolution->M, NULL );
|
vips_matrixprint( convolution->M, NULL );
|
||||||
@ -86,19 +92,25 @@ vips_conv_build( VipsObject *object )
|
|||||||
!im_local_dmask( convolution->out, dmsk ) )
|
!im_local_dmask( convolution->out, dmsk ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
/* Unpack for processing.
|
||||||
|
*/
|
||||||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
switch( conv->precision ) {
|
switch( conv->precision ) {
|
||||||
case VIPS_PRECISION_INTEGER:
|
case VIPS_PRECISION_INTEGER:
|
||||||
if( im_conv( convolution->in, convolution->out, imsk ) )
|
if( im_conv( in, convolution->out, imsk ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_PRECISION_FLOAT:
|
case VIPS_PRECISION_FLOAT:
|
||||||
if( im_conv_f( convolution->in, convolution->out, dmsk ) )
|
if( im_conv_f( in, convolution->out, dmsk ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_PRECISION_APPROXIMATE:
|
case VIPS_PRECISION_APPROXIMATE:
|
||||||
if( im_aconv( convolution->in, convolution->out, dmsk,
|
if( im_aconv( in, convolution->out, dmsk,
|
||||||
conv->layers, conv->cluster ) )
|
conv->layers, conv->cluster ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
break;
|
break;
|
||||||
|
@ -100,7 +100,7 @@ vips_convsep_class_init( VipsConvsepClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "convsep";
|
object_class->nickname = "convsep";
|
||||||
object_class->description = _( "convolution operation" );
|
object_class->description = _( "seperable convolution operation" );
|
||||||
object_class->build = vips_convsep_build;
|
object_class->build = vips_convsep_build;
|
||||||
|
|
||||||
VIPS_ARG_ENUM( class, "precision", 203,
|
VIPS_ARG_ENUM( class, "precision", 203,
|
||||||
|
@ -108,7 +108,7 @@ vips_gaussblur_class_init( VipsGaussblurClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "gaussblur";
|
object_class->nickname = "gaussblur";
|
||||||
object_class->description = _( "Unsharp masking for print" );
|
object_class->description = _( "gaussian blur" );
|
||||||
object_class->build = vips_gaussblur_build;
|
object_class->build = vips_gaussblur_build;
|
||||||
|
|
||||||
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
||||||
|
@ -309,7 +309,7 @@ vips_sharpen_class_init( VipsSharpenClass *class )
|
|||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "sharpen";
|
object_class->nickname = "sharpen";
|
||||||
object_class->description = _( "Unsharp masking for print" );
|
object_class->description = _( "unsharp masking for print" );
|
||||||
object_class->build = vips_sharpen_build;
|
object_class->build = vips_sharpen_build;
|
||||||
|
|
||||||
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
||||||
|
@ -98,7 +98,9 @@ static const char *openslide_suffs[] = {
|
|||||||
".vms", ".vmu", ".ndpi", /* Hamamatsu */
|
".vms", ".vmu", ".ndpi", /* Hamamatsu */
|
||||||
".scn", /* Leica */
|
".scn", /* Leica */
|
||||||
".mrxs", /* MIRAX */
|
".mrxs", /* MIRAX */
|
||||||
|
".svslide", /* Sakura */
|
||||||
".tif", /* Trestle */
|
".tif", /* Trestle */
|
||||||
|
".bif", /* Ventana */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -183,8 +183,7 @@ vips_wrap7_vargv_dispose( im_function *fn, im_object *vargv )
|
|||||||
|
|
||||||
case VIPS_WRAP7_INTERPOLATE:
|
case VIPS_WRAP7_INTERPOLATE:
|
||||||
case VIPS_WRAP7_IMAGE:
|
case VIPS_WRAP7_IMAGE:
|
||||||
if( vargv[i] )
|
VIPS_UNREF( vargv[i] );
|
||||||
VIPS_UNREF( vargv[i] );
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_WRAP7_IMAGEVEC:
|
case VIPS_WRAP7_IMAGEVEC:
|
||||||
@ -193,13 +192,21 @@ vips_wrap7_vargv_dispose( im_function *fn, im_object *vargv )
|
|||||||
int j;
|
int j;
|
||||||
|
|
||||||
for( j = 0; j < iv->n; j++ )
|
for( j = 0; j < iv->n; j++ )
|
||||||
if( iv->vec[j] )
|
VIPS_UNREF( iv->vec[j] );
|
||||||
VIPS_UNREF( iv->vec[j] );
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_WRAP7_GVALUE:
|
case VIPS_WRAP7_GVALUE:
|
||||||
g_value_unset( vargv[i] );
|
if( vargv[i] ) {
|
||||||
|
GValue *value = (GValue *) vargv[i];
|
||||||
|
|
||||||
|
if( G_VALUE_TYPE( value ) )
|
||||||
|
g_value_unset( value );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_WRAP7_STRING:
|
||||||
|
VIPS_FREE( vargv[i] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -686,6 +693,7 @@ vips_wrap7_class_init( VipsWrap7Class *class )
|
|||||||
{
|
{
|
||||||
GObjectClass *gobject_class = (GObjectClass *) class;
|
GObjectClass *gobject_class = (GObjectClass *) class;
|
||||||
VipsObjectClass *vobject_class = (VipsObjectClass *) class;
|
VipsObjectClass *vobject_class = (VipsObjectClass *) class;
|
||||||
|
VipsOperationClass *operation_class = (VipsOperationClass *) class;
|
||||||
|
|
||||||
gobject_class->dispose = vips_wrap7_dispose;
|
gobject_class->dispose = vips_wrap7_dispose;
|
||||||
gobject_class->finalize = vips_wrap7_finalize;
|
gobject_class->finalize = vips_wrap7_finalize;
|
||||||
@ -695,6 +703,8 @@ vips_wrap7_class_init( VipsWrap7Class *class )
|
|||||||
vobject_class->build = vips_wrap7_build;
|
vobject_class->build = vips_wrap7_build;
|
||||||
vobject_class->summary_class = vips_wrap7_summary_class;
|
vobject_class->summary_class = vips_wrap7_summary_class;
|
||||||
vobject_class->dump = vips_wrap7_dump;
|
vobject_class->dump = vips_wrap7_dump;
|
||||||
|
|
||||||
|
operation_class->flags = VIPS_OPERATION_DEPRECATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2357,18 +2357,17 @@ vips_openexrload( const char *filename, VipsImage **out, ... )
|
|||||||
*
|
*
|
||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
* @layer: load this layer
|
* @level: load this level
|
||||||
* @associated: load this associated image
|
* @associated: load this associated image
|
||||||
*
|
*
|
||||||
* Read a virtual slide supported by the OpenSlide library into a VIPS image.
|
* Read a virtual slide supported by the OpenSlide library into a VIPS image.
|
||||||
* OpenSlide supports images in Aperio, Hamamatsu VMS, Hamamatsu VMU, MIRAX,
|
* OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle,
|
||||||
* and Trestle formats.
|
* and Ventana formats.
|
||||||
*
|
*
|
||||||
* To facilitate zooming, virtual slide formats include multiple scaled-down
|
* To facilitate zooming, virtual slide formats include multiple scaled-down
|
||||||
* versions of the high-resolution image. These are typically called
|
* versions of the high-resolution image. These are typically called
|
||||||
* "levels", though OpenSlide and im_openslide2vips() call them "layers".
|
* "levels". By default, vips_openslideload() reads the highest-resolution
|
||||||
* By default, vips_openslideload() reads the highest-resolution layer
|
* level (level 0). Set @level to the level number you want.
|
||||||
* (layer 0). Set @layer to the layer number you want.
|
|
||||||
*
|
*
|
||||||
* In addition to the slide image itself, virtual slide formats sometimes
|
* In addition to the slide image itself, virtual slide formats sometimes
|
||||||
* include additional images, such as a scan of the slide's barcode.
|
* include additional images, such as a scan of the slide's barcode.
|
||||||
@ -2405,6 +2404,14 @@ vips_openslideload( const char *filename, VipsImage **out, ... )
|
|||||||
*
|
*
|
||||||
* Read a FITS image file into a VIPS image.
|
* Read a FITS image file into a VIPS image.
|
||||||
*
|
*
|
||||||
|
* This operation can read images with up to three dimensions. Any higher
|
||||||
|
* dimensions must be empty.
|
||||||
|
*
|
||||||
|
* It can read 8, 16 and 32-bit integer images, signed and unsigned, float and
|
||||||
|
* double.
|
||||||
|
*
|
||||||
|
* FITS metadata is attached with the "fits-" prefix.
|
||||||
|
*
|
||||||
* See also: vips_image_new_from_file().
|
* See also: vips_image_new_from_file().
|
||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
@ -2428,7 +2435,7 @@ vips_fitsload( const char *filename, VipsImage **out, ... )
|
|||||||
* @filename: file to write to
|
* @filename: file to write to
|
||||||
* @...: %NULL-terminated list of optional named arguments
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
*
|
*
|
||||||
* Write a VIPS image to a file as FITS.
|
* Write a VIPS image to a file in FITS format.
|
||||||
*
|
*
|
||||||
* See also: vips_image_write_file().
|
* See also: vips_image_write_file().
|
||||||
*
|
*
|
||||||
|
@ -150,6 +150,10 @@ typedef struct _ReadJpeg {
|
|||||||
/* Set if we need to finish the decompress.
|
/* Set if we need to finish the decompress.
|
||||||
*/
|
*/
|
||||||
gboolean decompressing;
|
gboolean decompressing;
|
||||||
|
|
||||||
|
/* Track the y pos during a read with this.
|
||||||
|
*/
|
||||||
|
int y_pos;
|
||||||
} ReadJpeg;
|
} ReadJpeg;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -222,6 +226,8 @@ readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean readbehind )
|
|||||||
jpeg->eman.pub.output_message = vips__new_output_message;
|
jpeg->eman.pub.output_message = vips__new_output_message;
|
||||||
jpeg->eman.fp = NULL;
|
jpeg->eman.fp = NULL;
|
||||||
|
|
||||||
|
jpeg->y_pos = 0;
|
||||||
|
|
||||||
/* jpeg_create_decompress() can fail on some sanity checks. Don't
|
/* jpeg_create_decompress() can fail on some sanity checks. Don't
|
||||||
* readjpeg_free() since we don't want to jpeg_destroy_decompress().
|
* readjpeg_free() since we don't want to jpeg_destroy_decompress().
|
||||||
*/
|
*/
|
||||||
@ -888,7 +894,7 @@ read_jpeg_generate( VipsRegion *or,
|
|||||||
printf( "read_jpeg_generate: line %d, %d rows\n",
|
printf( "read_jpeg_generate: line %d, %d rows\n",
|
||||||
r->top, r->height );
|
r->top, r->height );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
VIPS_GATE_START( "read_jpeg_generate: work" );
|
VIPS_GATE_START( "read_jpeg_generate: work" );
|
||||||
|
|
||||||
/* We're inside a tilecache where tiles are the full image width, so
|
/* We're inside a tilecache where tiles are the full image width, so
|
||||||
@ -907,6 +913,11 @@ read_jpeg_generate( VipsRegion *or,
|
|||||||
*/
|
*/
|
||||||
g_assert( r->height == VIPS_MIN( 8, or->im->Ysize - r->top ) );
|
g_assert( r->height == VIPS_MIN( 8, or->im->Ysize - r->top ) );
|
||||||
|
|
||||||
|
/* And check that y_pos is correct. It should be, since we are inside
|
||||||
|
* a vips_sequential().
|
||||||
|
*/
|
||||||
|
g_assert( r->top == jpeg->y_pos );
|
||||||
|
|
||||||
/* Here for longjmp() from vips__new_error_exit().
|
/* Here for longjmp() from vips__new_error_exit().
|
||||||
*/
|
*/
|
||||||
if( setjmp( jpeg->eman.jmp ) )
|
if( setjmp( jpeg->eman.jmp ) )
|
||||||
@ -926,6 +937,8 @@ read_jpeg_generate( VipsRegion *or,
|
|||||||
for( x = 0; x < sz; x++ )
|
for( x = 0; x < sz; x++ )
|
||||||
row_pointer[0][x] = 255 - row_pointer[0][x];
|
row_pointer[0][x] = 255 - row_pointer[0][x];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jpeg->y_pos += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIPS_GATE_STOP( "read_jpeg_generate: work" );
|
VIPS_GATE_STOP( "read_jpeg_generate: work" );
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* Benjamin Gilbert
|
* Benjamin Gilbert
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011-2012 Carnegie Mellon University
|
* Copyright (c) 2011-2014 Carnegie Mellon University
|
||||||
*
|
*
|
||||||
* 26/11/11
|
* 26/11/11
|
||||||
* - initial version
|
* - initial version
|
||||||
@ -39,6 +39,8 @@
|
|||||||
* - use threaded tile cache
|
* - use threaded tile cache
|
||||||
* 6/8/13
|
* 6/8/13
|
||||||
* - always output solid (not transparent) pixels
|
* - always output solid (not transparent) pixels
|
||||||
|
* 25/1/14
|
||||||
|
* - use openslide_detect_vendor() on >= 3.4.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -105,13 +107,28 @@ typedef struct {
|
|||||||
int
|
int
|
||||||
vips__openslide_isslide( const char *filename )
|
vips__openslide_isslide( const char *filename )
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_OPENSLIDE_3_4
|
||||||
|
const char *vendor;
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
vendor = openslide_detect_vendor( filename );
|
||||||
|
|
||||||
|
/* Generic tiled tiff images can be opened by openslide as well.
|
||||||
|
* Only offer to load this file if it's not a generic tiff since
|
||||||
|
* we want vips_tiffload() to handle these.
|
||||||
|
*/
|
||||||
|
ok = ( vendor &&
|
||||||
|
strcmp( vendor, "generic-tiff" ) != 0 );
|
||||||
|
|
||||||
|
VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok );
|
||||||
|
|
||||||
|
return( ok );
|
||||||
|
#else
|
||||||
openslide_t *osr;
|
openslide_t *osr;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
ok = 0;
|
ok = 0;
|
||||||
vips_error_freeze();
|
|
||||||
osr = openslide_open( filename );
|
osr = openslide_open( filename );
|
||||||
vips_error_thaw();
|
|
||||||
|
|
||||||
if( osr ) {
|
if( osr ) {
|
||||||
const char *vendor;
|
const char *vendor;
|
||||||
@ -135,6 +152,7 @@ vips__openslide_isslide( const char *filename )
|
|||||||
VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok );
|
VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok );
|
||||||
|
|
||||||
return( ok );
|
return( ok );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -140,7 +140,9 @@ static const char *vips_foreign_openslide_suffs[] = {
|
|||||||
".vms", ".vmu", ".ndpi", /* Hamamatsu */
|
".vms", ".vmu", ".ndpi", /* Hamamatsu */
|
||||||
".scn", /* Leica */
|
".scn", /* Leica */
|
||||||
".mrxs", /* MIRAX */
|
".mrxs", /* MIRAX */
|
||||||
|
".svslide", /* Sakura */
|
||||||
".tif", /* Trestle */
|
".tif", /* Trestle */
|
||||||
|
".bif", /* Ventana */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
* - support sequential read
|
* - support sequential read
|
||||||
* 5/11/13
|
* 5/11/13
|
||||||
* - rewritten scanline encode and decode, now much faster
|
* - rewritten scanline encode and decode, now much faster
|
||||||
|
* 23/1/14
|
||||||
|
* - put the reader globals into a struct so we can have many active
|
||||||
|
* readers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -617,38 +620,57 @@ register RESOLU *rp;
|
|||||||
#define BUFFER_SIZE (4096)
|
#define BUFFER_SIZE (4096)
|
||||||
#define BUFFER_MARGIN (256)
|
#define BUFFER_MARGIN (256)
|
||||||
|
|
||||||
static unsigned char buffer[BUFFER_SIZE + BUFFER_MARGIN];
|
/* Read from a FILE with a rolling memory buffer ... this lets us reduce the
|
||||||
static int buffer_length = 0;
|
* number of fgetc() and gives us some very quick readahead.
|
||||||
static int buffer_position = 0;
|
*/
|
||||||
static FILE *buffer_fp = NULL;
|
|
||||||
|
|
||||||
static void
|
typedef struct _Buffer {
|
||||||
buffer_init( FILE *fp )
|
unsigned char text[BUFFER_SIZE + BUFFER_MARGIN];
|
||||||
|
int length;
|
||||||
|
int position;
|
||||||
|
FILE *fp;
|
||||||
|
} Buffer;
|
||||||
|
|
||||||
|
static Buffer *
|
||||||
|
buffer_new( FILE *fp )
|
||||||
{
|
{
|
||||||
buffer_length = 0;
|
Buffer *buffer = g_new0( Buffer, 1 );
|
||||||
buffer_position = 0;
|
|
||||||
buffer_fp = fp;
|
buffer->length = 0;
|
||||||
|
buffer->position = 0;
|
||||||
|
buffer->fp = fp;
|
||||||
|
|
||||||
|
return( buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_free( Buffer *buffer )
|
||||||
|
{
|
||||||
|
g_free( buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure there are at least @require bytes of readahead available.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
buffer_need( int require )
|
buffer_need( Buffer *buffer, int require )
|
||||||
{
|
{
|
||||||
int remaining;
|
int remaining;
|
||||||
|
|
||||||
g_assert( require < BUFFER_MARGIN );
|
g_assert( require < BUFFER_MARGIN );
|
||||||
|
|
||||||
remaining = buffer_length - buffer_position;
|
remaining = buffer->length - buffer->position;
|
||||||
if( remaining < require ) {
|
if( remaining < require ) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
memcpy( buffer, buffer + buffer_position, remaining );
|
memcpy( buffer->text,
|
||||||
buffer_position = 0;
|
buffer->text + buffer->position, remaining );
|
||||||
buffer_length = remaining;
|
buffer->position = 0;
|
||||||
|
buffer->length = remaining;
|
||||||
|
|
||||||
len = fread( buffer + buffer_length, 1, BUFFER_SIZE,
|
len = fread( buffer->text + buffer->length,
|
||||||
buffer_fp );
|
1, BUFFER_SIZE, buffer->fp );
|
||||||
buffer_length += len;
|
buffer->length += len;
|
||||||
remaining = buffer_length - buffer_position;
|
remaining = buffer->length - buffer->position;
|
||||||
|
|
||||||
if( remaining < require ) {
|
if( remaining < require ) {
|
||||||
vips_error( "rad2vips", "%s", _( "end of file" ) );
|
vips_error( "rad2vips", "%s", _( "end of file" ) );
|
||||||
@ -659,26 +681,26 @@ buffer_need( int require )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BUFFER_FETCH (buffer[buffer_position++])
|
#define BUFFER_FETCH(B) ((B)->text[(B)->position++])
|
||||||
#define BUFFER_PEEK (buffer[buffer_position])
|
#define BUFFER_PEEK(B) ((B)->text[(B)->position])
|
||||||
|
|
||||||
/* Read a single scanlne, encoded in the old style.
|
/* Read a single scanlne, encoded in the old style.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
scanline_read_old( COLR *scanline, int width )
|
scanline_read_old( Buffer *buffer, COLR *scanline, int width )
|
||||||
{
|
{
|
||||||
int rshift;
|
int rshift;
|
||||||
|
|
||||||
rshift = 0;
|
rshift = 0;
|
||||||
|
|
||||||
while( width > 0 ) {
|
while( width > 0 ) {
|
||||||
if( buffer_need( 4 ) )
|
if( buffer_need( buffer, 4 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
scanline[0][RED] = BUFFER_FETCH;
|
scanline[0][RED] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][GRN] = BUFFER_FETCH;
|
scanline[0][GRN] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][BLU] = BUFFER_FETCH;
|
scanline[0][BLU] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][EXP] = BUFFER_FETCH;
|
scanline[0][EXP] = BUFFER_FETCH( buffer );
|
||||||
|
|
||||||
if( scanline[0][RED] == 1 &&
|
if( scanline[0][RED] == 1 &&
|
||||||
scanline[0][GRN] == 1 &&
|
scanline[0][GRN] == 1 &&
|
||||||
@ -706,7 +728,7 @@ scanline_read_old( COLR *scanline, int width )
|
|||||||
/* Read a single encoded scanline.
|
/* Read a single encoded scanline.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
scanline_read( COLR *scanline, int width )
|
scanline_read( Buffer *buffer, COLR *scanline, int width )
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@ -714,21 +736,21 @@ scanline_read( COLR *scanline, int width )
|
|||||||
*/
|
*/
|
||||||
if( width < MINELEN ||
|
if( width < MINELEN ||
|
||||||
width > MAXELEN )
|
width > MAXELEN )
|
||||||
return( scanline_read_old( scanline, width ) );
|
return( scanline_read_old( buffer, scanline, width ) );
|
||||||
|
|
||||||
if( buffer_need( 4 ) )
|
if( buffer_need( buffer, 4 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( BUFFER_PEEK != 2 )
|
if( BUFFER_PEEK( buffer ) != 2 )
|
||||||
return( scanline_read_old( scanline, width ) );
|
return( scanline_read_old( buffer, scanline, width ) );
|
||||||
|
|
||||||
scanline[0][RED] = BUFFER_FETCH;
|
scanline[0][RED] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][GRN] = BUFFER_FETCH;
|
scanline[0][GRN] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][BLU] = BUFFER_FETCH;
|
scanline[0][BLU] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][EXP] = BUFFER_FETCH;
|
scanline[0][EXP] = BUFFER_FETCH( buffer );
|
||||||
if( scanline[0][GRN] != 2 ||
|
if( scanline[0][GRN] != 2 ||
|
||||||
scanline[0][BLU] & 128 )
|
scanline[0][BLU] & 128 )
|
||||||
return( scanline_read_old( scanline + 1, width - 1 ) );
|
return( scanline_read_old( buffer, scanline + 1, width - 1 ) );
|
||||||
|
|
||||||
if( ((scanline[0][BLU] << 8) | scanline[0][EXP]) != width ) {
|
if( ((scanline[0][BLU] << 8) | scanline[0][EXP]) != width ) {
|
||||||
vips_error( "rad2vips", "%s", _( "scanline length mismatch" ) );
|
vips_error( "rad2vips", "%s", _( "scanline length mismatch" ) );
|
||||||
@ -740,10 +762,10 @@ scanline_read( COLR *scanline, int width )
|
|||||||
int code, len;
|
int code, len;
|
||||||
gboolean run;
|
gboolean run;
|
||||||
|
|
||||||
if( buffer_need( 2 ) )
|
if( buffer_need( buffer, 2 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
code = BUFFER_FETCH;
|
code = BUFFER_FETCH( buffer );
|
||||||
run = code > 128;
|
run = code > 128;
|
||||||
len = run ? code & 127 : code;
|
len = run ? code & 127 : code;
|
||||||
|
|
||||||
@ -755,15 +777,16 @@ scanline_read( COLR *scanline, int width )
|
|||||||
if( run ) {
|
if( run ) {
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
val = BUFFER_FETCH;
|
val = BUFFER_FETCH( buffer );
|
||||||
while( len-- )
|
while( len-- )
|
||||||
scanline[j++][i] = val;
|
scanline[j++][i] = val;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( buffer_need( len ) )
|
if( buffer_need( buffer, len ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
while( len-- )
|
while( len-- )
|
||||||
scanline[j++][i] = BUFFER_FETCH;
|
scanline[j++][i] =
|
||||||
|
BUFFER_FETCH( buffer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,6 +884,7 @@ typedef struct {
|
|||||||
double aspect;
|
double aspect;
|
||||||
RGBPRIMS prims;
|
RGBPRIMS prims;
|
||||||
RESOLU rs;
|
RESOLU rs;
|
||||||
|
Buffer *buffer;
|
||||||
} Read;
|
} Read;
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -888,7 +912,7 @@ read_destroy( VipsObject *object, Read *read )
|
|||||||
{
|
{
|
||||||
VIPS_FREE( read->filename );
|
VIPS_FREE( read->filename );
|
||||||
VIPS_FREEF( fclose, read->fin );
|
VIPS_FREEF( fclose, read->fin );
|
||||||
buffer_init( NULL );
|
VIPS_FREEF( buffer_free, read->buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
static Read *
|
static Read *
|
||||||
@ -920,9 +944,9 @@ read_new( const char *filename, VipsImage *out )
|
|||||||
g_signal_connect( out, "close",
|
g_signal_connect( out, "close",
|
||||||
G_CALLBACK( read_destroy ), read );
|
G_CALLBACK( read_destroy ), read );
|
||||||
|
|
||||||
if( !(read->fin = vips__file_open_read( filename, NULL, FALSE )) )
|
if( !(read->fin = vips__file_open_read( filename, NULL, FALSE )) ||
|
||||||
|
!(read->buffer = buffer_new( read->fin )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
buffer_init( read->fin );
|
|
||||||
|
|
||||||
return( read );
|
return( read );
|
||||||
}
|
}
|
||||||
@ -1037,24 +1061,30 @@ rad2vips_generate( VipsRegion *or,
|
|||||||
void *seq, void *a, void *b, gboolean *stop )
|
void *seq, void *a, void *b, gboolean *stop )
|
||||||
{
|
{
|
||||||
VipsRect *r = &or->valid;
|
VipsRect *r = &or->valid;
|
||||||
|
Read *read = (Read *) a;
|
||||||
|
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "rad2vips_get_data\n" );
|
printf( "rad2vips_generate: line %d, %d rows\n",
|
||||||
|
r->top, r->height );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
VIPS_GATE_START( "rad2vips_generate: work" );
|
||||||
|
|
||||||
for( y = 0; y < r->height; y++ ) {
|
for( y = 0; y < r->height; y++ ) {
|
||||||
COLR *buf = (COLR *)
|
COLR *buf = (COLR *)
|
||||||
VIPS_REGION_ADDR( or, 0, r->top + y );
|
VIPS_REGION_ADDR( or, 0, r->top + y );
|
||||||
|
|
||||||
if( scanline_read( buf, or->im->Xsize ) ) {
|
if( scanline_read( read->buffer, buf, or->im->Xsize ) ) {
|
||||||
vips_error( "rad2vips",
|
vips_error( "rad2vips",
|
||||||
_( "read error line %d" ), r->top + y );
|
_( "read error line %d" ), r->top + y );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VIPS_GATE_STOP( "rad2vips_generate: work" );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,8 @@ int vips__tiff_write( VipsImage *in, const char *filename,
|
|||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
gboolean squash,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff );
|
gboolean bigtiff,
|
||||||
|
gboolean rgbjpeg );
|
||||||
|
|
||||||
int vips__tiff_read( const char *filename, VipsImage *out, int page,
|
int vips__tiff_read( const char *filename, VipsImage *out, int page,
|
||||||
gboolean readbehind );
|
gboolean readbehind );
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
* - wrap a class around the tiff writer
|
* - wrap a class around the tiff writer
|
||||||
* 17/3/12
|
* 17/3/12
|
||||||
* - argh xres/yres macro was wrong
|
* - argh xres/yres macro was wrong
|
||||||
|
* 26/1/14
|
||||||
|
* - add rgbjpeg flag
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -75,6 +77,7 @@ typedef struct _VipsForeignSaveTiff {
|
|||||||
double xres;
|
double xres;
|
||||||
double yres;
|
double yres;
|
||||||
gboolean bigtiff;
|
gboolean bigtiff;
|
||||||
|
gboolean rgbjpeg;
|
||||||
} VipsForeignSaveTiff;
|
} VipsForeignSaveTiff;
|
||||||
|
|
||||||
typedef VipsForeignSaveClass VipsForeignSaveTiffClass;
|
typedef VipsForeignSaveClass VipsForeignSaveTiffClass;
|
||||||
@ -123,7 +126,8 @@ vips_foreign_save_tiff_build( VipsObject *object )
|
|||||||
tiff->pyramid,
|
tiff->pyramid,
|
||||||
tiff->squash,
|
tiff->squash,
|
||||||
tiff->resunit, tiff->xres, tiff->yres,
|
tiff->resunit, tiff->xres, tiff->yres,
|
||||||
tiff->bigtiff ) )
|
tiff->bigtiff,
|
||||||
|
tiff->rgbjpeg ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -249,6 +253,13 @@ vips_foreign_save_tiff_class_init( VipsForeignSaveTiffClass *class )
|
|||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveTiff, bigtiff ),
|
G_STRUCT_OFFSET( VipsForeignSaveTiff, bigtiff ),
|
||||||
FALSE );
|
FALSE );
|
||||||
|
|
||||||
|
VIPS_ARG_BOOL( class, "rgbjpeg", 20,
|
||||||
|
_( "RGB JPEG" ),
|
||||||
|
_( "Output RGB JPEG rather than YCbCr" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveTiff, rgbjpeg ),
|
||||||
|
FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -136,6 +136,8 @@
|
|||||||
* 24/9/13
|
* 24/9/13
|
||||||
* - support many more vips formats, eg. complex, 32-bit int, any number
|
* - support many more vips formats, eg. complex, 32-bit int, any number
|
||||||
* of bands, etc., see the tiff loader
|
* of bands, etc., see the tiff loader
|
||||||
|
* 26/1/14
|
||||||
|
* - add RGB as well as YCbCr write
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -261,6 +263,7 @@ typedef struct tiff_write {
|
|||||||
float yres; /* Resolution in Y */
|
float yres; /* Resolution in Y */
|
||||||
char *icc_profile; /* Profile to embed */
|
char *icc_profile; /* Profile to embed */
|
||||||
int bigtiff; /* True for bigtiff write */
|
int bigtiff; /* True for bigtiff write */
|
||||||
|
int rgbjpeg; /* True for RGB not YCbCr */
|
||||||
|
|
||||||
GMutex *write_lock; /* Lock TIFF*() calls with this */
|
GMutex *write_lock; /* Lock TIFF*() calls with this */
|
||||||
} TiffWrite;
|
} TiffWrite;
|
||||||
@ -529,7 +532,8 @@ write_tiff_header( TiffWrite *tw, TIFF *tif, int width, int height )
|
|||||||
}
|
}
|
||||||
else if( tw->compression == COMPRESSION_JPEG &&
|
else if( tw->compression == COMPRESSION_JPEG &&
|
||||||
tw->im->Bands == 3 &&
|
tw->im->Bands == 3 &&
|
||||||
tw->im->BandFmt == VIPS_FORMAT_UCHAR ) {
|
tw->im->BandFmt == VIPS_FORMAT_UCHAR &&
|
||||||
|
!tw->rgbjpeg ) {
|
||||||
/* This signals to libjpeg that it can do
|
/* This signals to libjpeg that it can do
|
||||||
* YCbCr chrominance subsampling from RGB, not
|
* YCbCr chrominance subsampling from RGB, not
|
||||||
* that we will supply the image as YCbCr.
|
* that we will supply the image as YCbCr.
|
||||||
@ -1291,7 +1295,8 @@ make_tiff_write( VipsImage *im, const char *filename,
|
|||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
gboolean squash,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff )
|
gboolean bigtiff,
|
||||||
|
gboolean rgbjpeg )
|
||||||
{
|
{
|
||||||
TiffWrite *tw;
|
TiffWrite *tw;
|
||||||
|
|
||||||
@ -1313,6 +1318,7 @@ make_tiff_write( VipsImage *im, const char *filename,
|
|||||||
tw->onebit = squash;
|
tw->onebit = squash;
|
||||||
tw->icc_profile = profile;
|
tw->icc_profile = profile;
|
||||||
tw->bigtiff = bigtiff;
|
tw->bigtiff = bigtiff;
|
||||||
|
tw->rgbjpeg = rgbjpeg;
|
||||||
tw->write_lock = NULL;
|
tw->write_lock = NULL;
|
||||||
|
|
||||||
tw->resunit = get_resunit( resunit );
|
tw->resunit = get_resunit( resunit );
|
||||||
@ -1531,7 +1537,8 @@ vips__tiff_write( VipsImage *in, const char *filename,
|
|||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
gboolean squash,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff )
|
gboolean bigtiff,
|
||||||
|
gboolean rgbjpeg )
|
||||||
{
|
{
|
||||||
TiffWrite *tw;
|
TiffWrite *tw;
|
||||||
int res;
|
int res;
|
||||||
@ -1553,7 +1560,7 @@ vips__tiff_write( VipsImage *in, const char *filename,
|
|||||||
if( !(tw = make_tiff_write( in, filename,
|
if( !(tw = make_tiff_write( in, filename,
|
||||||
compression, Q, predictor, profile,
|
compression, Q, predictor, profile,
|
||||||
tile, tile_width, tile_height, pyramid, squash,
|
tile, tile_width, tile_height, pyramid, squash,
|
||||||
resunit, xres, yres, bigtiff )) )
|
resunit, xres, yres, bigtiff, rgbjpeg )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( tw->pyramid ) {
|
if( tw->pyramid ) {
|
||||||
if( !(tw->bname = vips__temp_name( "%s.tif" )) ||
|
if( !(tw->bname = vips__temp_name( "%s.tif" )) ||
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
#include "pfreqfilt.h"
|
#include "pfreqfilt.h"
|
||||||
|
|
||||||
#ifdef HAVE_FFTW
|
#ifdef HAVE_FFTW
|
||||||
@ -294,22 +295,30 @@ vips_fwfft_build( VipsObject *object )
|
|||||||
VipsFwfft *fwfft = (VipsFwfft *) object;
|
VipsFwfft *fwfft = (VipsFwfft *) object;
|
||||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 );
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 );
|
||||||
|
|
||||||
|
VipsImage *in;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_fwfft_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_fwfft_parent_class )->
|
||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_bandfmt_iscomplex( freqfilt->in->BandFmt ) ) {
|
in = freqfilt->in;
|
||||||
if( vips__fftproc( VIPS_OBJECT( fwfft ), freqfilt->in, &t[0],
|
|
||||||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
|
if( vips_bandfmt_iscomplex( in->BandFmt ) ) {
|
||||||
|
if( vips__fftproc( VIPS_OBJECT( fwfft ), in, &t[1],
|
||||||
cfwfft1 ) )
|
cfwfft1 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( vips__fftproc( VIPS_OBJECT( fwfft ), freqfilt->in, &t[0],
|
if( vips__fftproc( VIPS_OBJECT( fwfft ), in, &t[1],
|
||||||
rfwfft1 ) )
|
rfwfft1 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( vips_image_write( t[0], freqfilt->out ) )
|
if( vips_image_write( t[1], freqfilt->out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
#include "pfreqfilt.h"
|
#include "pfreqfilt.h"
|
||||||
|
|
||||||
#ifdef HAVE_FFTW
|
#ifdef HAVE_FFTW
|
||||||
@ -207,22 +208,30 @@ vips_invfft_build( VipsObject *object )
|
|||||||
VipsInvfft *invfft = (VipsInvfft *) object;
|
VipsInvfft *invfft = (VipsInvfft *) object;
|
||||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 );
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 );
|
||||||
|
|
||||||
|
VipsImage *in;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_invfft_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_invfft_parent_class )->
|
||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
in = freqfilt->in;
|
||||||
|
|
||||||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
if( invfft->real ) {
|
if( invfft->real ) {
|
||||||
if( vips__fftproc( VIPS_OBJECT( invfft ),
|
if( vips__fftproc( VIPS_OBJECT( invfft ),
|
||||||
freqfilt->in, &t[0], rinvfft1 ) )
|
in, &t[1], rinvfft1 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( vips__fftproc( VIPS_OBJECT( invfft ),
|
if( vips__fftproc( VIPS_OBJECT( invfft ),
|
||||||
freqfilt->in, &t[0], cinvfft1 ) )
|
in, &t[1], cinvfft1 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( vips_image_write( t[0], freqfilt->out ) )
|
if( vips_image_write( t[1], freqfilt->out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
typedef struct _VipsHistLocal {
|
typedef struct _VipsHistLocal {
|
||||||
VipsOperation parent_instance;
|
VipsOperation parent_instance;
|
||||||
@ -235,8 +236,11 @@ vips_hist_local_build( VipsObject *object )
|
|||||||
|
|
||||||
in = local->in;
|
in = local->in;
|
||||||
|
|
||||||
if( vips_check_uncoded( class->nickname, in ) ||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
|
if( vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( local->width > in->Xsize ||
|
if( local->width > in->Xsize ||
|
||||||
@ -247,13 +251,13 @@ vips_hist_local_build( VipsObject *object )
|
|||||||
|
|
||||||
/* Expand the input.
|
/* Expand the input.
|
||||||
*/
|
*/
|
||||||
if( vips_embed( in, &t[0],
|
if( vips_embed( in, &t[1],
|
||||||
local->width / 2, local->height / 2,
|
local->width / 2, local->height / 2,
|
||||||
in->Xsize + local->width - 1, in->Ysize + local->height - 1,
|
in->Xsize + local->width - 1, in->Ysize + local->height - 1,
|
||||||
"extend", VIPS_EXTEND_COPY,
|
"extend", VIPS_EXTEND_COPY,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[0];
|
in = t[1];
|
||||||
|
|
||||||
g_object_set( object, "out", vips_image_new(), NULL );
|
g_object_set( object, "out", vips_image_new(), NULL );
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ vips_histogram_build( VipsObject *object )
|
|||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsHistogramClass *hclass = VIPS_HISTOGRAM_GET_CLASS( histogram );
|
VipsHistogramClass *hclass = VIPS_HISTOGRAM_GET_CLASS( histogram );
|
||||||
|
|
||||||
|
VipsImage **decode;
|
||||||
VipsImage **format;
|
VipsImage **format;
|
||||||
VipsImage **band;
|
VipsImage **band;
|
||||||
VipsImage **size;
|
VipsImage **size;
|
||||||
@ -134,6 +135,7 @@ vips_histogram_build( VipsObject *object )
|
|||||||
*/
|
*/
|
||||||
g_assert( !histogram->in[histogram->n] );
|
g_assert( !histogram->in[histogram->n] );
|
||||||
|
|
||||||
|
decode = (VipsImage **) vips_object_local_array( object, histogram->n );
|
||||||
format = (VipsImage **) vips_object_local_array( object, histogram->n );
|
format = (VipsImage **) vips_object_local_array( object, histogram->n );
|
||||||
band = (VipsImage **) vips_object_local_array( object, histogram->n );
|
band = (VipsImage **) vips_object_local_array( object, histogram->n );
|
||||||
size = (VipsImage **) vips_object_local_array( object, histogram->n );
|
size = (VipsImage **) vips_object_local_array( object, histogram->n );
|
||||||
@ -141,8 +143,8 @@ vips_histogram_build( VipsObject *object )
|
|||||||
g_object_set( histogram, "out", vips_image_new(), NULL );
|
g_object_set( histogram, "out", vips_image_new(), NULL );
|
||||||
|
|
||||||
for( i = 0; i < histogram->n; i++ )
|
for( i = 0; i < histogram->n; i++ )
|
||||||
if( vips_check_uncoded( class->nickname, histogram->in[i] ) ||
|
if( vips__image_decode( histogram->in[i], &decode[i] ) ||
|
||||||
vips_check_hist( class->nickname, histogram->in[i] ) )
|
vips_check_hist( class->nickname, decode[i] ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Cast our input images up to a common format, bands and size. If
|
/* Cast our input images up to a common format, bands and size. If
|
||||||
@ -150,13 +152,12 @@ vips_histogram_build( VipsObject *object )
|
|||||||
*/
|
*/
|
||||||
if( hclass->input_format != VIPS_FORMAT_NOTSET ) {
|
if( hclass->input_format != VIPS_FORMAT_NOTSET ) {
|
||||||
for( i = 0; i < histogram->n; i++ )
|
for( i = 0; i < histogram->n; i++ )
|
||||||
if( vips_cast( histogram->in[i], &format[i],
|
if( vips_cast( decode[i], &format[i],
|
||||||
hclass->input_format, NULL ) )
|
hclass->input_format, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( vips__formatalike_vec( histogram->in,
|
if( vips__formatalike_vec( decode, format, histogram->n ) )
|
||||||
format, histogram->n ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
typedef struct _VipsStdif {
|
typedef struct _VipsStdif {
|
||||||
VipsOperation parent_instance;
|
VipsOperation parent_instance;
|
||||||
@ -223,8 +224,11 @@ vips_stdif_build( VipsObject *object )
|
|||||||
|
|
||||||
in = stdif->in;
|
in = stdif->in;
|
||||||
|
|
||||||
if( vips_check_uncoded( class->nickname, in ) ||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
|
if( vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( stdif->width > in->Xsize ||
|
if( stdif->width > in->Xsize ||
|
||||||
@ -239,13 +243,13 @@ vips_stdif_build( VipsObject *object )
|
|||||||
|
|
||||||
/* Expand the input.
|
/* Expand the input.
|
||||||
*/
|
*/
|
||||||
if( vips_embed( in, &t[0],
|
if( vips_embed( in, &t[1],
|
||||||
stdif->width / 2, stdif->height / 2,
|
stdif->width / 2, stdif->height / 2,
|
||||||
in->Xsize + stdif->width - 1, in->Ysize + stdif->height - 1,
|
in->Xsize + stdif->width - 1, in->Ysize + stdif->height - 1,
|
||||||
"extend", VIPS_EXTEND_COPY,
|
"extend", VIPS_EXTEND_COPY,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[0];
|
in = t[1];
|
||||||
|
|
||||||
g_object_set( object, "out", vips_image_new(), NULL );
|
g_object_set( object, "out", vips_image_new(), NULL );
|
||||||
|
|
||||||
|
@ -298,6 +298,8 @@ IMAGE *vips__deprecated_open_write( const char *filename );
|
|||||||
|
|
||||||
int vips__input_interpolate_init( im_object *obj, char *str );
|
int vips__input_interpolate_init( im_object *obj, char *str );
|
||||||
|
|
||||||
|
int vips__image_decode( VipsImage *in, VipsImage **out );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
@ -55,34 +55,6 @@ typedef struct _VipsObjectClass VipsObjectClass;
|
|||||||
/* Track extra stuff for arguments to objects
|
/* Track extra stuff for arguments to objects
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* VipsArgumentFlags:
|
|
||||||
* @VIPS_ARGUMENT_NONE: no flags
|
|
||||||
* @VIPS_ARGUMENT_REQUIRED: must be set in the constructor
|
|
||||||
* @VIPS_ARGUMENT_CONSTRUCT: can only be set in the constructor
|
|
||||||
* @VIPS_ARGUMENT_SET_ONCE: can only be set once
|
|
||||||
* @VIPS_ARGUMENT_SET_ALWAYS: don't do use-before-set checks
|
|
||||||
* @VIPS_ARGUMENT_INPUT: is an input argument (one we depend on)
|
|
||||||
* @VIPS_ARGUMENT_OUTPUT: is an output argument (depends on us)
|
|
||||||
* @VIPS_ARGUMENT_DEPRECATED: just there for back-compat, hide
|
|
||||||
*
|
|
||||||
* Flags we associate with each object argument.
|
|
||||||
*
|
|
||||||
* Have separate input & output flags. Both set is an error; neither set is OK.
|
|
||||||
*
|
|
||||||
* Input gobjects are automatically reffed, output gobjects automatically ref
|
|
||||||
* us. We also automatically watch for "destroy" and unlink.
|
|
||||||
*
|
|
||||||
* @VIPS_ARGUMENT_SET_ALWAYS is handy for arguments which are set from C. For
|
|
||||||
* example, VipsImage::width is a property that gives access to the Xsize
|
|
||||||
* member of struct _VipsImage. We default its 'assigned' to TRUE
|
|
||||||
* since the field is always set directly by C.
|
|
||||||
*
|
|
||||||
* @VIPS_ARGUMENT_DEPRECATED arguments are not shown in help text, are not
|
|
||||||
* looked for if required, are not checked for "have-been-set". You can
|
|
||||||
* deprecate a required argument, but you must obviously add a new required
|
|
||||||
* argument if you do.
|
|
||||||
*/
|
|
||||||
typedef enum /*< flags >*/ {
|
typedef enum /*< flags >*/ {
|
||||||
VIPS_ARGUMENT_NONE = 0,
|
VIPS_ARGUMENT_NONE = 0,
|
||||||
VIPS_ARGUMENT_REQUIRED = 1,
|
VIPS_ARGUMENT_REQUIRED = 1,
|
||||||
@ -461,6 +433,7 @@ struct _VipsObject {
|
|||||||
* profiling.
|
* profiling.
|
||||||
*/
|
*/
|
||||||
size_t local_memory;
|
size_t local_memory;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _VipsObjectClass {
|
struct _VipsObjectClass {
|
||||||
@ -561,6 +534,13 @@ struct _VipsObjectClass {
|
|||||||
*/
|
*/
|
||||||
GSList *argument_table_traverse;
|
GSList *argument_table_traverse;
|
||||||
GType argument_table_traverse_gtype;
|
GType argument_table_traverse_gtype;
|
||||||
|
|
||||||
|
/* Reserved for future expansion.
|
||||||
|
*/
|
||||||
|
void (*_vips_reserved1)( void );
|
||||||
|
void (*_vips_reserved2)( void );
|
||||||
|
void (*_vips_reserved3)( void );
|
||||||
|
void (*_vips_reserved4)( void );
|
||||||
};
|
};
|
||||||
|
|
||||||
gboolean vips_value_is_null( GParamSpec *psoec, const GValue *value );
|
gboolean vips_value_is_null( GParamSpec *psoec, const GValue *value );
|
||||||
|
@ -41,7 +41,8 @@ typedef enum /*< flags >*/ {
|
|||||||
VIPS_OPERATION_NONE = 0,
|
VIPS_OPERATION_NONE = 0,
|
||||||
VIPS_OPERATION_SEQUENTIAL = 1,
|
VIPS_OPERATION_SEQUENTIAL = 1,
|
||||||
VIPS_OPERATION_SEQUENTIAL_UNBUFFERED = 2,
|
VIPS_OPERATION_SEQUENTIAL_UNBUFFERED = 2,
|
||||||
VIPS_OPERATION_NOCACHE = 4
|
VIPS_OPERATION_NOCACHE = 4,
|
||||||
|
VIPS_OPERATION_DEPRECATED = 8
|
||||||
} VipsOperationFlags;
|
} VipsOperationFlags;
|
||||||
|
|
||||||
#define VIPS_TYPE_OPERATION (vips_operation_get_type())
|
#define VIPS_TYPE_OPERATION (vips_operation_get_type())
|
||||||
|
@ -89,8 +89,8 @@ typedef struct {
|
|||||||
GThread *thread; /* Just for sanity checking */
|
GThread *thread; /* Just for sanity checking */
|
||||||
} VipsBufferThread;
|
} VipsBufferThread;
|
||||||
|
|
||||||
/* Per-image buffer cache. Hash to this from VipsBufferCache.
|
/* Per-image buffer cache. Hash to this from VipsBufferThread::hash.
|
||||||
* We can't store the GSList directly in the hash table, as GHashTable lacks an
|
* We can't store the GSList directly in the hash table as GHashTable lacks an
|
||||||
* update operation and we'd need to _remove() and _insert() on every list
|
* update operation and we'd need to _remove() and _insert() on every list
|
||||||
* operation.
|
* operation.
|
||||||
*/
|
*/
|
||||||
@ -127,6 +127,8 @@ VipsBuffer *vips_buffer_unref_ref( VipsBuffer *buffer,
|
|||||||
struct _VipsImage *im, VipsRect *area );
|
struct _VipsImage *im, VipsRect *area );
|
||||||
void vips_buffer_print( VipsBuffer *buffer );
|
void vips_buffer_print( VipsBuffer *buffer );
|
||||||
|
|
||||||
|
void vips__render_shutdown( void );
|
||||||
|
|
||||||
/* Sections of region.h that are private to VIPS.
|
/* Sections of region.h that are private to VIPS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -120,6 +120,8 @@ int vips_region_prepare_to( VipsRegion *reg,
|
|||||||
VipsRegion *dest, VipsRect *r, int x, int y );
|
VipsRegion *dest, VipsRect *r, int x, int y );
|
||||||
int vips_region_prepare_many( VipsRegion **reg, VipsRect *r );
|
int vips_region_prepare_many( VipsRegion **reg, VipsRect *r );
|
||||||
|
|
||||||
|
void vips_region_invalidate( VipsRegion *reg );
|
||||||
|
|
||||||
void vips_region_dump_all( void );
|
void vips_region_dump_all( void );
|
||||||
|
|
||||||
/* Macros on VipsRegion.
|
/* Macros on VipsRegion.
|
||||||
|
@ -50,10 +50,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#define DEBUG_CREATE
|
|
||||||
#define DEBUG_VERBOSE
|
#define DEBUG_VERBOSE
|
||||||
#define DEBUG
|
#define DEBUG_CREATE
|
||||||
*/
|
*/
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -70,11 +70,11 @@
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/* Track all regions here for debugging.
|
/* Track all regions here for debugging.
|
||||||
*/
|
*/
|
||||||
static GSList *vips__buffers_all = NULL;
|
static GSList *vips__buffer_all = NULL;
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
#ifdef DEBUG_CREATE
|
#ifdef DEBUG_CREATE
|
||||||
static int buffer_cache_n = 0;
|
static GSList *vips__buffer_cache_all = NULL;
|
||||||
#endif /*DEBUG_CREATE*/
|
#endif /*DEBUG_CREATE*/
|
||||||
|
|
||||||
/* The maximum numbers of buffers we hold in reserve per image.
|
/* The maximum numbers of buffers we hold in reserve per image.
|
||||||
@ -87,13 +87,19 @@ static GPrivate *buffer_thread_key = NULL;
|
|||||||
static void *
|
static void *
|
||||||
vips_buffer_dump( VipsBuffer *buffer, size_t *reserve, size_t *alive )
|
vips_buffer_dump( VipsBuffer *buffer, size_t *reserve, size_t *alive )
|
||||||
{
|
{
|
||||||
|
vips_buffer_print( buffer );
|
||||||
|
|
||||||
if( buffer->im &&
|
if( buffer->im &&
|
||||||
buffer->buf ) {
|
buffer->buf &&
|
||||||
printf( "buffer %p, %gMB\n",
|
buffer->cache ) {
|
||||||
|
printf( "buffer %p, %.3g MB\n",
|
||||||
buffer, buffer->bsize / (1024 * 1024.0) );
|
buffer, buffer->bsize / (1024 * 1024.0) );
|
||||||
*alive += buffer->bsize;
|
*alive += buffer->bsize;
|
||||||
}
|
}
|
||||||
else if( !buffer->im )
|
else
|
||||||
|
if( buffer->im &&
|
||||||
|
buffer->buf &&
|
||||||
|
!buffer->cache )
|
||||||
*reserve += buffer->bsize;
|
*reserve += buffer->bsize;
|
||||||
else
|
else
|
||||||
printf( "buffer craziness!\n" );
|
printf( "buffer craziness!\n" );
|
||||||
@ -101,18 +107,47 @@ vips_buffer_dump( VipsBuffer *buffer, size_t *reserve, size_t *alive )
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CREATE
|
||||||
|
static void *
|
||||||
|
vips_buffer_cache_dump( VipsBufferCache *cache )
|
||||||
|
{
|
||||||
|
printf( "VipsBufferCache: %p\n", cache );
|
||||||
|
printf( "\t%d buffers\n", g_slist_length( cache->buffers ) );
|
||||||
|
printf( "\tthread %p\n", cache->thread );
|
||||||
|
printf( "\timage %p\n", cache->im );
|
||||||
|
printf( "\tbuffer_thread %p\n", cache->buffer_thread );
|
||||||
|
printf( "\t%d in reserve\n", g_slist_length( cache->reserve ) );
|
||||||
|
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
#endif /*DEBUG_CREATE*/
|
||||||
|
|
||||||
void
|
void
|
||||||
vips_buffer_dump_all( void )
|
vips_buffer_dump_all( void )
|
||||||
{
|
{
|
||||||
size_t reserve;
|
if( vips__buffer_all ) {
|
||||||
size_t alive;
|
size_t reserve;
|
||||||
|
size_t alive;
|
||||||
|
|
||||||
reserve = 0;
|
printf( "buffers:\n" );
|
||||||
alive = 0;
|
|
||||||
vips_slist_map2( vips__buffers_all,
|
reserve = 0;
|
||||||
(VipsSListMap2Fn) vips_buffer_dump, &reserve, &alive );
|
alive = 0;
|
||||||
printf( "%gMB alive\n", alive / (1024 * 1024.0) );
|
vips_slist_map2( vips__buffer_all,
|
||||||
printf( "%gMB in reserve\n", reserve / (1024 * 1024.0) );
|
(VipsSListMap2Fn) vips_buffer_dump, &reserve, &alive );
|
||||||
|
printf( "%.3g MB alive\n", alive / (1024 * 1024.0) );
|
||||||
|
printf( "%.3g MB in reserve\n", reserve / (1024 * 1024.0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CREATE
|
||||||
|
if( vips__buffer_cache_all ) {
|
||||||
|
printf( "buffers: %d buffer cache still alive\n",
|
||||||
|
g_slist_length( vips__buffer_cache_all ) );
|
||||||
|
vips_slist_map2( vips__buffer_cache_all,
|
||||||
|
(VipsSListMap2Fn) vips_buffer_cache_dump, NULL, NULL );
|
||||||
|
printf( "g_thread_self() == %p\n", g_thread_self() );
|
||||||
|
}
|
||||||
|
#endif /*DEBUG_CREATE*/
|
||||||
}
|
}
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
@ -126,8 +161,8 @@ vips_buffer_free( VipsBuffer *buffer )
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
g_mutex_lock( vips__global_lock );
|
g_mutex_lock( vips__global_lock );
|
||||||
|
|
||||||
g_assert( g_slist_find( vips__buffers_all, buffer ) );
|
g_assert( g_slist_find( vips__buffer_all, buffer ) );
|
||||||
vips__buffers_all = g_slist_remove( vips__buffers_all, buffer );
|
vips__buffer_all = g_slist_remove( vips__buffer_all, buffer );
|
||||||
|
|
||||||
g_mutex_unlock( vips__global_lock );
|
g_mutex_unlock( vips__global_lock );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
@ -146,11 +181,15 @@ buffer_cache_free( VipsBufferCache *cache )
|
|||||||
GSList *p;
|
GSList *p;
|
||||||
|
|
||||||
#ifdef DEBUG_CREATE
|
#ifdef DEBUG_CREATE
|
||||||
buffer_cache_n -= 1;
|
g_mutex_lock( vips__global_lock );
|
||||||
|
vips__buffer_cache_all =
|
||||||
|
g_slist_remove( vips__buffer_cache_all, cache );
|
||||||
|
g_mutex_unlock( vips__global_lock );
|
||||||
|
|
||||||
printf( "buffer_cache_free: freeing cache %p on thread %p\n",
|
printf( "buffer_cache_free: freeing cache %p on thread %p\n",
|
||||||
cache, g_thread_self() );
|
cache, g_thread_self() );
|
||||||
printf( "\t(%d caches left)\n", buffer_cache_n );
|
printf( "\t(%d caches left)\n",
|
||||||
|
g_slist_length( vips__buffer_cache_all ) );
|
||||||
#endif /*DEBUG_CREATE*/
|
#endif /*DEBUG_CREATE*/
|
||||||
|
|
||||||
/* Need to mark undone so we don't try and take them off this hash on
|
/* Need to mark undone so we don't try and take them off this hash on
|
||||||
@ -187,11 +226,15 @@ buffer_cache_new( VipsBufferThread *buffer_thread, VipsImage *im )
|
|||||||
cache->n_reserve = 0;
|
cache->n_reserve = 0;
|
||||||
|
|
||||||
#ifdef DEBUG_CREATE
|
#ifdef DEBUG_CREATE
|
||||||
buffer_cache_n += 1;
|
g_mutex_lock( vips__global_lock );
|
||||||
|
vips__buffer_cache_all =
|
||||||
|
g_slist_prepend( vips__buffer_cache_all, cache );
|
||||||
|
g_mutex_unlock( vips__global_lock );
|
||||||
|
|
||||||
printf( "buffer_cache_new: new cache %p for thread %p\n",
|
printf( "buffer_cache_new: new cache %p for thread %p\n",
|
||||||
cache, g_thread_self() );
|
cache, g_thread_self() );
|
||||||
printf( "\t(%d caches now)\n", buffer_cache_n );
|
printf( "\t(%d caches now)\n",
|
||||||
|
g_slist_length( vips__buffer_cache_all ) );
|
||||||
#endif /*DEBUG_CREATE*/
|
#endif /*DEBUG_CREATE*/
|
||||||
|
|
||||||
return( cache );
|
return( cache );
|
||||||
@ -276,7 +319,6 @@ vips_buffer_undone( VipsBuffer *buffer )
|
|||||||
{
|
{
|
||||||
if( buffer->done ) {
|
if( buffer->done ) {
|
||||||
VipsBufferCache *cache = buffer->cache;
|
VipsBufferCache *cache = buffer->cache;
|
||||||
VipsBufferThread *buffer_thread = cache->buffer_thread;
|
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#ifdef DEBUG_VERBOSE
|
||||||
printf( "vips_buffer_undone: thread %p removing "
|
printf( "vips_buffer_undone: thread %p removing "
|
||||||
@ -285,9 +327,9 @@ vips_buffer_undone( VipsBuffer *buffer )
|
|||||||
#endif /*DEBUG_VERBOSE*/
|
#endif /*DEBUG_VERBOSE*/
|
||||||
|
|
||||||
g_assert( cache->thread == g_thread_self() );
|
g_assert( cache->thread == g_thread_self() );
|
||||||
g_assert( buffer_thread->thread == cache->thread );
|
g_assert( cache->buffer_thread->thread == cache->thread );
|
||||||
g_assert( g_slist_find( cache->buffers, buffer ) );
|
g_assert( g_slist_find( cache->buffers, buffer ) );
|
||||||
g_assert( buffer_thread == buffer_thread_get() );
|
g_assert( cache->buffer_thread == buffer_thread_get() );
|
||||||
|
|
||||||
cache->buffers = g_slist_remove( cache->buffers, buffer );
|
cache->buffers = g_slist_remove( cache->buffers, buffer );
|
||||||
|
|
||||||
@ -404,8 +446,8 @@ vips_buffer_new( VipsImage *im, VipsRect *area )
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
g_mutex_lock( vips__global_lock );
|
g_mutex_lock( vips__global_lock );
|
||||||
vips__buffers_all =
|
vips__buffer_all =
|
||||||
g_slist_prepend( vips__buffers_all, buffer );
|
g_slist_prepend( vips__buffer_all, buffer );
|
||||||
g_mutex_unlock( vips__global_lock );
|
g_mutex_unlock( vips__global_lock );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
}
|
}
|
||||||
|
@ -624,6 +624,7 @@ vips_operation_flags_get_type( void )
|
|||||||
{VIPS_OPERATION_SEQUENTIAL, "VIPS_OPERATION_SEQUENTIAL", "sequential"},
|
{VIPS_OPERATION_SEQUENTIAL, "VIPS_OPERATION_SEQUENTIAL", "sequential"},
|
||||||
{VIPS_OPERATION_SEQUENTIAL_UNBUFFERED, "VIPS_OPERATION_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"},
|
{VIPS_OPERATION_SEQUENTIAL_UNBUFFERED, "VIPS_OPERATION_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"},
|
||||||
{VIPS_OPERATION_NOCACHE, "VIPS_OPERATION_NOCACHE", "nocache"},
|
{VIPS_OPERATION_NOCACHE, "VIPS_OPERATION_NOCACHE", "nocache"},
|
||||||
|
{VIPS_OPERATION_DEPRECATED, "VIPS_OPERATION_DEPRECATED", "deprecated"},
|
||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -937,6 +937,7 @@ vips_image_build( VipsObject *object )
|
|||||||
image->Type = VIPS_INTERPRETATION_MULTIBAND;
|
image->Type = VIPS_INTERPRETATION_MULTIBAND;
|
||||||
|
|
||||||
image->dtype = VIPS_IMAGE_SETBUF_FOREIGN;
|
image->dtype = VIPS_IMAGE_SETBUF_FOREIGN;
|
||||||
|
image->dhint = VIPS_DEMAND_STYLE_ANY;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -952,9 +953,9 @@ vips_image_build( VipsObject *object )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
vips_region_invalidate( VipsRegion *reg )
|
vips_image_real_invalidate_cb( VipsRegion *reg )
|
||||||
{
|
{
|
||||||
reg->invalid = TRUE;
|
vips_region_invalidate( reg );
|
||||||
|
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
@ -971,7 +972,7 @@ vips_image_real_invalidate( VipsImage *image )
|
|||||||
VIPS_GATE_STOP( "vips_image_real_invalidate: wait" );
|
VIPS_GATE_STOP( "vips_image_real_invalidate: wait" );
|
||||||
|
|
||||||
(void) vips_slist_map2( image->regions,
|
(void) vips_slist_map2( image->regions,
|
||||||
(VipsSListMap2Fn) vips_region_invalidate, NULL, NULL );
|
(VipsSListMap2Fn) vips_image_real_invalidate_cb, NULL, NULL );
|
||||||
|
|
||||||
g_mutex_unlock( image->sslock );
|
g_mutex_unlock( image->sslock );
|
||||||
}
|
}
|
||||||
@ -1273,6 +1274,8 @@ vips_image_invalidate_all_cb( VipsImage *image )
|
|||||||
* is, images which depend on this image.
|
* is, images which depend on this image.
|
||||||
*
|
*
|
||||||
* The "invalidate" callback is triggered for all invalidated images.
|
* The "invalidate" callback is triggered for all invalidated images.
|
||||||
|
*
|
||||||
|
* See also: vips_region_invalidate().
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vips_image_invalidate_all( VipsImage *image )
|
vips_image_invalidate_all( VipsImage *image )
|
||||||
|
@ -369,6 +369,10 @@ vips_leak( void )
|
|||||||
fprintf( stderr, "%s", vips_buf_all( &buf ) );
|
fprintf( stderr, "%s", vips_buf_all( &buf ) );
|
||||||
|
|
||||||
vips__type_leak();
|
vips__type_leak();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
vips_buffer_dump_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -419,6 +423,8 @@ vips_shutdown( void )
|
|||||||
vips__thread_gate_stop( "init: main" );
|
vips__thread_gate_stop( "init: main" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vips__render_shutdown();
|
||||||
|
|
||||||
vips_thread_shutdown();
|
vips_thread_shutdown();
|
||||||
|
|
||||||
vips__thread_profile_stop();
|
vips__thread_profile_stop();
|
||||||
|
@ -79,6 +79,35 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VipsArgumentFlags:
|
||||||
|
* @VIPS_ARGUMENT_NONE: no flags
|
||||||
|
* @VIPS_ARGUMENT_REQUIRED: must be set in the constructor
|
||||||
|
* @VIPS_ARGUMENT_CONSTRUCT: can only be set in the constructor
|
||||||
|
* @VIPS_ARGUMENT_SET_ONCE: can only be set once
|
||||||
|
* @VIPS_ARGUMENT_SET_ALWAYS: don't do use-before-set checks
|
||||||
|
* @VIPS_ARGUMENT_INPUT: is an input argument (one we depend on)
|
||||||
|
* @VIPS_ARGUMENT_OUTPUT: is an output argument (depends on us)
|
||||||
|
* @VIPS_ARGUMENT_DEPRECATED: just there for back-compat, hide
|
||||||
|
*
|
||||||
|
* Flags we associate with each object argument.
|
||||||
|
*
|
||||||
|
* Have separate input & output flags. Both set is an error; neither set is OK.
|
||||||
|
*
|
||||||
|
* Input gobjects are automatically reffed, output gobjects automatically ref
|
||||||
|
* us. We also automatically watch for "destroy" and unlink.
|
||||||
|
*
|
||||||
|
* @VIPS_ARGUMENT_SET_ALWAYS is handy for arguments which are set from C. For
|
||||||
|
* example, VipsImage::width is a property that gives access to the Xsize
|
||||||
|
* member of struct _VipsImage. We default its 'assigned' to TRUE
|
||||||
|
* since the field is always set directly by C.
|
||||||
|
*
|
||||||
|
* @VIPS_ARGUMENT_DEPRECATED arguments are not shown in help text, are not
|
||||||
|
* looked for if required, are not checked for "have-been-set". You can
|
||||||
|
* deprecate a required argument, but you must obviously add a new required
|
||||||
|
* argument if you do.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Our signals.
|
/* Our signals.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
@ -1708,9 +1737,9 @@ gboolean
|
|||||||
vips_object_argument_needsstring( VipsObject *object, const char *name )
|
vips_object_argument_needsstring( VipsObject *object, const char *name )
|
||||||
{
|
{
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
GType otype;
|
|
||||||
VipsArgumentClass *argument_class;
|
VipsArgumentClass *argument_class;
|
||||||
VipsArgumentInstance *argument_instance;
|
VipsArgumentInstance *argument_instance;
|
||||||
|
GType otype;
|
||||||
VipsObjectClass *oclass;
|
VipsObjectClass *oclass;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -1725,10 +1754,15 @@ vips_object_argument_needsstring( VipsObject *object, const char *name )
|
|||||||
/* Bools, input or output, don't need args.
|
/* Bools, input or output, don't need args.
|
||||||
*/
|
*/
|
||||||
return( FALSE );
|
return( FALSE );
|
||||||
else if( argument_class->flags & VIPS_ARGUMENT_INPUT )
|
|
||||||
|
if( argument_class->flags & VIPS_ARGUMENT_INPUT )
|
||||||
/* All other inputs need something.
|
/* All other inputs need something.
|
||||||
*/
|
*/
|
||||||
return( TRUE );
|
return( TRUE );
|
||||||
|
|
||||||
|
/* Just output objects.
|
||||||
|
*/
|
||||||
|
|
||||||
if( (otype = G_PARAM_SPEC_VALUE_TYPE( pspec )) &&
|
if( (otype = G_PARAM_SPEC_VALUE_TYPE( pspec )) &&
|
||||||
g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||||
(oclass = g_type_class_ref( otype )) )
|
(oclass = g_type_class_ref( otype )) )
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
* @VIPS_OPERATION_NONE: no flags
|
* @VIPS_OPERATION_NONE: no flags
|
||||||
* @VIPS_OPERATION_SEQUENTIAL: can work sequentially
|
* @VIPS_OPERATION_SEQUENTIAL: can work sequentially
|
||||||
* @VIPS_OPERATION_NOCACHE: must not be cached
|
* @VIPS_OPERATION_NOCACHE: must not be cached
|
||||||
|
* @VIPS_OPERATION_DEPRECATED: a compatibility thing
|
||||||
*
|
*
|
||||||
* Flags we associate with an operation.
|
* Flags we associate with an operation.
|
||||||
*
|
*
|
||||||
@ -83,6 +84,9 @@
|
|||||||
*
|
*
|
||||||
* @VIPS_OPERATION_NOCACHE means that the operation must not be cached by
|
* @VIPS_OPERATION_NOCACHE means that the operation must not be cached by
|
||||||
* vips.
|
* vips.
|
||||||
|
*
|
||||||
|
* @VIPS_OPERATION_DEPRECATED means this is an old operation kept in vips for
|
||||||
|
* compatibility only and should be hidden from users.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Abstract base class for operations.
|
/* Abstract base class for operations.
|
||||||
|
@ -1375,6 +1375,25 @@ vips_region_prepare_many( VipsRegion **reg, VipsRect *r )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_region_invalidate:
|
||||||
|
* @reg: region to invalidate
|
||||||
|
*
|
||||||
|
* Mark a region as containing invalid pixels. Calling this function means
|
||||||
|
* that the next time vips_region_prepare() is called, the region will be
|
||||||
|
* recalculated.
|
||||||
|
*
|
||||||
|
* This is faster than calling vips_image_invalidate_all(), but obviously only
|
||||||
|
* affects a single region.
|
||||||
|
*
|
||||||
|
* See also: vips_image_invalidate_all(), vips_region_prepare().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vips_region_invalidate( VipsRegion *reg )
|
||||||
|
{
|
||||||
|
reg->invalid = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef VIPS_DEBUG
|
#ifdef VIPS_DEBUG
|
||||||
static void *
|
static void *
|
||||||
vips_region_dump_all_cb( VipsRegion *region, size_t *alive )
|
vips_region_dump_all_cb( VipsRegion *region, size_t *alive )
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* 25/11/10
|
* 25/11/10
|
||||||
* - in synchronous mode, use a single region for input and save huge
|
* - in synchronous mode, use a single region for input and save huge
|
||||||
* mem use
|
* mem use
|
||||||
|
* 20/1/14
|
||||||
|
* - bg render thread quits on shutdown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -160,6 +162,10 @@ static GThread *render_thread = NULL;
|
|||||||
*/
|
*/
|
||||||
static VipsSemaphore render_dirty_sem;
|
static VipsSemaphore render_dirty_sem;
|
||||||
|
|
||||||
|
/* Set this to ask the render thread to quit.
|
||||||
|
*/
|
||||||
|
static gboolean render_kill = FALSE;
|
||||||
|
|
||||||
/* All the renders with dirty tiles.
|
/* All the renders with dirty tiles.
|
||||||
*/
|
*/
|
||||||
static GMutex *render_dirty_lock = NULL;
|
static GMutex *render_dirty_lock = NULL;
|
||||||
@ -424,6 +430,13 @@ render_work( VipsThreadState *state, void *a )
|
|||||||
}
|
}
|
||||||
tile->painted = TRUE;
|
tile->painted = TRUE;
|
||||||
|
|
||||||
|
/* All downstream images must drop caches, since we've (effectively)
|
||||||
|
* modified render->out.
|
||||||
|
*/
|
||||||
|
vips_image_invalidate_all( render->out );
|
||||||
|
if( render->mask )
|
||||||
|
vips_image_invalidate_all( render->mask );
|
||||||
|
|
||||||
/* Now clients can update.
|
/* Now clients can update.
|
||||||
*/
|
*/
|
||||||
if( render->notify )
|
if( render->notify )
|
||||||
@ -471,44 +484,67 @@ render_dirty_put( Render *render )
|
|||||||
static void *
|
static void *
|
||||||
render_thread_main( void *client )
|
render_thread_main( void *client )
|
||||||
{
|
{
|
||||||
for(;;) {
|
Render *render;
|
||||||
Render *render;
|
|
||||||
|
|
||||||
if( (render = render_dirty_get()) ) {
|
while( (render = render_dirty_get()) &&
|
||||||
/* Ignore errors, I'm not sure what we'd do with them
|
!render_kill ) {
|
||||||
* anyway.
|
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
||||||
*/
|
"threadpool start\n" );
|
||||||
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
|
||||||
"threadpool start\n" );
|
|
||||||
|
|
||||||
render_reschedule = FALSE;
|
render_reschedule = FALSE;
|
||||||
if( vips_threadpool_run( render->in,
|
if( vips_threadpool_run( render->in,
|
||||||
render_thread_state_new,
|
render_thread_state_new,
|
||||||
render_allocate,
|
render_allocate,
|
||||||
render_work,
|
render_work,
|
||||||
NULL,
|
NULL,
|
||||||
render ) )
|
render ) )
|
||||||
VIPS_DEBUG_MSG_RED( "render_thread_main: "
|
VIPS_DEBUG_MSG_RED( "render_thread_main: "
|
||||||
"threadpool_run failed\n" );
|
"threadpool_run failed\n" );
|
||||||
|
|
||||||
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
||||||
"threadpool return\n" );
|
"threadpool return\n" );
|
||||||
|
|
||||||
/* Add back to the jobs list, if we need to.
|
/* Add back to the jobs list, if we need to.
|
||||||
*/
|
*/
|
||||||
render_dirty_put( render );
|
render_dirty_put( render );
|
||||||
|
|
||||||
/* _get() does a ref to make sure we keep the render
|
/* _get() does a ref to make sure we keep the render
|
||||||
* alive during processing ... unref before we loop.
|
* alive during processing ... unref before we loop.
|
||||||
* This can kill off the render.
|
* This can kill off the render.
|
||||||
*/
|
*/
|
||||||
render_unref( render );
|
render_unref( render );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vips__render_shutdown( void )
|
||||||
|
{
|
||||||
|
/* We may come here without having inited.
|
||||||
|
*/
|
||||||
|
if( !render_dirty_lock )
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_mutex_lock( render_dirty_lock );
|
||||||
|
|
||||||
|
if( render_thread ) {
|
||||||
|
GThread *thread;
|
||||||
|
|
||||||
|
thread = render_thread;
|
||||||
|
render_thread = NULL;
|
||||||
|
|
||||||
|
g_mutex_unlock( render_dirty_lock );
|
||||||
|
|
||||||
|
render_reschedule = TRUE;
|
||||||
|
render_kill = TRUE;
|
||||||
|
vips_semaphore_up( &render_dirty_sem );
|
||||||
|
(void) g_thread_join( thread );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_mutex_unlock( render_dirty_lock );
|
||||||
|
}
|
||||||
|
|
||||||
/* Create our set of RenderThread. Assume we're single-threaded here.
|
/* Create our set of RenderThread. Assume we're single-threaded here.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -896,14 +932,17 @@ static int
|
|||||||
image_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
image_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
||||||
{
|
{
|
||||||
Render *render = (Render *) a;
|
Render *render = (Render *) a;
|
||||||
|
int tile_width = render->tile_width;
|
||||||
|
int tile_height = render->tile_height;
|
||||||
VipsRegion *reg = (VipsRegion *) seq;
|
VipsRegion *reg = (VipsRegion *) seq;
|
||||||
VipsRect *r = &out->valid;
|
VipsRect *r = &out->valid;
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
/* Find top left of tiles we need.
|
/* Find top left of tiles we need.
|
||||||
*/
|
*/
|
||||||
int xs = (r->left / render->tile_width) * render->tile_width;
|
int xs = (r->left / tile_width) * tile_width;
|
||||||
int ys = (r->top / render->tile_height) * render->tile_height;
|
int ys = (r->top / tile_height) * tile_height;
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "image_fill: left = %d, top = %d, "
|
VIPS_DEBUG_MSG( "image_fill: left = %d, top = %d, "
|
||||||
"width = %d, height = %d\n",
|
"width = %d, height = %d\n",
|
||||||
@ -918,15 +957,15 @@ image_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += render->tile_height )
|
for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += tile_height )
|
||||||
for( x = xs; x < VIPS_RECT_RIGHT( r ); x += render->tile_width ) {
|
for( x = xs; x < VIPS_RECT_RIGHT( r ); x += tile_width ) {
|
||||||
VipsRect area;
|
VipsRect area;
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
|
||||||
area.left = x;
|
area.left = x;
|
||||||
area.top = y;
|
area.top = y;
|
||||||
area.width = render->tile_width;
|
area.width = tile_width;
|
||||||
area.height = render->tile_height;
|
area.height = tile_height;
|
||||||
|
|
||||||
tile = render_tile_request( render, reg, &area );
|
tile = render_tile_request( render, reg, &area );
|
||||||
if( tile )
|
if( tile )
|
||||||
@ -956,13 +995,16 @@ static int
|
|||||||
mask_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
mask_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
||||||
{
|
{
|
||||||
Render *render = (Render *) a;
|
Render *render = (Render *) a;
|
||||||
|
int tile_width = render->tile_width;
|
||||||
|
int tile_height = render->tile_height;
|
||||||
VipsRect *r = &out->valid;
|
VipsRect *r = &out->valid;
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
/* Find top left of tiles we need.
|
/* Find top left of tiles we need.
|
||||||
*/
|
*/
|
||||||
int xs = (r->left / render->tile_width) * render->tile_width;
|
int xs = (r->left / tile_width) * tile_width;
|
||||||
int ys = (r->top / render->tile_height) * render->tile_height;
|
int ys = (r->top / tile_height) * tile_height;
|
||||||
|
|
||||||
VIPS_DEBUG_MSG( "mask_fill: left = %d, top = %d, "
|
VIPS_DEBUG_MSG( "mask_fill: left = %d, top = %d, "
|
||||||
"width = %d, height = %d\n",
|
"width = %d, height = %d\n",
|
||||||
@ -970,16 +1012,16 @@ mask_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
|||||||
|
|
||||||
g_mutex_lock( render->lock );
|
g_mutex_lock( render->lock );
|
||||||
|
|
||||||
for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += render->tile_height )
|
for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += tile_height )
|
||||||
for( x = xs; x < VIPS_RECT_RIGHT( r ); x += render->tile_width ) {
|
for( x = xs; x < VIPS_RECT_RIGHT( r ); x += tile_width ) {
|
||||||
VipsRect area;
|
VipsRect area;
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
area.left = x;
|
area.left = x;
|
||||||
area.top = y;
|
area.top = y;
|
||||||
area.width = render->tile_width;
|
area.width = tile_width;
|
||||||
area.height = render->tile_height;
|
area.height = tile_height;
|
||||||
|
|
||||||
tile = render_tile_lookup( render, &area );
|
tile = render_tile_lookup( render, &area );
|
||||||
value = (tile &&
|
value = (tile &&
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "pmorphology.h"
|
#include "pmorphology.h"
|
||||||
|
|
||||||
@ -83,15 +84,22 @@ vips_morph_build( VipsObject *object )
|
|||||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||||
|
|
||||||
INTMASK *imsk;
|
INTMASK *imsk;
|
||||||
|
VipsImage *in;
|
||||||
|
|
||||||
g_object_set( morph, "out", vips_image_new(), NULL );
|
g_object_set( morph, "out", vips_image_new(), NULL );
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_morph_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_morph_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_check_matrix( class->nickname, morph->mask, &t[0] ) )
|
in = morphology->in;
|
||||||
|
|
||||||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
|
if( vips_check_matrix( class->nickname, morph->mask, &t[1] ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
morph->M = t[0];
|
morph->M = t[1];
|
||||||
|
|
||||||
if( !(imsk = im_vips2imask( morph->M, class->nickname )) ||
|
if( !(imsk = im_vips2imask( morph->M, class->nickname )) ||
|
||||||
!im_local_imask( morph->out, imsk ) )
|
!im_local_imask( morph->out, imsk ) )
|
||||||
@ -99,12 +107,12 @@ vips_morph_build( VipsObject *object )
|
|||||||
|
|
||||||
switch( morph->morph ) {
|
switch( morph->morph ) {
|
||||||
case VIPS_OPERATION_MORPHOLOGY_DILATE:
|
case VIPS_OPERATION_MORPHOLOGY_DILATE:
|
||||||
if( im_dilate( morphology->in, morph->out, imsk ) )
|
if( im_dilate( in, morph->out, imsk ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_OPERATION_MORPHOLOGY_ERODE:
|
case VIPS_OPERATION_MORPHOLOGY_ERODE:
|
||||||
if( im_erode( morphology->in, morph->out, imsk ) )
|
if( im_erode( in, morph->out, imsk ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "pmorphology.h"
|
#include "pmorphology.h"
|
||||||
|
|
||||||
@ -340,8 +341,11 @@ vips_rank_build( VipsObject *object )
|
|||||||
|
|
||||||
in = morphology->in;
|
in = morphology->in;
|
||||||
|
|
||||||
if( vips_check_uncoded( class->nickname, in ) ||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
vips_check_noncomplex( class->nickname, in ) )
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
|
if( vips_check_noncomplex( class->nickname, in ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( rank->width > in->Xsize ||
|
if( rank->width > in->Xsize ||
|
||||||
rank->height > in->Ysize ) {
|
rank->height > in->Ysize ) {
|
||||||
@ -356,13 +360,13 @@ vips_rank_build( VipsObject *object )
|
|||||||
|
|
||||||
/* Expand the input.
|
/* Expand the input.
|
||||||
*/
|
*/
|
||||||
if( vips_embed( in, &t[0],
|
if( vips_embed( in, &t[1],
|
||||||
rank->width / 2, rank->height / 2,
|
rank->width / 2, rank->height / 2,
|
||||||
in->Xsize + rank->width - 1, in->Ysize + rank->height - 1,
|
in->Xsize + rank->width - 1, in->Ysize + rank->height - 1,
|
||||||
"extend", VIPS_EXTEND_COPY,
|
"extend", VIPS_EXTEND_COPY,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[0];
|
in = t[1];
|
||||||
|
|
||||||
g_object_set( object, "out", vips_image_new(), NULL );
|
g_object_set( object, "out", vips_image_new(), NULL );
|
||||||
|
|
||||||
|
@ -79,6 +79,8 @@
|
|||||||
* 14/12/12
|
* 14/12/12
|
||||||
* - redone as a class
|
* - redone as a class
|
||||||
* - added input space translation
|
* - added input space translation
|
||||||
|
* 22/1/14
|
||||||
|
* - auto RAD decode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -373,13 +375,33 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unpack to a format that we can compute with.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips__image_decode( VipsImage *in, VipsImage **out )
|
||||||
|
{
|
||||||
|
if( in->Coding == VIPS_CODING_LABQ ) {
|
||||||
|
if( vips_LabQ2LabS( in, out, NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
else if( in->Coding == VIPS_CODING_RAD ) {
|
||||||
|
if( vips_rad2float( in, out, NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( vips_copy( in, out, NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_affine_build( VipsObject *object )
|
vips_affine_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsResample *resample = VIPS_RESAMPLE( object );
|
VipsResample *resample = VIPS_RESAMPLE( object );
|
||||||
VipsAffine *affine = (VipsAffine *) object;
|
VipsAffine *affine = (VipsAffine *) object;
|
||||||
|
|
||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( object, 4 );
|
vips_object_local_array( object, 4 );
|
||||||
|
|
||||||
@ -392,7 +414,7 @@ vips_affine_build( VipsObject *object )
|
|||||||
if( VIPS_OBJECT_CLASS( vips_affine_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_affine_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_check_coding_noneorlabq( class->nickname, resample->in ) )
|
if( vips_check_coding_known( class->nickname, resample->in ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( vips_check_vector_length( class->nickname,
|
if( vips_check_vector_length( class->nickname,
|
||||||
affine->matrix->n, 4 ) )
|
affine->matrix->n, 4 ) )
|
||||||
@ -463,23 +485,19 @@ vips_affine_build( VipsObject *object )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unpack labq for processing.
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
*/
|
return( -1 );
|
||||||
if( in->Coding == VIPS_CODING_LABQ ) {
|
in = t[0];
|
||||||
if( vips_LabQ2LabS( in, &t[0], NULL ) )
|
|
||||||
return( -1 );
|
|
||||||
in = t[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add new pixels around the input so we can interpolate at the edges.
|
/* Add new pixels around the input so we can interpolate at the edges.
|
||||||
*/
|
*/
|
||||||
if( vips_embed( in, &t[1],
|
if( vips_embed( in, &t[2],
|
||||||
window_offset, window_offset,
|
window_offset, window_offset,
|
||||||
in->Xsize + window_size, in->Ysize + window_size,
|
in->Xsize + window_size, in->Ysize + window_size,
|
||||||
"extend", VIPS_EXTEND_COPY,
|
"extend", VIPS_EXTEND_COPY,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[1];
|
in = t[2];
|
||||||
|
|
||||||
/* Normally SMALLTILE ... except if this is a size up/down affine.
|
/* Normally SMALLTILE ... except if this is a size up/down affine.
|
||||||
*/
|
*/
|
||||||
|
@ -428,7 +428,7 @@ vips_interpolate_bicubic_class_init( VipsInterpolateBicubicClass *iclass )
|
|||||||
VIPS_INTERPOLATE_CLASS( iclass );
|
VIPS_INTERPOLATE_CLASS( iclass );
|
||||||
|
|
||||||
object_class->nickname = "bicubic";
|
object_class->nickname = "bicubic";
|
||||||
object_class->description = _( "Bicubic interpolation (Catmull-Rom)" );
|
object_class->description = _( "bicubic interpolation (Catmull-Rom)" );
|
||||||
|
|
||||||
interpolate_class->interpolate = vips_interpolate_bicubic_interpolate;
|
interpolate_class->interpolate = vips_interpolate_bicubic_interpolate;
|
||||||
interpolate_class->window_size = 4;
|
interpolate_class->window_size = 4;
|
||||||
|
@ -354,7 +354,7 @@ vips_interpolate_nearest_class_init( VipsInterpolateNearestClass *class )
|
|||||||
VIPS_INTERPOLATE_CLASS( class );
|
VIPS_INTERPOLATE_CLASS( class );
|
||||||
|
|
||||||
object_class->nickname = "nearest";
|
object_class->nickname = "nearest";
|
||||||
object_class->description = _( "Nearest-neighbour interpolation" );
|
object_class->description = _( "nearest-neighbour interpolation" );
|
||||||
|
|
||||||
interpolate_class->interpolate = vips_interpolate_nearest_interpolate;
|
interpolate_class->interpolate = vips_interpolate_nearest_interpolate;
|
||||||
interpolate_class->window_size = 1;
|
interpolate_class->window_size = 1;
|
||||||
@ -525,7 +525,7 @@ vips_interpolate_bilinear_class_init( VipsInterpolateBilinearClass *class )
|
|||||||
(VipsInterpolateClass *) class;
|
(VipsInterpolateClass *) class;
|
||||||
|
|
||||||
object_class->nickname = "bilinear";
|
object_class->nickname = "bilinear";
|
||||||
object_class->description = _( "Bilinear interpolation" );
|
object_class->description = _( "bilinear interpolation" );
|
||||||
|
|
||||||
interpolate_class->interpolate = vips_interpolate_bilinear_interpolate;
|
interpolate_class->interpolate = vips_interpolate_bilinear_interpolate;
|
||||||
interpolate_class->window_size = 2;
|
interpolate_class->window_size = 2;
|
||||||
|
@ -856,7 +856,7 @@ vips_interpolate_lbb_class_init( VipsInterpolateLbbClass *klass )
|
|||||||
VIPS_INTERPOLATE_CLASS( klass );
|
VIPS_INTERPOLATE_CLASS( klass );
|
||||||
|
|
||||||
object_class->nickname = "lbb";
|
object_class->nickname = "lbb";
|
||||||
object_class->description = _( "Reduced halo bicubic" );
|
object_class->description = _( "reduced halo bicubic" );
|
||||||
|
|
||||||
interpolate_class->interpolate = vips_interpolate_lbb_interpolate;
|
interpolate_class->interpolate = vips_interpolate_lbb_interpolate;
|
||||||
interpolate_class->window_size = 4;
|
interpolate_class->window_size = 4;
|
||||||
|
@ -1577,7 +1577,7 @@ vips_interpolate_nohalo_class_init( VipsInterpolateNohaloClass *klass )
|
|||||||
|
|
||||||
object_class->nickname = "nohalo";
|
object_class->nickname = "nohalo";
|
||||||
object_class->description =
|
object_class->description =
|
||||||
_( "Edge sharpening resampler with halo reduction" );
|
_( "edge sharpening resampler with halo reduction" );
|
||||||
|
|
||||||
interpolate_class->interpolate = vips_interpolate_nohalo_interpolate;
|
interpolate_class->interpolate = vips_interpolate_nohalo_interpolate;
|
||||||
interpolate_class->window_size = 5;
|
interpolate_class->window_size = 5;
|
||||||
|
@ -85,6 +85,7 @@
|
|||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
#include <vips/debug.h>
|
#include <vips/debug.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#include "presample.h"
|
#include "presample.h"
|
||||||
|
|
||||||
@ -310,6 +311,10 @@ vips_shrink_build( VipsObject *object )
|
|||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsResample *resample = VIPS_RESAMPLE( object );
|
VipsResample *resample = VIPS_RESAMPLE( object );
|
||||||
VipsShrink *shrink = (VipsShrink *) object;
|
VipsShrink *shrink = (VipsShrink *) object;
|
||||||
|
VipsImage **t = (VipsImage **)
|
||||||
|
vips_object_local_array( object, 1 );
|
||||||
|
|
||||||
|
VipsImage *in;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_shrink_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_shrink_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -318,7 +323,9 @@ vips_shrink_build( VipsObject *object )
|
|||||||
shrink->mh = ceil( shrink->yshrink );
|
shrink->mh = ceil( shrink->yshrink );
|
||||||
shrink->np = shrink->mw * shrink->mh;
|
shrink->np = shrink->mw * shrink->mh;
|
||||||
|
|
||||||
if( vips_check_noncomplex( class->nickname, resample->in ) )
|
in = resample->in;
|
||||||
|
|
||||||
|
if( vips_check_noncomplex( class->nickname, in ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( shrink->xshrink < 1.0 ||
|
if( shrink->xshrink < 1.0 ||
|
||||||
@ -336,14 +343,20 @@ vips_shrink_build( VipsObject *object )
|
|||||||
|
|
||||||
if( shrink->xshrink == 1.0 &&
|
if( shrink->xshrink == 1.0 &&
|
||||||
shrink->yshrink == 1.0 )
|
shrink->yshrink == 1.0 )
|
||||||
return( vips_image_write( resample->in, resample->out ) );
|
return( vips_image_write( in, resample->out ) );
|
||||||
|
|
||||||
|
/* Unpack for processing.
|
||||||
|
*/
|
||||||
|
if( vips__image_decode( in, &t[0] ) )
|
||||||
|
return( -1 );
|
||||||
|
in = t[0];
|
||||||
|
|
||||||
/* THINSTRIP will work, anything else will break seq mode. If you
|
/* THINSTRIP will work, anything else will break seq mode. If you
|
||||||
* combine shrink with conv you'll need to use a line cache to maintain
|
* combine shrink with conv you'll need to use a line cache to maintain
|
||||||
* sequentiality.
|
* sequentiality.
|
||||||
*/
|
*/
|
||||||
if( vips_image_pipelinev( resample->out,
|
if( vips_image_pipelinev( resample->out,
|
||||||
VIPS_DEMAND_STYLE_THINSTRIP, resample->in, NULL ) )
|
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Size output. Note: we round the output width down!
|
/* Size output. Note: we round the output width down!
|
||||||
@ -352,8 +365,8 @@ vips_shrink_build( VipsObject *object )
|
|||||||
* example, vipsthumbnail knows the true shrink factor (including the
|
* example, vipsthumbnail knows the true shrink factor (including the
|
||||||
* fractional part), we just see the integer part here.
|
* fractional part), we just see the integer part here.
|
||||||
*/
|
*/
|
||||||
resample->out->Xsize = resample->in->Xsize / shrink->xshrink;
|
resample->out->Xsize = in->Xsize / shrink->xshrink;
|
||||||
resample->out->Ysize = resample->in->Ysize / shrink->yshrink;
|
resample->out->Ysize = in->Ysize / shrink->yshrink;
|
||||||
if( resample->out->Xsize <= 0 ||
|
if( resample->out->Xsize <= 0 ||
|
||||||
resample->out->Ysize <= 0 ) {
|
resample->out->Ysize <= 0 ) {
|
||||||
vips_error( class->nickname,
|
vips_error( class->nickname,
|
||||||
@ -363,7 +376,7 @@ vips_shrink_build( VipsObject *object )
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "vips_shrink_build: shrinking %d x %d image to %d x %d\n",
|
printf( "vips_shrink_build: shrinking %d x %d image to %d x %d\n",
|
||||||
resample->in->Xsize, resample->in->Ysize,
|
in->Xsize, in->Ysize,
|
||||||
resample->out->Xsize, resample->out->Ysize );
|
resample->out->Xsize, resample->out->Ysize );
|
||||||
printf( "vips_shrink_build: %d x %d block average\n",
|
printf( "vips_shrink_build: %d x %d block average\n",
|
||||||
shrink->mw, shrink->mh );
|
shrink->mw, shrink->mh );
|
||||||
@ -371,7 +384,7 @@ vips_shrink_build( VipsObject *object )
|
|||||||
|
|
||||||
if( vips_image_generate( resample->out,
|
if( vips_image_generate( resample->out,
|
||||||
vips_shrink_start, vips_shrink_gen, vips_shrink_stop,
|
vips_shrink_start, vips_shrink_gen, vips_shrink_stop,
|
||||||
resample->in, shrink ) )
|
in, shrink ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user