add --with-gmic configure option

This commit is contained in:
John Cupitt 2014-10-07 14:54:53 +01:00
parent ea2d6e5283
commit ca2ae681cd
15 changed files with 172 additions and 325 deletions

View File

@ -15,8 +15,7 @@
- better extra band handling by colour, again
- move zoomify ImageProperties file, now a better match to the offical tool
- rename VIPS_ANGLE_180 as VIPS_ANGLE_D180 etc. to help python
- update cimg
- add gmic
- update cimg, add gmic, plus a configure option to turn it on
8/9/14 started 7.40.10
- icc_import and icc_transform checks the input profile for compatibility

8
TODO
View File

@ -1,3 +1,11 @@
- im_greyc_mask compat is not working?
vips im_greyc_mask k2.jpg x.jpg k4.jpg 1 100 0.5 0.5 0.5 0.5 0.5 0.5 1
1 1
vips_gmic_gen is never called
- python:
- could import like this:

View File

@ -665,6 +665,19 @@ if test x"$with_pangoft2" != "xno"; then
])
fi
# g'mic ... embedding the gmic interpreter needs a C++ compiler and a lot of
# patience. And tolerance for huge object files.
AC_ARG_WITH([gmic],
AS_HELP_STRING([--with-gmic], [build with gmic (default: no)]))
if test x"$with_gmic" == "xyes"; then
AC_DEFINE(HAVE_GMIC,1,[define to enable the gmic interpreter.])
AM_CONDITIONAL(ENABLE_GMIC, true)
else
AM_CONDITIONAL(ENABLE_GMIC, false)
with_gmic=no
fi
# hmm, these don't have .pc files on ubuntu 5.10, how odd
FIND_ZIP(
[with_zip=yes],
@ -869,4 +882,5 @@ file import/export with libjpeg: $with_jpeg
image pyramid export: $with_gsf
(requires libgsf-1 1.14.27 or later)
use libexif to load/save JPEG metadata: $with_libexif
build Python binding: $with_python])
build Python binding: $with_python
embed gmic interpreter: $with_gmic])

View File

@ -1,11 +1,20 @@
noinst_LTLIBRARIES = libcimg.la
OPTIONAL_SRC =
OPTIONAL_DIST =
if ENABLE_GMIC
OPTIONAL_SRC += vips_gmic.cpp gmic.cpp
else
OPTIONAL_DIST += vips_gmic.cpp gmic.cpp
endif
libcimg_la_SOURCES = \
CImg.h \
cimg_dispatch.c \
cimg.cpp \
vips_gmic.cpp \
gmic.cpp
gmic_def.h \
gmic.h \
cimg.c \
$(OPTIONAL_SRC)
# various cimg settings as well
# display=0 means don't build the cimg display stuff
@ -31,6 +40,8 @@ AM_CPPFLAGS = \
endif
# used by the final libvips link rather than us
EXTRA_DIST = dummy2.cc
EXTRA_DIST = \
dummy2.cc \
$(OPTIONAL_DIST)
AM_CPPFLAGS += -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

95
libvips/cimg/cimg.c Normal file
View File

@ -0,0 +1,95 @@
/* pass images through gmic
*/
/*
Copyright (C) 1991-2005 The National Gallery
This library 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.1 of the License, or (at your option) any later version.
This library 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 library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
#define DEBUG
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <vips/vips.h>
/**
* SECTION: cimg
* @short_description: pass images through the gmic interpreter
* @see_also: <link linkend="libvips-boolean">boolean</link>
* @stability: Stable
* @include: vips/vips.h
*
* Pass images through the gmic interpreter.
*/
/**
* vips_gmic:
* @in: (array length=n) (transfer none): array of input images
* @out: output image
* @n: number of input images
* @padding: overlap tiles by this much
* @x_scale:
* @y_scale:
* @command: command to execute
*
* Returns: 0 on success, -1 on failure.
*/
int
vips_gmic( VipsImage **in, VipsImage **out, int n,
int padding, double x_scale, double y_scale, const char *command, ... )
{
VipsArrayImage *array;
va_list ap;
int result;
array = vips_array_image_new( in, n );
va_start( ap, command );
result = vips_call_split( "gmic", ap, array, out,
padding, x_scale, y_scale, command );
va_end( ap );
vips_area_unref( VIPS_AREA( array ) );
return( result );
}
/* Called from iofuncs to init all operations in this dir. Use a plugin system
* instead?
*/
void
vips_cimg_operation_init( void )
{
#ifdef HAVE_GMIC
extern GType vips_gmic_get_type( void );
#endif /*HAVE_GMIC*/
#ifdef HAVE_GMIC
vips_gmic_get_type();
#endif /*HAVE_GMIC*/
}

