/* 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 ); }
/* Read an ascii 1 bit file. */ static int read_1bit_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 ); if( val == 1 ) buf[x] = 0; else buf[x] = 255; } if( im_writeline( y, out, buf ) ) return( -1 ); } return( 0 ); }
/** * im_buildlut: * @input: input mask * @output: output image * * This operation builds a lookup table from a set of points. Intermediate * values are generated by piecewise linear interpolation. * * For example, consider this 2 x 2 matrix of (x, y) coordinates: * * <tgroup cols='2' align='left' colsep='1' rowsep='1'> * <tbody> * <row> * <entry>0</entry> * <entry>0</entry> * </row> * <row> * <entry>255</entry> * <entry>100</entry> * </row> * </tbody> * </tgroup> * * We then generate: * * <tgroup cols='2' align='left' colsep='1' rowsep='1'> * <thead> * <row> * <entry>Index</entry> * <entry>Value</entry> * </row> * </thead> * <tbody> * <row> * <entry>0</entry> * <entry>0</entry> * </row> * <row> * <entry>1</entry> * <entry>0.4</entry> * </row> * <row> * <entry>...</entry> * <entry>etc. by linear interpolation</entry> * </row> * <row> * <entry>255</entry> * <entry>100</entry> * </row> * </tbody> * </tgroup> * * This is then written as the output image, with the left column giving the * index in the image to place the value. * * The (x, y) points don't need to be sorted: we do that. You can have * several Ys, each becomes a band in the output LUT. You don't need to * start at zero, any integer will do, including negatives. * * See also: im_identity(), im_invertlut(). * * Returns: 0 on success, -1 on error */ int im_buildlut( DOUBLEMASK *input, IMAGE *output ) { State state; if( !input || input->xsize < 2 || input->ysize < 1 ) { im_error( "im_buildlut", "%s", _( "bad input matrix size" ) ); return( -1 ); } if( build_state( &state, input ) || buildlut( &state ) ) { free_state( &state ); return( -1 ); } im_initdesc( output, state.lut_size, 1, input->xsize - 1, IM_BBITS_DOUBLE, IM_BANDFMT_DOUBLE, IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 ); if( im_setupout( output ) || im_writeline( 0, output, (PEL *) state.buf ) ) { free_state( &state ); return( -1 ); } free_state( &state ); return( 0 ); }
/* Read a 1 bit binary file. */ static int read_1bit_binary( FILE *fp, IMAGE *out ) { int x, y, i; int bits; PEL *buf; if( im_outcheck( out ) || im_setupout( out ) || !(buf = IM_ARRAY( out, IM_IMAGE_SIZEOF_LINE( out ), PEL )) ) return( -1 ); bits = fgetc( fp ); for( i = 0, y = 0; y < out->Ysize; y++ ) { for( x = 0; x < out->Xsize * out->Bands; x++, i++ ) { buf[x] = (bits & 128) ? 255 : 0; bits <<= 1; if( (i & 7) == 7 ) bits = fgetc( fp ); } if( im_writeline( y, out, buf ) ) 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 ); }
static int hist_write( IMAGE *out, Histogram *hist ) { if( im_cp_descv( out, hist->index, hist->value, NULL ) ) return( -1 ); im_initdesc( out, hist->mx + 1, 1, hist->value->Bands, IM_BBITS_DOUBLE, IM_BANDFMT_DOUBLE, IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 ); if( im_setupout( out ) ) return( -1 ); if( im_writeline( 0, out, (PEL *) hist->bins ) ) 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 ); }
/** * im_mask2vips: * @in: input mask * @out: output image * * Write a one-band, %IM_BANDFMT_DOUBLE image to @out based on mask @in. * * See also: im_vips2mask(). * * Returns: 0 on success, -1 on error */ int im_mask2vips( DOUBLEMASK *in, IMAGE *out ) { int x, y; double *buf, *p, *q; /* Check the mask. */ if( !in || !in->coeff ) { im_error( "im_mask2vips", "%s", _( "bad input mask" ) ); return( -1 ); } /* Make the output image. */ im_initdesc( out, in->xsize, in->ysize, 1, IM_BBITS_DOUBLE, IM_BANDFMT_DOUBLE, IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 ); if( im_setupout( out ) ) return( -1 ); /* Make an output buffer. */ if( !(buf = IM_ARRAY( out, in->xsize, double )) ) return( -1 ); /* Write! */ for( p = in->coeff, y = 0; y < out->Ysize; y++ ) { q = buf; for( x = 0; x < out->Xsize; x++ ) *q++ = *p++; if( im_writeline( y, out, (void *) 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 ); }
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 ); }
/** * im_fav4: * @in: array of 4 input #IMAGE s * @out: output #IMAGE * * Average four identical images. * * Deprecated. */ int im_fav4( IMAGE **in, IMAGE *out) { PEL *result, *buffer, *p1, *p2, *p3, *p4; int x,y; int linebytes, PICY; /* check IMAGEs parameters */ if(im_iocheck(in[1], out)) return(-1); /* BYTE images only! */ if( (in[0]->BandFmt != IM_BANDFMT_CHAR) && (in[0]->BandFmt != IM_BANDFMT_UCHAR)) return(-1); if ( im_cp_desc(out, in[1]) == -1) /* copy image descriptors */ return(-1); if ( im_setupout(out) == -1) return(-1); linebytes = in[0]->Xsize * in[0]->Bands; PICY = in[0]->Ysize; buffer = (PEL*)im_malloc(NULL,linebytes); memset(buffer, 0, linebytes); p1 = (PEL*)in[0]->data; p2 = (PEL*)in[1]->data; p3 = (PEL*)in[2]->data; p4 = (PEL*)in[3]->data; for (y = 0; y < PICY; y++) { result = buffer; /* average 4 pels with rounding, for whole line*/ for (x = 0; x < linebytes; x++) { *result++ = (PEL)((int)((int)*p1++ + (int)*p2++ + (int)*p3++ + (int)*p4++ +2) >> 2); } im_writeline(y,out, buffer); } im_free(buffer); 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 ); }
/** * 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 ); }
/** * im_profile: * @in: input image * @out: output image * @dir: search direction * * im_profile() searches inward from the edge of @in and finds the * first non-zero pixel. It outputs an image containing a list of the offsets * for each row or column. * * If @dir == 0, then im_profile() searches down from the top edge, writing an * image as wide as the input image, but only 1 pixel high, containing the * number of pixels down to the first non-zero pixel for each column of input * pixels. * * If @dir == 1, then im_profile() searches across from the left edge, * writing an image as high as the input image, but only 1 pixel wide, * containing the number of pixels across to the * first non-zero pixel for each row of input pixels. * * See also: im_cntlines(). * * Returns: 0 on success, -1 on error */ int im_profile( IMAGE *in, IMAGE *out, int dir ) { int sz; unsigned short *buf; int x, y, b; /* If in is not uchar, do (!=0) to make a uchar image. */ if( in->BandFmt != IM_BANDFMT_UCHAR ) { IMAGE *t; if( !(t = im_open_local( out, "im_profile", "p" )) || im_notequalconst( in, t, 0 ) ) return( -1 ); in = t; } /* Check im. */ if( im_iocheck( in, out ) || im_check_uncoded( "im_profile", in ) || im_check_format( "im_profile", in, IM_BANDFMT_UCHAR ) ) return( -1 ); if( dir != 0 && dir != 1 ) { im_error( "im_profile", "%s", _( "dir not 0 or 1" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Type = IM_TYPE_HISTOGRAM; if( dir == 0 ) { out->Xsize = in->Xsize; out->Ysize = 1; } else { out->Xsize = 1; out->Ysize = in->Ysize; } out->BandFmt = IM_BANDFMT_USHORT; if( im_setupout( out ) ) return( -1 ); sz = IM_IMAGE_N_ELEMENTS( out ); if( !(buf = IM_ARRAY( out, sz, unsigned short )) ) return( -1 ); if( dir == 0 ) { /* Find vertical lines. */ for( x = 0; x < sz; x++ ) { PEL *p = (PEL *) IM_IMAGE_ADDR( in, 0, 0 ) + x; int lsk = IM_IMAGE_SIZEOF_LINE( in ); for( y = 0; y < in->Ysize; y++ ) { if( *p ) break; p += lsk; } buf[x] = y; } if( im_writeline( 0, out, (PEL *) buf ) ) return( -1 ); } else { /* Search horizontal lines. */ for( y = 0; y < in->Ysize; y++ ) { PEL *p = (PEL *) IM_IMAGE_ADDR( in, 0, y ); for( b = 0; b < in->Bands; b++ ) { PEL *p1; p1 = p + b; for( x = 0; x < in->Xsize; x++ ) { if( *p1 ) break; p1 += in->Bands; } buf[b] = x; } 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 ); }
/* 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); }
int im_resize_linear( IMAGE *in, IMAGE *out, int X, int Y ) { double dx, dy, xscale, yscale; double Xnew, Ynew; /* inv. coord. of the interpolated pt */ int x, y; int Xint, Yint; int bb; PEL *input, *opline; PEL *q, *p; int ils, ips, ies; /* Input and output line, pel and */ int ols, ops, oes; /* element sizes */ if( im_iocheck( in, out ) ) return( -1 ); if( im_iscomplex( in ) ) { im_errormsg( "im_lowpass: non-complex input only" ); return( -1 ); } if( in->Coding != IM_CODING_NONE ) { im_errormsg("im_lowpass: input should be uncoded"); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize = X; out->Ysize = Y; if( im_setupout( out ) ) return( -1 ); ils = IM_IMAGE_SIZEOF_LINE( in ); ips = IM_IMAGE_SIZEOF_PEL( in ); ies = IM_IMAGE_SIZEOF_ELEMENT( in ); ols = IM_IMAGE_SIZEOF_LINE( out ); ops = IM_IMAGE_SIZEOF_PEL( out ); oes = IM_IMAGE_SIZEOF_ELEMENT( out ); /* buffer lines ***************/ if( !(opline = IM_ARRAY( out, ols, PEL )) ) return( -1 ); /* Resampling *************/ input = (PEL*) in->data; xscale = ((double)in->Xsize-1)/(X-1); yscale = ((double)in->Ysize-1)/(Y-1); for (y=0; y<Y; y++) { q = opline; for (x=0; x<X; x++) { Xnew = x*xscale; Ynew = y*yscale; Xint = floor(Xnew); Yint = floor(Ynew); dx = Xnew - Xint; dy = Ynew - Yint; p = input + Xint*ips + Yint*ils; switch( in->BandFmt ) { case IM_BANDFMT_UCHAR: LOOP( unsigned char); break; case IM_BANDFMT_USHORT: LOOP( unsigned short ); break; case IM_BANDFMT_UINT: LOOP( unsigned int ); break; case IM_BANDFMT_CHAR: LOOP( signed char ); break; case IM_BANDFMT_SHORT: LOOP( signed short ); break; case IM_BANDFMT_INT: LOOP( signed int ); break; case IM_BANDFMT_FLOAT: LOOP( float ); break; case IM_BANDFMT_DOUBLE: LOOP( double ); break; default: im_errormsg( "im_lowpass: unsupported image type" ); return( -1 ); /*NOTREACHED*/ } } if (im_writeline(y, out, opline) ) return(-1); } return(0); }