static int ifthenelse( IMAGE *c, IMAGE *a, IMAGE *b, IMAGE *out ) { IMAGE **in; /* Check args. */ if( im_check_uncoded( "im_ifthenelse", c ) || im_check_coding_known( "im_ifthenelse", a ) || im_check_coding_known( "im_ifthenelse", b ) || im_check_format( "ifthenelse", c, IM_BANDFMT_UCHAR ) || im_check_format_same( "ifthenelse", a, b ) || im_check_bands_same( "ifthenelse", a, b ) || im_check_bands_1orn( "im_ifthenelse", c, a ) || im_piocheck( c, out ) || im_pincheck( a ) || im_pincheck( b ) ) return( -1 ); /* Make output image. */ if( im_demand_hint( out, IM_THINSTRIP, c, a, b, NULL ) || im_cp_descv( out, a, b, c, NULL ) || !(in = im_allocate_input_array( out, c, a, b, NULL )) || im_generate( out, im_start_many, ifthenelse_gen, im_stop_many, in, NULL ) ) return( -1 ); return( 0 ); }
/** * im_hist_indexed: * @index: input image * @value: input image * @out: output image * * Make a histogram of @value, but use image @index to pick the bins. In other * words, element zero in @out contains the sum of all the pixels in @value * whose corresponding pixel in @index is zero. * * @index must have just one band and be u8 or u16. @value must be * non-complex. @out always has the same size and format as @value. * * This operation is useful in conjunction with im_label_regions(). You can * use it to find the centre of gravity of blobs in an image, for example. * * See also: im_histgr(), im_label_regions(). * * Returns: 0 on success, -1 on error */ int im_hist_indexed( IMAGE *index, IMAGE *value, IMAGE *out ) { int size; /* Length of hist */ Histogram *mhist; VipsGenerateFn scanfn; /* Check images. PIO from in, WIO to out. */ if( im_pincheck( index ) || im_pincheck( value ) || im_outcheck( out ) || im_check_uncoded( "im_hist_indexed", index ) || im_check_uncoded( "im_hist_indexed", value ) || im_check_noncomplex( "im_hist_indexed", value ) || im_check_size_same( "im_hist_indexed", index, value ) || im_check_u8or16( "im_hist_indexed", index ) || im_check_mono( "im_hist_indexed", index ) ) return( -1 ); /* Find the range of pixel values we must handle. */ if( index->BandFmt == IM_BANDFMT_UCHAR ) { size = 256; scanfn = hist_scan_uchar; } else { size = 65536; scanfn = hist_scan_ushort; } /* Build main hist we accumulate data in. */ if( !(mhist = hist_build( index, value, out, value->Bands, size )) ) return( -1 ); /* Accumulate data. */ if( vips_sink( index, hist_start, scanfn, hist_stop, mhist, NULL ) || hist_write( out, mhist ) ) { hist_free( mhist ); return( -1 ); } hist_free( mhist ); return( 0 ); }
int im_subtract( IMAGE *in1, IMAGE *in2, IMAGE *out ) { /* Basic checks. */ if( im_piocheck( in1, out ) || im_pincheck( in2 ) ) return( -1 ); if( in1->Bands != in2->Bands && (in1->Bands != 1 && in2->Bands != 1) ) { im_error( "im_subtract", _( "not same number of bands" ) ); return( -1 ); } if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) { im_error( "im_subtract", _( "not uncoded" ) ); return( -1 ); } if( im_cp_descv( out, in1, in2, NULL ) ) return( -1 ); /* What number of bands will we write? */ out->Bands = IM_MAX( in1->Bands, in2->Bands ); /* What output type will we write? int, float or complex. */ if( im_iscomplex( in1 ) || im_iscomplex( in2 ) ) { /* What kind of complex? */ if( in1->BandFmt == IM_BANDFMT_DPCOMPLEX || in2->BandFmt == IM_BANDFMT_DPCOMPLEX ) /* Output will be DPCOMPLEX. */ out->BandFmt = IM_BANDFMT_DPCOMPLEX; else out->BandFmt = IM_BANDFMT_COMPLEX; } else if( im_isfloat( in1 ) || im_isfloat( in2 ) ) { /* What kind of float? */ if( in1->BandFmt == IM_BANDFMT_DOUBLE || in2->BandFmt == IM_BANDFMT_DOUBLE ) out->BandFmt = IM_BANDFMT_DOUBLE; else out->BandFmt = IM_BANDFMT_FLOAT; } else /* Must be int+int -> int. */ out->BandFmt = iformat[in1->BandFmt][in2->BandFmt]; /* And process! */ if( im__cast_and_call( in1, in2, out, (im_wrapmany_fn) subtract_buffer, NULL ) ) return( -1 ); /* Success! */ return( 0 ); }
/* Wrap up as a partial. */ int im_wraptwo( IMAGE *in1, IMAGE *in2, IMAGE *out, im_wraptwo_fn fn, void *a, void *b ) { if( im_pincheck( in1 ) || im_pincheck( in2 ) || im_poutcheck( out )) return -1; { UserBundle *bun= IM_NEW( out, UserBundle ); IMAGE **ins= im_allocate_input_array( out, in1, in2, NULL ); if( ! bun || ! ins ) return -1; bun-> fn= fn; bun-> a= a; bun-> b= b; return im_demand_hint( out, IM_THINSTRIP, in1, in2, NULL ) || im_generate( out, im_start_many, process_region, im_stop_many, (void*) ins, (void*) bun ); } }
/** * im_vips2raw: * @in: image to save * @fd: file descriptor to write to * * Writes the pixels in @in to the file descriptor. It's handy for writing * writers for other formats. * * See also: #VipsFormat, im_raw2vips(). * * Returns: 0 on success, -1 on error. */ int im_vips2raw( IMAGE *in, int fd ) { Write *write; if( im_pincheck( in ) || !(write = write_new( in, fd )) ) return( -1 ); if( vips_sink_disc( in, write_block, write ) ) { write_destroy( write ); return( -1 ); } write_destroy( write ); return( 0 ); }
/* Transform an n-band image with a 1-band processing function. */ int im__fftproc( IMAGE *dummy, IMAGE *in, IMAGE *out, im__fftproc_fn fn ) { if( im_pincheck( in ) || im_outcheck( out ) ) return( -1 ); if( in->Bands == 1 ) { if( fn( dummy, in, out ) ) return( -1 ); } else { IMAGE *acc; int b; for( acc = NULL, b = 0; b < in->Bands; b++ ) { IMAGE *t1 = im_open_local( dummy, "fwfftn:1", "p" ); IMAGE *t2 = im_open_local( dummy, "fwfftn:2", "p" ); if( !t1 || !t2 || im_extract_band( in, t1, b ) || fn( dummy, t1, t2 ) ) return( -1 ); if( !acc ) acc = t2; else { IMAGE *t3 = im_open_local( dummy, "fwfftn:3", "p" ); if( !t3 || im_bandjoin( acc, t2, t3 ) ) return( -1 ); acc = t3; } } if( im_copy( acc, out ) ) return( -1 ); } return( 0 ); }
/** * im_maxpos_avg: * @im: image to scan * @xpos: returned X position * @ypos: returned Y position * @out: returned value * * Function to find the maximum of an image. Returns coords and value at * double precision. In the event of a draw, returns average of all * drawing coords. * * See also: im_maxpos(), im_min(), im_stats(). * * Returns: 0 on success, -1 on error */ int im_maxpos_avg( IMAGE *in, double *xpos, double *ypos, double *out ) { Maxposavg *global_maxposavg; if( im_pincheck( in ) || im_check_uncoded( "im_maxpos_avg", in ) ) return( -1 ); if( !(global_maxposavg = IM_NEW( in, Maxposavg )) ) return( -1 ); if( im__value( in, &global_maxposavg->max ) ) return( -1 ); global_maxposavg->xpos = 0; global_maxposavg->ypos = 0; global_maxposavg->occurences = 1; /* We use square mod for scanning, for speed. */ if( vips_band_format_iscomplex( in->BandFmt ) ) global_maxposavg->max *= global_maxposavg->max; if( vips_sink( in, maxposavg_start, maxposavg_scan, maxposavg_stop, in, global_maxposavg ) ) return( -1 ); /* Back to modulus. */ if( vips_band_format_iscomplex( in->BandFmt ) ) global_maxposavg->max = sqrt( global_maxposavg->max ); if( xpos ) *xpos = (double) global_maxposavg->xpos / global_maxposavg->occurences; if( ypos ) *ypos = (double) global_maxposavg->ypos / global_maxposavg->occurences; if( out ) *out = global_maxposavg->max; return( 0 ); }
int im_gradcor_raw( IMAGE *large, IMAGE *small, IMAGE *out ){ #define FUNCTION_NAME "im_gradcor_raw" if( im_piocheck( large, out ) || im_pincheck( small ) ) return -1; if( im_check_uncoded( "im_gradcor", large ) || im_check_mono( "im_gradcor", large ) || im_check_uncoded( "im_gradcor", small ) || im_check_mono( "im_gradcor", small ) || im_check_format_same( "im_gradcor", large, small ) || im_check_int( "im_gradcor", large ) ) return( -1 ); if( large-> Xsize < small-> Xsize || large-> Ysize < small-> Ysize ){ im_error( FUNCTION_NAME, "second image must be smaller than first" ); return -1; } if( im_cp_desc( out, large ) ) return -1; out-> Xsize= 1 + large-> Xsize - small-> Xsize; out-> Ysize= 1 + large-> Ysize - small-> Ysize; out-> BandFmt= IM_BANDFMT_FLOAT; if( im_demand_hint( out, IM_FATSTRIP, large, NULL ) ) return -1; { IMAGE *xgrad= im_open_local( out, FUNCTION_NAME ": xgrad", "t" ); IMAGE *ygrad= im_open_local( out, FUNCTION_NAME ": ygrad", "t" ); IMAGE **grads= im_allocate_input_array( out, xgrad, ygrad, NULL ); return ! xgrad || ! ygrad || ! grads || im_grad_x( small, xgrad ) || im_grad_y( small, ygrad ) || im_generate( out, gradcor_start, gradcor_gen, gradcor_stop, (void*) large, (void*) grads ); } #undef FUNCTION_NAME }
/* Find the average of an image. */ int im_deviate( IMAGE *in, double *out ) { double sum[2] = { 0.0, 0.0 }; gint64 N; /* Check our args. */ if( im_pincheck( in ) ) return( -1 ); if( in->Coding != IM_CODING_NONE ) { im_error( "im_deviate", _( "not uncoded" ) ); return( -1 ); } if( im_iscomplex( in ) ) { im_error( "im_deviate", _( "bad input type" ) ); return( -1 ); } /* Loop over input, summing pixels. */ if( im_iterate( in, start_fn, scan_fn, stop_fn, &sum, NULL ) ) return( -1 ); /* NOTE: NR suggests a two-pass algorithm to minimise roundoff. But that's too expensive for us :-( so do it the old one-pass way. */ /* Calculate and return deviation. Add a fabs to stop sqrt(<=0). */ N = (gint64) in->Xsize * in->Ysize * in->Bands; *out = sqrt( fabs( sum[1] - (sum[0] * sum[0] / N) ) / (N - 1) ); return( 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] ); }
int im_min( IMAGE *in, double *out ) { MinInfo inf; inf.in = in; inf.out = out; inf.valid = 0; if( im_pincheck( in ) ) return( -1 ); if( in->Coding != IM_CODING_NONE ) { im_error( "im_min", _( "not uncoded" ) ); return( -1 ); } if( im_iterate( in, start_fn, scan_fn, stop_fn, &inf, NULL ) ) return( -1 ); *out = inf.value; return( 0 ); }
int im_histnD( IMAGE *in, IMAGE *out, int bins ) { int max_val; Histogram *mhist; int x, y, z, i; unsigned int *obuffer; /* Check images. PIO from in, WIO to out. */ if( im_pincheck( in ) || im_outcheck( out ) ) return( -1 ); if( in->Coding != IM_CODING_NONE ) { im_error( "im_histnD", _( " uncoded images only" ) ); return( -1 ); } if( in->BandFmt != IM_BANDFMT_UCHAR && in->BandFmt != IM_BANDFMT_USHORT ) { im_error( "im_histnD", _( " unsigned 8 or 16 bit images only" ) ); return( -1 ); } max_val = in->BandFmt == IM_BANDFMT_UCHAR ? 256 : 65536; if( bins < 1 || bins > max_val ) { im_error( "im_histnD", _( " bins out of range [1,%d]" ), max_val ); return( -1 ); } /* Build main hist we accumulate to. */ if( !(mhist = build_hist( in, out, bins )) ) return( -1 ); /* Accumulate data. */ if( im_iterate( in, build_subhist, find_hist, merge_subhist, mhist, NULL ) ) return( -1 ); /* Make the output image. */ if( im_cp_desc( out, in ) ) return( -1 ); im_initdesc( out, bins, in->Bands > 1 ? bins : 1, in->Bands > 2 ? bins : 1, IM_BBITS_INT, IM_BANDFMT_UINT, IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 ); if( im_setupout( out ) ) return( -1 ); /* Interleave to output buffer. */ if( !(obuffer = IM_ARRAY( out, IM_IMAGE_N_ELEMENTS( out ), unsigned int )) ) return( -1 ); for( y = 0; y < out->Ysize; y++ ) { for( i = 0, x = 0; x < out->Xsize; x++ ) for( z = 0; z < out->Bands; z++, i++ ) obuffer[i] = mhist->data[z][y][x]; if( im_writeline( y, out, (PEL *) obuffer ) ) return( -1 ); } return( 0 ); }
/* Call rfftw for a 1 band real image. */ static int rfwfft1( IMAGE *dummy, IMAGE *in, IMAGE *out ) { const int size = in->Xsize * in->Ysize; const int half_width = in->Xsize / 2 + 1; /* Pack to double real here. */ IMAGE *real = im_open_local( dummy, "fwfft1:1", "t" ); /* Transform to halfcomplex here. */ double *half_complex = IM_ARRAY( dummy, in->Ysize * half_width * 2, double ); rfftwnd_plan plan; double *buf, *q, *p; int x, y; if( !real || !half_complex || im_pincheck( in ) || im_outcheck( out ) ) return( -1 ); if( in->Coding != IM_CODING_NONE || in->Bands != 1 ) { im_error( "im_fwfft", _( "one band uncoded only" ) ); return( -1 ); } if( im_clip2d( in, real ) ) return( -1 ); /* 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_FORWARD, FFTW_MEASURE | FFTW_USE_WISDOM )) ) { im_error( "im_fwfft", _( "unable to create transform plan" ) ); return( -1 ); } rfftwnd_one_real_to_complex( plan, (fftw_real *) real->data, (fftw_complex *) half_complex ); rfftwnd_destroy_plan( plan ); /* WIO to out. */ if( im_cp_desc( out, in ) ) return( -1 ); out->Bbits = IM_BBITS_DPCOMPLEX; out->BandFmt = IM_BANDFMT_DPCOMPLEX; if( im_setupout( out ) ) return( -1 ); if( !(buf = (double *) IM_ARRAY( dummy, IM_IMAGE_SIZEOF_LINE( out ), PEL )) ) return( -1 ); /* Copy to out and normalise. The right half is the up/down and * left/right flip of the left, but conjugated. Do the first * row separately, then mirror around the centre row. */ p = half_complex; q = buf; for( x = 0; x < half_width; x++ ) { q[0] = p[0] / size; q[1] = p[1] / size; p += 2; q += 2; } p = half_complex + ((in->Xsize + 1) / 2 - 1) * 2; for( x = half_width; x < out->Xsize; x++ ) { q[0] = p[0] / size; q[1] = -1.0 * p[1] / size; p -= 2; q += 2; } if( im_writeline( 0, out, (PEL *) buf ) ) return( -1 ); for( y = 1; y < out->Ysize; y++ ) { p = half_complex + y * half_width * 2; q = buf; for( x = 0; x < half_width; x++ ) { q[0] = p[0] / size; q[1] = p[1] / size; p += 2; q += 2; } /* Good grief. */ p = half_complex + 2 * ((out->Ysize - y + 1) * half_width - 2 + (in->Xsize & 1)); for( x = half_width; x < out->Xsize; x++ ) { q[0] = p[0] / size; q[1] = -1.0 * p[1] / size; p -= 2; q += 2; } if( im_writeline( y, out, (PEL *) buf ) ) return( -1 ); } return( 0 ); }
/* Transform a 1 band image with vips's built-in fft routine. */ static int fwfft1( IMAGE *dummy, IMAGE *in, IMAGE *out ) { int size = in->Xsize * in->Ysize; int bpx = im_ispoweroftwo( in->Xsize ); int bpy = im_ispoweroftwo( in->Ysize ); float *buf, *q, *p1, *p2; int x, y; /* Buffers for real and imaginary parts. */ IMAGE *real = im_open_local( dummy, "fwfft1:1", "t" ); IMAGE *imag = im_open_local( dummy, "fwfft1:2", "t" ); /* Temporaries. */ IMAGE *t1 = im_open_local( dummy, "fwfft1:3", "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_fwfft", _( "one band non-complex uncoded only" ) ); return( -1 ); } if( !bpx || !bpy ) { im_error( "im_fwfft", _( "sides must be power of 2" ) ); return( -1 ); } /* Make sure we have a float input image. */ if( im_clip2f( in, real ) ) return( -1 ); /* Make a buffer of 0 floats of the same size for the imaginary part. */ if( im_black( t1, in->Xsize, in->Ysize, 1 ) ) return( -1 ); if( im_clip2f( t1, imag ) ) return( -1 ); /* Transform! */ if( im__fft_sp( (float *) real->data, (float *) imag->data, bpx - 1, bpy - 1 ) ) { im_error( "im_fwfft", _( "fft_sp failed" ) ); return( -1 ); } /* WIO to out. */ if( im_cp_desc( out, in ) ) return( -1 ); out->Bbits = IM_BBITS_COMPLEX; out->BandFmt = IM_BANDFMT_COMPLEX; if( im_setupout( out ) ) return( -1 ); if( !(buf = (float *) IM_ARRAY( dummy, IM_IMAGE_SIZEOF_LINE( out ), PEL )) ) return( -1 ); /* Gather together real and imag parts. We have to normalise output! */ for( p1 = (float *) real->data, p2 = (float *) imag->data, y = 0; y < out->Ysize; y++ ) { q = buf; for( x = 0; x < out->Xsize; x++ ) { q[0] = *p1++ / size; q[1] = *p2++ / size; q += 2; } if( im_writeline( y, out, (PEL *) buf ) ) return( -1 ); } return( 0 ); }
/* Complex to complex forward transform. */ static int cfwfft1( IMAGE *dummy, IMAGE *in, IMAGE *out ) { fftw_plan plan; double *buf, *q, *p; int x, y; IMAGE *cmplx = im_open_local( dummy, "fwfft1:1", "t" ); /* We have to have a separate buffer for the planner to work on. */ double *planner_scratch = IM_ARRAY( dummy, in->Xsize * in->Ysize * 2, double ); /* Make dp complex image. */ if( !cmplx || im_pincheck( in ) || im_outcheck( out ) ) return( -1 ); if( in->Coding != IM_CODING_NONE || in->Bands != 1 ) { im_error( "im_fwfft", _( "one band uncoded only" ) ); return( -1 ); } if( im_clip2dcm( in, cmplx ) ) return( -1 ); /* Make the plan for the transform. */ if( !(plan = fftw_plan_dft_2d( in->Ysize, in->Xsize, (fftw_complex *) planner_scratch, (fftw_complex *) planner_scratch, FFTW_FORWARD, 0 )) ) { im_error( "im_fwfft", _( "unable to create transform plan" ) ); return( -1 ); } fftw_execute_dft( plan, (fftw_complex *) cmplx->data, (fftw_complex *) cmplx->data ); fftw_destroy_plan( plan ); /* WIO to out. */ if( im_cp_desc( out, in ) ) return( -1 ); out->Bbits = IM_BBITS_DPCOMPLEX; out->BandFmt = IM_BANDFMT_DPCOMPLEX; if( im_setupout( out ) ) return( -1 ); if( !(buf = (double *) IM_ARRAY( dummy, IM_IMAGE_SIZEOF_LINE( out ), PEL )) ) return( -1 ); /* Copy to out, normalise. */ for( p = (double *) cmplx->data, y = 0; y < out->Ysize; y++ ) { int size = out->Xsize * out->Ysize; q = buf; for( x = 0; x < out->Xsize; x++ ) { q[0] = p[0] / size; q[1] = p[1] / size; p += 2; q += 2; } if( im_writeline( y, out, (PEL *) buf ) ) return( -1 ); } return( 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 ); }
/** * im_linreg: * @ins: NULL-terminated array of input images * @out: results of analysis * @xs: X position of each image (pixel value is Y) * * Function to find perform pixelwise linear regression on an array of * single band images. The output is a seven-band douuble image * * TODO: figure out how this works and fix up these docs! */ int im_linreg( IMAGE **ins, IMAGE *out, double *xs ){ #define FUNCTION_NAME "im_linreg" int n; x_set *x_vals; if( im_poutcheck( out ) ) return( -1 ); for( n= 0; ins[ n ]; ++n ){ /* if( ! isfinite( xs[ n ] ) ){ im_error( FUNCTION_NAME, "invalid argument" ); return( -1 ); } */ if( im_pincheck( ins[ n ] ) ) return( -1 ); if( 1 != ins[ n ]-> Bands ){ im_error( FUNCTION_NAME, "image is not single band" ); return( -1 ); } if( ins[ n ]-> Coding ){ im_error( FUNCTION_NAME, "image is not uncoded" ); return( -1 ); } if( n ){ if( ins[ n ]-> BandFmt != ins[ 0 ]-> BandFmt ){ im_error( FUNCTION_NAME, "image band formats differ" ); return( -1 ); } } else { if( vips_bandfmt_iscomplex( ins[ 0 ]->BandFmt ) ){ im_error( FUNCTION_NAME, "image has non-scalar band format" ); return( -1 ); } } if( n && ( ins[ n ]-> Xsize != ins[ 0 ]-> Xsize || ins[ n ]-> Ysize != ins[ 0 ]-> Ysize ) ){ im_error( FUNCTION_NAME, "image sizes differ" ); return( -1 ); } } if( n < 3 ){ im_error( FUNCTION_NAME, "not enough input images" ); return( -1 ); } if( im_cp_desc_array( out, ins ) ) return( -1 ); out-> Bands= 7; out-> BandFmt= IM_BANDFMT_DOUBLE; out-> Type= 0; if( im_demand_hint_array( out, IM_THINSTRIP, ins ) ) return( -1 ); x_vals= x_anal( out, xs, n ); if( ! x_vals ) return( -1 ); switch( ins[ 0 ]-> BandFmt ){ #define LINREG_RET( TYPE ) return im_generate( out, linreg_start_ ## TYPE, linreg_gen_ ## TYPE, linreg_stop_ ## TYPE, ins, x_vals ) case IM_BANDFMT_CHAR: LINREG_RET( gint8 ); case IM_BANDFMT_UCHAR: LINREG_RET( guint8 ); case IM_BANDFMT_SHORT: LINREG_RET( gint16 ); case IM_BANDFMT_USHORT: LINREG_RET( guint16 ); case IM_BANDFMT_INT: LINREG_RET( gint32 ); case IM_BANDFMT_UINT: LINREG_RET( guint32 ); case IM_BANDFMT_FLOAT: LINREG_RET( float ); case IM_BANDFMT_DOUBLE: LINREG_RET( double ); default: /* keep -Wall happy */ return( -1 ); } #undef FUNCTION_NAME }
/* Write a VIPS image to a JPEG compress struct. */ static int write_vips( Write *write, int qfac, const char *profile ) { IMAGE *in; J_COLOR_SPACE space; /* The image we'll be writing ... can change, see CMYK. */ in = write->in; /* Should have been converted for save. */ g_assert( in->BandFmt == IM_BANDFMT_UCHAR ); g_assert( in->Coding == IM_CODING_NONE ); g_assert( in->Bands == 1 || in->Bands == 3 || in->Bands == 4 ); /* Check input image. */ if( im_pincheck( in ) ) return( -1 ); if( qfac < 0 || qfac > 100 ) { im_error( "im_vips2jpeg", "%s", _( "qfac should be in 0-100" ) ); return( -1 ); } /* Set compression parameters. */ write->cinfo.image_width = in->Xsize; write->cinfo.image_height = in->Ysize; write->cinfo.input_components = in->Bands; if( in->Bands == 4 && in->Type == IM_TYPE_CMYK ) { space = JCS_CMYK; /* IJG always sets an Adobe marker, so we should invert CMYK. */ if( !(write->inverted = im_open( "vips2jpeg_invert", "p" )) || im_invert( in, write->inverted ) ) return( -1 ); in = write->inverted; } else if( in->Bands == 3 ) space = JCS_RGB; else if( in->Bands == 1 ) space = JCS_GRAYSCALE; else /* Use luminance compression for all channels. */ space = JCS_UNKNOWN; write->cinfo.in_color_space = space; /* Build VIPS output stuff now we know the image we'll be writing. */ if( !(write->row_pointer = IM_ARRAY( NULL, write->in->Ysize, JSAMPROW )) ) return( -1 ); /* Rest to default. */ jpeg_set_defaults( &write->cinfo ); jpeg_set_quality( &write->cinfo, qfac, TRUE ); /* Build compress tables. */ jpeg_start_compress( &write->cinfo, TRUE ); /* Write any APP markers we need. */ if( write_exif( write ) ) return( -1 ); /* A profile supplied as an argument overrides an embedded profile. * "none" means don't attach a profile. */ if( profile && strcmp( profile, "none" ) != 0 && write_profile_file( write, profile ) ) return( -1 ); if( !profile && im_header_get_typeof( in, IM_META_ICC_NAME ) && write_profile_meta( write ) ) return( -1 ); /* Write data. Note that the write function grabs the longjmp()! */ if( vips_sink_disc( write->in, write_jpeg_block, write ) ) return( -1 ); /* We have to reinstate the setjmp() before we jpeg_finish_compress(). */ if( setjmp( write->eman.jmp ) ) return( -1 ); jpeg_finish_compress( &write->cinfo ); return( 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 ); }