Пример #1
0
/* A colour difference operation.
 */
int
im__colour_difference( const char *domain,
	IMAGE *in1, IMAGE *in2, IMAGE *out, 
	im_wrapmany_fn buffer_fn, void *a, void *b )
{
	IMAGE *t[3];

	if( im_check_uncoded( domain, in1 ) ||
		im_check_uncoded( domain, in2 ) ||
		im_check_bands( domain, in1, 3 ) ||
		im_check_bands( domain, in2, 3 ) ||
		im_check_size_same( domain, in1, in2 ) ||
		im_open_local_array( out, t, 2, domain, "p" ) ||
		im_clip2fmt( in1, t[0], IM_BANDFMT_FLOAT ) ||
		im_clip2fmt( in2, t[1], IM_BANDFMT_FLOAT ) )
		return( -1 );

	if( im_cp_descv( out, t[0], t[1], NULL ) )
		return( -1 );
	out->Bands = 1;
	out->Type = IM_TYPE_B_W;

	t[2] = NULL;
	if( im_wrapmany( t, out, buffer_fn, a, b ) )
		return( -1 );

	return( 0 );
}
Пример #2
0
/**
 * im_LabS2LabQ:
 * @in: input image
 * @out: output image
 *
 * Convert a LabS three-band signed short image to LabQ
 *
 * See also: im_LabQ2LabS().
 *
 * Returns: 0 on success, -1 on error.
 */
int
im_LabS2LabQ( IMAGE *in, IMAGE *out )
{
	IMAGE *t[1];

	if( im_check_uncoded( "im_LabS2LabQ", in ) ||
		im_check_bands( "im_LabS2LabQ", in, 3 ) ||
		im_open_local_array( out, t, 1, "im_LabS2LabQ", "p" ) ||
		im_clip2fmt( in, t[0], IM_BANDFMT_SHORT ) )
		return( -1 );

	/* Set up output image 
	 */
	if( im_cp_desc( out, in ) )
		return( -1 );
	out->Bands = 4;
	out->Type = IM_TYPE_LABQ;
	out->BandFmt = IM_BANDFMT_UCHAR;
	out->Coding = IM_CODING_LABQ;

	if( im_wrapone( in, out, 
		(im_wrapone_fn) imb_LabS2LabQ, NULL, NULL ) )
		return( -1 );

	return( 0 );
}
Пример #3
0
/* Call im_clip2fmt via arg vector.
 */
static int
clip2fmt_vec( im_object *argv )
{
	int ofmt = *((int *) argv[2]);

	return( im_clip2fmt( argv[0], argv[1], ofmt ) );
}
Пример #4
0
/**
 * im_scaleps:
 * @in: input image
 * @out: output image
 *
 * Scale a power spectrum. Transform with log10(1.0 + pow(x, 0.25)) + .5, 
 * then scale so max == 255.
 *
 * See also: im_scale().
 *
 * Returns: 0 on success, -1 on error
 */
int 
im_scaleps( IMAGE *in, IMAGE *out )
{
	IMAGE *t[4];
	double mx;
	double scale;

	if( im_open_local_array( out, t, 4, "im_scaleps-1", "p" ) || 
		im_max( in, &mx ) )
		return( -1 );

	if( mx <= 0.0 ) 
		/* Range of zero: just return black.
		 */
		return( im_black( out, in->Xsize, in->Ysize, in->Bands ) );

	scale = 255.0 / log10( 1.0 + pow( mx, .25 ) );

	/* Transform!
	 */
	if( im_powtra( in, t[0], 0.25 ) ||
		im_lintra( 1.0, t[0], 1.0, t[1] ) ||
		im_log10tra( t[1], t[2] ) ||
		im_lintra( scale, t[2], 0.0, t[3] ) ||
		im_clip2fmt( t[3], out, IM_BANDFMT_UCHAR ) )
		return( -1 );

	return( 0 );
}
Пример #5
0
/**
 * im_maplut:
 * @in: input image
 * @out: output image
 * @lut: look-up table
 *
 * Map an image through another image acting as a LUT (Look Up Table). 
 * The lut may have any type, and the output image will be that type.
 * 
 * The input image will be cast to one of the unsigned integer types, that is,
 * IM_BANDFMT_UCHAR, IM_BANDFMT_USHORT or IM_BANDFMT_UINT.
 * 
 * If @lut is too small for the input type (for example, if @in is
 * IM_BANDFMT_UCHAR but @lut only has 100 elements), the lut is padded out
 * by copying the last element. Overflows are reported at the end of 
 * computation.
 * If @lut is too large, extra values are ignored. 
 * 
 * If @lut has one band, then all bands of @in pass through it. If @lut
 * has same number of bands as @in, then each band is mapped
 * separately. If @in has one band, then @lut may have many bands and
 * the output will have the same number of bands as @lut.
 *
 * See also: im_histgr(), im_identity().
 *
 * Returns: 0 on success, -1 on error
 */
