/* Yuk! Have to malloc enough space for the whole image. Interlaced PNG * is not really suitable for large objects ... */ static int png2vips_interlace( Read *read ) { const int rowbytes = IM_IMAGE_SIZEOF_LINE( read->out ); int y; if( !(read->row_pointer = IM_ARRAY( NULL, read->pInfo->height, png_bytep )) ) return( -1 ); if( !(read->data = (png_bytep) im_malloc( NULL, read->pInfo->height * rowbytes )) ) return( -1 ); for( y = 0; y < (int) read->pInfo->height; y++ ) read->row_pointer[y] = read->data + y * rowbytes; if( im_outcheck( read->out ) || im_setupout( read->out ) || setjmp( read->pPng->jmpbuf ) ) return( -1 ); png_read_image( read->pPng, read->row_pointer ); for( y = 0; y < (int) read->pInfo->height; y++ ) if( im_writeline( y, read->out, read->row_pointer[y] ) ) return( -1 ); return( 0 ); }
static int mat2vips_get_data( mat_t *mat, matvar_t *var, IMAGE *im ) { int y; PEL *buffer; const int es = IM_IMAGE_SIZEOF_ELEMENT( im ); /* Matlab images are plane-separate, so we have to assemble bands in * image-size chunks. */ const int is = es * im->Xsize * im->Ysize; if( Mat_VarReadDataAll( mat, var ) ) { im_error( "im_mat2vips", "%s", _( "Mat_VarReadDataAll failed" ) ); return( -1 ); } if( im_outcheck( im ) || im_setupout( im ) ) return( -1 ); /* Matlab images are in columns, so we have to transpose into * scanlines with this buffer. */ if( !(buffer = IM_ARRAY( im, IM_IMAGE_SIZEOF_LINE( im ), PEL )) ) return( -1 ); for( y = 0; y < im->Ysize; y++ ) { const PEL *p = var->data + y * es; int x; PEL *q; q = buffer; for( x = 0; x < im->Xsize; x++ ) { int b; for( b = 0; b < im->Bands; b++ ) { const PEL *p2 = p + b * is; int z; for( z = 0; z < es; z++ ) q[z] = p2[z]; q += es; } p += es * im->Ysize; } if( im_writeline( y, im, buffer ) ) 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 ); }
/* 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 ); }
/* Read a cinfo to a VIPS image. */ static int read_jpeg_image( struct jpeg_decompress_struct *cinfo, IMAGE *out, gboolean invert_pels ) { int x, y, sz; JSAMPROW row_pointer[1]; /* Check VIPS. */ if( im_outcheck( out ) || im_setupout( out ) ) return( -1 ); /* Get size of output line and make a buffer. */ sz = cinfo->output_width * cinfo->output_components; row_pointer[0] = (JSAMPLE *) (*cinfo->mem->alloc_large) ( (j_common_ptr) cinfo, JPOOL_IMAGE, sz ); /* Start up decompressor. */ jpeg_start_decompress( cinfo ); /* Process image. */ for( y = 0; y < out->Ysize; y++ ) { /* We set an error handler that longjmps() out, so I don't * think this can fail. */ jpeg_read_scanlines( cinfo, &row_pointer[0], 1 ); if( invert_pels ) { for( x = 0; x < sz; x++ ) row_pointer[0][x] = 255 - row_pointer[0][x]; } if( im_writeline( y, out, row_pointer[0] ) ) return( -1 ); } /* Stop decompressor. */ jpeg_finish_decompress( cinfo ); return( 0 ); }
int im_fzone( IMAGE *image, int size ) { int x, y; int i, j; float *buf; const int size2 = size/2; /* Check args. */ if( im_outcheck( image ) ) return( -1 ); if( size <= 0 || (size % 2) != 0 ) { im_error( "im_zone", "%s", _( "size must be even and positive" ) ); return( -1 ); } /* Set up output image. */ im_initdesc( image, size, size, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT, IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 ); if( im_setupout( image ) ) return( -1 ); /* Create output buffer. */ if( !(buf = IM_ARRAY( image, size, float )) ) return( -1 ); /* Make zone plate. */ for( y = 0, j = -size2; j < size2; j++, y++ ) { for( x = 0, i = -size2; i < size2; i++, x++ ) buf[x] = cos( (IM_PI / size) * (i * i + j * j) ); if( im_writeline( y, image, (PEL *) buf ) ) return( -1 ); } return( 0 ); }
/* Read an ascii ppm/pgm file. */ static int read_ascii( FILE *fp, IMAGE *out ) { int x, y; PEL *buf; if( im_outcheck( out ) || im_setupout( out ) || !(buf = IM_ARRAY( out, IM_IMAGE_SIZEOF_LINE( out ), PEL )) ) return( -1 ); for( y = 0; y < out->Ysize; y++ ) { for( x = 0; x < out->Xsize * out->Bands; x++ ) { int val; if( read_int( fp, &val ) ) return( -1 ); switch( out->BandFmt ) { case IM_BANDFMT_UCHAR: buf[x] = IM_CLIP( 0, val, 255 ); break; case IM_BANDFMT_USHORT: ((unsigned short *) buf)[x] = IM_CLIP( 0, val, 65535 ); break; case IM_BANDFMT_UINT: ((unsigned int *) buf)[x] = val; break; default: g_assert( 0 ); } } if( im_writeline( y, out, buf ) ) return( -1 ); } return( 0 ); }
static int lgrab_capture( LGrab *lg, IMAGE *im ) { int x, y; unsigned char *line; if( lgrab_capturen( lg ) ) return( -1 ); if( im_outcheck( im ) ) return( -1 ); im_initdesc( im, lg->c_width, lg->c_height, 3, IM_BBITS_BYTE, IM_BANDFMT_UCHAR, IM_CODING_NONE, IM_TYPE_MULTIBAND, 1.0, 1.0, 0, 0 ); if( im_setupout( im ) ) return( -1 ); if( !(line = IM_ARRAY( im, IM_IMAGE_SIZEOF_LINE( im ), unsigned char )) ) return( -1 ); for( y = 0; y < lg->c_height; y++ ) { unsigned char *p = (unsigned char *) lg->capture_buffer + y * IM_IMAGE_SIZEOF_LINE( im ); unsigned char *q = line; for( x = 0; x < lg->c_width; x++ ) { q[0] = p[2]; q[1] = p[1]; q[2] = p[0]; p += 3; q += 3; } if( im_writeline( y, im, line ) ) return( -1 ); } return( 0 ); }
/* Noninterlaced images can be read without needing enough RAM for the whole * image. */ static int png2vips_noninterlace( Read *read ) { const int rowbytes = IM_IMAGE_SIZEOF_LINE( read->out ); int y; if( !(read->data = (png_bytep) im_malloc( NULL, rowbytes )) ) return( -1 ); if( im_outcheck( read->out ) || im_setupout( read->out ) || setjmp( read->pPng->jmpbuf ) ) return( -1 ); for( y = 0; y < (int) read->pInfo->height; y++ ) { png_read_row( read->pPng, read->data, NULL ); if( im_writeline( y, read->out, read->data ) ) 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 ); }
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 ); }
/** * im_simcontr: * @out: output image * @xsize: image size * @ysize: image size * * Creates a pattern showing the similtaneous constrast effect. * * See also: im_eye(). * * Returns: 0 on success, -1 on error */ int im_simcontr( IMAGE *out, int xsize, int ysize ) { int x, y; unsigned char *line1, *line2, *cpline; /* Check input args */ if( im_outcheck( out ) ) return( -1 ); /* Set now image properly */ im_initdesc(out, xsize, ysize, 1, IM_BBITS_BYTE, IM_BANDFMT_UCHAR, IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 ); /* Set up image checking whether the output is a buffer or a file */ if (im_setupout( out ) == -1 ) return( -1 ); /* Create data */ line1 = (unsigned char *)calloc((unsigned)xsize, sizeof(char)); line2 = (unsigned char *)calloc((unsigned)xsize, sizeof(char)); if ( (line1 == NULL) || (line2 == NULL) ) { im_error( "im_simcontr", "%s", _( "calloc failed") ); return(-1); } cpline = line1; for (x=0; x<xsize; x++) *cpline++ = (PEL)255; cpline = line1; for (x=0; x<xsize/2; x++) *cpline++ = (PEL)0; cpline = line2; for (x=0; x<xsize; x++) *cpline++ = (PEL)255; cpline = line2; for (x=0; x<xsize/8; x++) *cpline++ = (PEL)0; for (x=0; x<xsize/4; x++) *cpline++ = (PEL)128; for (x=0; x<xsize/8; x++) *cpline++ = (PEL)0; for (x=0; x<xsize/8; x++) *cpline++ = (PEL)255; for (x=0; x<xsize/4; x++) *cpline++ = (PEL)128; for (y=0; y<ysize/4; y++) { if ( im_writeline( y, out, (PEL *)line1 ) == -1 ) { free ( (char *)line1 ); free ( (char *)line2 ); return( -1 ); } } for (y=ysize/4; y<(ysize/4+ysize/2); y++) { if ( im_writeline( y, out, (PEL *)line2 ) == -1 ) { free ( (char *)line1 ); free ( (char *)line2 ); return( -1 ); } } for (y=(ysize/4 + ysize/2); y<ysize; y++) { if ( im_writeline( y, out, (PEL *)line1 ) == -1 ) { free ( (char *)line1 ); free ( (char *)line2 ); return( -1 ); } } free ( (char *)line1 ); free ( (char *)line2 ); 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 ); }
/** * im_tone_build_range: * @out: output image * @in_max: input range * @out_max: output range * @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) * * im_tone_build_range() generates a tone curve for the adjustment of image * levels. It is mostly designed for adjusting the L* part of a LAB image in * way suitable for print work, but you can use it for other things too. * * The curve is an unsigned 16-bit image with (@in_max + 1) entries, * each in the range [0, @out_max]. * * @Lb, @Lw are expressed as 0-100, as in LAB colour space. You * specify the scaling for the input and output images with the @in_max and * @out_max parameters. * * See also: im_ismonotonic(), im_tone_map(), im_tone_analyse(). * * Returns: 0 on success, -1 on error */ int im_tone_build_range( IMAGE *out, int in_max, int out_max, double Lb, double Lw, double Ps, double Pm, double Ph, double S, double M, double H ) { ToneShape *ts; unsigned short lut[65536]; int i; /* Check args. */ if( !(ts = IM_NEW( out, ToneShape )) || im_outcheck( out ) ) return( -1 ); if( in_max < 0 || in_max > 65535 || out_max < 0 || out_max > 65535 ) { im_error( "im_tone_build", "%s", _( "bad in_max, out_max parameters" ) ); return( -1 ); } if( Lb < 0 || Lb > 100 || Lw < 0 || Lw > 100 || Lb > Lw ) { im_error( "im_tone_build", "%s", _( "bad Lb, Lw parameters" ) ); return( -1 ); } if( Ps < 0.0 || Ps > 1.0 ) { im_error( "im_tone_build", "%s", _( "Ps not in range [0.0,1.0]" ) ); return( -1 ); } if( Pm < 0.0 || Pm > 1.0 ) { im_error( "im_tone_build", "%s", _( "Pm not in range [0.0,1.0]" ) ); return( -1 ); } if( Ph < 0.0 || Ph > 1.0 ) { im_error( "im_tone_build", "%s", _( "Ph not in range [0.0,1.0]" ) ); return( -1 ); } if( S < -30 || S > 30 ) { im_error( "im_tone_build", "%s", _( "S not in range [-30,+30]" ) ); return( -1 ); } if( M < -30 || M > 30 ) { im_error( "im_tone_build", "%s", _( "M not in range [-30,+30]" ) ); return( -1 ); } if( H < -30 || H > 30 ) { im_error( "im_tone_build", "%s", _( "H not in range [-30,+30]" ) ); return( -1 ); } /* Note params. */ ts->Lb = Lb; ts->Lw = Lw; ts->Ps = Ps; ts->Pm = Pm; ts->Ph = Ph; ts->S = S; ts->M = M; ts->H = H; /* Note derived params. */ ts->Ls = Lb + Ps * (Lw - Lb); ts->Lm = Lb + Pm * (Lw - Lb); ts->Lh = Lb + Ph * (Lw - Lb); /* Generate curve. */ for( i = 0; i <= in_max; i++ ) { int v = (out_max / 100.0) * tone_curve( ts, 100.0 * i / in_max ); if( v < 0 ) v = 0; else if( v > out_max ) v = out_max; lut[i] = v; } /* Make the output image. */ im_initdesc( out, in_max + 1, 1, 1, IM_BBITS_SHORT, IM_BANDFMT_USHORT, IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 ); if( im_setupout( out ) ) return( -1 ); if( im_writeline( 0, out, (VipsPel *) lut ) ) 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 ); }
/** * im_sines: * @out: output image * @xsize: image size * @ysize: image size * @horfreq: horizontal frequency * @verfreq: vertical frequency * * im_sines() creates a float one band image of the a sine waveform in two * dimensions. * * The number of horizontal and vertical spatial frequencies are * determined by the variables @horfreq and @verfreq respectively. The * function is useful for creating displayable sine waves and * square waves in two dimensions. * * If horfreq and verfreq are integers the resultant image is periodical * and therfore the Fourier transform doesnot present spikes * * See also: im_grey(), im_make_xy(). * * Returns: 0 on success, -1 on error */ int im_sines( IMAGE *out, int xsize, int ysize, double horfreq, double verfreq ) { int x, y; float *line, *cpline; int size; double cons, factor; double theta_rad, costheta, sintheta, ysintheta; /* Check input args */ if( im_outcheck( out ) ) return( -1 ); if ( xsize <= 0 || ysize <= 0 ) { im_error( "im_sines", "%s", _( "wrong sizes") ); return(-1); } /* Set now out properly */ im_initdesc(out, xsize, ysize, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT, IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0); /* Set up out checking whether the output is a buffer or a file */ if (im_setupout( out ) == -1 ) return( -1 ); /* Create data */ size = out->Xsize; if ( (line=(float *)calloc((unsigned)size, sizeof(float))) == NULL ) { im_error( "im_sines", "%s", _( "calloc failed") ); return(-1); } /* make angle in rad */ if (horfreq == 0) theta_rad = IM_PI/2.0; else theta_rad = atan(verfreq/horfreq); costheta = cos(theta_rad); sintheta = sin(theta_rad); factor = sqrt ((double)(horfreq*horfreq + verfreq*verfreq)); cons = factor * IM_PI * 2.0/(double)out->Xsize; /* There is a bug (rounding error ?) for horfreq=0, *so do this calculation independantly */ if ( horfreq != 0 ) { for (y=0; y<out->Ysize; y++) { ysintheta = y * sintheta; cpline = line; for (x=0; x<out->Xsize; x++) *cpline++ = (float)(cos(cons*(x*costheta-ysintheta))); if ( im_writeline( y, out, (PEL *)line ) == -1 ) { free ( (char *)line ); return( -1 ); } } } else { for (y=0; y<out->Ysize; y++) { cpline = line; ysintheta = cos (- cons * y * sintheta); for (x=0; x<out->Xsize; x++) *cpline++ = (float)ysintheta; if ( im_writeline( y, out, (PEL *)line ) == -1 ) { free ( (char *)line ); return( -1 ); } } } free ( (char *)line ); return(0); }