/* Function dispatch tables for mosaicing.
 *
 * J. Cupitt, 23/2/95
 */

/*

	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 <glib/gi18n-lib.h>

#include <stdio.h>

#include <vips/vips.h>
#include <vips/vips7compat.h>
#include <vips/internal.h>
#include <vips/transform.h>

/* Merge args.
 */
static im_arg_desc merge_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_INT("dx"),
	IM_INPUT_INT("dy"),
	IM_INPUT_INT("mwidth")
};

/* Merge1 args.
 */
static im_arg_desc merge1_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_INT("xr1"),
	IM_INPUT_INT("yr1"),
	IM_INPUT_INT("xs1"),
	IM_INPUT_INT("ys1"),
	IM_INPUT_INT("xr2"),
	IM_INPUT_INT("yr2"),
	IM_INPUT_INT("xs2"),
	IM_INPUT_INT("ys2"),
	IM_INPUT_INT("mwidth")
};

/* Mosaic args.
 */
static im_arg_desc mosaic_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_INT("bandno"),
	IM_INPUT_INT("xr"),
	IM_INPUT_INT("yr"),
	IM_INPUT_INT("xs"),
	IM_INPUT_INT("ys"),
	IM_INPUT_INT("halfcorrelation"),
	IM_INPUT_INT("halfarea"),
	IM_INPUT_INT("balancetype"), // Deprecated
	IM_INPUT_INT("mwidth")
};

/* Mosaic1 args.
 */
static im_arg_desc mosaic1_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_INT("bandno"), // Deprecated
	IM_INPUT_INT("xr1"),
	IM_INPUT_INT("yr1"),
	IM_INPUT_INT("xs1"),
	IM_INPUT_INT("ys1"),
	IM_INPUT_INT("xr2"),
	IM_INPUT_INT("yr2"),
	IM_INPUT_INT("xs2"),
	IM_INPUT_INT("ys2"),
	IM_INPUT_INT("halfcorrelation"),
	IM_INPUT_INT("halfarea"),
	IM_INPUT_INT("balancetype"), // Deprecated
	IM_INPUT_INT("mwidth")
};

/* Call im_lrmosaic via arg vector.
 */
static int
lrmosaic_vec(im_object *argv)
{
	int bandno = *((int *) argv[3]);
	int xr = *((int *) argv[4]);
	int yr = *((int *) argv[5]);
	int xs = *((int *) argv[6]);
	int ys = *((int *) argv[7]);
	int halfcorrelation = *((int *) argv[8]);
	int halfarea = *((int *) argv[9]);
	int mwidth = *((int *) argv[11]);

	return vips__lrmosaic(argv[0], argv[1], argv[2],
		bandno,
		xr, yr, xs, ys,
		halfcorrelation, halfarea,
		mwidth);
}

/* Call im_lrmosaic1 via arg vector.
 */
static int
lrmosaic1_vec(im_object *argv)
{
	int xr1 = *((int *) argv[4]);
	int yr1 = *((int *) argv[5]);
	int xs1 = *((int *) argv[6]);
	int ys1 = *((int *) argv[7]);
	int xr2 = *((int *) argv[8]);
	int yr2 = *((int *) argv[9]);
	int xs2 = *((int *) argv[10]);
	int ys2 = *((int *) argv[11]);
	int halfcorrelation = *((int *) argv[12]);
	int halfarea = *((int *) argv[13]);
	int mwidth = *((int *) argv[15]);

	return im_lrmosaic1(argv[0], argv[1], argv[2],
		0,
		xr1, yr1, xs1, ys1,
		xr2, yr2, xs2, ys2,
		halfcorrelation, halfarea,
		0, mwidth);
}

/* Description of im_lrmosaic.
 */
static im_function lrmosaic_desc = {
	"im_lrmosaic",						/* Name */
	"left-right mosaic of ref and sec", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,		/* Flags */
	lrmosaic_vec,						/* Dispatch function */
	IM_NUMBER(mosaic_args),				/* Size of arg list */
	mosaic_args							/* Arg list */
};

static im_arg_desc find_overlap_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_INPUT_INT("bandno"),
	IM_INPUT_INT("xr"),
	IM_INPUT_INT("yr"),
	IM_INPUT_INT("xs"),
	IM_INPUT_INT("ys"),
	IM_INPUT_INT("halfcorrelation"),
	IM_INPUT_INT("halfarea"),
	IM_OUTPUT_INT("dx0"),
	IM_OUTPUT_INT("dy0"),
	IM_OUTPUT_DOUBLE("scale1"),
	IM_OUTPUT_DOUBLE("angle1"),
	IM_OUTPUT_DOUBLE("dx1"),
	IM_OUTPUT_DOUBLE("dy1")
};