int 
im_maplut( IMAGE *in, IMAGE *out, IMAGE *lut )
{
	IMAGE *t;
	LutInfo *st;

	/* Check input output. Old-style IO from lut, for simplicity.
	 */
	if( im_check_hist( "im_maplut", lut ) ||
		im_check_uncoded( "im_maplut", lut ) ||
		im_check_uncoded( "im_maplut", in ) ||
		im_check_bands_1orn( "im_maplut", in, lut ) ||
		im_piocheck( in, out ) || 
		im_incheck( lut ) )
		return( -1 );

	/* Cast in to u8/u16/u32.
	 */
	if( !(t = im_open_local( out, "im_maplut", "p" )) ||
		im_clip2fmt( in, t, bandfmt_maplut[in->BandFmt] ) )
		return( -1 );

	/* Prepare the output header.
	 */
        if( im_cp_descv( out, t, lut, NULL ) )
                return( -1 );

	/* Force output to be the same type as lut.
	 */
	out->BandFmt = lut->BandFmt;

	/* Output has same number of bands as LUT, unless LUT has 1 band, in
	 * which case output has same number of bands as input.
	 */
	if( lut->Bands != 1 )
		out->Bands = lut->Bands;

	/* Make tables.
	 */
	if( !(st = build_luts( out, lut )) )
		return( -1 );

	/* Set demand hints.
	 */
	if( im_demand_hint( out, IM_THINSTRIP, t, NULL ) )
		return( -1 );

	/* Process!
	 */
        if( im_generate( out, maplut_start, maplut_gen, maplut_stop, t, st ) )
                return( -1 );

        return( 0 );
}
Пример #6
0
/**
 * im_label_regions:
 * @test: image to test
 * @mask: write labelled regions here
 * @segments: return number of regions here
 *
 * im_label_regions() repeatedly scans @test for regions of 4-connected pixels
 * with the same pixel value. Every time a region is discovered, those
 * pixels are marked in @mask with a unique serial number. Once all pixels
 * have been labelled, the operation returns, setting @segments to the number
 * of discrete regions which were detected.
 *
 * @mask is always a 1-band %IM_BANDFMT_UINT image of the same dimensions as
 * @test.
 *
 * This operation is useful for, for example, blob counting. You can use the
 * morphological operators to detect and isolate a series of objects, then use
 * im_label_regions() to number them all.
 *
 * Use im_histindexed() to (for example) find blob coordinates.
 *
 * See also: im_histindexed()
 *
 * Returns: 0 on success, -1 on error.
 */
