update cimg, integrate gmic

try:

$ vips gmic 1 x.jpg 20 1 1 --in0 k2.jpg -- "-blur 10"

output is black, but it does seem to almost work
This commit is contained in:
John Cupitt 2014-10-06 14:37:44 +01:00
parent 23c04fcfee
commit ae7d81d748
10 changed files with 260221 additions and 19635 deletions

File diff suppressed because it is too large Load Diff

View File

@ -3,21 +3,30 @@ noinst_LTLIBRARIES = libcimg.la
libcimg_la_SOURCES = \ libcimg_la_SOURCES = \
CImg.h \ CImg.h \
cimg_dispatch.c \ cimg_dispatch.c \
cimg.cpp cimg.cpp \
vips_gmic.cpp \
gmic.cpp
# various cimg settings as well # various cimg settings as well
# we need to change these a bit for win32 # display=0 means don't build the cimg display stuff
# don't turn on the parallel stuff, we rely on vips for that
# don't use cimg_use_rng, we want the system generator
# don't turn on jpg/png/tiff/exr read write, we use vips for that
# don't use -Dcimg_use_fftw3, CImg wants fftw_init_threads() etc. which
# are not widely available
if OS_WIN32 if OS_WIN32
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-Dcimg_strict \ -Dcimg_OS=2 \
-Dcimg_OS=0 \ -Dgmic_build \
-Dcimg_display_type=0 \ -Dcimg_strict_warnings \
-Dcimg_display=0 \
-DLOCALEDIR=\""$(LOCALEDIR)"\" -DLOCALEDIR=\""$(LOCALEDIR)"\"
else else
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-Dcimg_strict \
-Dcimg_OS=1 \ -Dcimg_OS=1 \
-Dcimg_display_type=0 \ -Dgmic_build \
-Dcimg_strict_warnings \
-Dcimg_display=0 \
-DLOCALEDIR=\""$(LOCALEDIR)"\" -DLOCALEDIR=\""$(LOCALEDIR)"\"
endif endif

View File

