/* @(#) Function which convolves and subsamples VASARI format picture * @(#) with a mask stored in a file argument. * @(#) * @(#) int im_convsub( in, out, mask, xskip, yskip ) * @(#) IMAGE *in, *out; * @(#) INTMASK *mask; details in vips.h * @(#) int xskip, yskip; is the subsamping factor along both directions * @(#) * @(#) Returns either 0 (sucess) or -1 (fail) * @(#) * @(#) Picture can have any number of channels (max 64). * @(#) It is assummed that the output picture is subsampled on * @(#) both directions by a factor of xskip horizontally and yskip vertically. * * Copyright: 1990, N. Dessipris. * * Author: Nicos Dessipris * Written on: 29/04/1991 * Modified on: */ /* 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 #endif /*HAVE_CONFIG_H*/ #include #include #include #include #include #include /* Create multiplication luts for all non zero elements of the original mask; * which is kept in buffer of length buffersize * cnt is needed for freeing luts */ static int im__create_int_luts( int *buffer, int buffersize, int **orig_luts, int **luts, int *cnt ) { int *pbuffer; int *buf1, *buf2, *pbuf1, *pbuf2; int i, j; int min, max; int mark; /* used to mark the buffer mark = max+1 */ int counter; /* counts the no of unique elms in mask; returned in cnt*/ buf1 = (int*)calloc( (unsigned)buffersize, sizeof(int) ); buf2 = (int*)calloc( (unsigned)buffersize, sizeof(int) ); if ( ( buf1 == NULL ) || ( buf2 == NULL ) ) { im_error( "im_create_int_luts", "%s", _( "calloc failed (1)") ); return( -1 ); } pbuffer = buffer; pbuf1 = buf1; /* find max and copy mask to buf1 */ max = *pbuffer; for ( i=0; i < buffersize; i++ ) { if ( *pbuffer > max ) max = *pbuffer; *pbuf1++ = *pbuffer++; } mark = max + 1; pbuf1 = buf1; pbuf2 = buf2; counter = 0; /* find a min at a time; put it into buf2 and mark all values of * buf1 equal to found min, to INT_MAX */ for ( i=0; i < buffersize; i++ ) { min = mark + 1; /* force min to be greater than mark */ pbuf1 = buf1; /* find a min */ for ( j=0; j < buffersize; j++ ) { if ( *pbuf1 < min ) min = *pbuf1; pbuf1++; } if ( min == mark ) /* all min are found */ break; *pbuf2++ = min; counter++; pbuf1 = buf1; for ( j=0; j < buffersize; j++ ) /* mark values equal to min */ { if ( *pbuf1 == min ) *pbuf1 = mark; pbuf1++; } } /* buf2 should keep now counter unique values of the mask, descending order * Malloc counter luts and initialise them */ pbuf2 = buf2; for ( i=0; ixsize * m->ysize */ int **lut_orig, **lut; int lutcnt = 0; int rounding, sum; int tempsize; /* Check input, output and vars */ if ((xskip < 1)||(yskip < 1)) { im_error( "im_convsub", "%s", _( "xskip and yskip must be >= 1") ); return(-1); } if (im_iocheck(in, out) == -1) return( -1 ); if ( (in->Coding != IM_CODING_NONE)|| (in->BandFmt != IM_BANDFMT_UCHAR) ) { im_error( "im_convsub", "%s", _( "nput should be unsigned char uncoded") ); return(-1); } /* Prepare output */ if (im_cp_desc(out, in) == -1) return( -1 ); tempsize = in->Xsize/xskip; while ( 1 ) { if ( tempsize * xskip + m->xsize < in->Xsize ) break; else tempsize--; if ( tempsize < 0 ) break; } out->Xsize = tempsize; tempsize = in->Ysize/yskip; while ( 1 ) { if ( tempsize * yskip + m->ysize < in->Ysize ) break; else tempsize--; if ( tempsize < 0 ) break; } out->Ysize = tempsize; if ( ( out->Xsize < 2 )||( out->Ysize < 2 ) ) { im_error( "im_convsub", "%s", _( "too small output sizes") ); return(-1); } if( im_setupout(out) == -1) return(-1); /* Malloc one line of output data */ os = out->Xsize * out->Bands; if ( (line=(PEL*)calloc( (unsigned)os, sizeof(char))) == NULL) { im_error( "im_convsub", "%s", _( "unable to calloc(1)") ); return(-1); } /* Malloc pointers and put them at correct location */ ms = m->xsize * m->ysize; count = 0; /* exclude the non-zero elms */ pm = m->coeff; for ( i=0; idata; pm = m->coeff; pnewm = newm; for (y=0; yysize; y++) { for (x=0; xxsize; x++) { if ( *pm != 0 ) { *pnewm++ = *pm; pnt[i] = (input +(x + y*in->Xsize) * in->Bands); i++; } pm++; } } if ( i != count ) { im_error( "im_convsub", "%s", _( "impossible state") ); return(-1); } /* Malloc pointers; not all lut_orig are used necessarily */ lut_orig = (int**)calloc((unsigned)count, sizeof(int**) ); lut = (int**)calloc((unsigned)count, sizeof(int**) ); if ( (lut == NULL) || (lut_orig == NULL) ) { im_error( "im_conv", "%s", _( "unable to calloc(1)") ); return(-1); } /* Create luts; count is needed for freeing pointers. Not all lut_orig are used * if zero elms are detected. */ if ( im__create_int_luts(newm, count, lut_orig, lut, &lutcnt ) == -1 ) { im_error( "im_convsub", "%s", _( "im_create_int_luts failed") ); return(-1); } rounding = m->scale/2; /* Output out->Ysize processed lines */ for(y=0; y < out->Ysize; y++) { cpline = line; for (i=0; iXsize * in->Bands * yskip ); } /* process out->Xsize points */ for( x = 0; x < out->Xsize; x++ ) { for (i=0; iBands; } for ( b=0; bBands; b++ ) { sum = 0; for (i=0; iscale ) + m->offset; if ( sum < (int)0 ) { n_clipped++; sum = (int)0; } else if ( sum > (int)255) { p_clipped++; sum = (int)255; } *cpline++ = (unsigned char)sum; } } /* Output the calculated line */ if ( im_writeline(y, out, (PEL*)line) == -1 ) { free((char*)line); free((char*)newm); free((char*)pnts); free((char*)cpnt1s); free((char*)cpnt2s); for ( i=0; i