/* Call im__find_lroverlap via arg vector.
 */
static int
find_lroverlap_vec(im_object *argv)
{
	int bandno = *((int *) argv[2]);
	int xr = *((int *) argv[3]);
	int yr = *((int *) argv[4]);
	int xs = *((int *) argv[5]);
	int ys = *((int *) argv[6]);
	int halfcorrelation = *((int *) argv[7]);
	int halfarea = *((int *) argv[8]);
	int *dx0 = (int *) argv[9];
	int *dy0 = (int *) argv[10];
	double *scale1 = (double *) argv[11];
	double *angle1 = (double *) argv[12];
	double *dx1 = (double *) argv[13];
	double *dy1 = (double *) argv[14];

	IMAGE *t;
	int result;

	if (!(t = im_open("find_lroverlap_vec", "p")))
		return -1;
	result = vips__find_lroverlap(argv[0], argv[1], t,
		bandno,
		xr, yr, xs, ys,
		halfcorrelation, halfarea,
		dx0, dy0, scale1, angle1, dx1, dy1);
	im_close(t);

	return result;
}

/* Description of im__find_lroverlap.
 */
static im_function find_lroverlap_desc = {
	"im__find_lroverlap",							/* Name */
	"search for left-right overlap of ref and sec", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,					/* Flags */
	find_lroverlap_vec,								/* Dispatch function */
	IM_NUMBER(find_overlap_args),					/* Size of arg list */
	find_overlap_args								/* Arg list */
};

/* Description of im_lrmosaic1.
 */
static im_function lrmosaic1_desc = {
	"im_lrmosaic1",									/* Name */
	"first-order left-right mosaic of ref and sec", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,					/* Flags */
	lrmosaic1_vec,									/* Dispatch function */
	IM_NUMBER(mosaic1_args),						/* Size of arg list */
	mosaic1_args									/* Arg list */
};

/* Call im_tbmosaic via arg vector.
 */
static int
tbmosaic_vec(im_object *argv)
{
	int bandno = *((int *) argv[3]);
	int x1 = *((int *) argv[4]);
	int y1 = *((int *) argv[5]);
	int x2 = *((int *) argv[6]);
	int y2 = *((int *) argv[7]);
	int halfcorrelation = *((int *) argv[8]);
	int halfarea = *((int *) argv[9]);
	int mwidth = *((int *) argv[11]);

	return vips__tbmosaic(argv[0], argv[1], argv[2],
		bandno,
		x1, y1, x2, y2,
		halfcorrelation, halfarea,
		mwidth);
}

/* Call im_tbmosaic1 via arg vector.
 */
static int
tbmosaic1_vec(im_object *argv)
{
	int xr1 = *((int *) argv[4]);
	int yr1 = *((int *) argv[5]);
	int xs1 = *((int *) argv[6]);
	int ys1 = *((int *) argv[7]);
	int xr2 = *((int *) argv[8]);
	int yr2 = *((int *) argv[9]);
	int xs2 = *((int *) argv[10]);
	int ys2 = *((int *) argv[11]);
	int halfcorrelation = *((int *) argv[12]);
	int halfarea = *((int *) argv[13]);
	int mwidth = *((int *) argv[15]);

	return im_tbmosaic1(argv[0], argv[1], argv[2],
		0,
		xr1, yr1, xs1, ys1,
		xr2, yr2, xs2, ys2,
		halfcorrelation, halfarea,
		0, mwidth);
}

/* Call im__find_tboverlap via arg vector.
 */
static int
find_tboverlap_vec(im_object *argv)
{
	int bandno = *((int *) argv[2]);
	int xr = *((int *) argv[3]);
	int yr = *((int *) argv[4]);
	int xs = *((int *) argv[5]);
	int ys = *((int *) argv[6]);
	int halfcorrelation = *((int *) argv[7]);
	int halfarea = *((int *) argv[8]);
	int *dx0 = (int *) argv[9];
	int *dy0 = (int *) argv[10];
	double *scale1 = (double *) argv[11];
	double *angle1 = (double *) argv[12];
	double *dx1 = (double *) argv[13];
	double *dy1 = (double *) argv[14];

	IMAGE *t;
	int result;

	if (!(t = im_open("find_tboverlap_vec", "p")))
		return -1;
	result = vips__find_tboverlap(argv[0], argv[1], t,
		bandno,
		xr, yr, xs, ys,
		halfcorrelation, halfarea,
		dx0, dy0, scale1, angle1, dx1, dy1);
	im_close(t);

	return result;
}