int
im_label_regions( IMAGE *test, IMAGE *mask, int *segments )
{
	IMAGE *t[2];
	int serial;
	int *m;
	int x, y;

	/* Create the zero mask image.
	 */
	if( im_open_local_array( mask, t, 2, "im_label_regions", "p" ) ||
		im_black( t[0], test->Xsize, test->Ysize, 1 ) ||
		im_clip2fmt( t[0], t[1], IM_BANDFMT_INT ) ) 
		return( -1 );

	/* Search the mask image, flooding as we find zero pixels.
	 */
	if( im_rwcheck( t[1] ) )
		return( -1 );
	serial = 0;
	m = (int *) t[1]->data;
	for( y = 0; y < test->Ysize; y++ ) {
		for( x = 0; x < test->Xsize; x++ ) {
			if( !m[x] ) {
				/*
				if( im_flood_other_old( t[1], test, 
					x, y, serial ) )
				 */
				if( im_flood_other( test, t[1], 
					x, y, serial, NULL ) )
//				if( im_flood_other_old( t[1], test,
//					x, y, serial ) )
					return( -1 );

				serial += 1;
			}
		}

		m += test->Xsize;
	}

	/* Copy result to mask.
	 */
	if( im_copy( t[1], mask ) )
		return( -1 );
	if( segments )
		*segments = serial;

	return( 0 );
}
Пример #7
0
int 
im_freqflt( IMAGE *in, IMAGE *mask, IMAGE *out )
{
	IMAGE *dummy;

	/* Placeholder for memory free.
	 */
	if( !(dummy = im_open( "memory-1", "p" )) )
		return( -1 );

	if( im_iscomplex( in ) ) {
		/* Easy case! Assume it has already been transformed.
		 */
		IMAGE *t1 = im_open_local( dummy, "im_freqflt-1", "p" );

		if( !t1 ||
			im_multiply( in, mask, t1 ) ||
			im_invfftr( t1, out ) ) {
			im_close( dummy );
			return( -1 );
		}
	}
	else {
		/* Harder - fft first, then mult, then force back to start
		 * type.
		 * 
		 * Optimisation: output of im_invfft() is float buffer, we 
		 * will usually chagetype to char, so rather than keeping a
		 * large float buffer and partial to char from that, do
		 * changetype to a memory buffer, and copy to out from that.
		 */
		IMAGE *t[3];
		IMAGE *t3;

		if( im_open_local_array( dummy, t, 3, "im_freqflt-1", "p" ) ||
			!(t3 = im_open_local( out, "im_freqflt-3", "t" )) ||
			im_fwfft( in, t[0] ) ||
			im_multiply( t[0], mask, t[1] ) ||
			im_invfftr( t[1], t[2] ) ||
			im_clip2fmt( t[2], t3, in->BandFmt ) ||
			im_copy( t3, out ) ) {
			im_close( dummy );
			return( -1 );
		}	
	}

	im_close( dummy );

	return( 0 );
}
Пример #8
0
/**
 * im_grey:
 * @out: output image
 * @xsize: image size
 * @ysize: image size
 *
 * Create a one-band uchar image with the left-most column zero and the
 * right-most 255. Intermediate pixels are a linear ramp.
 *
 * See also: im_fgrey(), im_make_xy(), im_identity().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_grey( IMAGE *out, const int xsize, const int ysize )
{
	IMAGE *t[2];

	/* Change range to [0,255].
	 */
	if( im_open_local_array( out, t, 2, "im_grey", "p" ) ||
		im_fgrey( t[0], xsize, ysize ) || 
		im_lintra( 255.0, t[0], 0.0, t[1] ) ||
		im_clip2fmt( t[1], out, IM_BANDFMT_UCHAR ) )
		return( -1 );

	return( 0 );
}
Пример #9
0
/**
 * im_tone_build:
 * @out: output image
 * @Lb: black-point [0-100]
 * @Lw: white-point [0-100]
 * @Ps: shadow point (eg. 0.2)
 * @Pm: mid-tone point (eg. 0.5)
 * @Ph: highlight point (eg. 0.8)
 * @S: shadow adjustment (+/- 30)
 * @M: mid-tone adjustment (+/- 30)
 * @H: highlight adjustment (+/- 30)
 *
 * As im_tone_build_range(), but set 32767 and 32767 as values for @in_max
 * and @out_max. This makes a curve suitable for correcting LABS
 * images, the most common case.
 *
 * See also: im_tone_build_range().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_tone_build( IMAGE *out,
               double Lb, double Lw,
               double Ps, double Pm, double Ph,
               double S, double M, double H )
{
    IMAGE *t1;

    if( !(t1 = im_open_local( out, "im_tone_build", "p" )) ||
            im_tone_build_range( t1, 32767, 32767,
                                 Lb, Lw, Ps, Pm, Ph, S, M, H ) ||
            im_clip2fmt( t1, out, IM_BANDFMT_SHORT ) )
        return( -1 );

    return( 0 );
}
Пример #10
0
/* As above, but make a IM_BANDFMT_UCHAR image.
 */
