| /* wrapmany |
| * |
| * Modified: |
| * 1/8/95 JC |
| * - buffer functions now get their own copies of the input pointer |
| * array |
| * 28/7/97 JC |
| * - amazing error ... only worked if ir and or had same valid |
| * 23/1/08 |
| * - do im_wrapone() in terms of this |
| * 8/10/09 |
| * - gtkdoc comments |
| * - move im_wraptwo in here |
| */ |
| |
| /* |
| |
| 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 |
| |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif /*HAVE_CONFIG_H*/ |
| #include <vips/intl.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include <vips/vips.h> |
| |
| #ifdef WITH_DMALLOC |
| #include <dmalloc.h> |
| #endif /*WITH_DMALLOC*/ |
| |
| typedef struct { |
| im_wrapmany_fn fn; /* Function we call */ |
| void *a, *b; /* User values for function */ |
| } Bundle; |
| |
| /* Maximum number of input images -- why not? |
| */ |
| #define IM_MAX_INPUT_IMAGES (64) |
| |
| /* Convert a REGION. |
| */ |
| static int |
| process_region( REGION *or, void *seq, void *a, void *b ) |
| { |
| REGION **ir = (REGION **) seq; |
| Bundle *bun = (Bundle *) b; |
| |
| PEL *p[IM_MAX_INPUT_IMAGES], *q; |
| int i, y; |
| |
| /* Prepare all input regions and make buffer pointers. |
| */ |
| for( i = 0; ir[i]; i++ ) { |
| if( im_prepare( ir[i], &or->valid ) ) |
| return( -1 ); |
| p[i] = (PEL *) IM_REGION_ADDR( ir[i], |
| or->valid.left, or->valid.top ); |
| } |
| p[i] = NULL; |
| q = (PEL *) IM_REGION_ADDR( or, or->valid.left, or->valid.top ); |
| |
| /* Convert linewise. |
| */ |
| for( y = 0; y < or->valid.height; y++ ) { |
| PEL *p1[IM_MAX_INPUT_IMAGES]; |
| |
| /* Make a copy of p[] which the buffer function can mess up if |
| * it wants. |
| */ |
| for( i = 0; ir[i]; i++ ) |
| p1[i] = p[i]; |
| |
| /* Bizarre double-cast stops a bogus gcc 4.1 compiler warning. |
| */ |
| bun->fn( (void **) ((void *)p1), q, |
| or->valid.width, bun->a, bun->b ); |
| |
| /* Move pointers on. |
| */ |
| for( i = 0; ir[i]; i++ ) |
| p[i] += IM_REGION_LSKIP( ir[i] ); |
| q += IM_REGION_LSKIP( or ); |
| } |
| |
| return( 0 ); |
| } |
| |
| /* Make a copy of an array of input images. |
| */ |
| static IMAGE ** |
| dupims( IMAGE *out, IMAGE **in ) |
| { |
| IMAGE **new; |
| int i, n; |
| |
| /* Count input images. |
| */ |
| for( n = 0; in[n]; n++ ) |
| ; |
| |
| /* Allocate new array. |
| */ |
| if( !(new = IM_ARRAY( out, n + 1, IMAGE * )) ) |
| return( NULL ); |
| |
| /* Copy. |
| */ |
| for( i = 0; i < n; i++ ) |
| new[i] = in[i]; |
| new[n] = NULL; |
| |
| return( new ); |
| } |
| |
| /** |
| * im_wrapmany_fn: |
| * @in: %NULL-terminated array of input buffers |
| * @out: write processed pixels here |
| * @width: number of pixels in buffer |
| * @a: user data |
| * @b: user data |
| * |
| * Given an array of buffers of input pixels, write a buffer of output pixels. |
| */ |
| |
| /** |
| * im_wrapmany: |
| * @in: %NULL-terminated array of input images |
| * @out: image to generate |
| * @fn: buffer-processing function |
| * @a: user data |
| * @b: user data |
| * |
| * Wrap-up a buffer processing function as a PIO VIPS function. |
| * |
| * Given a NULL-terminated list of input images all of the same size, an |
| * output image and a buffer processing function, make a PIO image processing |
| * operation. |
| * |
| * See also: im_wrapone(), im_wraptwo(), im_generate(). |
| * |
| * Returns: 0 on success, or -1 on error. |
| */ |
| int |
| im_wrapmany( IMAGE **in, IMAGE *out, im_wrapmany_fn fn, void *a, void *b ) |
| { |
| Bundle *bun = IM_NEW( out, Bundle ); |
| int i, n; |
| |
| /* Count input images. |
| */ |
| for( n = 0; in[n]; n++ ) |
| ; |
| if( n >= IM_MAX_INPUT_IMAGES - 1 ) { |
| im_error( "im_wrapmany", "%s", _( "too many input images" ) ); |
| return( -1 ); |
| } |
| |
| /* Save args. |
| */ |
| if( !bun || !(in = dupims( out, in )) ) |
| return( -1 ); |
| bun->fn = fn; |
| bun->a = a; |
| bun->b = b; |
| |
| /* Check descriptors --- make sure that our caller has done this |
| * correctly. |
| */ |
| for( i = 0; i < n; i++ ) { |
| if( in[i]->Xsize != out->Xsize || in[i]->Ysize != out->Ysize ) { |
| im_error( "im_wrapmany", |
| "%s", _( "descriptors differ in size" ) ); |
| return( -1 ); |
| } |
| |
| /* Check io style. |
| */ |
| if( im_piocheck( in[i], out ) ) |
| return( -1 ); |
| } |
| |
| /* Hint demand style. Being a buffer processor, we are happiest with |
| * thin strips. |
| */ |
| if( im_demand_hint_array( out, IM_THINSTRIP, in ) ) |
| return( -1 ); |
| |
| /* Generate! |
| */ |
| if( im_generate( out, |
| im_start_many, process_region, im_stop_many, in, bun ) ) |
| return( -1 ); |
| |
| return( 0 ); |
| } |
| |
| static void |
| wrapone_gen( void **ins, void *out, int width, Bundle *bun, void *dummy ) |
| { |
| ((im_wrapone_fn) (bun->fn)) (ins[0], out, width, bun->a, bun->b ); |
| } |
| |
| /** |
| * im_wrapone_fn: |
| * @in: input pixels |
| * @out: write processed pixels here |
| * @width: number of pixels in buffer |
| * @a: user data |
| * @b: user data |
| * |
| * Given a buffer of input pixels, write a buffer of output pixels. |
| */ |
| |
| /** |
| * im_wrapone: |
| * @in: input image |
| * @out: image to generate |
| * @fn: buffer-processing function |
| * @a: user data |
| * @b: user data |
| * |
| * Wrap-up a buffer processing function as a PIO VIPS function. |
| * |
| * Given an input image, an |
| * output image and a buffer processing function, make a PIO image processing |
| * operation. |
| * |
| * See also: im_wrapmany(), im_wraptwo(), im_generate(). |
| * |
| * Returns: 0 on success, or -1 on error. |
| */ |
| int |
| im_wrapone( IMAGE *in, IMAGE *out, im_wrapone_fn fn, void *a, void *b ) |
| { |
| Bundle *bun = IM_NEW( out, Bundle ); |
| IMAGE *invec[2]; |
| |
| /* Heh, yuk. We cast back above. |
| */ |
| bun->fn = (im_wrapmany_fn) fn; |
| bun->a = a; |
| bun->b = b; |
| invec[0] = in; invec[1] = NULL; |
| |
| return( im_wrapmany( invec, out, |
| (im_wrapmany_fn) wrapone_gen, bun, NULL ) ); |
| } |
| |
| static void |
| wraptwo_gen( void **ins, void *out, int width, Bundle *bun, void *dummy ) |
| { |
| ((im_wraptwo_fn) (bun->fn)) (ins[0], ins[1], out, |
| width, bun->a, bun->b ); |
| } |
| |
| /** |
| * im_wraptwo_fn: |
| * @in1: input pixels from image 1 |
| * @in2: input pixels from image 2 |
| * @out: write processed pixels here |
| * @width: number of pixels in buffer |
| * @a: user data |
| * @b: user data |
| * |
| * Given a pair of buffers of input pixels, write a buffer of output pixels. |
| */ |
| |
| /** |
| * im_wraptwo: |
| * @in1: first input image |
| * @in2: second input image |
| * @out: image to generate |
| * @fn: buffer-processing function |
| * @a: user data |
| * @b: user data |
| * |
| * Wrap-up a buffer processing function as a PIO VIPS function. |
| * |
| * Given a pair of input images of the same size, an |
| * output image and a buffer processing function, make a PIO image processing |
| * operation. |
| * |
| * See also: im_wrapone(), im_wrapmany(), im_generate(). |
| * |
| * Returns: 0 on success, or -1 on error. |
| */ |
| int |
| im_wraptwo( IMAGE *in1, IMAGE *in2, IMAGE *out, |
| im_wraptwo_fn fn, void *a, void *b ) |
| { |
| Bundle *bun = IM_NEW( out, Bundle ); |
| IMAGE *invec[3]; |
| |
| bun->fn = (im_wrapmany_fn) fn; |
| bun->a = a; |
| bun->b = b; |
| invec[0] = in1; invec[1] = in2; invec[2] = NULL; |
| |
| return( im_wrapmany( invec, out, |
| (im_wrapmany_fn) wraptwo_gen, bun, NULL ) ); |
| } |