/* Description of im__find_tboverlap.
 */
static im_function find_tboverlap_desc = {
	"im__find_tboverlap",							/* Name */
	"search for top-bottom overlap of ref and sec", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,					/* Flags */
	find_tboverlap_vec,								/* Dispatch function */
	IM_NUMBER(find_overlap_args),					/* Size of arg list */
	find_overlap_args								/* Arg list */
};

/* Description of im_tbmosaic.
 */
static im_function tbmosaic_desc = {
	"im_tbmosaic",						/* Name */
	"top-bottom mosaic of in1 and in2", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,		/* Flags */
	tbmosaic_vec,						/* Dispatch function */
	IM_NUMBER(mosaic_args),				/* Size of arg list */
	mosaic_args							/* Arg list */
};

/* Description of im_tbmosaic1.
 */
static im_function tbmosaic1_desc = {
	"im_tbmosaic1",									/* Name */
	"first-order top-bottom mosaic of ref and sec", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,					/* Flags */
	tbmosaic1_vec,									/* Dispatch function */
	IM_NUMBER(mosaic1_args),						/* Size of arg list */
	mosaic1_args									/* Arg list */
};

/* Call im_lrmerge via arg vector.
 */
static int
lrmerge_vec(im_object *argv)
{
	int dx = *((int *) argv[3]);
	int dy = *((int *) argv[4]);
	int mwidth = *((int *) argv[5]);

	return im_lrmerge(argv[0], argv[1], argv[2], dx, dy, mwidth);
}

/* Call im_lrmerge1 via arg vector.
 */
static int
lrmerge1_vec(im_object *argv)
{
	int xr1 = *((int *) argv[3]);
	int yr1 = *((int *) argv[4]);
	int xs1 = *((int *) argv[5]);
	int ys1 = *((int *) argv[6]);
	int xr2 = *((int *) argv[7]);
	int yr2 = *((int *) argv[8]);
	int xs2 = *((int *) argv[9]);
	int ys2 = *((int *) argv[10]);
	int mwidth = *((int *) argv[11]);

	return im_lrmerge1(argv[0], argv[1], argv[2],
		xr1, yr1, xs1, ys1,
		xr2, yr2, xs2, ys2, mwidth);
}

/* Description of im_lrmerge.
 */
static im_function lrmerge_desc = {
	"im_lrmerge",					   /* Name */
	"left-right merge of in1 and in2", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,	   /* Flags */
	lrmerge_vec,					   /* Dispatch function */
	IM_NUMBER(merge_args),			   /* Size of arg list */
	merge_args						   /* Arg list */
};

/* Description of im_lrmerge1.
 */
static im_function lrmerge1_desc = {
	"im_lrmerge1",								   /* Name */
	"first-order left-right merge of ref and sec", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,				   /* Flags */
	lrmerge1_vec,								   /* Dispatch function */
	IM_NUMBER(merge1_args),						   /* Size of arg list */
	merge1_args									   /* Arg list */
};

/* Call im_tbmerge via arg vector.
 */
static int
tbmerge_vec(im_object *argv)
{
	int dx = *((int *) argv[3]);
	int dy = *((int *) argv[4]);
	int mwidth = *((int *) argv[5]);

	return im_tbmerge(argv[0], argv[1], argv[2], dx, dy, mwidth);
}

/* Call im_tbmerge1 via arg vector.
 */
static int
tbmerge1_vec(im_object *argv)
{
	int xr1 = *((int *) argv[3]);
	int yr1 = *((int *) argv[4]);
	int xs1 = *((int *) argv[5]);
	int ys1 = *((int *) argv[6]);
	int xr2 = *((int *) argv[7]);
	int yr2 = *((int *) argv[8]);
	int xs2 = *((int *) argv[9]);
	int ys2 = *((int *) argv[10]);
	int mwidth = *((int *) argv[11]);

	return im_tbmerge1(argv[0], argv[1], argv[2],
		xr1, yr1, xs1, ys1,
		xr2, yr2, xs2, ys2, mwidth);
}

/* Description of im_tbmerge.
 */
static im_function tbmerge_desc = {
	"im_tbmerge",					   /* Name */
	"top-bottom merge of in1 and in2", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,	   /* Flags */
	tbmerge_vec,					   /* Dispatch function */
	IM_NUMBER(merge_args),			   /* Size of arg list */
	merge_args						   /* Arg list */
};

/* Description of im_tbmerge1.
 */
