2007-08-29 18:23:50 +02:00
|
|
|
/* Various useful definitions.
|
|
|
|
*
|
|
|
|
* J.Cupitt, 8/4/93
|
|
|
|
* 15/7/96 JC
|
|
|
|
* - C++ stuff added
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
This file is part of VIPS.
|
|
|
|
|
|
|
|
VIPS is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef IM_UTIL_H
|
|
|
|
#define IM_UTIL_H
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif /*__cplusplus*/
|
|
|
|
|
2008-11-17 23:56:16 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2007-08-29 18:23:50 +02:00
|
|
|
/* Some platforms don't have M_PI in math.h :-(
|
|
|
|
*/
|
|
|
|
#define IM_PI (3.14159265358979323846)
|
|
|
|
|
|
|
|
/* Only define if IM_ENABLE_DEPRECATED is set.
|
|
|
|
*/
|
|
|
|
#ifdef IM_ENABLE_DEPRECATED
|
|
|
|
|
|
|
|
#ifndef MAX
|
|
|
|
#define MAX(A,B) ((A)>(B)?(A):(B))
|
|
|
|
#define MIN(A,B) ((A)<(B)?(A):(B))
|
|
|
|
#endif /*MAX*/
|
|
|
|
|
|
|
|
#define CLIP(A,V,B) MAX( (A), MIN( (B), (V) ) )
|
|
|
|
#define NEW(IM,A) ((A *)im_malloc((IM),sizeof(A)))
|
|
|
|
#define NUMBER(R) (sizeof(R)/sizeof(R[0]))
|
|
|
|
#define ARRAY(IM,N,T) ((T *)im_malloc((IM),(N) * sizeof(T)))
|
|
|
|
|
|
|
|
/* Duff's device. Do OPERation N times in a 16-way unrolled loop.
|
|
|
|
*/
|
|
|
|
#define UNROLL( N, OPER ) { \
|
|
|
|
if( (N) ) { \
|
|
|
|
int duff_count = ((N) + 15) / 16; \
|
|
|
|
\
|
|
|
|
switch( (N) % 16 ) { \
|
|
|
|
case 0: do { OPER; \
|
|
|
|
case 15: OPER; \
|
|
|
|
case 14: OPER; \
|
|
|
|
case 13: OPER; \
|
|
|
|
case 12: OPER; \
|
|
|
|
case 11: OPER; \
|
|
|
|
case 10: OPER; \
|
|
|
|
case 9: OPER; \
|
|
|
|
case 8: OPER; \
|
|
|
|
case 7: OPER; \
|
|
|
|
case 6: OPER; \
|
|
|
|
case 5: OPER; \
|
|
|
|
case 4: OPER; \
|
|
|
|
case 3: OPER; \
|
|
|
|
case 2: OPER; \
|
|
|
|
case 1: OPER; \
|
|
|
|
} while( --duff_count > 0 ); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Round a float to the nearest integer. This should give an identical result
|
|
|
|
* to the math.h rint() function (and the old SunOS nint() function), but be
|
|
|
|
* much faster. Beware: it evaluates its argument more than once, so don't use
|
|
|
|
* ++!
|
|
|
|
*/
|
|
|
|
#define RINT( R ) ((int)((R)>0?((R)+0.5):((R)-0.5)))
|
|
|
|
|
|
|
|
/* Various integer range clips. Record over/under flows.
|
|
|
|
*/
|
|
|
|
#define CLIP_UCHAR( V, SEQ ) { \
|
|
|
|
if( (V) & (UCHAR_MAX ^ -1) ) { \
|
|
|
|
if( (V) < 0 ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = 0; \
|
|
|
|
} \
|
|
|
|
if( (V) > UCHAR_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = UCHAR_MAX; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CLIP_USHORT( V, SEQ ) { \
|
|
|
|
if( (V) & (USHRT_MAX ^ -1) ) { \
|
|
|
|
if( (V) < 0 ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = 0; \
|
|
|
|
} \
|
|
|
|
if( (V) > USHRT_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = USHRT_MAX; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CLIP_CHAR( V, SEQ ) { \
|
|
|
|
if( (V) < SCHAR_MIN ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = SCHAR_MIN; \
|
|
|
|
} \
|
|
|
|
if( (V) > SCHAR_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = SCHAR_MAX; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CLIP_SHORT( V, SEQ ) { \
|
|
|
|
if( (V) < SHRT_MIN ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = SHRT_MIN; \
|
|
|
|
} \
|
|
|
|
if( (V) > SHRT_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = SHRT_MAX; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CLIP_NONE( V, SEQ ) {}
|
|
|
|
|
|
|
|
#endif /*IM_ENABLE_DEPRECATED*/
|
|
|
|
|
|
|
|
#define IM_MAX(A,B) ((A)>(B)?(A):(B))
|
|
|
|
#define IM_MIN(A,B) ((A)<(B)?(A):(B))
|
|
|
|
#define IM_ABS(x) (((x) >= 0) ? (x) : -(x))
|
|
|
|
|
|
|
|
#define IM_CLIP(A,V,B) IM_MAX( (A), IM_MIN( (B), (V) ) )
|
|
|
|
#define IM_NEW(IM,A) ((A *)im_malloc((IM),sizeof(A)))
|
|
|
|
#define IM_NUMBER(R) ((int)(sizeof(R)/sizeof(R[0])))
|
|
|
|
#define IM_ARRAY(IM,N,T) ((T *)im_malloc((IM),(N) * sizeof(T)))
|
|
|
|
#define IM_FREEF( F, S ) do { \
|
|
|
|
if( S ) { \
|
|
|
|
(void) F( (S) ); \
|
|
|
|
(S) = 0; \
|
|
|
|
} \
|
|
|
|
} while( 0 )
|
|
|
|
#define IM_FREE( A ) IM_FREEF( im_free, A )
|
|
|
|
#define IM_SETSTR( S, V ) do { \
|
2008-05-12 20:16:38 +02:00
|
|
|
const char *sst = (V); \
|
|
|
|
\
|
|
|
|
if( (S) != sst ) { \
|
|
|
|
if( !(S) || !sst || strcmp( (S), sst ) != 0 ) { \
|
2007-08-29 18:23:50 +02:00
|
|
|
IM_FREE( S ); \
|
|
|
|
if( sst ) \
|
|
|
|
(S) = im_strdup( NULL, sst ); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} while( 0 )
|
|
|
|
|
|
|
|
/* Duff's device. Do OPERation N times in a 16-way unrolled loop.
|
|
|
|
*/
|
|
|
|
#define IM_UNROLL( N, OPER ) { \
|
|
|
|
if( (N) ) { \
|
|
|
|
int duff_count = ((N) + 15) / 16; \
|
|
|
|
\
|
|
|
|
switch( (N) % 16 ) { \
|
|
|
|
case 0: do { OPER; \
|
|
|
|
case 15: OPER; \
|
|
|
|
case 14: OPER; \
|
|
|
|
case 13: OPER; \
|
|
|
|
case 12: OPER; \
|
|
|
|
case 11: OPER; \
|
|
|
|
case 10: OPER; \
|
|
|
|
case 9: OPER; \
|
|
|
|
case 8: OPER; \
|
|
|
|
case 7: OPER; \
|
|
|
|
case 6: OPER; \
|
|
|
|
case 5: OPER; \
|
|
|
|
case 4: OPER; \
|
|
|
|
case 3: OPER; \
|
|
|
|
case 2: OPER; \
|
|
|
|
case 1: OPER; \
|
|
|
|
} while( --duff_count > 0 ); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Round a float to the nearest integer. This should give an identical result
|
|
|
|
* to the math.h rint() function (and the old SunOS nint() function), but be
|
|
|
|
* much faster. Beware: it evaluates its argument more than once, so don't use
|
|
|
|
* ++!
|
|
|
|
*/
|
|
|
|
#define IM_RINT( R ) ((int)((R)>0?((R)+0.5):((R)-0.5)))
|
|
|
|
|
|
|
|
/* Various integer range clips. Record over/under flows.
|
|
|
|
*/
|
|
|
|
#define IM_CLIP_UCHAR( V, SEQ ) { \
|
|
|
|
if( (V) < 0 ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = 0; \
|
|
|
|
} \
|
|
|
|
else if( (V) > UCHAR_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = UCHAR_MAX; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define IM_CLIP_USHORT( V, SEQ ) { \
|
|
|
|
if( (V) < 0 ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = 0; \
|
|
|
|
} \
|
|
|
|
else if( (V) > USHRT_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = USHRT_MAX; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define IM_CLIP_CHAR( V, SEQ ) { \
|
|
|
|
if( (V) < SCHAR_MIN ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = SCHAR_MIN; \
|
|
|
|
} \
|
|
|
|
else if( (V) > SCHAR_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = SCHAR_MAX; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define IM_CLIP_SHORT( V, SEQ ) { \
|
|
|
|
if( (V) < SHRT_MIN ) { \
|
|
|
|
(SEQ)->underflow++; \
|
|
|
|
(V) = SHRT_MIN; \
|
|
|
|
} \
|
|
|
|
else if( (V) > SHRT_MAX ) { \
|
|
|
|
(SEQ)->overflow++; \
|
|
|
|
(V) = SHRT_MAX; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define IM_CLIP_NONE( V, SEQ ) {}
|
|
|
|
|
|
|
|
/* Now implemented as macros.
|
|
|
|
*/
|
|
|
|
#define im_open_local( IM, NAME, MODE ) \
|
|
|
|
((IMAGE *) im_local( (IM), \
|
|
|
|
(im_construct_fn) im_open, (im_callback_fn) im_close, \
|
|
|
|
(void *) (NAME), (void *) (MODE), NULL ))
|
|
|
|
|
|
|
|
/* Strange double cast stops bogus warnings from gcc 4.1
|
|
|
|
*/
|
|
|
|
#define im_open_local_array( IM, OUT, N, NAME, MODE ) \
|
|
|
|
(im_local_array( (IM), (void **)((void*)(OUT)), (N),\
|
|
|
|
(im_construct_fn) im_open, (im_callback_fn) im_close, \
|
|
|
|
(void *) (NAME), (void *) (MODE), NULL ))
|
|
|
|
|
2008-11-17 23:56:16 +01:00
|
|
|
/* Basic function types.
|
|
|
|
*/
|
|
|
|
typedef int (*im_callback_fn)( void *, void * );
|
|
|
|
typedef void *(*im_construct_fn)( void *, void *, void * );
|
|
|
|
|
2007-08-29 18:23:50 +02:00
|
|
|
/* strtok replacement.
|
|
|
|
*/
|
|
|
|
char *im__break_token( char *str, char *brk );
|
|
|
|
|
|
|
|
/* Like GFunc, but return a value.
|
|
|
|
*/
|
|
|
|
typedef void *(*VSListMap2Fn)( void *, void *, void * );
|
|
|
|
typedef void *(*VSListMap4Fn)( void *, void *, void *, void *, void * );
|
|
|
|
typedef void *(*VSListFold2Fn)( void *, void *, void *, void * );
|
|
|
|
|
|
|
|
gboolean im_slist_equal( GSList *l1, GSList *l2 );
|
|
|
|
void *im_slist_map2( GSList *list, VSListMap2Fn fn, void *a, void *b );
|
|
|
|
void *im_slist_map2_rev( GSList *list, VSListMap2Fn fn, void *a, void *b );
|
|
|
|
void *im_slist_map4( GSList *list,
|
|
|
|
VSListMap4Fn fn, void *a, void *b, void *c, void *d );
|
|
|
|
void *im_slist_fold2( GSList *list, void *start,
|
|
|
|
VSListFold2Fn fn, void *a, void *b );
|
|
|
|
GSList *im_slist_filter( GSList *list, VSListMap2Fn fn, void *a, void *b );
|
|
|
|
void im_slist_free_all( GSList *list );
|
|
|
|
|
|
|
|
void *im_map_equal( void *a, void *b );
|
|
|
|
|
2008-08-21 10:32:24 +02:00
|
|
|
void *im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b );
|
|
|
|
|
2008-11-28 17:26:33 +01:00
|
|
|
typedef void *(*VipsTypeMap)( GType, void * );
|
|
|
|
typedef void *(*VipsTypeMap2)( GType, void *, void * );
|
|
|
|
typedef void *(*VipsClassMap)( VipsObjectClass *, void * );
|
|
|
|
void *vips_type_map( GType base, VipsTypeMap2 fn, void *a, void *b );
|
|
|
|
void *vips_type_map_concrete_all( GType base, VipsTypeMap fn, void *a );
|
|
|
|
void *vips_class_map_concrete_all( GType base, VipsClassMap fn, void *a );
|
2008-11-30 10:32:18 +01:00
|
|
|
VipsObjectClass *vips_class_find( const char *basename, const char *nickname );
|
2008-11-28 17:26:33 +01:00
|
|
|
GType vips_type_find( const char *basename, const char *nickname );
|
2008-11-26 21:56:13 +01:00
|
|
|
|
2007-08-29 18:23:50 +02:00
|
|
|
char *im_strncpy( char *dest, const char *src, int n );
|
|
|
|
char *im_strrstr( const char *haystack, const char *needle );
|
|
|
|
char *im_strdup( IMAGE *im, const char *str );
|
|
|
|
gboolean im_ispostfix( const char *a, const char *b );
|
|
|
|
gboolean im_isprefix( const char *a, const char *b );
|
|
|
|
int im_vsnprintf( char *str, size_t size, const char *format, va_list ap );
|
|
|
|
int im_snprintf( char *str, size_t size, const char *format, ... )
|
|
|
|
__attribute__((format(printf, 3, 4)));
|
|
|
|
char *im_break_token( char *str, const char *brk );
|
|
|
|
|
|
|
|
const char *im_skip_dir( const char *filename );
|
|
|
|
void im_filename_split( const char *path, char *name, char *mode );
|
|
|
|
void im_filename_suffix( const char *path, char *suffix );
|
|
|
|
int im_filename_suffix_match( const char *path, const char *suffixes[] );
|
|
|
|
char *im_getnextoption( char **in );
|
|
|
|
char *im_getsuboption( const char *buf );
|
|
|
|
|
|
|
|
void *im_local( IMAGE *im,
|
|
|
|
im_construct_fn cons, im_callback_fn dest, void *a, void *b, void *c );
|
|
|
|
int im_local_array( IMAGE *im, void **out, int n,
|
|
|
|
im_construct_fn cons, im_callback_fn dest, void *a, void *b, void *c );
|
|
|
|
|
|
|
|
gint64 im_file_length( int fd );
|
2008-08-15 10:40:05 +02:00
|
|
|
int im__write( int fd, const void *buf, size_t count );
|
2007-08-29 18:23:50 +02:00
|
|
|
|
|
|
|
char *im__file_read( FILE *fp, const char *name, unsigned int *length_out );
|
|
|
|
char *im__file_read_name( const char *name, unsigned int *length_out );
|
2008-08-15 10:40:05 +02:00
|
|
|
int im__file_write( void *data, size_t size, size_t nmemb, FILE *stream );
|
|
|
|
|
2007-08-29 18:23:50 +02:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif /*__cplusplus*/
|
|
|
|
|
|
|
|
#endif /*IM_UTIL_H*/
|