int
im_zone( IMAGE *im, int size )
{
	IMAGE *t1 = im_open_local( im, "im_zone:1", "p" );
	IMAGE *t2 = im_open_local( im, "im_zone:2", "p" );

	if( !t1 || !t2 )
		return( -1 );
	
	if( im_fzone( t1, size ) || 
		im_lintra( 127.5, t1, 127.5, t2 ) ||
		im_clip2fmt( t2, im, IM_BANDFMT_UCHAR ) )
		return( -1 );

	return( 0 );
}
Пример #11
0
/**
 * im_tone_analyse:
 * @in: input image
 * @out: output image
 * @Ps: shadow point (eg. 0.2)
 * @Pm: mid-tone point (eg. 0.5)
 * @Ph: highlight point (eg. 0.8)
 * @S: shadow adjustment (+/- 30)
 * @M: mid-tone adjustment (+/- 30)
 * @H: highlight adjustment (+/- 30)
 *
 * As im_tone_build(), but analyse the histogram of @in and use it to
 * pick the 0.1% and 99.9% points for @Lb and @Lw.
 *
 * See also: im_tone_build().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_tone_analyse(
    IMAGE *in,
    IMAGE *out,
    double Ps, double Pm, double Ph,
    double S, double M, double H )
{
    IMAGE *t[4];
    int low, high;
    double Lb, Lw;

    if( im_open_local_array( out, t, 4, "im_tone_map", "p" ) )
        return( -1 );

    /* If in is IM_CODING_LABQ, unpack.
     */
    if( in->Coding == IM_CODING_LABQ ) {
        if( im_LabQ2LabS( in, t[0] ) )
            return( -1 );
    }
    else
        t[0] = in;

    /* Should now be 3-band short.
     */
    if( im_check_uncoded( "im_tone_analyse", t[0] ) ||
            im_check_bands( "im_tone_analyse", t[0], 3 ) ||
            im_check_format( "im_tone_analyse", t[0], IM_BANDFMT_SHORT ) )
        return( -1 );

    if( im_extract_band( t[0], t[1], 0 ) ||
            im_clip2fmt( t[1], t[2], IM_BANDFMT_USHORT ) ||
            im_histgr( t[2], t[3], -1 ) )
        return( -1 );

    if( im_mpercent_hist( t[3], 0.1 / 100.0, &high ) ||
            im_mpercent_hist( t[3], 99.9 / 100.0, &low ) )
        return( -1 );

    Lb = 100 * low / 32768;
    Lw = 100 * high / 32768;

    im_diag( "im_tone_analyse", "set Lb = %g, Lw = %g", Lb, Lw );

    return( im_tone_build( out, Lb, Lw, Ps, Pm, Ph, S, M, H ) );
}
Пример #12
0
/* Find stats on an area of an IMAGE ... consider only pixels for which the
 * mask is true.
 */
static DOUBLEMASK *
find_image_stats( IMAGE *in, IMAGE *mask, Rect *area )
{
	DOUBLEMASK *stats;
	IMAGE *t[4];
	gint64 count;

	/* Extract area, build black image, mask out pixels we want.
	 */
	if( im_open_local_array( in, t, 4, "find_image_stats", "p" ) ||
		extract_rect( in, t[0], area ) ||
		im_black( t[1], t[0]->Xsize, t[0]->Ysize, t[0]->Bands ) ||
		im_clip2fmt( t[1], t[2], t[0]->BandFmt ) ||
		im_ifthenelse( mask, t[0], t[2], t[3] ) )
		return( NULL );

	/* Get stats from masked image.
	 */
	if( !(stats = local_mask( in, im_stats( t[3] ) )) ) 
		return( NULL );

	/* Number of non-zero pixels in mask.
	 */
	if( count_nonzero( mask, &count ) )
		return( NULL );

	/* And scale masked average to match.
	 */
	stats->coeff[4] *= (double) count / 
		((double) mask->Xsize * mask->Ysize);

	/* Yuk! Zap the deviation column with the pixel count. Used later to
	 * determine if this is likely to be a significant overlap.
	 */
	stats->coeff[5] = count;

#ifdef DEBUG
	if( count == 0 )
		im_warn( "global_balance", _( "empty overlap!" ) );
#endif /*DEBUG*/

	return( stats );
}
Пример #13
0
/* The common part of most binary inplace operators.
 *
 * Unlike im__formatalike() and friends, we can only change one of the images,
 * since the other is being updated.
 */
VipsImage *
im__inplace_base( const char *domain,
                  VipsImage *main, VipsImage *sub, VipsImage *out )
{
    VipsImage *t[2];

    if( im_rwcheck( main ) ||
            im_pincheck( sub ) ||
            im_check_coding_known( domain, main ) ||
            im_check_coding_same( domain, main, sub ) ||
            im_check_bands_1orn_unary( domain, sub, main->Bands ) )
        return( NULL );

    /* Cast sub to match main in bands and format.
     */
    if( im_open_local_array( out, t, 2, domain, "p" ) ||
            im__bandup( domain, sub, t[0], main->Bands ) ||
            im_clip2fmt( t[0], t[1], main->BandFmt ) )
        return( NULL );

    return( t[1] );
}
Пример #14
0
/**
 * im_gammacorrect:
 * @in: input image
 * @out: output image
 * @exponent: gamma factor
 *
 * Gamma-correct an 8- or 16-bit unsigned image with a lookup table. The
 * output format is the same as the input format.
 *
 * See also: im_identity(), im_powtra(), im_maplut()
 *
 * Returns: 0 on success, -1 on error
 */