View File

@ -1,288 +0,0 @@
/* Pass VIPS images through CImg
*
* JC, 15/10/07
* 29/4/10
* - oop, should be smalltile, probably
* - tiny cleanups
* - gtkdoc
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <vips/vips.h>
#include <vips/internal.h>
/* CImg needs to call pthread directly, this is the preproc magic they
* prefer.
*/
#if defined(sun) || defined(__sun) || defined(linux) || defined(__linux) \
|| defined(__linux__) || defined(__CYGWIN__) || defined(BSD) || defined(__FreeBSD__) \
|| defined(__OPENBSD__) || defined(__MACOSX__) || defined(__APPLE__) || defined(sgi) \
|| defined(__sgi)
#include <pthread.h>
#endif
#include "CImg.h"
using namespace cimg_library;
/* Save params here.
*/
struct Greyc {
IMAGE *in;
IMAGE *out;
IMAGE *mask;
IMAGE **arry;
int iterations;
float amplitude;
float dl;
float da;
float gauss_prec;
int interpolation;
bool fast_approx;
};
// copy part of a vips region into a cimg
template<typename T> static CImg<T> *
vips_to_cimg( REGION *in, Rect *area )
{
IMAGE *im = in->im;
CImg<T> *img = new CImg<T>( area->width, area->height, 1, im->Bands );
for( int y = 0; y < area->height; y++ ) {
T *p = (T *) IM_REGION_ADDR( in, area->left, area->top + y );
for( int x = 0; x < area->width; x++ ) {
for( int z = 0; z < im->Bands; z++ )
(*img)( x, y, z ) = p[z];
p += im->Bands;
}
}
return( img );
}
// write a CImg to a vips region
// fill out->valid, img has pixels in img_rect
template<typename T> static void
cimg_to_vips( CImg<T> *img, Rect *img_rect, REGION *out )
{
IMAGE *im = out->im;
Rect *valid = &out->valid;
g_assert( im_rect_includesrect( img_rect, valid ) );
int x_off = valid->left - img_rect->left;
int y_off = valid->top - img_rect->top;
for( int y = 0; y < valid->height; y++ ) {
T *p = (T *) IM_REGION_ADDR( out, valid->left, valid->top + y );
for( int x = 0; x < valid->width; x++ ) {
for( int z = 0; z < im->Bands; z++ )
p[z] = static_cast<T>( (*img)(
x + x_off, y + y_off, z ) );
p += im->Bands;
}
}
}
template<typename T> static int
greyc_gen( REGION *out, REGION **in, IMAGE **arry, Greyc *greyc )
{
static const int tile_border = 4;
Rect *ir = &out->valid;
Rect need;
Rect image;
CImg<T> *img;
CImg<unsigned char> *msk;
need = *ir;
im_rect_marginadjust( &need, tile_border );
image.left = 0;
image.top = 0;
image.width = in[0]->im->Xsize;
image.height = in[0]->im->Ysize;
im_rect_intersectrect( &need, &image, &need );
if( im_prepare( in[0], &need ) )
return( -1 );
if( in[1] && im_prepare( in[1], &need ) )
return( -1 );
img = NULL;
msk = NULL;
try {
img = vips_to_cimg<T>( in[0], &need );
if( in[1] )
msk = vips_to_cimg<unsigned char>( in[1], &need );
else
// empty mask
msk = new CImg<unsigned char>();
for( int i = 0; i < greyc->iterations; i++ )
img->blur_anisotropic( *msk,
greyc->amplitude,
greyc->dl, greyc->da, greyc->gauss_prec,
greyc->interpolation, greyc->fast_approx );
cimg_to_vips<T>( img, &need, out );
}
catch( CImgException e ) {
if( img )
delete( img );
if( msk )
delete( msk );
im_error( "GREYCstoration", "%s", e.what() );
return( -1 );
}
if( img )
delete( img );
if( msk )
delete( msk );
return( 0 );
}
// Hmm, strange double-cast needed
typedef int (*generate_fn)( REGION *out, REGION **in,
IMAGE **im, Greyc *greyc );
// as a plain C function
/**
* im_greyc_mask:
* @in: input image
* @out: output image
* @mask: input mask
* @iterations: number of iterations to perform (eg. 1)
* @amplitude: scaling factor (eg. 40)
* @sharpness: (unused)
* @anisotropy: (unused)
* @alpha: (unused)
* @sigma: (unused)
* @dl: spatial integration step (eg. 0.8)
* @da: angular integration step (eg. 30)
* @gauss_prec: precision (eg. 2)
* @interpolation: interpolation (eg. 0 for nearest-neighbour)
*
* This operation calls the blur_anisotropic() method of the CImag image
* processing library. It is handy for denoising images and for upscaling.
*
* See also: im_conv().
*
* Returns: 0 on success, -1 on error
*/
int
im_greyc_mask( IMAGE *in, IMAGE *out, IMAGE *mask,
int iterations,
float amplitude, float sharpness, float anisotropy,
float alpha, float sigma,
float dl, float da, float gauss_prec,
int interpolation, int fast_approx )
{
IMAGE **arry;
Greyc *greyc;
if( im_piocheck( in, out ) ||
im_check_uncoded( "im_greyc_mask", in ) ||
im_check_u8or16orf( "im_greyc_mask", in ) )
return( -1 );
if( mask ) {
if( im_pincheck( mask ) ||
im_check_uncoded( "im_greyc_mask", mask ) ||
im_check_size_same( "im_greyc_mask", in, mask ) ||
im_check_format( "im_greyc_mask",
mask, IM_BANDFMT_UCHAR ) )
return( -1 );
}
if( im_cp_desc( out, in ) ||
!(arry = im_allocate_input_array( out, in, mask, NULL )) ||
!(greyc = IM_NEW( out, Greyc )) ||
im_demand_hint( out, IM_SMALLTILE, in, NULL ) )
return( -1 );
greyc->in = in;
greyc->out = out;
greyc->mask = mask;
greyc->arry = arry;
greyc->iterations = iterations;
greyc->amplitude = amplitude;
greyc->dl = dl;
greyc->da = da;
greyc->gauss_prec = gauss_prec;
greyc->interpolation = interpolation;
greyc->fast_approx = fast_approx;
switch( in->BandFmt ) {
case IM_BANDFMT_UCHAR:
if( im_generate( out,
im_start_many,
// double-cast to give g++ enough context to expand the
// template correctly
(im_generate_fn) (
(generate_fn) greyc_gen<unsigned char>),
im_stop_many, arry, greyc ) )
return( -1 );
break;
case IM_BANDFMT_USHORT:
if( im_generate( out,
im_start_many,
(im_generate_fn) (
(generate_fn) greyc_gen<unsigned short>),
im_stop_many, arry, greyc ) )
return( -1 );
break;
case IM_BANDFMT_FLOAT:
if( im_generate( out,
im_start_many,
(im_generate_fn) (
(generate_fn) greyc_gen<float>),
im_stop_many, arry, greyc ) )
return( -1 );
break;
default:
g_assert( 0 );
}
return( 0 );
}