static im_function tbmerge1_desc = {
	"im_tbmerge1",								   /* Name */
	"first-order top-bottom merge of in1 and in2", /* Description */
	IM_FN_TRANSFORM | IM_FN_PIO,				   /* Flags */
	tbmerge1_vec,								   /* Dispatch function */
	IM_NUMBER(merge1_args),						   /* Size of arg list */
	merge1_args									   /* Arg list */
};

/* match_linear args
 */
static im_arg_desc match_linear_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_INT("xref1"),
	IM_INPUT_INT("yref1"),
	IM_INPUT_INT("xsec1"),
	IM_INPUT_INT("ysec1"),
	IM_INPUT_INT("xref2"),
	IM_INPUT_INT("yref2"),
	IM_INPUT_INT("xsec2"),
	IM_INPUT_INT("ysec2")
};

/* Call im_match_linear via arg vector.
 */
static int
match_linear_vec(im_object *argv)
{
	int xref1 = *((int *) argv[3]);
	int yref1 = *((int *) argv[4]);
	int xsec1 = *((int *) argv[5]);
	int ysec1 = *((int *) argv[6]);
	int xref2 = *((int *) argv[7]);
	int yref2 = *((int *) argv[8]);
	int xsec2 = *((int *) argv[9]);
	int ysec2 = *((int *) argv[10]);

	return im_match_linear(argv[0], argv[1], argv[2],
		xref1, yref1, xsec1, ysec1,
		xref2, yref2, xsec2, ysec2);
}

/* Description of im_match_linear.
 */
static im_function match_linear_desc = {
	"im_match_linear", /* Name */
	"resample ref so that tie-points match",
	IM_FN_PIO,					  /* Flags */
	match_linear_vec,			  /* Dispatch function */
	IM_NUMBER(match_linear_args), /* Size of arg list */
	match_linear_args			  /* Arg list */
};

/* match_linear_search args
 */
static im_arg_desc match_linear_search_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_INT("xref1"),
	IM_INPUT_INT("yref1"),
	IM_INPUT_INT("xsec1"),
	IM_INPUT_INT("ysec1"),
	IM_INPUT_INT("xref2"),
	IM_INPUT_INT("yref2"),
	IM_INPUT_INT("xsec2"),
	IM_INPUT_INT("ysec2"),
	IM_INPUT_INT("hwindowsize"),
	IM_INPUT_INT("hsearchsize")
};

/* Call im_match_linear_search via arg vector.
 */
static int
match_linear_search_vec(im_object *argv)
{
	int xref1 = *((int *) argv[3]);
	int yref1 = *((int *) argv[4]);
	int xsec1 = *((int *) argv[5]);
	int ysec1 = *((int *) argv[6]);
	int xref2 = *((int *) argv[7]);
	int yref2 = *((int *) argv[8]);
	int xsec2 = *((int *) argv[9]);
	int ysec2 = *((int *) argv[10]);
	int hwin = *((int *) argv[11]);
	int hsrch = *((int *) argv[12]);

	return im_match_linear_search(argv[0], argv[1], argv[2],
		xref1, yref1, xsec1, ysec1,
		xref2, yref2, xsec2, ysec2,
		hwin, hsrch);
}

/* Description of im_match_linear_search.
 */
static im_function match_linear_search_desc = {
	"im_match_linear_search", /* Name */
	"search sec, then resample so that tie-points match",
	IM_FN_PIO,							 /* Flags */
	match_linear_search_vec,			 /* Dispatch function */
	IM_NUMBER(match_linear_search_args), /* Size of arg list */
	match_linear_search_args			 /* Arg list */
};

/* correl args
 */
static im_arg_desc correl_args[] = {
	IM_INPUT_IMAGE("ref"),
	IM_INPUT_IMAGE("sec"),
	IM_INPUT_INT("xref"),
	IM_INPUT_INT("yref"),
	IM_INPUT_INT("xsec"),
	IM_INPUT_INT("ysec"),
	IM_INPUT_INT("hwindowsize"),
	IM_INPUT_INT("hsearchsize"),
	IM_OUTPUT_DOUBLE("correlation"),
	IM_OUTPUT_INT("x"),
	IM_OUTPUT_INT("y")
};

/* Call im_correl via arg vector.
 */
static int
correl_vec(im_object *argv)
{
	int xref = *((int *) argv[2]);
	int yref = *((int *) argv[3]);
	int xsec = *((int *) argv[4]);
	int ysec = *((int *) argv[5]);
	int cor = *((int *) argv[6]);
	int area = *((int *) argv[7]);
	int *x = (int *) argv[8];
	int *y = (int *) argv[9];
	double *correlation = (double *) argv[10];

	return vips__correl(argv[0], argv[1],
		xref, yref, xsec, ysec, cor, area, correlation, x, y);
}

/* Description of im_correl.
 */