int 
im_gammacorrect( IMAGE *in, IMAGE *out, double exponent )
{
	IMAGE *t[4];
	double mx1, mx2;

	if( im_open_local_array( out, t, 4, "im_gammacorrect", "p" ) ||
		im_check_u8or16( "im_gammacorrect", in ) ||
		im_piocheck( in, out ) ||
		(in->BandFmt == IM_BANDFMT_UCHAR ?
			im_identity( t[0], 1 ) :
			im_identity_ushort( t[0], 1, 65536 )) ||
		im_powtra( t[0], t[1], exponent ) ||
		im_max( t[0], &mx1 ) ||
		im_max( t[1], &mx2 ) ||
		im_lintra( mx1 / mx2, t[1], 0, t[2] ) ||
		im_clip2fmt( t[2], t[3], in->BandFmt ) ||
		im_maplut( in, out, t[3] ) )
		return( -1 );

	return( 0 );
}
Пример #15
0
int
im__colour_unary( const char *domain,
	IMAGE *in, IMAGE *out, VipsType type,
	im_wrapone_fn buffer_fn, void *a, void *b )
{
	IMAGE *t[1];

	if( im_check_uncoded( domain, in ) ||
		im_check_bands( domain, in, 3 ) ||
		im_open_local_array( out, t, 1, domain, "p" ) ||
		im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) )
		return( -1 );

	if( im_cp_desc( out, t[0] ) )
		return( -1 );
	out->Type = type;

	if( im_wrapone( t[0], out, 
		(im_wrapone_fn) buffer_fn, a, b ) )
		return( -1 );

	return( 0 );
}
Пример #16
0
int
im_clip2c( IMAGE *in, IMAGE *out )
{
	return( im_clip2fmt( in, out, IM_BANDFMT_CHAR ) );
}
Пример #17
0
int
im_clip2dcm( IMAGE *in, IMAGE *out )
{
	return( im_clip2fmt( in, out, IM_BANDFMT_DPCOMPLEX ) );
}
Пример #18
0
/* Convert to a saveable format. 
 *
 * im__saveable_t gives the general type of image
 * we make: vanilla 1/3 bands (eg. PPM), with an optional alpha (eg. PNG), or
 * with CMYK as an option (eg. JPEG). 
 *
 * format_table[] says how to convert each input format. 
 *
 * Need to im_close() the result IMAGE.
 */
