Exemple #1
0
/* Rotate an imask with a set of offsets.
 */
static INTMASK *
rotimask( offset_fn fn, INTMASK *m, const char *name )
{
	INTMASK *out;
	int size = m->xsize * m->ysize;
	int *offsets;
	int i;

	if( m->xsize != m->ysize || (m->xsize % 2) == 0 ) {
		im_errormsg( "im_rotate_*mask*: mask should "
			"be square of even size" );
		return( NULL );
	}
	if( !(offsets = fn( m->xsize )) )
		return( NULL );
	if( !(out = im_create_imask( name, m->xsize, m->ysize )) ) {
		im_free( offsets );
		return( NULL );
	}
	out->scale = m->scale;
	out->offset = m->offset;

	for( i = 0; i < size; i++ )
		out->coeff[i] = m->coeff[offsets[i]];

	im_free( offsets );

	return( out );
}
Exemple #2
0
/**
 * im_scale_dmask:
 * @in: mask to scale
 * @filename: filename for returned mask
 *
 * Scale the dmask to make an imask with a maximum value of 20.
 *
 * See also: im_norm_dmask().
 *
 * Returns: the converted mask, or NULL on error.
 */
INTMASK *
im_scale_dmask( DOUBLEMASK *in, const char *filename )
{
	const int size = in->xsize * in->ysize;

	INTMASK *out;
	double maxval, dsum; 
	int i;
	int isum;

	if( im_check_dmask( "im_scale_dmask", in ) ||
		!(out = im_create_imask( filename, in->xsize, in->ysize )) )
		return( NULL );

	/* Find mask max.
	 */
	maxval = in->coeff[0];
	for( i = 0; i < size; i++ ) 
		if( in->coeff[i] > maxval )
			maxval = in->coeff[i];

	/* Copy and scale, setting max to 20.
	 */
	for( i = 0; i < size; i++ ) 
		out->coeff[i] = IM_RINT( in->coeff[i] * 20.0 / maxval );
	out->offset = in->offset;

	/* Set the scale to match the adjustment to max.
	 */
	isum = 0;
	dsum = 0.0;
	for( i = 0; i < size; i++ ) { 
		isum += out->coeff[i]; 
		dsum += in->coeff[i];
	}

	if( dsum == in->scale )
		out->scale = isum;
	else if( dsum == 0.0 )
		out->scale = 1.0;
	else
		out->scale = IM_RINT( in->scale * isum / dsum );

	return( out );	
}
Exemple #3
0
/**
 * im_dup_imask:
 * @in: mask to duplicate
 * @filename: filename to set for the new mask
 *
 * Duplicate an imask.
 *
 * See also: im_dup_dmask().
 *
 * Returns: the mask copy, or NULL on error.
 */
INTMASK *
im_dup_imask( INTMASK *in, const char *filename )
{
	INTMASK *out;
	int i;

	if( im_check_imask( "im_dup_imask", in ) ||
		!(out = im_create_imask( filename, in->xsize, in->ysize )) )
		return( NULL );

        out->offset = in->offset; 
	out->scale = in->scale;

        for( i = 0; i < in->xsize * in->ysize; i++ )
		out->coeff[i] = in->coeff[i];

        return( out );
}
Exemple #4
0
/**
 * im_create_imaskv:
 * @filename: set mask filename to this
 * @xsize: mask width
 * @ysize: mask height
 * @...: values to set for the mask
 *
 * Create an imask and initialise it from the function parameter list.
 *
 * See also: im_create_imask().
 *
 * Returns: The newly-allocated mask.
 */
INTMASK *
im_create_imaskv( const char *filename, int xsize, int ysize, ... )
{
	va_list ap;

	INTMASK *out;
	int i;

	if( !(out = im_create_imask( filename, xsize, ysize )) )
		return( NULL );

	va_start( ap, ysize );
	for( i = 0; i < xsize * ysize; i++ )
		out->coeff[i] = va_arg( ap, int );
	va_end( ap );

	return( out );
}
Exemple #5
0
/**
 * im_read_imask:
 * @filename: read matrix from this file
 *
 * Reads an integer matrix from a file.
 *
 * This function works exactly as im_read_dmask(), but the loaded matrix is
 * checked for 'int-ness'. All coefficients must be integers, and scale and
 * offset must be integers.
 *
 * See also: im_read_dmask().
 *
 * Returns: the loaded mask on success, or NULL on error.
 */