static im_function correl_desc = {
	"im_correl", /* Name */
	"search area around sec for match for area around ref",
	IM_FN_PIO,				/* Flags */
	correl_vec,				/* Dispatch function */
	IM_NUMBER(correl_args), /* Size of arg list */
	correl_args				/* Arg list */
};

/* global_balance args
 */
static im_arg_desc global_balance_args[] = {
	IM_INPUT_IMAGE("in"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_DOUBLE("gamma")
};

/* Call im_global_balance via arg vector.
 */
static int
global_balance_vec(im_object *argv)
{
	double gamma = *((double *) argv[2]);

	return im_global_balance(argv[0], argv[1], gamma);
}

/* Description of im_global_balance.
 */
static im_function global_balance_desc = {
	"im_global_balance", /* Name */
	"automatically rebuild mosaic with balancing",
	IM_FN_TRANSFORM | IM_FN_PIO,	/* Flags */
	global_balance_vec,				/* Dispatch function */
	IM_NUMBER(global_balance_args), /* Size of arg list */
	global_balance_args				/* Arg list */
};

/* Call im_global_balancef via arg vector.
 */
static int
global_balancef_vec(im_object *argv)
{
	double gamma = *((double *) argv[2]);

	return im_global_balancef(argv[0], argv[1], gamma);
}

/* Description of im_global_balancef.
 */
static im_function global_balancef_desc = {
	"im_global_balancef", /* Name */
	"automatically rebuild mosaic with balancing, float output",
	IM_FN_TRANSFORM | IM_FN_PIO,	/* Flags */
	global_balancef_vec,			/* Dispatch function */
	IM_NUMBER(global_balance_args), /* Size of arg list */
	global_balance_args				/* Arg list */
};

/* remosaic args
 */
static im_arg_desc remosaic_args[] = {
	IM_INPUT_IMAGE("in"),
	IM_OUTPUT_IMAGE("out"),
	IM_INPUT_STRING("old_str"),
	IM_INPUT_STRING("new_str")
};

/* Call im_remosaic via arg vector.
 */
static int
remosaic_vec(im_object *argv)
{
	return im_remosaic(argv[0], argv[1], argv[2], argv[3]);
}

/* Description of im_remosaic.
 */
static im_function remosaic_desc = {
	"im_remosaic", /* Name */
	"automatically rebuild mosaic with new files",
	IM_FN_TRANSFORM | IM_FN_PIO, /* Flags */
	remosaic_vec,				 /* Dispatch function */
	IM_NUMBER(remosaic_args),	 /* Size of arg list */
	remosaic_args				 /* Arg list */
};

static int
align_bands_vec(im_object *argv)
{
	return im_align_bands((IMAGE *) argv[0], (IMAGE *) argv[1]);
}

static im_arg_desc align_bands_arg_types[] = {
	IM_INPUT_IMAGE("in"),
	IM_OUTPUT_IMAGE("out")
};

static im_function align_bands_desc = {
	"im_align_bands",
	"align the bands of an image",
	0,
	align_bands_vec,
	IM_NUMBER(align_bands_arg_types),
	align_bands_arg_types
};

static int
maxpos_subpel_vec(im_object *argv)
{
	return im_maxpos_subpel((IMAGE *) argv[0], (double *) argv[1], (double *) argv[2]);
}

static im_arg_desc maxpos_subpel_arg_types[] = {
	IM_INPUT_IMAGE("im"),
	IM_OUTPUT_DOUBLE("x"),
	IM_OUTPUT_DOUBLE("y")
};

static im_function maxpos_subpel_desc = {
	"im_maxpos_subpel",
	"subpixel position of maximum of (phase correlation) image",
	IM_FN_PIO,
	maxpos_subpel_vec,
	IM_NUMBER(maxpos_subpel_arg_types),
	maxpos_subpel_arg_types
};

/* Package up all these functions.
 */
static im_function *mos_list[] = {
	&align_bands_desc,
	&correl_desc,
	&find_lroverlap_desc,
	&find_tboverlap_desc,
	&global_balance_desc,
	&global_balancef_desc,
	&lrmerge_desc,
	&lrmerge1_desc,
	&lrmosaic_desc,
	&lrmosaic1_desc,
	&match_linear_desc,
	&match_linear_search_desc,
	&maxpos_subpel_desc,
	&remosaic_desc,
	&tbmerge_desc,
	&tbmerge1_desc,
	&tbmosaic_desc,
	&tbmosaic1_desc
};

/* Package of functions.
 */
im_package im__mosaicing = {
	"mosaicing",
	IM_NUMBER(mos_list),
	mos_list
};