IMAGE *
im__convert_saveable( IMAGE *in, 
	im__saveable_t saveable, int format_table[10] ) 
{
	IMAGE *out;

	if( !(out = im_open( "convert-for-save", "p" )) )
		return( NULL );

	/* If this is an IM_CODING_LABQ, we can go straight to RGB.
	 */
	if( in->Coding == IM_CODING_LABQ ) {
		IMAGE *t = im_open_local( out, "conv:1", "p" );
		static void *table = NULL;

		/* Make sure fast LabQ2disp tables are built. 7 is sRGB.
		 */
		if( !table ) 
			table = im_LabQ2disp_build_table( NULL, 
				im_col_displays( 7 ) );

		if( !t || im_LabQ2disp_table( in, t, table ) ) {
			im_close( out );
			return( NULL );
		}

		in = t;
	}

	/* If this is an IM_CODING_RAD, we go to float RGB or XYZ. We should
	 * probably un-gamma-correct the RGB :(
	 */
	if( in->Coding == IM_CODING_RAD ) {
		IMAGE *t;

		if( !(t = im_open_local( out, "conv:1", "p" )) || 
			im_rad2float( in, t ) ) {
			im_close( out );
			return( NULL );
		}

		in = t;
	}

	/* Get the bands right. 
	 */
	if( in->Coding == IM_CODING_NONE ) {
		if( in->Bands == 2 && saveable != IM__RGBA ) {
			IMAGE *t = im_open_local( out, "conv:1", "p" );

			if( !t || im_extract_band( in, t, 0 ) ) {
				im_close( out );
				return( NULL );
			}

			in = t;
		}
		else if( in->Bands > 3 && saveable == IM__RGB ) {
			IMAGE *t = im_open_local( out, "conv:1", "p" );

			if( !t ||
				im_extract_bands( in, t, 0, 3 ) ) {
				im_close( out );
				return( NULL );
			}

			in = t;
		}
		else if( in->Bands > 4 && 
			(saveable == IM__RGB_CMYK || saveable == IM__RGBA) ) {
			IMAGE *t = im_open_local( out, "conv:1", "p" );

			if( !t ||
				im_extract_bands( in, t, 0, 4 ) ) {
				im_close( out );
				return( NULL );
			}

			in = t;
		}

		/* Else we have saveable IM__ANY and we don't chop bands down.
		 */
	}

	/* Interpret the Type field for colorimetric images.
	 */
	if( in->Bands == 3 && in->BandFmt == IM_BANDFMT_SHORT && 
		in->Type == IM_TYPE_LABS ) {
		IMAGE *t = im_open_local( out, "conv:1", "p" );

		if( !t || im_LabS2LabQ( in, t ) ) {
			im_close( out );
			return( NULL );
		}

		in = t;
	}

	if( in->Coding == IM_CODING_LABQ ) {
		IMAGE *t = im_open_local( out, "conv:1", "p" );

		if( !t || im_LabQ2Lab( in, t ) ) {
			im_close( out );
			return( NULL );
		}

		in = t;
	}

	if( in->Coding != IM_CODING_NONE ) {
		im_close( out );
		return( NULL );
	}

	if( in->Bands == 3 && in->Type == IM_TYPE_LCH ) {
		IMAGE *t[2];

                if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
			im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
			im_LCh2Lab( t[0], t[1] ) ) {
			im_close( out );
			return( NULL );
		}

		in = t[1];
	}

	if( in->Bands == 3 && in->Type == IM_TYPE_YXY ) {
		IMAGE *t[2];

                if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
			im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
			im_Yxy2XYZ( t[0], t[1] ) ) {
			im_close( out );
			return( NULL );
		}

		in = t[1];
	}

	if( in->Bands == 3 && in->Type == IM_TYPE_UCS ) {
		IMAGE *t[2];

                if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
			im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
			im_UCS2XYZ( t[0], t[1] ) ) {
			im_close( out );
			return( NULL );
		}

		in = t[1];
	}

	if( in->Bands == 3 && in->Type == IM_TYPE_LAB ) {
		IMAGE *t[2];

                if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
			im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
			im_Lab2XYZ( t[0], t[1] ) ) {
			im_close( out );
			return( NULL );
		}

		in = t[1];
	}

	if( in->Bands == 3 && in->Type == IM_TYPE_XYZ ) {
		IMAGE *t[2];

                if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
			im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
			im_XYZ2disp( t[0], t[1], im_col_displays( 7 ) ) ) {
			im_close( out );
			return( NULL );
		}

		in = t[1];
	}

	/* Cast to the output format.
	 */
	{
		IMAGE *t = im_open_local( out, "conv:1", "p" );

		if( !t || im_clip2fmt( in, t, format_table[in->BandFmt] ) ) {
			im_close( out );
			return( NULL );
		}

		in = t;
	}

	if( im_copy( in, out ) ) {
		im_close( out );
		return( NULL );
	}

	return( out );
}
Пример #19
0
int
im_clip2f( IMAGE *in, IMAGE *out )
{
	return( im_clip2fmt( in, out, IM_BANDFMT_FLOAT ) );
}
Пример #20
0
int
im_clip2d( IMAGE *in, IMAGE *out )
{
	return( im_clip2fmt( in, out, IM_BANDFMT_DOUBLE ) );
}
Пример #21
0
int
im_clip2i( IMAGE *in, IMAGE *out )
{
	return( im_clip2fmt( in, out, IM_BANDFMT_INT ) );
}
Пример #22
0
static VipsFits *
vips_fits_new_write( VipsImage *in, const char *filename )
{
	VipsImage *flip;
	VipsImage *type;
	VipsFits *fits;
	int status;

	status = 0;

	if( im_check_noncomplex( "im_vips2fits", in ) ||
		im_check_uncoded( "im_vips2fits", in ) )
		return( NULL );

	/* Cast to a supported format.
	 */
	if( !(type = vips_image_new()) ||
		vips_object_local( in, type ) ||
		im_clip2fmt( in, type, vips_fits_bandfmt[in->BandFmt] ) )
		return( NULL );
	in = type;

	/* FITS has (0,0) in the bottom left, we need to flip.
	 */
	if( !(flip = vips_image_new()) ||
		vips_object_local( in, flip ) ||
		im_flipver( in, flip ) )
		return( NULL );
	in = flip;

	if( !(fits = VIPS_NEW( in, VipsFits )) )
		return( NULL );
	fits->filename = im_strdup( NULL, filename );
	fits->image = in;
	fits->fptr = NULL;
	fits->lock = NULL;
	fits->band_select = -1;
	fits->buffer = NULL;
	g_signal_connect( in, "close", 
		G_CALLBACK( vips_fits_close_cb ), fits );

	if( !(fits->filename = im_strdup( NULL, filename )) )
		return( NULL );

	/* We need to be able to hold one scanline of one band.
	 */
	if( !(fits->buffer = VIPS_ARRAY( NULL, 
		VIPS_IMAGE_SIZEOF_ELEMENT( in ) * in->Xsize, PEL )) )
		return( NULL );

	/* fits_create_file() will fail if there's a file of thet name, unless
	 * we put a "!" in front ofthe filename. This breaks conventions with
	 * the rest of vips, so just unlink explicitly.
	 */
	g_unlink( filename );

	if( fits_create_file( &fits->fptr, filename, &status ) ) {
		im_error( "fits", _( "unable to write to \"%s\"" ), filename );
		vips_fits_error( status );
		return( NULL );
	}

	fits->lock = g_mutex_new();

	return( fits );
}
Пример #23
0
/* Use fftw2.
 */