INTMASK *
im_read_imask( const char *filename )
{
	DOUBLEMASK *dmask;
	INTMASK *imask;
	int i;

	if( !(dmask = im_read_dmask( filename )) )
		return( NULL );

	if( ceil( dmask->scale ) != dmask->scale || 
		ceil( dmask->offset ) != dmask->offset ) {
		im_error( "im_read_imask", 
			"%s", _( "scale and offset should be int" ) );
		im_free_dmask( dmask );

		return( NULL );
	}

	for( i = 0; i < dmask->xsize * dmask->ysize; i++ ) 
		if( ceil( dmask->coeff[i] ) != dmask->coeff[i] ) {
			im_error( "im_read_imask", _( "ceofficient at "
				"position (%d, %d) is not int" ), 
				i % dmask->xsize,
				i / dmask->xsize );
			im_free_dmask( dmask );

			return( NULL );
		}

	if( !(imask = im_create_imask( filename, 
		dmask->xsize, dmask->ysize )) ) {
		im_free_dmask( dmask );
		return( NULL );
	}
	imask->scale = dmask->scale;
	imask->offset = dmask->offset;
	for( i = 0; i < dmask->xsize * dmask->ysize; i++ ) 
		imask->coeff[i] = dmask->coeff[i];

	im_free_dmask( dmask );

	return( imask );
}
Exemple #6
0
/**
 * im_dmask2imask:
 * @in: mask to convert
 * @filename: filename for returned mask
 *
 * Make an imask from the dmask, rounding to nearest. 
 *
 * See also: im_scale_dmask().
 *
 * Returns: the converted mask, or NULL on error.
 */
INTMASK *
im_dmask2imask( DOUBLEMASK *in, const char *filename )
{
	const int size = in->xsize * in->ysize;

	INTMASK *out;
	int i;

	if( im_check_dmask( "im_dmask2imask", in ) ||
		!(out = im_create_imask( filename, in->xsize, in->ysize )) )
		return( NULL );

	for( i = 0; i < size; i++ ) 
		out->coeff[i] = IM_RINT( in->coeff[i] );
	out->offset = IM_RINT( in->offset );
	out->scale = IM_RINT( in->scale );

	return( out );	
}
Exemple #7
0
INTMASK *
im_vips2imask( IMAGE *in, const char *filename )
{
	int width, height;
	INTMASK *out;

	double *data;
	int x, y;
	double double_result;
	int int_result;

	/* double* only: cast if necessary.
	 */
	if( in->BandFmt != IM_BANDFMT_DOUBLE ) {
		IMAGE *t;

		if( !(t = im_open( "im_vips2imask", "p" )) )
			return( NULL );
		if( im_clip2fmt( in, t, IM_BANDFMT_DOUBLE ) ||
			!(out = im_vips2imask( t, filename )) ) {
			im_close( t );
			return( NULL );
		}
		im_close( t );

		return( out );
	}

	/* Check the image.
	 */
	if( im_incheck( in ) ||
		im_check_uncoded( "im_vips2imask", in ) )
		return( NULL );

	if( in->Bands == 1 ) {
		width = in->Xsize;
		height = in->Ysize;
	}
	else if( in->Xsize == 1 ) {
		width = in->Bands;
		height = in->Ysize;
	}
	else if( in->Ysize == 1 ) {
		width = in->Xsize;
		height = in->Bands;
	}
	else {
		im_error( "im_vips2imask", 
			"%s", _( "one band, nx1, or 1xn images only" ) );
		return( NULL );
	}

	data = (double *) in->data;
	if( !(out = im_create_imask( filename, width, height )) )
		return( NULL );

	/* We want to make an intmask which has the same input to output ratio
	 * as the double image.
	 *
	 * Imagine convolving with the double image, what's the ratio of
	 * brightness between input and output? We want the same ratio for the
	 * int version, if we can.
	 *
	 * Imaging an input image where every pixel is 1, what will the output
	 * be?
	 */
	double_result = 0;
	for( y = 0; y < height; y++ )
		for( x = 0; x < width; x++ )
			double_result += data[x + width * y];
	double_result /= vips_image_get_scale( in );

	for( y = 0; y < height; y++ )
		for( x = 0; x < width; x++ )
			if( in->Bands > 1 && in->Ysize == 1 ) 
				/* Need to transpose: the image is RGBRGBRGB, 
				 * we need RRRGGGBBB.
				 */
				out->coeff[x + y * width] =
					VIPS_RINT( data[x * height + y] );
			else
				out->coeff[x + y * width] =
					VIPS_RINT( data[x + y * width] );

	out->scale = VIPS_RINT( vips_image_get_scale( in ) );
	if( out->scale == 0 )
		out->scale = 1;
	out->offset = VIPS_RINT( vips_image_get_offset( in ) );

	/* Now convolve a 1 everywhere image with the int version we've made,
	 * what do we get?
	 */
	int_result = 0;
	for( y = 0; y < height; y++ )
		for( x = 0; x < width; x++ )
			int_result += out->coeff[x + width * y];
	int_result /= out->scale;

	/* And adjust the scale to get as close to a match as we can. 
	 */
	out->scale = VIPS_RINT( out->scale + (int_result - double_result) );
	if( out->scale == 0 ) 
		out->scale = 1;

	return( out );
}