@ -65,10 +65,6 @@ struct Greyc {
int iterations; int iterations;
float amplitude; float amplitude;
float sharpness;
float anisotropy;
float alpha;
float sigma;
float dl; float dl;
float da; float da;
float gauss_prec; float gauss_prec;
@ -126,7 +122,6 @@ cimg_to_vips( CImg<T> *img, Rect *img_rect, REGION *out )
template<typename T> static int template<typename T> static int
greyc_gen( REGION *out, REGION **in, IMAGE **arry, Greyc *greyc ) greyc_gen( REGION *out, REGION **in, IMAGE **arry, Greyc *greyc )
{ {
static const float gfact = (sizeof( T ) == 2) ? 1.0 / 256 : 1.0;
static const int tile_border = 4; static const int tile_border = 4;
Rect *ir = &out->valid; Rect *ir = &out->valid;
@ -161,12 +156,9 @@ greyc_gen( REGION *out, REGION **in, IMAGE **arry, Greyc *greyc )
for( int i = 0; i < greyc->iterations; i++ ) for( int i = 0; i < greyc->iterations; i++ )
img->blur_anisotropic( *msk, img->blur_anisotropic( *msk,
greyc->amplitude, greyc->sharpness, greyc->amplitude,
greyc->anisotropy, greyc->dl, greyc->da, greyc->gauss_prec,
greyc->alpha, greyc->sigma, greyc->dl, greyc->interpolation, greyc->fast_approx );
greyc->da, greyc->gauss_prec,
greyc->interpolation, greyc->fast_approx,
gfact );
cimg_to_vips<T>( img, &need, out ); cimg_to_vips<T>( img, &need, out );
} }
@ -176,7 +168,7 @@ greyc_gen( REGION *out, REGION **in, IMAGE **arry, Greyc *greyc )
if( msk ) if( msk )
delete( msk ); delete( msk );
im_error( "GREYCstoration", "%s", e.message ); im_error( "GREYCstoration", "%s", e.what() );
return( -1 ); return( -1 );
} }
@ -201,10 +193,10 @@ typedef int (*generate_fn)( REGION *out, REGION **in,
* @mask: input mask * @mask: input mask
* @iterations: number of iterations to perform (eg. 1) * @iterations: number of iterations to perform (eg. 1)
* @amplitude: scaling factor (eg. 40) * @amplitude: scaling factor (eg. 40)
* @sharpness: degree of sharpening to apply (eg. 0.9) * @sharpness: (unused)
* @anisotropy: how much to blur along lines (eg. 0.15) * @anisotropy: (unused)
* @alpha: blur by this much before calculating geometry (eg. 0.6) * @alpha: (unused)
* @sigma: blur geometry by this much (eg. 1.1) * @sigma: (unused)
* @dl: spatial integration step (eg. 0.8) * @dl: spatial integration step (eg. 0.8)
* @da: angular integration step (eg. 30) * @da: angular integration step (eg. 30)
* @gauss_prec: precision (eg. 2) * @gauss_prec: precision (eg. 2)
@ -252,10 +244,6 @@ im_greyc_mask( IMAGE *in, IMAGE *out, IMAGE *mask,
greyc->arry = arry; greyc->arry = arry;
greyc->iterations = iterations; greyc->iterations = iterations;
greyc->amplitude = amplitude; greyc->amplitude = amplitude;
greyc->sharpness = sharpness;
greyc->anisotropy = anisotropy;
greyc->alpha = alpha;
greyc->sigma = sigma;
greyc->dl = dl; greyc->dl = dl;
greyc->da = da; greyc->da = da;
greyc->gauss_prec = gauss_prec; greyc->gauss_prec = gauss_prec;

13211
libvips/cimg/gmic.cpp Normal file

File diff suppressed because it is too large Load Diff

327
libvips/cimg/gmic.h Normal file
View File

@ -0,0 +1,327 @@
/*
#
# File : gmic.h
# ( C++ header file )
#
# Description : GREYC's Magic for Image Computing
# ( http://gmic.sourceforge.net )
# This file is also a part of the CImg Library project.
# ( http://cimg.sourceforge.net )
#
# Note : Include this file in your C++ source code, if you
# want to use the G'MIC interpreter in your own program.
#
# Copyright : David Tschumperle
# ( http://tschumperle.users.greyc.fr/ )
#
# License : CeCILL v2.0
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
#
# This software is governed by the CeCILL license under French law and
# abiding by the rules of distribution of free software. You can use,
# modify and/ or redistribute the software under the terms of the CeCILL
# license as circulated by CEA, CNRS and INRIA at the following URL
# "http://www.cecill.info".
#
# As a counterpart to the access to the source code and rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty and the software's author, the holder of the
# economic rights, and the successive licensors have only limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading, using, modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also
# therefore means that it is reserved for developers and experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and, more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
#
*/
#include <locale>
#ifndef gmic_version
#define gmic_version 1600
// Define environment variables.
#ifndef gmic_is_beta
#define gmic_is_beta 0
#endif // #ifndef gmic_is_beta
#ifndef cimg_verbosity
#define cimg_verbosity 1
#endif // #ifndef cimg_verbosity
#ifdef gmic_build
#define cimg_plugin "gmic.cpp"
#include "./CImg.h"
#if cimg_OS==2
#include <process.h>
#ifdef _MSC_VER
#pragma comment(linker,"/STACK:16777216")
#endif // #ifdef _MSC_VER
#elif cimg_OS==1
#include <cerrno>
#include <sys/resource.h>
static struct gmic_increase_stack {
gmic_increase_stack() {
const rlim_t requested_stack_size = 16777216;
struct rlimit rl;
const int result = getrlimit(RLIMIT_STACK,&rl);
if (!result && rl.rlim_cur<requested_stack_size) {
rl.rlim_cur = requested_stack_size;
setrlimit(RLIMIT_STACK,&rl);
}
}
} _gmic_increase_stack;
#endif // #if cimg_OS==2
#else // #ifdef gmic_build
#include <cstdio>
#include <cstring>
#ifndef cimg_version
namespace cimg_library {
// Define the G'MIC image structure.
//----------------------------------
template<typename T> struct CImg {
unsigned int _width; // Number of image columns (dimension along the X-axis).
unsigned int _height; // Number of image lines (dimension along the Y-axis)
unsigned int _depth; // Number of image slices (dimension along the Z-axis).
unsigned int _spectrum; // Number of image channels (dimension along the C-axis).
bool _is_shared; // Tells if the data buffer is shared by another structure.
T *_data; // Pointer to the first pixel value.
// Destructor.
~CImg();
// Empty constructor.
CImg():_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {}
// Use to allocate a new image with specified dimension.
CImg<T>& assign(const unsigned int w, const unsigned int h=1,
const unsigned int d=1, const unsigned int s=1);
};
// Define the G'MIC image list structure.
//---------------------------------------
template<typename T> struct CImgList {
unsigned int _width; // Number of images in the list.
unsigned int _allocated_width; // Allocated items in the list (must be 2^N and >size).
CImg<T> *_data; // Pointer to the first image of the list.
// Destructor.
~CImgList();
// Empty constructor.
CImgList():_width(0),_allocated_width(0),_data(0) {}
// Use to allocate a new image list with specified dimension.
CImgList<T>& assign(const unsigned int n);
};
}
#endif // #ifndef cimg_version
#endif // #ifdef gmic_build
#define gmic_image cimg_library::CImg
#define gmic_list cimg_library::CImgList
#define gmic_display cimg_library::CImgDisplay
// Define some special character codes used for replacement in double quoted strings.
const char _dollar = 23, _lbrace = 24, _rbrace = 25, _comma = 26, _dquote = 28, _arobace = 29,
_newline = 30;
// Define the G'MIC exception class.
//----------------------------------
struct gmic_exception {
gmic_image<char> _command_help, _message;
gmic_exception() {}
gmic_exception(const char *const command, const char *const message) {
if (command) {
_command_help.assign(std::strlen(command)+1,1,1,1);
std::strcpy(_command_help._data,command);
}
if (message) {
_message.assign(std::strlen(message)+1,1,1,1);
std::strcpy(_message._data,message);
}
}
const char *what() const { // Give the error message returned by the G'MIC interpreter.
return _message._data?_message._data:"";
}
const char *command_help() const {
return _command_help._data?_command_help._data:"";
}
};
// Define the G'MIC interpreter class.
//------------------------------------
struct gmic {
// Constructors - Destructors.
// Use the methods below to create and run the G'MIC interpreter from your C++ source.
gmic();
gmic(const char *const commands_line,
const char *const custom_commands=0,
const bool include_default_commands=true,
float *const p_progress=0, int *const p_cancel=0);
template<typename T>
gmic(const char *const commands_line,
gmic_list<T>& images, gmic_list<char>& images_names,
const char *const custom_commands=0,
const bool include_default_commands=true,
float *const p_progress=0, int *const p_cancel=0);
~gmic();
// Methods to call interpreter on an already constructed gmic instance.
gmic& run(const char *const commands_line,
float *const p_progress=0, int *const p_cancel=0) {
gmic_list<float> images;
gmic_list<char> images_names;
return run(commands_line,images,images_names,
p_progress,p_cancel);
}
template<typename T>
gmic& run(const char *const commands_line,
gmic_list<T> &images, gmic_list<char> &images_names,
float *const p_progress=0, int *const p_cancel=0) {
starting_commands_line = commands_line;
is_debug = false;
return _run(commands_line_to_CImgList(commands_line),
images,images_names,p_progress,p_cancel);
}
//--------------------------------------------------------------------------------------
// All functions below should be considered as 'private' and thus, should not be used
// in your own C++ source code. Use them at your own risk.
//--------------------------------------------------------------------------------------
template<typename T>
void _gmic(const char *const commands_line,
gmic_list<T>& images, gmic_list<char>& images_names,
const char *const custom_commands, const bool include_default_commands,
float *const p_progress, int *const p_cancel);
gmic& add_variable(const char *const variable_name, const char *const variable_content);
gmic& add_commands(const char *const data_commands, const char *const commands_file=0);
gmic& add_commands(std::FILE *const file, const char *const filename=0);
gmic_image<char> scope2string() const;
gmic_image<char> scope2string(const gmic_image<unsigned int>& scope_selection) const;
gmic_image<char> scope2string(const gmic_image<unsigned int>* scope_selection) const;
gmic_image<unsigned int> selection2cimg(const char *const string, const unsigned int indice_max,
const gmic_list<char>& names,
const char *const command, const bool is_selection,
const bool allow_new_name, gmic_image<char>& new_name);
gmic_image<char> selection2string(const gmic_image<unsigned int>& selection,
const gmic_list<char>& images_names,
const bool display_selection) const;
gmic_list<char> commands_line_to_CImgList(const char *const commands_line);
template<typename T>
gmic_image<char> substitute_item(const char *const source,
gmic_list<T>& images, gmic_list<char>& images_names,
gmic_list<T>& parent_images, gmic_list<char>& parent_images_names,
unsigned int variables_sizes[256]);
gmic& print(const char *format, ...);
gmic& error(const char *format, ...);
gmic& debug(const char *format, ...);
template<typename T>
gmic& print(const gmic_list<T>& list, const gmic_image<unsigned int> *const scope_selection,
const char *format, ...);
template<typename T>
gmic& warn(const gmic_list<T>& list, const gmic_image<unsigned int> *const scope_selection,
const char *format, ...);
template<typename T>
gmic& error(const gmic_list<T>& list, const gmic_image<unsigned int> *const scope_selection,
const char *const command, const char *format, ...);
template<typename T>
gmic& debug(const gmic_list<T>& list, const char *format, ...);
template<typename T>
gmic& print_images(const gmic_list<T>& images,
const gmic_list<char>& images_names,
const gmic_image<unsigned int>& selection,
const bool is_header=true);
template<typename T>
gmic& display_images(const gmic_list<T>& images,
const gmic_list<char>& images_names,
const gmic_image<unsigned int>& selection,
unsigned int *const XYZ);
template<typename T>
gmic& display_plots(const gmic_list<T>& images,
const gmic_list<char>& images_names,
const gmic_image<unsigned int>& selection,
const unsigned int plot_type, const unsigned int vertex_type,
const double xmin, const double xmax,
const double ymin, const double ymax);
template<typename T>
gmic& display_objects3d(const gmic_list<T>& images,
const gmic_list<char>& images_names,
const gmic_image<unsigned int>& selection,
const gmic_image<unsigned char>& background3d);
template<typename T>
gmic_image<T>& check_image(const gmic_list<T>& list, gmic_image<T>& img);
template<typename T>
const gmic_image<T>& check_image(const gmic_list<T>& list, const gmic_image<T>& img);
template<typename T>
gmic& remove_images(gmic_list<T>& images, gmic_list<char>& images_names,
const gmic_image<unsigned int>& selection,
const unsigned int start, const unsigned int end);
template<typename T>
gmic& _run(const gmic_list<char>& commands_line,
gmic_list<T> &images, gmic_list<char> &images_names,
float *const p_progress=0, int *const p_cancel=0);
template<typename T>
gmic& _run(const gmic_list<char>& commands_line, unsigned int& position,
gmic_list<T>& images, gmic_list<char>&images_names,
gmic_list<T>& parent_images, gmic_list<char>& parent_images_names,
unsigned int variables_sizes[256],
bool *const is_noargs=0);
// Internal environment variables of the interpreter.
#if cimg_display!=0
gmic_display instant_window[10];
#endif // #if cimg_display!=0
gmic_list<char> *const commands, *const commands_names, *const commands_has_arguments,
*const _variables, *const _variables_names, **const variables, **const variables_names,
commands_files, scope;
gmic_list<unsigned int> dowhiles, repeatdones;
gmic_image<unsigned char> light3d;
gmic_image<char> status;
float focale3d, light3d_x, light3d_y, light3d_z, specular_lightness3d, specular_shininess3d,
_progress, *progress;
bool is_released, is_debug, is_start, is_quit, is_return, is_double3d, is_default_type,
is_debug_infos, check_elif;
int verbosity, render3d, renderd3d;
volatile int _cancel, *cancel;
unsigned int nb_carriages, debug_filename, debug_line, cimg_exception_mode;
unsigned long reference_time;
const char *starting_commands_line;
}; // End of the 'gmic' class.
#endif // #ifndef gmic_version
// Local Variables:
// mode: c++
// End:

199458
libvips/cimg/gmic_def.h Normal file

File diff suppressed because it is too large Load Diff

410
libvips/cimg/vips_gmic.cpp Normal file
View File

@ -0,0 +1,410 @@
/* Pass VIPS images through gmic
*
* AF, 6/10/14
*/
/*
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/dispatch.h>
#include <limits.h>
#include <iostream>
/* 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"
#include "gmic.h"
using namespace cimg_library;
//#define gmic_image cimg_library::CImg
#define GMIC_MAX_INPUT_IMAGES 10
typedef struct _VipsGMic {
VipsOperation parent_instance;
VipsImage* in[GMIC_MAX_INPUT_IMAGES];
int ninput;
VipsImage* out;
char* command;
int padding;
double x_scale;
double y_scale;
} VipsGMic;
typedef VipsOperationClass VipsGMicClass;
#define VIPS_TYPE_GMIC (vips_gmic_get_type())
#define VIPS_GMIC( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
VIPS_TYPE_GMIC, VipsGMic ))
#define VIPS_LAYER_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_CAST( (klass), \
VIPS_TYPE_GMIC, VipsGMicClass))
#define VIPS_IS_LAYER( obj ) \
(G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_GMIC ))
#define VIPS_IS_LAYER_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_GMIC ))
#define VIPS_LAYER_GET_CLASS( obj ) \
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
VIPS_TYPE_GMIC, VipsGMicClass ))
extern "C" {
G_DEFINE_TYPE( VipsGMic, vips_gmic, VIPS_TYPE_OPERATION );
}
static int gmic_get_tile_border( VipsGMic* vipsgmic )
{
return vipsgmic->padding;
}
// copy part of a vips region into a cimg
template<typename T> static void
vips_to_gmic( VipsRegion *in, VipsRect *area, CImg<T>* img )
{
VipsImage *im = in->im;
for( int y = 0; y < area->height; y++ ) {
T *p = (T *) VIPS_REGION_ADDR( in, area->left, area->top + y );
for( int x = 0; x < area->width; x++ ) {
for( int z = 0; z < im->Bands; z++ ) {
//const unsigned long off = (unsigned long)img->offset(x,y,z,c);
(*img)( (unsigned int)x, (unsigned int)y, (unsigned int)z, 0 ) = p[z];
}
p += im->Bands;
}
}
}
// write a CImg to a vips region
// fill out->valid, img has pixels in img_rect
template<typename T> static void
gmic_to_vips( gmic_image<T> *img, VipsRect *img_rect, VipsRegion *out )
{
VipsImage *im = out->im;
VipsRect *valid = &out->valid;
g_assert( vips_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 *) VIPS_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)(
(unsigned int)(x + x_off), (unsigned int)(y + y_off), (unsigned int)z, 0 ) );
p += im->Bands;
}
}
}
template<typename T> static int
_gmic_gen( VipsRegion *oreg, void *seq, void *a, void *b, gboolean *stop )
{
VipsRegion **ir = (VipsRegion **) seq;
VipsGMic *vipsgmic = (VipsGMic *) b;
const int tile_border = gmic_get_tile_border( vipsgmic );
const VipsRect *r = &oreg->valid;
VipsRect* need = vips_rect_dup( r );
std::cout<<"_gmic_gen(): need before adjust="<<need->left<<","<<need->top<<"+"<<need->width<<"+"<<need->height<<std::endl;
std::cout<<"_gmic_gen(): tile_border="<<tile_border<<std::endl;
vips_rect_marginadjust( need, tile_border );
std::cout<<"_gmic_gen(): need after adjust="<<need->left<<","<<need->top<<"+"<<need->width<<"+"<<need->height<<std::endl;
VipsRect image;
if( !ir ) return -1;
image.left = 0;
image.top = 0;
image.width = ir[0]->im->Xsize;
image.height = ir[0]->im->Ysize;
vips_rect_intersectrect( need, &image, need );
std::cout<<"_gmic_gen(): need="<<need->left<<","<<need->top<<"+"<<need->width<<"+"<<need->height<<std::endl;
for( int i = 0; ir[i]; i++ ) {
if( vips_region_prepare( ir[i], need ) ) {
vips_free( need );
return( -1 );
}
}
//CImg<T> img;
//vips_to_gmic<T>( ir[0], need, &img );
/**/
gmic gmic_instance; // Construct first an empty 'gmic' instance.
gmic_list<T> images; // List of images, will contain all images pixel data.
gmic_list<char> images_names; // List of images names. Can be left empty if no names are associated to images.
try {
images.assign( (unsigned int)vipsgmic->ninput );
for( int i = 0; ir[i]; i++ ) {
gmic_image<T>& img = images._data[i];
img.assign(need->width,need->height,1,ir[i]->im->Bands);
vips_to_gmic<T>( ir[0], need, &img );
}
printf("G'MIC command: %s\n",vipsgmic->command);
std::cout<<" ninput="<<vipsgmic->ninput
<<std::endl;
std::cout<<" padding="<<vipsgmic->padding
<<" x scale="<<vipsgmic->x_scale<<std::endl;
gmic_instance.run(vipsgmic->command,images,images_names);
gmic_to_vips<T>( &images._data[0], need, oreg );
}
catch( gmic_exception e ) {
images.assign((unsigned int)0);
vips_error( "VipsGMic", "%s", e.what() );
return( -1 );
}
images.assign((unsigned int)0);
/**/
return( 0 );
}
static int
gmic_gen( VipsRegion *oreg, void *seq, void *a, void *b, gboolean *stop )
{
VipsRegion **ir = (VipsRegion **) seq;
if( !ir ) return -1;
std::cout<<"ir[0]->im->BandFmt: "<<ir[0]->im->BandFmt<<std::endl;
switch( ir[0]->im->BandFmt ) {
case VIPS_FORMAT_UCHAR:
//return _gmic_gen<unsigned char>(oreg, seq, a, b, stop);
break;
case VIPS_FORMAT_CHAR:
break;
case VIPS_FORMAT_USHORT:
//return _gmic_gen<unsigned short int>(oreg, seq, a, b, stop);
break;
case VIPS_FORMAT_SHORT:
break;
case VIPS_FORMAT_UINT:
break;
case VIPS_FORMAT_INT:
break;
case VIPS_FORMAT_FLOAT:
return _gmic_gen<float>(oreg, seq, a, b, stop);
break;
case VIPS_FORMAT_DOUBLE:
break;
default:
g_assert( 0 );
break;
}
return 0;
}
static int _gmic_build( VipsObject *object )
{
VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS( object );
//VipsOperation *operation = VIPS_OPERATION( object );
VipsGMic *vipsgmic = (VipsGMic *) object;
int i;
if( vipsgmic->ninput < 1 ) return -1;
if( !(vipsgmic->in[0]) ) return -1;
if( VIPS_OBJECT_CLASS( vips_gmic_parent_class )->build( object ) )
return( -1 );
for( i = 0; i < vipsgmic->ninput; i++ ) {
if( vips_image_pio_input( vipsgmic->in[i] ) ||
vips_check_coding_known( klass->nickname, vipsgmic->in[i] ) )
return( -1 );
}
/* Get ready to write to @out. @out must be set via g_object_set() so
* that vips can see the assignment. It'll complain that @out hasn't
* been set otherwise.
*/
g_object_set( vipsgmic, "out", vips_image_new(), NULL );
VipsImage** in = (VipsImage**)im_malloc( vipsgmic->out, sizeof(VipsImage*)*(vipsgmic->ninput+1) );
if( !in ) return( -1 );
for( i = 0; i < vipsgmic->ninput; i++ ) {
in[i] = vipsgmic->in[i];
}
in[vipsgmic->ninput] = NULL;
/* Set demand hints.
*/
if( vips_image_pipeline_array( vipsgmic->out,
VIPS_DEMAND_STYLE_ANY,
in ) )
return( -1 );
vips_image_init_fields( vipsgmic->out,
in[0]->Xsize, in[0]->Ysize,
in[0]->Bands, in[0]->BandFmt,
in[0]->Coding, in[0]->Type,
1.0, 1.0);
if(vipsgmic->ninput > 0) {
if( vips_image_generate( vipsgmic->out,
vips_start_many, gmic_gen, vips_stop_many,
in, vipsgmic ) )
return( -1 );
} else {
if( vips_image_generate( vipsgmic->out,
NULL, gmic_gen, NULL, NULL, vipsgmic ) )
return( -1 );
}
return( 0 );
}
static void
vips_gmic_class_init( VipsGMicClass *klass )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( klass );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( klass );
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
vobject_class->nickname = "gmic";
vobject_class->description = _( "Vips G'MIC" );
vobject_class->build = _gmic_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED;
VIPS_ARG_INT( klass, "ninput", 0,
_( "NInput" ),
_( "Number of input images" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsGMic, ninput ),
0, GMIC_MAX_INPUT_IMAGES, 0 );
VIPS_ARG_IMAGE( klass, "out", 1,
_( "Output" ),
_( "Output image" ),
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsGMic, out ) );
VIPS_ARG_INT( klass, "padding", 3,
_( "padding" ),
_( "Tile overlap" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsGMic, padding ),
0, INT_MAX, 0);
VIPS_ARG_DOUBLE( klass, "x_scale", 4,
_( "x_scale" ),
_( "X Scale" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsGMic, x_scale ),
0, 100000000, 1);
VIPS_ARG_DOUBLE( klass, "y_scale", 5,
_( "y_scale" ),
_( "Y Scale" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsGMic, y_scale ),
0, 100000000, 1);
VIPS_ARG_STRING( klass, "command", 10,
_( "command" ),
_( "G'MIC command string" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsGMic, command ),
NULL );
char tstr[100];
char tstr2[100];
char tstr3[100];
for( int imgid = 0; imgid < GMIC_MAX_INPUT_IMAGES; imgid++ ) {
snprintf(tstr,99,"in%d",imgid);
snprintf(tstr2,99,"Input%d",imgid);
snprintf(tstr3,99,"Input image %d",imgid);
VIPS_ARG_IMAGE( klass, tstr, imgid+11,
_( tstr2 ),
_( tstr3 ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsGMic, in )+sizeof(VipsImage*)*imgid );
}
}
static void
vips_gmic_init( VipsGMic *vipsgmic )
{
}
int
vips_gmic(int n, VipsImage** out, const char* command, int padding, float x_scale, float y_scale,...)
{
va_list ap;
int result;
va_start( ap, y_scale );
//result = vips_call_split( "vips_gmic", ap, n, out, command, padding, x_scale, y_scale );
result = vips_call_split( "gmic", ap, n, out, padding, x_scale, y_scale, command );
va_end( ap );
return( result );
}