static int 
invfft1( IMAGE *dummy, IMAGE *in, IMAGE *out )
{
	IMAGE *cmplx = im_open_local( dummy, "invfft1-1", "t" );
	IMAGE *real = im_open_local( out, "invfft1-2", "t" );
	const int half_width = in->Xsize / 2 + 1;

	/* Transform to halfcomplex here.
	 */
	double *half_complex = IM_ARRAY( dummy, 
		in->Ysize * half_width * 2, double );

	rfftwnd_plan plan;
	int x, y;
	double *q, *p;

	if( !cmplx || !real || !half_complex || im_pincheck( in ) || 
		im_poutcheck( out ) )
		return( -1 );
	if( in->Coding != IM_CODING_NONE || in->Bands != 1 ) {
                im_error( "im_invfft", _( "one band uncoded only" ) );
                return( -1 );
	}

	/* Make dp complex image for input.
	 */
	if( im_clip2fmt( in, cmplx, IM_BANDFMT_DPCOMPLEX ) )
                return( -1 );

	/* Make mem buffer real image for output.
	 */
        if( im_cp_desc( real, in ) )
                return( -1 );
	real->BandFmt = IM_BANDFMT_DOUBLE;
        if( im_setupout( real ) )
                return( -1 );

	/* Build half-complex image.
	 */
	q = half_complex;
	for( y = 0; y < cmplx->Ysize; y++ ) {
		p = ((double *) cmplx->data) + y * in->Xsize * 2; 

		for( x = 0; x < half_width; x++ ) {
			q[0] = p[0];
			q[1] = p[1];
			p += 2;
			q += 2;
		}
	}

	/* Make the plan for the transform. Yes, they really do use nx for
	 * height and ny for width.
	 */
	if( !(plan = rfftw2d_create_plan( in->Ysize, in->Xsize,
		FFTW_BACKWARD, FFTW_MEASURE | FFTW_USE_WISDOM )) ) {
                im_error( "im_invfft", _( "unable to create transform plan" ) );
		return( -1 );
	}

	rfftwnd_one_complex_to_real( plan, 
		(fftw_complex *) half_complex, (fftw_real *) real->data );

	rfftwnd_destroy_plan( plan );

	/* Copy to out.
	 */
        if( im_copy( real, out ) )
                return( -1 );

	return( 0 );
}
Пример #24
0
/**
 * im_vips2mask:
 * @in: input image
 * @filename: name for output mask 
 *
 * Make a mask from an image. All images are cast to %IM_BANDFMT_DOUBLE
 * before processing. There are two cases for handling bands:
 *
 * If the image has a single band, im_vips2mask() will write a mask the same
 * size as the image.
 *
 * If the image has more than one band, it must be one pixel high or wide. In
 * this case the output mask uses that axis to represent band values.
 *
 * See also: im_mask2vips(), im_measure_area().
 *
 * Returns: a #DOUBLEMASK with @outname set as the name, or NULL on error
 */
