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
|
||||
- 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
|
||||
- bump soname, thanks benjamin
|
||||
|
@ -189,7 +189,7 @@ OpenEXR images.
|
||||
## OpenSlide
|
||||
|
||||
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
|
||||
|
||||
|
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
|
||||
|
||||
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
|
||||
don't really exist any more
|
||||
|
||||
|
||||
- need to do mosaicing and inplace, plus im_label_regions in morph
|
||||
|
||||
- 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
|
||||
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?
|
||||
|
||||
|
15
configure.ac
15
configure.ac
@ -497,12 +497,19 @@ AC_ARG_WITH([openslide],
|
||||
AS_HELP_STRING([--without-openslide], [build without OpenSlide (default: test)]))
|
||||
|
||||
if test x"$with_openslide" != x"no"; then
|
||||
PKG_CHECK_MODULES(OPENSLIDE, openslide >= 3.3.0,
|
||||
[AC_DEFINE(HAVE_OPENSLIDE,1,[define if you have OpenSlide >= 3.3.0 installed.])
|
||||
PKG_CHECK_MODULES(OPENSLIDE, [openslide >= 3.4.0],
|
||||
[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
|
||||
PACKAGES_USED="$PACKAGES_USED openslide"],
|
||||
[AC_MSG_WARN([OpenSlide >= 3.3.0 not found; disabling virtual slide support])
|
||||
with_openslide=no
|
||||
[AC_MSG_NOTICE([OpenSlide >= 3.4.0 not found; checking for >= 3.3.0])
|
||||
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
|
||||
|
||||
|
80
libvips.supp
80
libvips.supp
@ -45,7 +45,7 @@
|
||||
init7
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_malloc0
|
||||
fun:*alloc*
|
||||
...
|
||||
fun:_dl_init
|
||||
}
|
||||
@ -85,13 +85,29 @@
|
||||
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
|
||||
{
|
||||
dbus
|
||||
Memcheck:Leak
|
||||
fun:*alloc
|
||||
...
|
||||
obj:/lib/libdbus-1.so.*
|
||||
obj:*/libdbus-1.so.*
|
||||
}
|
||||
|
||||
# hide all orbit leaks, not our problem
|
||||
@ -112,6 +128,31 @@
|
||||
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
|
||||
Memcheck:Leak
|
||||
@ -120,6 +161,14 @@
|
||||
fun:FT_Open_Face
|
||||
}
|
||||
|
||||
{
|
||||
harfbuzz
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:hb_shape_plan_execute
|
||||
}
|
||||
|
||||
{
|
||||
goffice_init
|
||||
Memcheck:Leak
|
||||
@ -257,8 +306,6 @@
|
||||
fun:write_vips
|
||||
}
|
||||
|
||||
# ubuntu 13.04 suppressions
|
||||
|
||||
{
|
||||
pixman1
|
||||
Memcheck:Cond
|
||||
@ -272,6 +319,30 @@
|
||||
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
|
||||
|
||||
{
|
||||
@ -304,3 +375,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "parithmetic.h"
|
||||
|
||||
@ -500,6 +501,7 @@ vips_arithmetic_build( VipsObject *object )
|
||||
VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
|
||||
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
|
||||
|
||||
VipsImage **decode;
|
||||
VipsImage **format;
|
||||
VipsImage **band;
|
||||
VipsImage **size;
|
||||
@ -524,12 +526,9 @@ vips_arithmetic_build( VipsObject *object )
|
||||
"%s", _( "too many input images" ) );
|
||||
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 **)
|
||||
vips_object_local_array( object, arithmetic->n );
|
||||
band = (VipsImage **)
|
||||
@ -537,9 +536,15 @@ vips_arithmetic_build( VipsObject *object )
|
||||
size = (VipsImage **)
|
||||
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.
|
||||
*/
|
||||
if( vips__formatalike_vec( arithmetic->in, format, arithmetic->n ) ||
|
||||
if( vips__formatalike_vec( decode, format, arithmetic->n ) ||
|
||||
vips__bandalike_vec( class->nickname,
|
||||
format, band, arithmetic->n, arithmetic->base_bands ) ||
|
||||
vips__sizealike_vec( band, size, arithmetic->n ) )
|
||||
|
@ -492,7 +492,7 @@ vips_complex2_class_init( VipsComplex2Class *class )
|
||||
|
||||
object_class->nickname = "complex2";
|
||||
object_class->description =
|
||||
_( "perform a binary complex operation on two images" );
|
||||
_( "complex binary operations on two images" );
|
||||
|
||||
aclass->process_line = vips_complex2_buffer;
|
||||
|
||||
|
@ -210,7 +210,7 @@ vips_deviate_class_init( VipsDeviateClass *class )
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "deviate";
|
||||
object_class->description = _( "find image average" );
|
||||
object_class->description = _( "find image standard deviation" );
|
||||
object_class->build = vips_deviate_build;
|
||||
|
||||
sclass->start = vips_deviate_start;
|
||||
|
@ -130,7 +130,7 @@ vips_hist_find_indexed_build( VipsObject *object )
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsStatistic *statistic = VIPS_STATISTIC( 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,
|
||||
"out", vips_image_new(),
|
||||
|
@ -286,7 +286,7 @@ vips_hist_find_ndim_class_init( VipsHistFindNDimClass *class )
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
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;
|
||||
|
||||
sclass->start = vips_hist_find_ndim_start;
|
||||
|
@ -122,8 +122,22 @@ vips_linear_build( VipsObject *object )
|
||||
VipsUnary *unary = (VipsUnary *) object;
|
||||
VipsLinear *linear = (VipsLinear *) object;
|
||||
|
||||
int bands;
|
||||
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
|
||||
* match.
|
||||
*/
|
||||
@ -133,7 +147,7 @@ vips_linear_build( VipsObject *object )
|
||||
if( linear->b )
|
||||
linear->n = VIPS_MAX( linear->n, linear->b->n );
|
||||
if( unary->in )
|
||||
linear->n = VIPS_MAX( linear->n, unary->in->Bands );
|
||||
linear->n = VIPS_MAX( linear->n, bands );
|
||||
arithmetic->base_bands = linear->n;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
aclass->process_line = vips_math_buffer;
|
||||
|
@ -216,8 +216,7 @@ vips_relational_class_init( VipsRelationalClass *class )
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "relational";
|
||||
object_class->description =
|
||||
_( "a relational operation on a pair of images" );
|
||||
object_class->description = _( "relational operation on two images" );
|
||||
object_class->build = vips_relational_build;
|
||||
|
||||
aclass->process_line = vips_relational_buffer;
|
||||
|
@ -50,6 +50,7 @@
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/debug.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "statistic.h"
|
||||
|
||||
@ -109,9 +110,7 @@ vips_statistic_build( VipsObject *object )
|
||||
{
|
||||
VipsStatistic *statistic = VIPS_STATISTIC( object );
|
||||
VipsStatisticClass *sclass = VIPS_STATISTIC_GET_CLASS( statistic );
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
const char *domain = class->nickname;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_statistic_build: " );
|
||||
@ -122,20 +121,20 @@ vips_statistic_build( VipsObject *object )
|
||||
if( VIPS_OBJECT_CLASS( vips_statistic_parent_class )->build( object ) )
|
||||
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( sclass->format_table ) {
|
||||
if( vips_cast( statistic->in, &t[0],
|
||||
if( vips_cast( statistic->ready, &t[1],
|
||||
sclass->format_table[statistic->in->BandFmt], NULL ) )
|
||||
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,
|
||||
vips_statistic_scan_start,
|
||||
|
@ -627,30 +627,18 @@ vips_colour_difference_build( VipsObject *object )
|
||||
right = difference->right;
|
||||
extra = NULL;
|
||||
|
||||
/* Unpack LABQ images,
|
||||
*/
|
||||
if( left &&
|
||||
left->Coding == VIPS_CODING_LABQ ) {
|
||||
if( vips_LabQ2Lab( left, &t[0], NULL ) )
|
||||
if( left ) {
|
||||
if( vips__image_decode( left, &t[0] ) )
|
||||
return( -1 );
|
||||
left = t[0];
|
||||
}
|
||||
if( right &&
|
||||
right->Coding == VIPS_CODING_LABQ ) {
|
||||
if( vips_LabQ2Lab( right, &t[1], NULL ) )
|
||||
|
||||
if( right ) {
|
||||
if( vips__image_decode( right, &t[1] ) )
|
||||
return( -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
|
||||
* have extra bands, give up.
|
||||
*/
|
||||
|
@ -8,6 +8,8 @@
|
||||
* - add RGB16 as a source
|
||||
* 19/1/14
|
||||
* - auto-decode RAD images
|
||||
* 3/2/14
|
||||
* - add "source_space", overrides source space guess
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -388,6 +390,7 @@ typedef struct _VipsColourspace {
|
||||
VipsImage *in;
|
||||
VipsImage *out;
|
||||
VipsInterpretation space;
|
||||
VipsInterpretation source_space;
|
||||
} VipsColourspace;
|
||||
|
||||
typedef VipsOperationClass VipsColourspaceClass;
|
||||
@ -408,7 +411,6 @@ vips_colourspace_build( VipsObject *object )
|
||||
|
||||
VipsInterpretation interpretation;
|
||||
|
||||
|
||||
/* Verify that all input args have been set.
|
||||
*/
|
||||
if( VIPS_OBJECT_CLASS( vips_colourspace_parent_class )->
|
||||
@ -426,7 +428,10 @@ vips_colourspace_build( VipsObject *object )
|
||||
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,
|
||||
* you'll need to use the icc funcs.
|
||||
@ -506,11 +511,20 @@ vips_colourspace_class_init( VipsColourspaceClass *class )
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsColourspace, space ),
|
||||
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
|
||||
vips_colourspace_init( VipsColourspace *colourspace )
|
||||
{
|
||||
colourspace->source_space = VIPS_INTERPRETATION_sRGB;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -519,7 +533,12 @@ vips_colourspace_init( VipsColourspace *colourspace )
|
||||
* @out: output image
|
||||
* @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.
|
||||
*
|
||||
* For example, given an image tagged as #VIPS_INTERPRETATION_YXY, running
|
||||
|
@ -123,6 +123,7 @@ vips_bandary_build( VipsObject *object )
|
||||
VipsBandary *bandary = (VipsBandary *) object;
|
||||
|
||||
int i;
|
||||
VipsImage **decode;
|
||||
VipsImage **format;
|
||||
VipsImage **size;
|
||||
|
||||
@ -139,14 +140,15 @@ vips_bandary_build( VipsObject *object )
|
||||
"%s", _( "too many input images" ) );
|
||||
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 );
|
||||
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 ) )
|
||||
return( -1 );
|
||||
bandary->ready = size;
|
||||
|
@ -429,36 +429,41 @@ vips_cast_gen( VipsRegion *or, void *vseq, void *a, void *b,
|
||||
static int
|
||||
vips_cast_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConversion *conversion = VIPS_CONVERSION( 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 ) )
|
||||
return( -1 );
|
||||
|
||||
in = cast->in;
|
||||
|
||||
/* Trivial case: fall back to copy().
|
||||
*/
|
||||
if( cast->in->BandFmt == cast->format )
|
||||
return( vips_image_write( cast->in, conversion->out ) );
|
||||
if( in->BandFmt == cast->format )
|
||||
return( vips_image_write( in, conversion->out ) );
|
||||
|
||||
if( vips_check_uncoded( class->nickname, cast->in ) ||
|
||||
vips_image_pio_input( cast->in ) )
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, cast->in, NULL ) )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
conversion->out->BandFmt = cast->format;
|
||||
|
||||
g_signal_connect( cast->in, "preeval",
|
||||
g_signal_connect( in, "preeval",
|
||||
G_CALLBACK( vips_cast_preeval ), cast );
|
||||
g_signal_connect( cast->in, "posteval",
|
||||
g_signal_connect( in, "posteval",
|
||||
G_CALLBACK( vips_cast_posteval ), cast );
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_cast_start, vips_cast_gen, vips_cast_stop,
|
||||
cast->in, cast ) )
|
||||
in, cast ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
|
@ -14,6 +14,8 @@
|
||||
* - force input to mono 8-bit for the user
|
||||
* 1/8/13
|
||||
* - 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 <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "pconversion.h"
|
||||
|
||||
@ -329,10 +332,9 @@ static unsigned char vips_falsecolour_pet[][3] = {
|
||||
static int
|
||||
vips_falsecolour_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConversion *conversion = VIPS_CONVERSION( 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 )->
|
||||
build( object ) )
|
||||
@ -343,13 +345,15 @@ vips_falsecolour_build( VipsObject *object )
|
||||
VIPS_FORMAT_UCHAR )) )
|
||||
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 ) ||
|
||||
vips_extract_band( falsecolour->in, &t[1], 0, NULL ) ||
|
||||
vips_cast( t[1], &t[2], VIPS_FORMAT_UCHAR, NULL ) ||
|
||||
vips_maplut( falsecolour->in, &t[3], t[0], NULL ) ||
|
||||
vips_image_write( t[3], conversion->out ) )
|
||||
if( vips__image_decode( falsecolour->in, &t[1] ) ||
|
||||
vips_extract_band( t[1], &t[2], 0, NULL ) ||
|
||||
vips_cast( t[2], &t[3], VIPS_FORMAT_UCHAR, NULL ) ||
|
||||
vips_maplut( t[3], &t[4], t[0], NULL ) ||
|
||||
vips_image_write( t[4], conversion->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
|
@ -300,24 +300,31 @@ vips_flatten_build( VipsObject *object )
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConversion *conversion = VIPS_CONVERSION( object );
|
||||
VipsFlatten *flatten = (VipsFlatten *) object;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 1 );
|
||||
|
||||
VipsImage *in;
|
||||
int i;
|
||||
gboolean black;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_flatten_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
in = flatten->in;
|
||||
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
/* Trivial case: fall back to copy().
|
||||
*/
|
||||
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 ) ||
|
||||
vips_check_noncomplex( class->nickname, flatten->in ) ||
|
||||
vips_image_pio_input( flatten->in ) )
|
||||
if( vips_check_noncomplex( class->nickname, in ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, flatten->in, NULL ) )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
conversion->out->Bands -= 1;
|
||||
@ -334,7 +341,7 @@ vips_flatten_build( VipsObject *object )
|
||||
if( black ) {
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, vips_flatten_black_gen, vips_stop_one,
|
||||
flatten->in, flatten ) )
|
||||
in, flatten ) )
|
||||
return( -1 );
|
||||
}
|
||||
else {
|
||||
@ -347,7 +354,7 @@ vips_flatten_build( VipsObject *object )
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, vips_flatten_gen, vips_stop_one,
|
||||
flatten->in, flatten ) )
|
||||
in, flatten ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "pconversion.h"
|
||||
|
||||
@ -142,19 +143,25 @@ vips_recomb_build( VipsObject *object )
|
||||
VipsRecomb *recomb = (VipsRecomb *) object;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||
|
||||
VipsImage *in;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_recomb_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_pio_input( recomb->in ) ||
|
||||
vips_check_uncoded( class->nickname, recomb->in ) ||
|
||||
vips_check_noncomplex( class->nickname, recomb->in ) )
|
||||
in = recomb->in;
|
||||
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
if( vips_check_noncomplex( class->nickname, in ) )
|
||||
return( -1 );
|
||||
if( vips_image_pio_input( recomb->m ) ||
|
||||
vips_check_uncoded( class->nickname, recomb->m ) ||
|
||||
vips_check_noncomplex( class->nickname, recomb->m ) ||
|
||||
vips_check_mono( class->nickname, recomb->m ) )
|
||||
return( -1 );
|
||||
if( recomb->in->Bands != recomb->m->Xsize ) {
|
||||
if( in->Bands != recomb->m->Xsize ) {
|
||||
vips_error( class->nickname,
|
||||
"%s", _( "bands in must equal matrix width" ) );
|
||||
return( -1 );
|
||||
@ -165,16 +172,16 @@ vips_recomb_build( VipsObject *object )
|
||||
recomb->coeff = t[0];
|
||||
|
||||
if( vips_image_pipelinev( conversion->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, recomb->in, NULL ) )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
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;
|
||||
|
||||
if( vips_image_generate( conversion->out,
|
||||
vips_start_one, vips_recomb_gen, vips_stop_one,
|
||||
recomb->in, recomb ) )
|
||||
in, recomb ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
|
@ -142,7 +142,7 @@ vips_compass_class_init( VipsCompassClass *class )
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "compass";
|
||||
object_class->description = _( "convolution operation" );
|
||||
object_class->description = _( "convolve with rotaing mask" );
|
||||
object_class->build = vips_compass_build;
|
||||
|
||||
VIPS_ARG_INT( class, "times", 101,
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "pconvolution.h"
|
||||
|
||||
@ -65,7 +66,10 @@ vips_conv_build( VipsObject *object )
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsConvolution *convolution = (VipsConvolution *) object;
|
||||
VipsConv *conv = (VipsConv *) object;
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( object, 4 );
|
||||
|
||||
VipsImage *in;
|
||||
INTMASK *imsk;
|
||||
DOUBLEMASK *dmsk;
|
||||
|
||||
@ -74,6 +78,8 @@ vips_conv_build( VipsObject *object )
|
||||
if( VIPS_OBJECT_CLASS( vips_conv_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
in = convolution->in;
|
||||
|
||||
/*
|
||||
printf( "vips_conv_build: convolving with:\n" );
|
||||
vips_matrixprint( convolution->M, NULL );
|
||||
@ -86,19 +92,25 @@ vips_conv_build( VipsObject *object )
|
||||
!im_local_dmask( convolution->out, dmsk ) )
|
||||
return( -1 );
|
||||
|
||||
/* Unpack for processing.
|
||||
*/
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
switch( conv->precision ) {
|
||||
case VIPS_PRECISION_INTEGER:
|
||||
if( im_conv( convolution->in, convolution->out, imsk ) )
|
||||
if( im_conv( in, convolution->out, imsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
case VIPS_PRECISION_FLOAT:
|
||||
if( im_conv_f( convolution->in, convolution->out, dmsk ) )
|
||||
if( im_conv_f( in, convolution->out, dmsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
case VIPS_PRECISION_APPROXIMATE:
|
||||
if( im_aconv( convolution->in, convolution->out, dmsk,
|
||||
if( im_aconv( in, convolution->out, dmsk,
|
||||
conv->layers, conv->cluster ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
@ -100,7 +100,7 @@ vips_convsep_class_init( VipsConvsepClass *class )
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "convsep";
|
||||
object_class->description = _( "convolution operation" );
|
||||
object_class->description = _( "seperable convolution operation" );
|
||||
object_class->build = vips_convsep_build;
|
||||
|
||||
VIPS_ARG_ENUM( class, "precision", 203,
|
||||
|
@ -108,7 +108,7 @@ vips_gaussblur_class_init( VipsGaussblurClass *class )
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "gaussblur";
|
||||
object_class->description = _( "Unsharp masking for print" );
|
||||
object_class->description = _( "gaussian blur" );
|
||||
object_class->build = vips_gaussblur_build;
|
||||
|
||||
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
||||
|
@ -309,7 +309,7 @@ vips_sharpen_class_init( VipsSharpenClass *class )
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "sharpen";
|
||||
object_class->description = _( "Unsharp masking for print" );
|
||||
object_class->description = _( "unsharp masking for print" );
|
||||
object_class->build = vips_sharpen_build;
|
||||
|
||||
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
||||
|
@ -98,7 +98,9 @@ static const char *openslide_suffs[] = {
|
||||
".vms", ".vmu", ".ndpi", /* Hamamatsu */
|
||||
".scn", /* Leica */
|
||||
".mrxs", /* MIRAX */
|
||||
".svslide", /* Sakura */
|
||||
".tif", /* Trestle */
|
||||
".bif", /* Ventana */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -183,8 +183,7 @@ vips_wrap7_vargv_dispose( im_function *fn, im_object *vargv )
|
||||
|
||||
case VIPS_WRAP7_INTERPOLATE:
|
||||
case VIPS_WRAP7_IMAGE:
|
||||
if( vargv[i] )
|
||||
VIPS_UNREF( vargv[i] );
|
||||
VIPS_UNREF( vargv[i] );
|
||||
break;
|
||||
|
||||
case VIPS_WRAP7_IMAGEVEC:
|
||||
@ -193,13 +192,21 @@ vips_wrap7_vargv_dispose( im_function *fn, im_object *vargv )
|
||||
int j;
|
||||
|
||||
for( j = 0; j < iv->n; j++ )
|
||||
if( iv->vec[j] )
|
||||
VIPS_UNREF( iv->vec[j] );
|
||||
VIPS_UNREF( iv->vec[j] );
|
||||
}
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
@ -686,6 +693,7 @@ vips_wrap7_class_init( VipsWrap7Class *class )
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) class;
|
||||
VipsObjectClass *vobject_class = (VipsObjectClass *) class;
|
||||
VipsOperationClass *operation_class = (VipsOperationClass *) class;
|
||||
|
||||
gobject_class->dispose = vips_wrap7_dispose;
|
||||
gobject_class->finalize = vips_wrap7_finalize;
|
||||
@ -695,6 +703,8 @@ vips_wrap7_class_init( VipsWrap7Class *class )
|
||||
vobject_class->build = vips_wrap7_build;
|
||||
vobject_class->summary_class = vips_wrap7_summary_class;
|
||||
vobject_class->dump = vips_wrap7_dump;
|
||||
|
||||
operation_class->flags = VIPS_OPERATION_DEPRECATED;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2357,18 +2357,17 @@ vips_openexrload( const char *filename, VipsImage **out, ... )
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @layer: load this layer
|
||||
* @level: load this level
|
||||
* @associated: load this associated image
|
||||
*
|
||||
* Read a virtual slide supported by the OpenSlide library into a VIPS image.
|
||||
* OpenSlide supports images in Aperio, Hamamatsu VMS, Hamamatsu VMU, MIRAX,
|
||||
* and Trestle formats.
|
||||
* OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle,
|
||||
* and Ventana formats.
|
||||
*
|
||||
* To facilitate zooming, virtual slide formats include multiple scaled-down
|
||||
* versions of the high-resolution image. These are typically called
|
||||
* "levels", though OpenSlide and im_openslide2vips() call them "layers".
|
||||
* By default, vips_openslideload() reads the highest-resolution layer
|
||||
* (layer 0). Set @layer to the layer number you want.
|
||||
* "levels". By default, vips_openslideload() reads the highest-resolution
|
||||
* level (level 0). Set @level to the level number you want.
|
||||
*
|
||||
* In addition to the slide image itself, virtual slide formats sometimes
|
||||
* 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.
|
||||
*
|
||||
* 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().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
@ -2428,7 +2435,7 @@ vips_fitsload( const char *filename, VipsImage **out, ... )
|
||||
* @filename: file to write to
|
||||
* @...: %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().
|
||||
*
|
||||
|
@ -150,6 +150,10 @@ typedef struct _ReadJpeg {
|
||||
/* Set if we need to finish the decompress.
|
||||
*/
|
||||
gboolean decompressing;
|
||||
|
||||
/* Track the y pos during a read with this.
|
||||
*/
|
||||
int y_pos;
|
||||
} ReadJpeg;
|
||||
|
||||
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.fp = NULL;
|
||||
|
||||
jpeg->y_pos = 0;
|
||||
|
||||
/* jpeg_create_decompress() can fail on some sanity checks. Don't
|
||||
* 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",
|
||||
r->top, r->height );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
|
||||
VIPS_GATE_START( "read_jpeg_generate: work" );
|
||||
|
||||
/* 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 ) );
|
||||
|
||||
/* 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().
|
||||
*/
|
||||
if( setjmp( jpeg->eman.jmp ) )
|
||||
@ -926,6 +937,8 @@ read_jpeg_generate( VipsRegion *or,
|
||||
for( x = 0; x < sz; x++ )
|
||||
row_pointer[0][x] = 255 - row_pointer[0][x];
|
||||
}
|
||||
|
||||
jpeg->y_pos += 1;
|
||||
}
|
||||
|
||||
VIPS_GATE_STOP( "read_jpeg_generate: work" );
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* Benjamin Gilbert
|
||||
*
|
||||
* Copyright (c) 2011-2012 Carnegie Mellon University
|
||||
* Copyright (c) 2011-2014 Carnegie Mellon University
|
||||
*
|
||||
* 26/11/11
|
||||
* - initial version
|
||||
@ -39,6 +39,8 @@
|
||||
* - use threaded tile cache
|
||||
* 6/8/13
|
||||
* - always output solid (not transparent) pixels
|
||||
* 25/1/14
|
||||
* - use openslide_detect_vendor() on >= 3.4.0
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -105,13 +107,28 @@ typedef struct {
|
||||
int
|
||||
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;
|
||||
int ok;
|
||||
|
||||
ok = 0;
|
||||
vips_error_freeze();
|
||||
osr = openslide_open( filename );
|
||||
vips_error_thaw();
|
||||
|
||||
if( osr ) {
|
||||
const char *vendor;
|
||||
@ -135,6 +152,7 @@ vips__openslide_isslide( const char *filename )
|
||||
VIPS_DEBUG_MSG( "vips__openslide_isslide: %s - %d\n", filename, ok );
|
||||
|
||||
return( ok );
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -140,7 +140,9 @@ static const char *vips_foreign_openslide_suffs[] = {
|
||||
".vms", ".vmu", ".ndpi", /* Hamamatsu */
|
||||
".scn", /* Leica */
|
||||
".mrxs", /* MIRAX */
|
||||
".svslide", /* Sakura */
|
||||
".tif", /* Trestle */
|
||||
".bif", /* Ventana */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,9 @@
|
||||
* - support sequential read
|
||||
* 5/11/13
|
||||
* - 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_MARGIN (256)
|
||||
|
||||
static unsigned char buffer[BUFFER_SIZE + BUFFER_MARGIN];
|
||||
static int buffer_length = 0;
|
||||
static int buffer_position = 0;
|
||||
static FILE *buffer_fp = NULL;
|
||||
/* Read from a FILE with a rolling memory buffer ... this lets us reduce the
|
||||
* number of fgetc() and gives us some very quick readahead.
|
||||
*/
|
||||
|
||||
static void
|
||||
buffer_init( FILE *fp )
|
||||
typedef struct _Buffer {
|
||||
unsigned char text[BUFFER_SIZE + BUFFER_MARGIN];
|
||||
int length;
|
||||
int position;
|
||||
FILE *fp;
|
||||
} Buffer;
|
||||
|
||||
static Buffer *
|
||||
buffer_new( FILE *fp )
|
||||
{
|
||||
buffer_length = 0;
|
||||
buffer_position = 0;
|
||||
buffer_fp = fp;
|
||||
Buffer *buffer = g_new0( Buffer, 1 );
|
||||
|
||||
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
|
||||
buffer_need( int require )
|
||||
buffer_need( Buffer *buffer, int require )
|
||||
{
|
||||
int remaining;
|
||||
|
||||
g_assert( require < BUFFER_MARGIN );
|
||||
|
||||
remaining = buffer_length - buffer_position;
|
||||
remaining = buffer->length - buffer->position;
|
||||
if( remaining < require ) {
|
||||
size_t len;
|
||||
|
||||
memcpy( buffer, buffer + buffer_position, remaining );
|
||||
buffer_position = 0;
|
||||
buffer_length = remaining;
|
||||
memcpy( buffer->text,
|
||||
buffer->text + buffer->position, remaining );
|
||||
buffer->position = 0;
|
||||
buffer->length = remaining;
|
||||
|
||||
len = fread( buffer + buffer_length, 1, BUFFER_SIZE,
|
||||
buffer_fp );
|
||||
buffer_length += len;
|
||||
remaining = buffer_length - buffer_position;
|
||||
len = fread( buffer->text + buffer->length,
|
||||
1, BUFFER_SIZE, buffer->fp );
|
||||
buffer->length += len;
|
||||
remaining = buffer->length - buffer->position;
|
||||
|
||||
if( remaining < require ) {
|
||||
vips_error( "rad2vips", "%s", _( "end of file" ) );
|
||||
@ -659,26 +681,26 @@ buffer_need( int require )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#define BUFFER_FETCH (buffer[buffer_position++])
|
||||
#define BUFFER_PEEK (buffer[buffer_position])
|
||||
#define BUFFER_FETCH(B) ((B)->text[(B)->position++])
|
||||
#define BUFFER_PEEK(B) ((B)->text[(B)->position])
|
||||
|
||||
/* Read a single scanlne, encoded in the old style.
|
||||
*/
|
||||
static int
|
||||
scanline_read_old( COLR *scanline, int width )
|
||||
scanline_read_old( Buffer *buffer, COLR *scanline, int width )
|
||||
{
|
||||
int rshift;
|
||||
|
||||
rshift = 0;
|
||||
|
||||
while( width > 0 ) {
|
||||
if( buffer_need( 4 ) )
|
||||
if( buffer_need( buffer, 4 ) )
|
||||
return( -1 );
|
||||
|
||||
scanline[0][RED] = BUFFER_FETCH;
|
||||
scanline[0][GRN] = BUFFER_FETCH;
|
||||
scanline[0][BLU] = BUFFER_FETCH;
|
||||
scanline[0][EXP] = BUFFER_FETCH;
|
||||
scanline[0][RED] = BUFFER_FETCH( buffer );
|
||||
scanline[0][GRN] = BUFFER_FETCH( buffer );
|
||||
scanline[0][BLU] = BUFFER_FETCH( buffer );
|
||||
scanline[0][EXP] = BUFFER_FETCH( buffer );
|
||||
|
||||
if( scanline[0][RED] == 1 &&
|
||||
scanline[0][GRN] == 1 &&
|
||||
@ -706,7 +728,7 @@ scanline_read_old( COLR *scanline, int width )
|
||||
/* Read a single encoded scanline.
|
||||
*/
|
||||
static int
|
||||
scanline_read( COLR *scanline, int width )
|
||||
scanline_read( Buffer *buffer, COLR *scanline, int width )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@ -714,21 +736,21 @@ scanline_read( COLR *scanline, int width )
|
||||
*/
|
||||
if( width < MINELEN ||
|
||||
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 );
|
||||
|
||||
if( BUFFER_PEEK != 2 )
|
||||
return( scanline_read_old( scanline, width ) );
|
||||
if( BUFFER_PEEK( buffer ) != 2 )
|
||||
return( scanline_read_old( buffer, scanline, width ) );
|
||||
|
||||
scanline[0][RED] = BUFFER_FETCH;
|
||||
scanline[0][GRN] = BUFFER_FETCH;
|
||||
scanline[0][BLU] = BUFFER_FETCH;
|
||||
scanline[0][EXP] = BUFFER_FETCH;
|
||||
scanline[0][RED] = BUFFER_FETCH( buffer );
|
||||
scanline[0][GRN] = BUFFER_FETCH( buffer );
|
||||
scanline[0][BLU] = BUFFER_FETCH( buffer );
|
||||
scanline[0][EXP] = BUFFER_FETCH( buffer );
|
||||
if( scanline[0][GRN] != 2 ||
|
||||
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 ) {
|
||||
vips_error( "rad2vips", "%s", _( "scanline length mismatch" ) );
|
||||
@ -740,10 +762,10 @@ scanline_read( COLR *scanline, int width )
|
||||
int code, len;
|
||||
gboolean run;
|
||||
|
||||
if( buffer_need( 2 ) )
|
||||
if( buffer_need( buffer, 2 ) )
|
||||
return( -1 );
|
||||
|
||||
code = BUFFER_FETCH;
|
||||
code = BUFFER_FETCH( buffer );
|
||||
run = code > 128;
|
||||
len = run ? code & 127 : code;
|
||||
|
||||
@ -755,15 +777,16 @@ scanline_read( COLR *scanline, int width )
|
||||
if( run ) {
|
||||
int val;
|
||||
|
||||
val = BUFFER_FETCH;
|
||||
val = BUFFER_FETCH( buffer );
|
||||
while( len-- )
|
||||
scanline[j++][i] = val;
|
||||
}
|
||||
else {
|
||||
if( buffer_need( len ) )
|
||||
if( buffer_need( buffer, len ) )
|
||||
return( -1 );
|
||||
while( len-- )
|
||||
scanline[j++][i] = BUFFER_FETCH;
|
||||
scanline[j++][i] =
|
||||
BUFFER_FETCH( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
@ -861,6 +884,7 @@ typedef struct {
|
||||
double aspect;
|
||||
RGBPRIMS prims;
|
||||
RESOLU rs;
|
||||
Buffer *buffer;
|
||||
} Read;
|
||||
|
||||
int
|
||||
@ -888,7 +912,7 @@ read_destroy( VipsObject *object, Read *read )
|
||||
{
|
||||
VIPS_FREE( read->filename );
|
||||
VIPS_FREEF( fclose, read->fin );
|
||||
buffer_init( NULL );
|
||||
VIPS_FREEF( buffer_free, read->buffer );
|
||||
}
|
||||
|
||||
static Read *
|
||||
@ -920,9 +944,9 @@ read_new( const char *filename, VipsImage *out )
|
||||
g_signal_connect( out, "close",
|
||||
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 );
|
||||
buffer_init( read->fin );
|
||||
|
||||
return( read );
|
||||
}
|
||||
@ -1037,24 +1061,30 @@ rad2vips_generate( VipsRegion *or,
|
||||
void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
VipsRect *r = &or->valid;
|
||||
Read *read = (Read *) a;
|
||||
|
||||
int y;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "rad2vips_get_data\n" );
|
||||
printf( "rad2vips_generate: line %d, %d rows\n",
|
||||
r->top, r->height );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
VIPS_GATE_START( "rad2vips_generate: work" );
|
||||
|
||||
for( y = 0; y < r->height; y++ ) {
|
||||
COLR *buf = (COLR *)
|
||||
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",
|
||||
_( "read error line %d" ), r->top + y );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
VIPS_GATE_STOP( "rad2vips_generate: work" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,8 @@ int vips__tiff_write( VipsImage *in, const char *filename,
|
||||
gboolean pyramid,
|
||||
gboolean squash,
|
||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||
gboolean bigtiff );
|
||||
gboolean bigtiff,
|
||||
gboolean rgbjpeg );
|
||||
|
||||
int vips__tiff_read( const char *filename, VipsImage *out, int page,
|
||||
gboolean readbehind );
|
||||
|
@ -4,6 +4,8 @@
|
||||
* - wrap a class around the tiff writer
|
||||
* 17/3/12
|
||||
* - argh xres/yres macro was wrong
|
||||
* 26/1/14
|
||||
* - add rgbjpeg flag
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -75,6 +77,7 @@ typedef struct _VipsForeignSaveTiff {
|
||||
double xres;
|
||||
double yres;
|
||||
gboolean bigtiff;
|
||||
gboolean rgbjpeg;
|
||||
} VipsForeignSaveTiff;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignSaveTiffClass;
|
||||
@ -123,7 +126,8 @@ vips_foreign_save_tiff_build( VipsObject *object )
|
||||
tiff->pyramid,
|
||||
tiff->squash,
|
||||
tiff->resunit, tiff->xres, tiff->yres,
|
||||
tiff->bigtiff ) )
|
||||
tiff->bigtiff,
|
||||
tiff->rgbjpeg ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -249,6 +253,13 @@ vips_foreign_save_tiff_class_init( VipsForeignSaveTiffClass *class )
|
||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveTiff, bigtiff ),
|
||||
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
|
||||
|
@ -136,6 +136,8 @@
|
||||
* 24/9/13
|
||||
* - support many more vips formats, eg. complex, 32-bit int, any number
|
||||
* 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 */
|
||||
char *icc_profile; /* Profile to embed */
|
||||
int bigtiff; /* True for bigtiff write */
|
||||
int rgbjpeg; /* True for RGB not YCbCr */
|
||||
|
||||
GMutex *write_lock; /* Lock TIFF*() calls with this */
|
||||
} TiffWrite;
|
||||
@ -529,7 +532,8 @@ write_tiff_header( TiffWrite *tw, TIFF *tif, int width, int height )
|
||||
}
|
||||
else if( tw->compression == COMPRESSION_JPEG &&
|
||||
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
|
||||
* YCbCr chrominance subsampling from RGB, not
|
||||
* that we will supply the image as YCbCr.
|
||||
@ -1291,7 +1295,8 @@ make_tiff_write( VipsImage *im, const char *filename,
|
||||
gboolean pyramid,
|
||||
gboolean squash,
|
||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||
gboolean bigtiff )
|
||||
gboolean bigtiff,
|
||||
gboolean rgbjpeg )
|
||||
{
|
||||
TiffWrite *tw;
|
||||
|
||||
@ -1313,6 +1318,7 @@ make_tiff_write( VipsImage *im, const char *filename,
|
||||
tw->onebit = squash;
|
||||
tw->icc_profile = profile;
|
||||
tw->bigtiff = bigtiff;
|
||||
tw->rgbjpeg = rgbjpeg;
|
||||
tw->write_lock = NULL;
|
||||
|
||||
tw->resunit = get_resunit( resunit );
|
||||
@ -1531,7 +1537,8 @@ vips__tiff_write( VipsImage *in, const char *filename,
|
||||
gboolean pyramid,
|
||||
gboolean squash,
|
||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||
gboolean bigtiff )
|
||||
gboolean bigtiff,
|
||||
gboolean rgbjpeg )
|
||||
{
|
||||
TiffWrite *tw;
|
||||
int res;
|
||||
@ -1553,7 +1560,7 @@ vips__tiff_write( VipsImage *in, const char *filename,
|
||||
if( !(tw = make_tiff_write( in, filename,
|
||||
compression, Q, predictor, profile,
|
||||
tile, tile_width, tile_height, pyramid, squash,
|
||||
resunit, xres, yres, bigtiff )) )
|
||||
resunit, xres, yres, bigtiff, rgbjpeg )) )
|
||||
return( -1 );
|
||||
if( tw->pyramid ) {
|
||||
if( !(tw->bname = vips__temp_name( "%s.tif" )) ||
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include "pfreqfilt.h"
|
||||
|
||||
#ifdef HAVE_FFTW
|
||||
@ -294,22 +295,30 @@ vips_fwfft_build( VipsObject *object )
|
||||
VipsFwfft *fwfft = (VipsFwfft *) object;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 );
|
||||
|
||||
VipsImage *in;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_fwfft_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_bandfmt_iscomplex( freqfilt->in->BandFmt ) ) {
|
||||
if( vips__fftproc( VIPS_OBJECT( fwfft ), freqfilt->in, &t[0],
|
||||
in = freqfilt->in;
|
||||
|
||||
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 ) )
|
||||
return( -1 );
|
||||
}
|
||||
else {
|
||||
if( vips__fftproc( VIPS_OBJECT( fwfft ), freqfilt->in, &t[0],
|
||||
if( vips__fftproc( VIPS_OBJECT( fwfft ), in, &t[1],
|
||||
rfwfft1 ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips_image_write( t[0], freqfilt->out ) )
|
||||
if( vips_image_write( t[1], freqfilt->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include "pfreqfilt.h"
|
||||
|
||||
#ifdef HAVE_FFTW
|
||||
@ -207,22 +208,30 @@ vips_invfft_build( VipsObject *object )
|
||||
VipsInvfft *invfft = (VipsInvfft *) object;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 );
|
||||
|
||||
VipsImage *in;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_invfft_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
in = freqfilt->in;
|
||||
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
if( invfft->real ) {
|
||||
if( vips__fftproc( VIPS_OBJECT( invfft ),
|
||||
freqfilt->in, &t[0], rinvfft1 ) )
|
||||
in, &t[1], rinvfft1 ) )
|
||||
return( -1 );
|
||||
}
|
||||
else {
|
||||
if( vips__fftproc( VIPS_OBJECT( invfft ),
|
||||
freqfilt->in, &t[0], cinvfft1 ) )
|
||||
in, &t[1], cinvfft1 ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips_image_write( t[0], freqfilt->out ) )
|
||||
if( vips_image_write( t[1], freqfilt->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
typedef struct _VipsHistLocal {
|
||||
VipsOperation parent_instance;
|
||||
@ -235,8 +236,11 @@ vips_hist_local_build( VipsObject *object )
|
||||
|
||||
in = local->in;
|
||||
|
||||
if( vips_check_uncoded( class->nickname, in ) ||
|
||||
vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
if( vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
||||
return( -1 );
|
||||
|
||||
if( local->width > in->Xsize ||
|
||||
@ -247,13 +251,13 @@ vips_hist_local_build( VipsObject *object )
|
||||
|
||||
/* Expand the input.
|
||||
*/
|
||||
if( vips_embed( in, &t[0],
|
||||
if( vips_embed( in, &t[1],
|
||||
local->width / 2, local->height / 2,
|
||||
in->Xsize + local->width - 1, in->Ysize + local->height - 1,
|
||||
"extend", VIPS_EXTEND_COPY,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
in = t[1];
|
||||
|
||||
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 );
|
||||
VipsHistogramClass *hclass = VIPS_HISTOGRAM_GET_CLASS( histogram );
|
||||
|
||||
VipsImage **decode;
|
||||
VipsImage **format;
|
||||
VipsImage **band;
|
||||
VipsImage **size;
|
||||
@ -134,6 +135,7 @@ vips_histogram_build( VipsObject *object )
|
||||
*/
|
||||
g_assert( !histogram->in[histogram->n] );
|
||||
|
||||
decode = (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 );
|
||||
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 );
|
||||
|
||||
for( i = 0; i < histogram->n; i++ )
|
||||
if( vips_check_uncoded( class->nickname, histogram->in[i] ) ||
|
||||
vips_check_hist( class->nickname, histogram->in[i] ) )
|
||||
if( vips__image_decode( histogram->in[i], &decode[i] ) ||
|
||||
vips_check_hist( class->nickname, decode[i] ) )
|
||||
return( -1 );
|
||||
|
||||
/* 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 ) {
|
||||
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 ) )
|
||||
return( -1 );
|
||||
}
|
||||
else {
|
||||
if( vips__formatalike_vec( histogram->in,
|
||||
format, histogram->n ) )
|
||||
if( vips__formatalike_vec( decode, format, histogram->n ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
typedef struct _VipsStdif {
|
||||
VipsOperation parent_instance;
|
||||
@ -223,8 +224,11 @@ vips_stdif_build( VipsObject *object )
|
||||
|
||||
in = stdif->in;
|
||||
|
||||
if( vips_check_uncoded( class->nickname, in ) ||
|
||||
vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
if( vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
||||
return( -1 );
|
||||
|
||||
if( stdif->width > in->Xsize ||
|
||||
@ -239,13 +243,13 @@ vips_stdif_build( VipsObject *object )
|
||||
|
||||
/* Expand the input.
|
||||
*/
|
||||
if( vips_embed( in, &t[0],
|
||||
if( vips_embed( in, &t[1],
|
||||
stdif->width / 2, stdif->height / 2,
|
||||
in->Xsize + stdif->width - 1, in->Ysize + stdif->height - 1,
|
||||
"extend", VIPS_EXTEND_COPY,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
in = t[1];
|
||||
|
||||
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__image_decode( VipsImage *in, VipsImage **out );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -55,34 +55,6 @@ typedef struct _VipsObjectClass VipsObjectClass;
|
||||
/* 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 >*/ {
|
||||
VIPS_ARGUMENT_NONE = 0,
|
||||
VIPS_ARGUMENT_REQUIRED = 1,
|
||||
@ -461,6 +433,7 @@ struct _VipsObject {
|
||||
* profiling.
|
||||
*/
|
||||
size_t local_memory;
|
||||
|
||||
};
|
||||
|
||||
struct _VipsObjectClass {
|
||||
@ -561,6 +534,13 @@ struct _VipsObjectClass {
|
||||
*/
|
||||
GSList *argument_table_traverse;
|
||||
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 );
|
||||
|
@ -41,7 +41,8 @@ typedef enum /*< flags >*/ {
|
||||
VIPS_OPERATION_NONE = 0,
|
||||
VIPS_OPERATION_SEQUENTIAL = 1,
|
||||
VIPS_OPERATION_SEQUENTIAL_UNBUFFERED = 2,
|
||||
VIPS_OPERATION_NOCACHE = 4
|
||||
VIPS_OPERATION_NOCACHE = 4,
|
||||
VIPS_OPERATION_DEPRECATED = 8
|
||||
} VipsOperationFlags;
|
||||
|
||||
#define VIPS_TYPE_OPERATION (vips_operation_get_type())
|
||||
|
@ -89,8 +89,8 @@ typedef struct {
|
||||
GThread *thread; /* Just for sanity checking */
|
||||
} VipsBufferThread;
|
||||
|
||||
/* Per-image buffer cache. Hash to this from VipsBufferCache.
|
||||
* We can't store the GSList directly in the hash table, as GHashTable lacks an
|
||||
/* 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
|
||||
* update operation and we'd need to _remove() and _insert() on every list
|
||||
* operation.
|
||||
*/
|
||||
@ -127,6 +127,8 @@ VipsBuffer *vips_buffer_unref_ref( VipsBuffer *buffer,
|
||||
struct _VipsImage *im, VipsRect *area );
|
||||
void vips_buffer_print( VipsBuffer *buffer );
|
||||
|
||||
void vips__render_shutdown( void );
|
||||
|
||||
/* 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 );
|
||||
int vips_region_prepare_many( VipsRegion **reg, VipsRect *r );
|
||||
|
||||
void vips_region_invalidate( VipsRegion *reg );
|
||||
|
||||
void vips_region_dump_all( void );
|
||||
|
||||
/* Macros on VipsRegion.
|
||||
|
@ -50,10 +50,10 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
#define DEBUG_CREATE
|
||||
#define DEBUG_VERBOSE
|
||||
#define DEBUG
|
||||
#define DEBUG_CREATE
|
||||
*/
|
||||
#define DEBUG
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -70,11 +70,11 @@
|
||||
#ifdef DEBUG
|
||||
/* Track all regions here for debugging.
|
||||
*/
|
||||
static GSList *vips__buffers_all = NULL;
|
||||
static GSList *vips__buffer_all = NULL;
|
||||
#endif /*DEBUG*/
|
||||
|
||||
#ifdef DEBUG_CREATE
|
||||
static int buffer_cache_n = 0;
|
||||
static GSList *vips__buffer_cache_all = NULL;
|
||||
#endif /*DEBUG_CREATE*/
|
||||
|
||||
/* The maximum numbers of buffers we hold in reserve per image.
|
||||
@ -87,13 +87,19 @@ static GPrivate *buffer_thread_key = NULL;
|
||||
static void *
|
||||
vips_buffer_dump( VipsBuffer *buffer, size_t *reserve, size_t *alive )
|
||||
{
|
||||
vips_buffer_print( buffer );
|
||||
|
||||
if( buffer->im &&
|
||||
buffer->buf ) {
|
||||
printf( "buffer %p, %gMB\n",
|
||||
buffer->buf &&
|
||||
buffer->cache ) {
|
||||
printf( "buffer %p, %.3g MB\n",
|
||||
buffer, buffer->bsize / (1024 * 1024.0) );
|
||||
*alive += buffer->bsize;
|
||||
}
|
||||
else if( !buffer->im )
|
||||
else
|
||||
if( buffer->im &&
|
||||
buffer->buf &&
|
||||
!buffer->cache )
|
||||
*reserve += buffer->bsize;
|
||||
else
|
||||
printf( "buffer craziness!\n" );
|
||||
@ -101,18 +107,47 @@ vips_buffer_dump( VipsBuffer *buffer, size_t *reserve, size_t *alive )
|
||||
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
|
||||
vips_buffer_dump_all( void )
|
||||
{
|
||||
size_t reserve;
|
||||
size_t alive;
|
||||
if( vips__buffer_all ) {
|
||||
size_t reserve;
|
||||
size_t alive;
|
||||
|
||||
reserve = 0;
|
||||
alive = 0;
|
||||
vips_slist_map2( vips__buffers_all,
|
||||
(VipsSListMap2Fn) vips_buffer_dump, &reserve, &alive );
|
||||
printf( "%gMB alive\n", alive / (1024 * 1024.0) );
|
||||
printf( "%gMB in reserve\n", reserve / (1024 * 1024.0) );
|
||||
printf( "buffers:\n" );
|
||||
|
||||
reserve = 0;
|
||||
alive = 0;
|
||||
vips_slist_map2( vips__buffer_all,
|
||||
(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*/
|
||||
|
||||
@ -126,8 +161,8 @@ vips_buffer_free( VipsBuffer *buffer )
|
||||
#ifdef DEBUG
|
||||
g_mutex_lock( vips__global_lock );
|
||||
|
||||
g_assert( g_slist_find( vips__buffers_all, buffer ) );
|
||||
vips__buffers_all = g_slist_remove( vips__buffers_all, buffer );
|
||||
g_assert( g_slist_find( vips__buffer_all, buffer ) );
|
||||
vips__buffer_all = g_slist_remove( vips__buffer_all, buffer );
|
||||
|
||||
g_mutex_unlock( vips__global_lock );
|
||||
#endif /*DEBUG*/
|
||||
@ -146,11 +181,15 @@ buffer_cache_free( VipsBufferCache *cache )
|
||||
GSList *p;
|
||||
|
||||
#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",
|
||||
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*/
|
||||
|
||||
/* 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;
|
||||
|
||||
#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",
|
||||
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*/
|
||||
|
||||
return( cache );
|
||||
@ -276,7 +319,6 @@ vips_buffer_undone( VipsBuffer *buffer )
|
||||
{
|
||||
if( buffer->done ) {
|
||||
VipsBufferCache *cache = buffer->cache;
|
||||
VipsBufferThread *buffer_thread = cache->buffer_thread;
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf( "vips_buffer_undone: thread %p removing "
|
||||
@ -285,9 +327,9 @@ vips_buffer_undone( VipsBuffer *buffer )
|
||||
#endif /*DEBUG_VERBOSE*/
|
||||
|
||||
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( buffer_thread == buffer_thread_get() );
|
||||
g_assert( cache->buffer_thread == buffer_thread_get() );
|
||||
|
||||
cache->buffers = g_slist_remove( cache->buffers, buffer );
|
||||
|
||||
@ -404,8 +446,8 @@ vips_buffer_new( VipsImage *im, VipsRect *area )
|
||||
|
||||
#ifdef DEBUG
|
||||
g_mutex_lock( vips__global_lock );
|
||||
vips__buffers_all =
|
||||
g_slist_prepend( vips__buffers_all, buffer );
|
||||
vips__buffer_all =
|
||||
g_slist_prepend( vips__buffer_all, buffer );
|
||||
g_mutex_unlock( vips__global_lock );
|
||||
#endif /*DEBUG*/
|
||||
}
|
||||
|
@ -624,6 +624,7 @@ vips_operation_flags_get_type( void )
|
||||
{VIPS_OPERATION_SEQUENTIAL, "VIPS_OPERATION_SEQUENTIAL", "sequential"},
|
||||
{VIPS_OPERATION_SEQUENTIAL_UNBUFFERED, "VIPS_OPERATION_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"},
|
||||
{VIPS_OPERATION_NOCACHE, "VIPS_OPERATION_NOCACHE", "nocache"},
|
||||
{VIPS_OPERATION_DEPRECATED, "VIPS_OPERATION_DEPRECATED", "deprecated"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -937,6 +937,7 @@ vips_image_build( VipsObject *object )
|
||||
image->Type = VIPS_INTERPRETATION_MULTIBAND;
|
||||
|
||||
image->dtype = VIPS_IMAGE_SETBUF_FOREIGN;
|
||||
image->dhint = VIPS_DEMAND_STYLE_ANY;
|
||||
|
||||
break;
|
||||
|
||||
@ -952,9 +953,9 @@ vips_image_build( VipsObject *object )
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_region_invalidate( VipsRegion *reg )
|
||||
vips_image_real_invalidate_cb( VipsRegion *reg )
|
||||
{
|
||||
reg->invalid = TRUE;
|
||||
vips_region_invalidate( reg );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
@ -971,7 +972,7 @@ vips_image_real_invalidate( VipsImage *image )
|
||||
VIPS_GATE_STOP( "vips_image_real_invalidate: wait" );
|
||||
|
||||
(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 );
|
||||
}
|
||||
@ -1273,6 +1274,8 @@ vips_image_invalidate_all_cb( VipsImage *image )
|
||||
* is, images which depend on this image.
|
||||
*
|
||||
* The "invalidate" callback is triggered for all invalidated images.
|
||||
*
|
||||
* See also: vips_region_invalidate().
|
||||
*/
|
||||
void
|
||||
vips_image_invalidate_all( VipsImage *image )
|
||||
|
@ -369,6 +369,10 @@ vips_leak( void )
|
||||
fprintf( stderr, "%s", vips_buf_all( &buf ) );
|
||||
|
||||
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__render_shutdown();
|
||||
|
||||
vips_thread_shutdown();
|
||||
|
||||
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.
|
||||
*/
|
||||
enum {
|
||||
@ -1708,9 +1737,9 @@ gboolean
|
||||
vips_object_argument_needsstring( VipsObject *object, const char *name )
|
||||
{
|
||||
GParamSpec *pspec;
|
||||
GType otype;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
GType otype;
|
||||
VipsObjectClass *oclass;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1725,10 +1754,15 @@ vips_object_argument_needsstring( VipsObject *object, const char *name )
|
||||
/* Bools, input or output, don't need args.
|
||||
*/
|
||||
return( FALSE );
|
||||
else if( argument_class->flags & VIPS_ARGUMENT_INPUT )
|
||||
|
||||
if( argument_class->flags & VIPS_ARGUMENT_INPUT )
|
||||
/* All other inputs need something.
|
||||
*/
|
||||
return( TRUE );
|
||||
|
||||
/* Just output objects.
|
||||
*/
|
||||
|
||||
if( (otype = G_PARAM_SPEC_VALUE_TYPE( pspec )) &&
|
||||
g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_ref( otype )) )
|
||||
|
@ -70,6 +70,7 @@
|
||||
* @VIPS_OPERATION_NONE: no flags
|
||||
* @VIPS_OPERATION_SEQUENTIAL: can work sequentially
|
||||
* @VIPS_OPERATION_NOCACHE: must not be cached
|
||||
* @VIPS_OPERATION_DEPRECATED: a compatibility thing
|
||||
*
|
||||
* Flags we associate with an operation.
|
||||
*
|
||||
@ -83,6 +84,9 @@
|
||||
*
|
||||
* @VIPS_OPERATION_NOCACHE means that the operation must not be cached by
|
||||
* 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.
|
||||
|
@ -1375,6 +1375,25 @@ vips_region_prepare_many( VipsRegion **reg, VipsRect *r )
|
||||
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
|
||||
static void *
|
||||
vips_region_dump_all_cb( VipsRegion *region, size_t *alive )
|
||||
|
@ -5,6 +5,8 @@
|
||||
* 25/11/10
|
||||
* - in synchronous mode, use a single region for input and save huge
|
||||
* 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;
|
||||
|
||||
/* Set this to ask the render thread to quit.
|
||||
*/
|
||||
static gboolean render_kill = FALSE;
|
||||
|
||||
/* All the renders with dirty tiles.
|
||||
*/
|
||||
static GMutex *render_dirty_lock = NULL;
|
||||
@ -424,6 +430,13 @@ render_work( VipsThreadState *state, void *a )
|
||||
}
|
||||
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.
|
||||
*/
|
||||
if( render->notify )
|
||||
@ -471,44 +484,67 @@ render_dirty_put( Render *render )
|
||||
static void *
|
||||
render_thread_main( void *client )
|
||||
{
|
||||
for(;;) {
|
||||
Render *render;
|
||||
Render *render;
|
||||
|
||||
if( (render = render_dirty_get()) ) {
|
||||
/* Ignore errors, I'm not sure what we'd do with them
|
||||
* anyway.
|
||||
*/
|
||||
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
||||
"threadpool start\n" );
|
||||
while( (render = render_dirty_get()) &&
|
||||
!render_kill ) {
|
||||
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
||||
"threadpool start\n" );
|
||||
|
||||
render_reschedule = FALSE;
|
||||
if( vips_threadpool_run( render->in,
|
||||
render_thread_state_new,
|
||||
render_allocate,
|
||||
render_work,
|
||||
NULL,
|
||||
render ) )
|
||||
VIPS_DEBUG_MSG_RED( "render_thread_main: "
|
||||
"threadpool_run failed\n" );
|
||||
render_reschedule = FALSE;
|
||||
if( vips_threadpool_run( render->in,
|
||||
render_thread_state_new,
|
||||
render_allocate,
|
||||
render_work,
|
||||
NULL,
|
||||
render ) )
|
||||
VIPS_DEBUG_MSG_RED( "render_thread_main: "
|
||||
"threadpool_run failed\n" );
|
||||
|
||||
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
||||
"threadpool return\n" );
|
||||
VIPS_DEBUG_MSG_GREEN( "render_thread_main: "
|
||||
"threadpool return\n" );
|
||||
|
||||
/* Add back to the jobs list, if we need to.
|
||||
*/
|
||||
render_dirty_put( render );
|
||||
/* Add back to the jobs list, if we need to.
|
||||
*/
|
||||
render_dirty_put( render );
|
||||
|
||||
/* _get() does a ref to make sure we keep the render
|
||||
* alive during processing ... unref before we loop.
|
||||
* This can kill off the render.
|
||||
*/
|
||||
render_unref( render );
|
||||
}
|
||||
/* _get() does a ref to make sure we keep the render
|
||||
* alive during processing ... unref before we loop.
|
||||
* This can kill off the render.
|
||||
*/
|
||||
render_unref( render );
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
static int
|
||||
@ -896,14 +932,17 @@ static int
|
||||
image_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
Render *render = (Render *) a;
|
||||
int tile_width = render->tile_width;
|
||||
int tile_height = render->tile_height;
|
||||
VipsRegion *reg = (VipsRegion *) seq;
|
||||
VipsRect *r = &out->valid;
|
||||
|
||||
int x, y;
|
||||
|
||||
/* Find top left of tiles we need.
|
||||
*/
|
||||
int xs = (r->left / render->tile_width) * render->tile_width;
|
||||
int ys = (r->top / render->tile_height) * render->tile_height;
|
||||
int xs = (r->left / tile_width) * tile_width;
|
||||
int ys = (r->top / tile_height) * tile_height;
|
||||
|
||||
VIPS_DEBUG_MSG( "image_fill: left = %d, top = %d, "
|
||||
"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( x = xs; x < VIPS_RECT_RIGHT( r ); x += render->tile_width ) {
|
||||
for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += tile_height )
|
||||
for( x = xs; x < VIPS_RECT_RIGHT( r ); x += tile_width ) {
|
||||
VipsRect area;
|
||||
Tile *tile;
|
||||
|
||||
area.left = x;
|
||||
area.top = y;
|
||||
area.width = render->tile_width;
|
||||
area.height = render->tile_height;
|
||||
area.width = tile_width;
|
||||
area.height = tile_height;
|
||||
|
||||
tile = render_tile_request( render, reg, &area );
|
||||
if( tile )
|
||||
@ -956,13 +995,16 @@ static int
|
||||
mask_fill( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
Render *render = (Render *) a;
|
||||
int tile_width = render->tile_width;
|
||||
int tile_height = render->tile_height;
|
||||
VipsRect *r = &out->valid;
|
||||
|
||||
int x, y;
|
||||
|
||||
/* Find top left of tiles we need.
|
||||
*/
|
||||
int xs = (r->left / render->tile_width) * render->tile_width;
|
||||
int ys = (r->top / render->tile_height) * render->tile_height;
|
||||
int xs = (r->left / tile_width) * tile_width;
|
||||
int ys = (r->top / tile_height) * tile_height;
|
||||
|
||||
VIPS_DEBUG_MSG( "mask_fill: left = %d, top = %d, "
|
||||
"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 );
|
||||
|
||||
for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += render->tile_height )
|
||||
for( x = xs; x < VIPS_RECT_RIGHT( r ); x += render->tile_width ) {
|
||||
for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += tile_height )
|
||||
for( x = xs; x < VIPS_RECT_RIGHT( r ); x += tile_width ) {
|
||||
VipsRect area;
|
||||
Tile *tile;
|
||||
int value;
|
||||
|
||||
area.left = x;
|
||||
area.top = y;
|
||||
area.width = render->tile_width;
|
||||
area.height = render->tile_height;
|
||||
area.width = tile_width;
|
||||
area.height = tile_height;
|
||||
|
||||
tile = render_tile_lookup( render, &area );
|
||||
value = (tile &&
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "pmorphology.h"
|
||||
|
||||
@ -83,15 +84,22 @@ vips_morph_build( VipsObject *object )
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
|
||||
|
||||
INTMASK *imsk;
|
||||
VipsImage *in;
|
||||
|
||||
g_object_set( morph, "out", vips_image_new(), NULL );
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_morph_parent_class )->build( object ) )
|
||||
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 );
|
||||
morph->M = t[0];
|
||||
morph->M = t[1];
|
||||
|
||||
if( !(imsk = im_vips2imask( morph->M, class->nickname )) ||
|
||||
!im_local_imask( morph->out, imsk ) )
|
||||
@ -99,12 +107,12 @@ vips_morph_build( VipsObject *object )
|
||||
|
||||
switch( morph->morph ) {
|
||||
case VIPS_OPERATION_MORPHOLOGY_DILATE:
|
||||
if( im_dilate( morphology->in, morph->out, imsk ) )
|
||||
if( im_dilate( in, morph->out, imsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
case VIPS_OPERATION_MORPHOLOGY_ERODE:
|
||||
if( im_erode( morphology->in, morph->out, imsk ) )
|
||||
if( im_erode( in, morph->out, imsk ) )
|
||||
return( -1 );
|
||||
break;
|
||||
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "pmorphology.h"
|
||||
|
||||
@ -340,8 +341,11 @@ vips_rank_build( VipsObject *object )
|
||||
|
||||
in = morphology->in;
|
||||
|
||||
if( vips_check_uncoded( class->nickname, in ) ||
|
||||
vips_check_noncomplex( class->nickname, in ) )
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
if( vips_check_noncomplex( class->nickname, in ) )
|
||||
return( -1 );
|
||||
if( rank->width > in->Xsize ||
|
||||
rank->height > in->Ysize ) {
|
||||
@ -356,13 +360,13 @@ vips_rank_build( VipsObject *object )
|
||||
|
||||
/* Expand the input.
|
||||
*/
|
||||
if( vips_embed( in, &t[0],
|
||||
if( vips_embed( in, &t[1],
|
||||
rank->width / 2, rank->height / 2,
|
||||
in->Xsize + rank->width - 1, in->Ysize + rank->height - 1,
|
||||
"extend", VIPS_EXTEND_COPY,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
in = t[1];
|
||||
|
||||
g_object_set( object, "out", vips_image_new(), NULL );
|
||||
|
||||
|
@ -79,6 +79,8 @@
|
||||
* 14/12/12
|
||||
* - redone as a class
|
||||
* - 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 );
|
||||
}
|
||||
|
||||
/* 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
|
||||
vips_affine_build( VipsObject *object )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsResample *resample = VIPS_RESAMPLE( object );
|
||||
VipsAffine *affine = (VipsAffine *) object;
|
||||
|
||||
VipsImage **t = (VipsImage **)
|
||||
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 ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_check_coding_noneorlabq( class->nickname, resample->in ) )
|
||||
if( vips_check_coding_known( class->nickname, resample->in ) )
|
||||
return( -1 );
|
||||
if( vips_check_vector_length( class->nickname,
|
||||
affine->matrix->n, 4 ) )
|
||||
@ -463,23 +485,19 @@ vips_affine_build( VipsObject *object )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Unpack labq for processing.
|
||||
*/
|
||||
if( in->Coding == VIPS_CODING_LABQ ) {
|
||||
if( vips_LabQ2LabS( in, &t[0], NULL ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
}
|
||||
if( vips__image_decode( in, &t[0] ) )
|
||||
return( -1 );
|
||||
in = t[0];
|
||||
|
||||
/* 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,
|
||||
in->Xsize + window_size, in->Ysize + window_size,
|
||||
"extend", VIPS_EXTEND_COPY,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
in = t[1];
|
||||
in = t[2];
|
||||
|
||||
/* 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 );
|
||||
|
||||
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->window_size = 4;
|
||||
|
@ -354,7 +354,7 @@ vips_interpolate_nearest_class_init( VipsInterpolateNearestClass *class )
|
||||
VIPS_INTERPOLATE_CLASS( class );
|
||||
|
||||
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->window_size = 1;
|
||||
@ -525,7 +525,7 @@ vips_interpolate_bilinear_class_init( VipsInterpolateBilinearClass *class )
|
||||
(VipsInterpolateClass *) class;
|
||||
|
||||
object_class->nickname = "bilinear";
|
||||
object_class->description = _( "Bilinear interpolation" );
|
||||
object_class->description = _( "bilinear interpolation" );
|
||||
|
||||
interpolate_class->interpolate = vips_interpolate_bilinear_interpolate;
|
||||
interpolate_class->window_size = 2;
|
||||
|
@ -856,7 +856,7 @@ vips_interpolate_lbb_class_init( VipsInterpolateLbbClass *klass )
|
||||
VIPS_INTERPOLATE_CLASS( klass );
|
||||
|
||||
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->window_size = 4;
|
||||
|
@ -1577,7 +1577,7 @@ vips_interpolate_nohalo_class_init( VipsInterpolateNohaloClass *klass )
|
||||
|
||||
object_class->nickname = "nohalo";
|
||||
object_class->description =
|
||||
_( "Edge sharpening resampler with halo reduction" );
|
||||
_( "edge sharpening resampler with halo reduction" );
|
||||
|
||||
interpolate_class->interpolate = vips_interpolate_nohalo_interpolate;
|
||||
interpolate_class->window_size = 5;
|
||||
|
@ -85,6 +85,7 @@
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/debug.h>
|
||||
#include <vips/internal.h>
|
||||
|
||||
#include "presample.h"
|
||||
|
||||
@ -310,6 +311,10 @@ vips_shrink_build( VipsObject *object )
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
VipsResample *resample = VIPS_RESAMPLE( 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 ) )
|
||||
return( -1 );
|
||||
@ -318,7 +323,9 @@ vips_shrink_build( VipsObject *object )
|
||||
shrink->mh = ceil( shrink->yshrink );
|
||||
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 );
|
||||
|
||||
if( shrink->xshrink < 1.0 ||
|
||||
@ -336,14 +343,20 @@ vips_shrink_build( VipsObject *object )
|
||||
|
||||
if( shrink->xshrink == 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
|
||||
* combine shrink with conv you'll need to use a line cache to maintain
|
||||
* sequentiality.
|
||||
*/
|
||||
if( vips_image_pipelinev( resample->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, resample->in, NULL ) )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* 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
|
||||
* fractional part), we just see the integer part here.
|
||||
*/
|
||||
resample->out->Xsize = resample->in->Xsize / shrink->xshrink;
|
||||
resample->out->Ysize = resample->in->Ysize / shrink->yshrink;
|
||||
resample->out->Xsize = in->Xsize / shrink->xshrink;
|
||||
resample->out->Ysize = in->Ysize / shrink->yshrink;
|
||||
if( resample->out->Xsize <= 0 ||
|
||||
resample->out->Ysize <= 0 ) {
|
||||
vips_error( class->nickname,
|
||||
@ -363,7 +376,7 @@ vips_shrink_build( VipsObject *object )
|
||||
|
||||
#ifdef DEBUG
|
||||
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 );
|
||||
printf( "vips_shrink_build: %d x %d block average\n",
|
||||
shrink->mw, shrink->mh );
|
||||
@ -371,7 +384,7 @@ vips_shrink_build( VipsObject *object )
|
||||
|
||||
if( vips_image_generate( resample->out,
|
||||
vips_shrink_start, vips_shrink_gen, vips_shrink_stop,
|
||||
resample->in, shrink ) )
|
||||
in, shrink ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
|
Loading…
Reference in New Issue
Block a user