View File

@ -45,6 +45,10 @@ int im_greyc_mask( VipsImage *in, VipsImage *out, VipsImage *mask,
float alpha, float sigma, float dl, float da, float gauss_prec, float alpha, float sigma, float dl, float da, float gauss_prec,
int interpolation, int fast_approx ); int interpolation, int fast_approx );
int vips_gmic( int n, VipsImage** out, const char* command,
int padding, float x_scale, float y_scale, ... )
__attribute__((sentinel));
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /*__cplusplus*/ #endif /*__cplusplus*/

View File

@ -107,11 +107,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_object( (NAME), (LONG), (DESC), \ pspec = g_param_spec_object( (NAME), (LONG), (DESC), \
VIPS_TYPE_IMAGE, \ VIPS_TYPE_IMAGE, \
G_PARAM_READWRITE ); \ (GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_INTERPOLATE( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \ #define VIPS_ARG_INTERPOLATE( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \
@ -119,11 +119,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_object( (NAME), (LONG), (DESC), \ pspec = g_param_spec_object( (NAME), (LONG), (DESC), \
VIPS_TYPE_INTERPOLATE, \ VIPS_TYPE_INTERPOLATE, \
G_PARAM_READWRITE ); \ (GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_BOOL( CLASS, NAME, PRIORITY, LONG, DESC, \ #define VIPS_ARG_BOOL( CLASS, NAME, PRIORITY, LONG, DESC, \
@ -132,11 +132,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_boolean( (NAME), (LONG), (DESC), \ pspec = g_param_spec_boolean( (NAME), (LONG), (DESC), \
(VALUE), \ (VALUE), \
G_PARAM_READWRITE ); \ (GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_DOUBLE( CLASS, NAME, PRIORITY, LONG, DESC, \ #define VIPS_ARG_DOUBLE( CLASS, NAME, PRIORITY, LONG, DESC, \
@ -145,11 +145,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_double( (NAME), (LONG), (DESC), \ pspec = g_param_spec_double( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \ (MIN), (MAX), (VALUE), \
G_PARAM_READWRITE );\ (GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_BOXED( CLASS, NAME, PRIORITY, LONG, DESC, \ #define VIPS_ARG_BOXED( CLASS, NAME, PRIORITY, LONG, DESC, \
@ -158,11 +158,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_boxed( (NAME), (LONG), (DESC), \ pspec = g_param_spec_boxed( (NAME), (LONG), (DESC), \
(TYPE), \ (TYPE), \
G_PARAM_READWRITE );\ (GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_INT( CLASS, NAME, PRIORITY, LONG, DESC, \ #define VIPS_ARG_INT( CLASS, NAME, PRIORITY, LONG, DESC, \
@ -171,11 +171,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_int( (NAME), (LONG), (DESC), \ pspec = g_param_spec_int( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \ (MIN), (MAX), (VALUE), \
G_PARAM_READWRITE );\ (GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_UINT64( CLASS, NAME, PRIORITY, LONG, DESC, \ #define VIPS_ARG_UINT64( CLASS, NAME, PRIORITY, LONG, DESC, \
@ -184,11 +184,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_uint64( (NAME), (LONG), (DESC), \ pspec = g_param_spec_uint64( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \ (MIN), (MAX), (VALUE), \
G_PARAM_READWRITE );\ (GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_ENUM( CLASS, NAME, PRIORITY, LONG, DESC, \ #define VIPS_ARG_ENUM( CLASS, NAME, PRIORITY, LONG, DESC, \
@ -197,11 +197,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_enum( (NAME), (LONG), (DESC), \ pspec = g_param_spec_enum( (NAME), (LONG), (DESC), \
(TYPE), (VALUE), \ (TYPE), (VALUE), \
G_PARAM_READWRITE );\ (GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_FLAGS( CLASS, NAME, PRIORITY, LONG, DESC, \ #define VIPS_ARG_FLAGS( CLASS, NAME, PRIORITY, LONG, DESC, \
@ -210,11 +210,11 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_flags( (NAME), (LONG), (DESC), \ pspec = g_param_spec_flags( (NAME), (LONG), (DESC), \
(TYPE), (VALUE), \ (TYPE), (VALUE), \
G_PARAM_READWRITE );\ (GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_STRING( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \ #define VIPS_ARG_STRING( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
@ -223,22 +223,22 @@ extern int _vips__argument_id;
\ \
pspec = g_param_spec_string( (NAME), (LONG), (DESC), \ pspec = g_param_spec_string( (NAME), (LONG), (DESC), \
(VALUE), \ (VALUE), \
G_PARAM_READWRITE ); \ (GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \ g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
#define VIPS_ARG_POINTER( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \ #define VIPS_ARG_POINTER( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET ) { \
GParamSpec *pspec; \ GParamSpec *pspec; \
\ \
pspec = g_param_spec_pointer( (NAME), (LONG), (DESC), \ pspec = g_param_spec_pointer( (NAME), (LONG), (DESC), \
G_PARAM_READWRITE ); \ (GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( gobject_class, \ g_object_class_install_property( gobject_class, \
_vips__argument_id++, pspec ); \ _vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \ vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \ pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
} }
/* Keep one of these for every argument. /* Keep one of these for every argument.

View File

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