DOUBLEMASK *
im_vips2mask( IMAGE *in, const char *filename )
{
	int width, height;
	DOUBLEMASK *out;

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

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

		return( out );
	}

	/* Check the image.
	 */
	if( im_incheck( in ) ||
		im_check_uncoded( "im_vips2mask", 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_vips2mask", 
			"%s", _( "one band, nx1, or 1xn images only" ) );
		return( NULL );
	}

	if( !(out = im_create_dmask( filename, width, height )) )
		return( NULL );
	if( in->Bands > 1 && in->Ysize == 1 ) {
		double *data = (double *) in->data;
		int x, y;

		/* Need to transpose: the image is RGBRGBRGB, we need RRRGGGBBB.
		 */
		for( y = 0; y < height; y++ )
			for( x = 0; x < width; x++ )
				out->coeff[x + y * width] =
					data[x * height + y];
	}
	else
		memcpy( out->coeff, in->data, 
			width * height * sizeof( double ) );

	out->scale = vips_image_get_scale( in );
	out->offset = vips_image_get_offset( in );

	return( out );
}
Пример #25
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 );
}
Пример #26
0
/* Fall back to vips's built-in fft.
 */
static int 
invfft1( IMAGE *dummy, IMAGE *in, IMAGE *out )
{
	int bpx = im_ispoweroftwo( in->Xsize );
	int bpy = im_ispoweroftwo( in->Ysize );
	float *buf, *q, *p1;
	int x, y;

	/* Buffers for real and imaginary parts.
	 */
	IMAGE *real = im_open_local( dummy, "invfft1:1", "t" );
	IMAGE *imag = im_open_local( dummy, "invfft1:2", "t" );

	/* Temps.
	 */
	IMAGE *t1 = im_open_local( dummy, "invfft1:3", "p" );
	IMAGE *t2 = im_open_local( dummy, "invfft1:4", "p" );

	if( !real || !imag || !t1 )
		return( -1 );
        if( im_pincheck( in ) || im_outcheck( out ) )
                return( -1 );
        if( in->Coding != IM_CODING_NONE || 
		in->Bands != 1 || !im_iscomplex( in ) ) {
                im_error( "im_invfft", 
			"%s", _( "one band complex uncoded only" ) );
                return( -1 );
	}
	if( !bpx || !bpy ) {
		im_error( "im_invfft", 
			"%s", _( "sides must be power of 2" ) );
		return( -1 );
	}

	/* Make sure we have a single-precision complex input image.
	 */
	if( im_clip2fmt( in, t1, IM_BANDFMT_COMPLEX ) )
		return( -1 );

	/* Extract real and imag parts. We have to complement the imaginary.
	 */
	if( im_c2real( t1, real ) )
		return( -1 );
	if( im_c2imag( t1, t2 ) || im_lintra( -1.0, t2, 0.0, imag ) )
		return( -1 );

	/* Transform!
	 */
	if( im__fft_sp( (float *) real->data, (float *) imag->data, 
		bpx - 1, bpy - 1 ) ) {
                im_error( "im_invfft", 
			"%s", _( "fft_sp failed" ) );
                return( -1 );
	}

	/* WIO to out.
	 */
        if( im_cp_desc( out, in ) )
                return( -1 );
	out->BandFmt = IM_BANDFMT_FLOAT;
        if( im_setupout( out ) )
                return( -1 );
	if( !(buf = (float *) IM_ARRAY( dummy, 
		IM_IMAGE_SIZEOF_LINE( out ), PEL )) )
		return( -1 );

	/* Just write real part.
	 */
	for( p1 = (float *) real->data, y = 0; y < out->Ysize; y++ ) {
		q = buf;

		for( x = 0; x < out->Xsize; x++ ) {
			q[x] = *p1++;
		}

		if( im_writeline( y, out, (PEL *) buf ) )
			return( -1 );
	}

	return( 0 );
}
Пример #27
0
int
im_clip2s( IMAGE *in, IMAGE *out )
{
	return( im_clip2fmt( in, out, IM_BANDFMT_SHORT ) );
}