@ -2,6 +2,28 @@
# include <vips/vips.h>
# include <vips/vips.h>
# include <vips/vips7compat.h>
# include <vips/vips7compat.h>
# ifdef VIPS_MAGICK_H
# define VIPS_MAGICK_SUPPORT 1
# else
# define VIPS_MAGICK_SUPPORT 0
# endif
/**
* Starting libvips 7.41 , VIPS_ANGLE_x has been renamed to VIPS_ANGLE_Dx
* " to help python " . So we provide the macro to correctly build for versions
* before 7.41 . x .
* https : //github.com/jcupitt/libvips/blob/master/ChangeLog#L128
*/
# if (VIPS_MAJOR_VERSION == 7 && VIPS_MINOR_VERSION < 41)
# define VIPS_ANGLE_D0 VIPS_ANGLE_0
# define VIPS_ANGLE_D90 VIPS_ANGLE_90
# define VIPS_ANGLE_D180 VIPS_ANGLE_180
# define VIPS_ANGLE_D270 VIPS_ANGLE_270
# endif
# define EXIF_IFD0_ORIENTATION "exif-ifd0-Orientation"
enum types {
enum types {
UNKNOWN = 0 ,
UNKNOWN = 0 ,
JPEG ,
JPEG ,
@ -12,9 +34,9 @@ enum types {
} ;
} ;
typedef struct {
typedef struct {
char * Text ;
const char * Text ;
char * Font ;
const char * Font ;
} w atermarkTextOptions;
} W atermarkTextOptions;
typedef struct {
typedef struct {
int Width ;
int Width ;
@ -23,35 +45,80 @@ typedef struct {
int NoReplicate ;
int NoReplicate ;
float Opacity ;
float Opacity ;
double Background [ 3 ] ;
double Background [ 3 ] ;
} watermarkOptions ;
} WatermarkOptions ;
static int
has_profile_embed ( VipsImage * image ) {
return vips_image_get_typeof ( image , VIPS_META_ICC_NAME ) ;
}
static void
remove_profile ( VipsImage * image ) {
vips_image_remove ( image , VIPS_META_ICC_NAME ) ;
}
static gboolean
with_interlace ( int interlace ) {
return interlace > 0 ? TRUE : FALSE ;
}
static int
has_alpha_channel ( VipsImage * image ) {
return (
( image - > Bands = = 2 & & image - > Type = = VIPS_INTERPRETATION_B_W ) | |
( image - > Bands = = 4 & & image - > Type ! = VIPS_INTERPRETATION_CMYK ) | |
( image - > Bands = = 5 & & image - > Type = = VIPS_INTERPRETATION_CMYK )
) ? 1 : 0 ;
}
/**
* This method is here to handle the weird initialization of the vips lib .
* libvips use a macro VIPS_INIT ( ) that call vips__init ( ) in version < 7.41 ,
* or calls vips_init ( ) in version > = 7.41 .
*
* Anyway , it ' s not possible to build bimg on Debian Jessie with libvips 7.40 . x ,
* as vips_init ( ) is a macro to VIPS_INIT ( ) , which is also a macro , hence , cgo
* is unable to determine the return type of vips_init ( ) , making the build impossible .
* In order to correctly build bimg , for version < 7.41 , we should undef vips_init and
* creates a vips_init ( ) method that calls VIPS_INIT ( ) .
*/
# if (VIPS_MAJOR_VERSION == 7 && VIPS_MINOR_VERSION < 41)
# undef vips_init
int
int
vips_affine_interpolator ( VipsImage * in , VipsImage * * out , double a , double b , double c , double d , VipsInterpolate * interpolator )
vips_ init( const char * argv0 )
{
{
return VIPS_INIT ( argv0 ) ;
}
# endif
void
vips_enable_cache_set_trace ( ) {
vips_cache_set_trace ( TRUE ) ;
}
int
vips_affine_interpolator ( VipsImage * in , VipsImage * * out , double a , double b , double c , double d , VipsInterpolate * interpolator ) {
return vips_affine ( in , out , a , b , c , d , " interpolate " , interpolator , NULL ) ;
return vips_affine ( in , out , a , b , c , d , " interpolate " , interpolator , NULL ) ;
} ;
}
int
int
vips_jpegload_buffer_shrink ( void * buf , size_t len , VipsImage * * out , int shrink )
vips_jpegload_buffer_shrink ( void * buf , size_t len , VipsImage * * out , int shrink ) {
{
return vips_jpegload_buffer ( buf , len , out , " shrink " , shrink , NULL ) ;
return vips_jpegload_buffer ( buf , len , out , " shrink " , shrink , NULL ) ;
} ;
}
int
int
vips_flip_bridge ( VipsImage * in , VipsImage * * out , int direction )
vips_flip_bridge ( VipsImage * in , VipsImage * * out , int direction ) {
{
return vips_flip ( in , out , direction , NULL ) ;
return vips_flip ( in , out , direction , NULL ) ;
} ;
}
int
int
vips_shrink_bridge ( VipsImage * in , VipsImage * * out , double xshrink , double yshrink )
vips_shrink_bridge ( VipsImage * in , VipsImage * * out , double xshrink , double yshrink ) {
{
return vips_shrink ( in , out , xshrink , yshrink , NULL ) ;
return vips_shrink ( in , out , xshrink , yshrink , NULL ) ;
} ;
}
int
int
vips_rotate ( VipsImage * in , VipsImage * * buf , int angle )
vips_rotate ( VipsImage * in , VipsImage * * out , int angle ) {
{
int rotate = VIPS_ANGLE_D0 ;
int rotate = VIPS_ANGLE_D0 ;
if ( angle = = 90 ) {
if ( angle = = 90 ) {
@ -62,35 +129,21 @@ vips_rotate(VipsImage *in, VipsImage **buf, int angle)
rotate = VIPS_ANGLE_D270 ;
rotate = VIPS_ANGLE_D270 ;
}
}
return vips_rot ( in , buf , rotate , NULL ) ;
return vips_rot ( in , out , rotate , NULL ) ;
} ;
}
int
int
vips_exif_orientation ( VipsImage * image ) {
vips_exif_orientation ( VipsImage * image ) {
int orientation = 0 ;
int orientation = 0 ;
const char * * exif ;
const char * exif ;
if (
if (
vips_image_get_typeof ( image , " exif-ifd0-Orientation " ) ! = 0 & &
vips_image_get_typeof ( image , EXIF_IFD0_ORIENTATION ) ! = 0 & &
! vips_image_get_string ( image , " exif-ifd0-Orientation " , exif )
! vips_image_get_string ( image , EXIF_IFD0_ORIENTATION , & exif )
) {
) {
orientation = atoi ( exif [ 0 ] ) ;
orientation = atoi ( & exif [ 0 ] ) ;
}
}
return orientation ;
return orientation ;
} ;
}
int
has_profile_embed ( VipsImage * image ) {
return ( vips_image_get_typeof ( image , VIPS_META_ICC_NAME ) > 0 ) ? 1 : 0 ;
} ;
int
has_alpha_channel ( VipsImage * image ) {
return (
( image - > Bands = = 2 & & image - > Type = = VIPS_INTERPRETATION_B_W ) | |
( image - > Bands = = 4 & & image - > Type ! = VIPS_INTERPRETATION_CMYK ) | |
( image - > Bands = = 5 & & image - > Type = = VIPS_INTERPRETATION_CMYK )
) ? 1 : 0 ;
} ;
int
int
interpolator_window_size ( char const * name ) {
interpolator_window_size ( char const * name ) {
@ -98,102 +151,137 @@ interpolator_window_size(char const *name) {
int window_size = vips_interpolate_get_window_size ( interpolator ) ;
int window_size = vips_interpolate_get_window_size ( interpolator ) ;
g_object_unref ( interpolator ) ;
g_object_unref ( interpolator ) ;
return window_size ;
return window_size ;
} ;
}
const char *
const char *
vips_enum_nick_bridge ( VipsImage * image ) {
vips_enum_nick_bridge ( VipsImage * image ) {
return vips_enum_nick ( VIPS_TYPE_INTERPRETATION , image - > Type ) ;
return vips_enum_nick ( VIPS_TYPE_INTERPRETATION , image - > Type ) ;
} ;
}
int
int
vips_zoom_bridge ( VipsImage * in , VipsImage * * out , int xfac , int yfac )
vips_zoom_bridge ( VipsImage * in , VipsImage * * out , int xfac , int yfac ) {
{
return vips_zoom ( in , out , xfac , yfac , NULL ) ;
return vips_zoom ( in , out , xfac , yfac , NULL ) ;
} ;
}
int
int
vips_colorspace_bridge ( VipsImage * in , VipsImage * * out )
vips_embed_bridge ( VipsImage * in , VipsImage * * out , int left , int top , int width , int height , int extend ) {
{
return vips_embed ( in , out , left , top , width , height , " extend " , extend , NULL ) ;
return vips_colourspace ( in , out , VIPS_INTERPRETATION_LAB , NULL ) ;
}
} ;
int
int
vips_hist_find_ndim_bridge ( VipsImage * in , VipsImage * * out )
vips_extract_area_bridge ( VipsImage * in , VipsImage * * out , int left , int top , int width , int height ) {
{
return vips_extract_area ( in , out , left , top , width , height , NULL ) ;
return vips_hist_find_ndim ( in , out , " bins " , 5 , NULL ) ;
}
} ;
int
int
vips_max_bridge ( VipsImage * in , double * out , int * * x , int * * y )
vips_colourspace_issupported_bridge ( VipsImage * in ) {
{
return vips_colourspace_issupported ( in ) ? 1 : 0 ;
double ones [ 3 ] = { 1 , 1 , 1 } ;
}
return vips_max ( in , ones , " x " , x , " y " , y , NULL ) ;
} ;
int
VipsInterpretation
vips_embed_bridge ( VipsImage * in , VipsImage * * out , int left , int top , int width , int height , int extend )
vips_image_guess_interpretation_bridge ( VipsImage * in ) {
{
return vips_image_guess_interpretation ( in ) ;
return vips_embed ( in , out , left , top , width , height , " extend " , extend , NULL ) ;
}
} ;
int
int
vips_extract_area_bridge ( VipsImage * in , VipsImage * * out , int left , int top , int width , int height )
vips_colourspace_bridge ( VipsImage * in , VipsImage * * out , VipsInterpretation space ) {
{
return vips_colourspace ( in , out , space , NULL ) ;
return vips_extract_area ( in , out , left , top , width , height , NULL ) ;
}
} ;
int
int
vips_jpegsave_bridge ( VipsImage * in , void * * buf , size_t * len , int strip , int quality , int interlace )
vips_jpegsave_bridge ( VipsImage * in , void * * buf , size_t * len , int strip , int quality , int interlace ) {
{
return vips_jpegsave_buffer ( in , buf , len ,
return vips_jpegsave_buffer ( in , buf , len , " strip " , strip , " Q " , quality , " optimize_coding " , TRUE , " interlace " , interlace , NULL ) ;
" strip " , strip ,
} ;
" Q " , quality ,
" optimize_coding " , TRUE ,
" interlace " , with_interlace ( interlace ) ,
NULL
) ;
}
int
int
vips_pngsave_bridge ( VipsImage * in , void * * buf , size_t * len , int strip , int compression , int quality , int interlace )
vips_pngsave_bridge ( VipsImage * in , void * * buf , size_t * len , int strip , int compression , int quality , int interlace ) {
{
# if (VIPS_MAJOR_VERSION >= 8 || (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 42))
# if (VIPS_MAJOR_VERSION >= 8 || (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 42))
return vips_pngsave_buffer ( in , buf , len , " strip " , FALSE , " compression " , compression ,
return vips_pngsave_buffer ( in , buf , len ,
" interlace " , interlace , " filter " , VIPS_FOREIGN_PNG_FILTER_NONE , NULL ) ;
" strip " , FALSE ,
" compression " , compression ,
" interlace " , with_interlace ( interlace ) ,
" filter " , VIPS_FOREIGN_PNG_FILTER_NONE ,
NULL
) ;
# else
# else
return vips_pngsave_buffer ( in , buf , len , " strip " , FALSE , " compression " , compression ,
return vips_pngsave_buffer ( in , buf , len ,
" interlace " , interlace , NULL ) ;
" strip " , FALSE ,
" compression " , compression ,
" interlace " , with_interlace ( interlace ) ,
NULL
) ;
# endif
# endif
} ;
}
int
int
vips_webpsave_bridge ( VipsImage * in , void * * buf , size_t * len , int strip , int quality , int interlace )
vips_webpsave_bridge ( VipsImage * in , void * * buf , size_t * len , int strip , int quality ) {
{
return vips_webpsave_buffer ( in , buf , len ,
return vips_webpsave_buffer ( in , buf , len , " strip " , strip , " Q " , quality , " optimize_coding " , TRUE , " interlace " , interlace , NULL ) ;
" strip " , strip ,
} ;
" Q " , quality ,
NULL
) ;
}
int
vips_flatten_background_brigde ( VipsImage * in , VipsImage * * out , double background [ 3 ] ) {
VipsArrayDouble * vipsBackground = vips_array_double_new ( background , 3 ) ;
return vips_flatten ( in , out ,
" background " , vipsBackground ,
NULL
) ;
}
int
int
vips_init_image ( void * buf , size_t len , int imageType , VipsImage * * out ) {
vips_init_image ( void * buf , size_t len , int imageType , VipsImage * * out ) {
int code = 1 ;
int code = 1 ;
if ( imageType = = JPEG ) {
if ( imageType = = JPEG ) {
code = vips_jpegload_buffer ( buf , len , out , " access " , VIPS_ACCESS_SEQUENTIAL , NULL ) ;
code = vips_jpegload_buffer ( buf , len , out , " access " , VIPS_ACCESS_ RANDOM , NULL ) ;
} else if ( imageType = = PNG ) {
} else if ( imageType = = PNG ) {
code = vips_pngload_buffer ( buf , len , out , " access " , VIPS_ACCESS_SEQUENTIAL , NULL ) ;
code = vips_pngload_buffer ( buf , len , out , " access " , VIPS_ACCESS_ RANDOM , NULL ) ;
} else if ( imageType = = WEBP ) {
} else if ( imageType = = WEBP ) {
code = vips_webpload_buffer ( buf , len , out , " access " , VIPS_ACCESS_SEQUENTIAL , NULL ) ;
code = vips_webpload_buffer ( buf , len , out , " access " , VIPS_ACCESS_ RANDOM , NULL ) ;
} else if ( imageType = = TIFF ) {
} else if ( imageType = = TIFF ) {
code = vips_tiffload_buffer ( buf , len , out , " access " , VIPS_ACCESS_ SEQUENTIAL , NULL ) ;
code = vips_tiffload_buffer ( buf , len , out , " access " , VIPS_ACCESS_ RANDOM , NULL ) ;
# if (VIPS_MAJOR_VERSION >= 8)
# if (VIPS_MAJOR_VERSION >= 8)
} else if ( imageType = = MAGICK ) {
} else if ( imageType = = MAGICK ) {
code = vips_magickload_buffer ( buf , len , out , " access " , VIPS_ACCESS_ SEQUENTIAL , NULL ) ;
code = vips_magickload_buffer ( buf , len , out , " access " , VIPS_ACCESS_ RANDOM , NULL ) ;
# endif
# endif
}
}
return code ;
return code ;
} ;
}
int
int
vips_watermark ( VipsImage * in , VipsImage * * out , watermarkTextOptions * to , watermarkOptions * o )
vips_watermark_replicate ( VipsImage * orig , VipsImage * in , VipsImage * * out ) {
{
VipsImage * cache = vips_image_new ( ) ;
if (
vips_replicate ( in , & cache ,
1 + orig - > Xsize / in - > Xsize ,
1 + orig - > Ysize / in - > Ysize , NULL ) | |
vips_crop ( cache , out , 0 , 0 , orig - > Xsize , orig - > Ysize , NULL )
) {
g_object_unref ( cache ) ;
return 1 ;
}
g_object_unref ( cache ) ;
return 0 ;
}
int
vips_watermark ( VipsImage * in , VipsImage * * out , WatermarkTextOptions * to , WatermarkOptions * o ) {
double ones [ 3 ] = { 1 , 1 , 1 } ;
double ones [ 3 ] = { 1 , 1 , 1 } ;
VipsImage * base = vips_image_new ( ) ;
VipsImage * base = vips_image_new ( ) ;
VipsImage * * t = ( VipsImage * * ) vips_object_local_array ( VIPS_OBJECT ( base ) , 12 ) ;
VipsImage * * t = ( VipsImage * * ) vips_object_local_array ( VIPS_OBJECT ( base ) , 1 0 ) ;
t [ 0 ] = in ;
t [ 0 ] = in ;
// Make the mask.
// Make the mask.
@ -205,48 +293,60 @@ vips_watermark(VipsImage *in, VipsImage **out, watermarkTextOptions *to, waterma
NULL ) | |
NULL ) | |
vips_linear1 ( t [ 1 ] , & t [ 2 ] , o - > Opacity , 0.0 , NULL ) | |
vips_linear1 ( t [ 1 ] , & t [ 2 ] , o - > Opacity , 0.0 , NULL ) | |
vips_cast ( t [ 2 ] , & t [ 3 ] , VIPS_FORMAT_UCHAR , NULL ) | |
vips_cast ( t [ 2 ] , & t [ 3 ] , VIPS_FORMAT_UCHAR , NULL ) | |
vips_embed ( t [ 3 ] , & t [ 4 ] , 100 , 100 ,
vips_embed ( t [ 3 ] , & t [ 4 ] , 100 , 100 , t [ 3 ] - > Xsize + o - > Margin , t [ 3 ] - > Ysize + o - > Margin , NULL )
t [ 3 ] - > Xsize + o - > Margin , t [ 3 ] - > Ysize + o - > Margin , NULL )
) {
) {
g_object_unref ( base ) ;
g_object_unref ( base ) ;
return ( 1 ) ;
return 1 ;
}
}
// Replicate if necessary
// Replicate if necessary
if ( o - > NoReplicate ! = 1 & & (
if ( o - > NoReplicate ! = 1 ) {
vips_replicate ( t [ 4 ] , & t [ 5 ] ,
VipsImage * cache = vips_image_new ( ) ;
1 + t [ 0 ] - > Xsize / t [ 4 ] - > Xsize ,
if ( vips_watermark_replicate ( t [ 0 ] , t [ 4 ] , & cache ) ) {
1 + t [ 0 ] - > Ysize / t [ 4 ] - > Ysize , NULL ) | |
g_object_unref ( cache ) ;
vips_crop ( t [ 5 ] , & t [ 6 ] , 0 , 0 ,
t [ 0 ] - > Xsize , t [ 0 ] - > Ysize , NULL )
) ) {
g_object_unref ( base ) ;
g_object_unref ( base ) ;
return ( 1 ) ;
return 1 ;
}
g_object_unref ( t [ 4 ] ) ;
t [ 4 ] = cache ;
}
}
// Make the constant image to paint the text with.
// Make the constant image to paint the text with.
if (
if (
vips_black ( & t [ 7 ] , 1 , 1 , NULL ) | |
vips_black ( & t [ 5 ] , 1 , 1 , NULL ) | |
vips_linear ( t [ 7 ] , & t [ 8 ] , ones , o - > Background , 3 , NULL ) | |
vips_linear ( t [ 5 ] , & t [ 6 ] , ones , o - > Background , 3 , NULL ) | |
vips_cast ( t [ 8 ] , & t [ 9 ] , VIPS_FORMAT_UCHAR , NULL ) | |
vips_cast ( t [ 6 ] , & t [ 7 ] , VIPS_FORMAT_UCHAR , NULL ) | |
vips_copy ( t [ 9 ] , & t [ 10 ] ,
vips_copy ( t [ 7 ] , & t [ 8 ] , " interpretation " , t [ 0 ] - > Type , NULL ) | |
" interpretation " , t [ 0 ] - > Type ,
vips_embed ( t [ 8 ] , & t [ 9 ] , 0 , 0 , t [ 0 ] - > Xsize , t [ 0 ] - > Ysize , " extend " , VIPS_EXTEND_COPY , NULL )
NULL ) | |
vips_embed ( t [ 10 ] , & t [ 11 ] , 0 , 0 ,
t [ 0 ] - > Xsize , t [ 0 ] - > Ysize ,
" extend " , VIPS_EXTEND_COPY ,
NULL )
) {
) {
g_object_unref ( base ) ;
g_object_unref ( base ) ;
return ( 1 ) ;
return 1 ;
}
}
// Blend the mask and text and write to output.
// Blend the mask and text and write to output.
if ( vips_ifthenelse ( t [ 6 ] , t [ 11 ] , t [ 0 ] , out , " blend " , TRUE , NULL ) ) {
if ( vips_ifthenelse ( t [ 4 ] , t [ 9 ] , t [ 0 ] , out , " blend " , TRUE , NULL ) ) {
g_object_unref ( base ) ;
g_object_unref ( base ) ;
return ( 1 ) ;
return 1 ;
}
}
g_object_unref ( base ) ;
g_object_unref ( base ) ;
return ( 0 ) ;
return 0 ;
} ;
}
int
vips_gaussblur_bridge ( VipsImage * in , VipsImage * * out , double sigma , double min_ampl ) {
# if (VIPS_MAJOR_VERSION == 7 && VIPS_MINOR_VERSION < 41)
return vips_gaussblur ( in , out , ( int ) sigma , NULL ) ;
# else
return vips_gaussblur ( in , out , sigma , NULL , " min_ampl " , min_ampl , NULL ) ;
# endif
}
int
vips_sharpen_bridge ( VipsImage * in , VipsImage * * out , int radius , double x1 , double y2 , double y3 , double m1 , double m2 ) {
# if (VIPS_MAJOR_VERSION == 7 && VIPS_MINOR_VERSION < 41)
return vips_sharpen ( in , out , radius , x1 , y2 , y3 , m1 , m2 , NULL ) ;
# else
return vips_sharpen ( in , out , " radius " , radius , " x1 " , x1 , " y2 " , y2 , " y3 " , y3 , " m1 " , m1 , " m2 " , m2 , NULL ) ;
# endif
}