View File

@ -349,21 +349,3 @@ static void
vips_gmic_init( VipsGMic *vipsgmic )
{
}
int
vips_gmic( VipsImage **in, VipsImage **out, int n,
int padding, double x_scale, double y_scale, const char *command, ...)
{
VipsArrayImage *array;
va_list ap;
int result;
array = vips_array_image_new( in, n );
va_start( ap, command );
result = vips_call_split( "gmic", ap, array, out,
padding, x_scale, y_scale, command );
va_end( ap );
vips_area_unref( VIPS_AREA( array ) );
return( result );
}

View File

@ -198,7 +198,7 @@ vips_bandjoinv( VipsImage **in, VipsImage **out, int n, va_list ap )
/**
* vips_bandjoin:
* @in: array of input images
* @in: (array length=n) (transfer none): array of input images
* @out: output image
* @n: number of input images
* @...: %NULL-terminated list of optional named arguments

View File

@ -1,6 +1,7 @@
noinst_LTLIBRARIES = libdeprecated.la
libdeprecated_la_SOURCES = \
cimg_dispatch.c \
inplace_dispatch.c \
tone.c \
freq_dispatch.c \

View File

@ -5343,3 +5343,29 @@ vips__init( const char *argv0 )
{
return( vips_init( argv0 ) );
}
int
im_greyc_mask( IMAGE *in, IMAGE *out, IMAGE *mask,
int iterations,
float amplitude, float sharpness, float anisotropy,
float alpha, float sigma,
float dl, float da, float gauss_prec,
int interpolation, int fast_approx )
{
VipsImage *input_images[2];
VipsImage *output_image;
char *command;
int result;
input_images[0] = in;
input_images[1] = mask;
command = g_strdup_printf( "-smooth %g,%g,%g,%g,%g,%g,%g,%g,%d,%d",
amplitude, sharpness, anisotropy,
alpha, sigma, dl, da, gauss_prec,
interpolation, fast_approx );
result = vips_gmic( input_images, &output_image, 2,
4, 1, 1, command, NULL );
g_free( command );
return( result );
}

View File

@ -40,13 +40,8 @@ extern "C" {
#include <vips/vips.h>
int im_greyc_mask( VipsImage *in, VipsImage *out, VipsImage *mask,
int iterations, float amplitude, float sharpness, float anisotropy,
float alpha, float sigma, float dl, float da, float gauss_prec,
int interpolation, int fast_approx );
int vips_gmic( int n, VipsImage** out, const char* command,
int padding, float x_scale, float y_scale, ... )
int vips_gmic( VipsImage **in, VipsImage **out, int n,
int padding, double x_scale, double y_scale, const char *command, ... )
__attribute__((sentinel));
#ifdef __cplusplus

View File

@ -216,6 +216,7 @@ void vips_morphology_operation_init( void );
void vips_convolution_operation_init( void );
void vips_draw_operation_init( void );
void vips_mosaicing_operation_init( void );
void vips_cimg_operation_init( void );
guint64 vips__parse_size( const char *size_string );
int vips__substitute( char *buf, size_t len, char *sub );

View File

@ -1225,6 +1225,11 @@ int *im_offsets45( int size );
int im_conv_f_raw( VipsImage *in, VipsImage *out, DOUBLEMASK *mask );
int im_convsep_f_raw( VipsImage *in, VipsImage *out, DOUBLEMASK *mask );
int im_greyc_mask( VipsImage *in, VipsImage *out, VipsImage *mask,
int iterations, float amplitude, float sharpness, float anisotropy,
float alpha, float sigma, float dl, float da, float gauss_prec,
int interpolation, int fast_approx );
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -285,9 +285,7 @@ vips_init( const char *argv0 )
vips_morphology_operation_init();
vips_draw_operation_init();
vips_mosaicing_operation_init();
extern int vips_gmic_get_type( void );
vips_gmic_get_type();
vips_cimg_operation_init();
/* Load up any plugins in the vips libdir. We don't error on failure,
* it's too annoying to have VIPS refuse to start because of a broken