diff --git a/ChangeLog b/ChangeLog index 21a8dacf..6fa04683 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ - im_wbuffer2() renamed as vips_discsink(), some cleanups - im_gammacorrect() can do 16-bit images too - im_histplot() could fail for signed int histograms +- im_fwfft() and im_invfft() could free their output image too early 16/1/10 started 7.21.2 - "invalidate" is careful to keep images alive, so invalidate callbacks can do diff --git a/TODO b/TODO index ca7787d2..465a95f4 100644 --- a/TODO +++ b/TODO @@ -2,6 +2,9 @@ - lots of stupid little files in hist, eg. im_hsp.c ... paste them into larger modules +- quite a few hist operations have no GUI ... lhisteq, for example? or + histspec? + - check the order of decls in hist.h, is it sensible? check the order in freq_flt as well diff --git a/libvips/freq_filt/im_fwfft.c b/libvips/freq_filt/im_fwfft.c index 8116773a..13220deb 100644 --- a/libvips/freq_filt/im_fwfft.c +++ b/libvips/freq_filt/im_fwfft.c @@ -30,6 +30,8 @@ * 7/2/10 * - cleanups * - gtkdoc + * 25/3/10 + * - have a "t" image linked to out to keep the image alive for longer */ /* @@ -573,6 +575,7 @@ im__fftproc( IMAGE *dummy, IMAGE *in, IMAGE *out, im__fftproc_fn fn ) { IMAGE **bands; IMAGE **fft; + IMAGE *t; int b; if( in->Bands == 1 ) @@ -589,7 +592,12 @@ im__fftproc( IMAGE *dummy, IMAGE *in, IMAGE *out, im__fftproc_fn fn ) fn( dummy, bands[b], fft[b] ) ) return( -1 ); - if( im_gbandjoin( fft, out, in->Bands ) ) + /* We need a "t" for the combined image that won't get freed too + * quickly. + */ + if( !(t = im_open_local( out, "im__fftproc", "t" )) || + im_gbandjoin( fft, t, in->Bands ) || + im_copy( t, out ) ) return( -1 ); return( 0 ); diff --git a/libvips/freq_filt/im_invfft.c b/libvips/freq_filt/im_invfft.c index 497e4324..444495d7 100644 --- a/libvips/freq_filt/im_invfft.c +++ b/libvips/freq_filt/im_invfft.c @@ -258,7 +258,6 @@ invfft1( IMAGE *dummy, IMAGE *in, IMAGE *out ) #endif /*HAVE_FFTW3*/ #endif /*HAVE_FFTW*/ - /** * im_invfft: * @in: input image diff --git a/libvips/histograms_lut/im_heq.c b/libvips/histograms_lut/im_heq.c index 92f65038..d69c52ef 100644 --- a/libvips/histograms_lut/im_heq.c +++ b/libvips/histograms_lut/im_heq.c @@ -63,7 +63,7 @@ * Histogram-equalise @in. Equalise using band @bandno, or if @bandno is -1, * equalise all bands. * - * See also: im_histgr(), im_histeq(). + * See also: im_lhisteq(), im_histgr(), im_histeq(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/histograms_lut/im_lhisteq.c b/libvips/histograms_lut/im_lhisteq.c index e37ccc35..0ffb31cd 100644 --- a/libvips/histograms_lut/im_lhisteq.c +++ b/libvips/histograms_lut/im_lhisteq.c @@ -1,12 +1,4 @@ -/* @(#) Performs local histogram equalisation on an image using a - * @(#) window of size xw by yw - * @(#) Works only on monochrome images - * @(#) - * @(#) int im_lhisteq(in, out, xwin, ywin) - * @(#) IMAGE *in, *out; - * @(#) int xwin, ywin; - * @(#) - * @(#) Returns 0 on sucess and -1 on error +/* local histogram equalisation * * Copyright: 1991, N. Dessipris * @@ -22,6 +14,9 @@ * - sets Xoffset/Yoffset * 23/6/08 * - check for window too small as well + * 25/3/10 + * - gtkdoc + * - small cleanups */ /* @@ -80,18 +75,12 @@ lhist_gen( REGION *or, void *seq, void *a, void *b ) { REGION *ir = (REGION *) seq; LhistInfo *inf = (LhistInfo *) b; - Rect irect; - Rect *r = &or->valid; - int le = r->left; - int to = r->top; - int bo = IM_RECT_BOTTOM( r ); - int ri = IM_RECT_RIGHT( r ); + Rect irect; int x, y, i, j; int lsk; - - int coff; /* Offset to move to centre of window */ + int centre; /* Offset to move to centre of window */ /* What part of ir do we need? */ @@ -99,49 +88,60 @@ lhist_gen( REGION *or, void *seq, void *a, void *b ) irect.top = or->valid.top; irect.width = or->valid.width + inf->xwin; irect.height = or->valid.height + inf->ywin; - if( im_prepare( ir, &irect ) ) return( -1 ); - lsk = IM_REGION_LSKIP( ir ); - coff = lsk * (inf->ywin / 2) + inf->xwin / 2; - for( y = to; y < bo; y++ ) { + lsk = IM_REGION_LSKIP( ir ); + centre = lsk * (inf->ywin / 2) + inf->xwin / 2; + + for( y = 0; y < r->height; y++ ) { /* Get input and output pointers for this line. */ - PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y ); - PEL *q = (PEL *) IM_REGION_ADDR( or, le, y ); - PEL *p1, *p2; + PEL *p = (PEL *) IM_REGION_ADDR( ir, r->left, r->top + y ); + PEL *q = (PEL *) IM_REGION_ADDR( or, r->left, r->top + y ); + + PEL *p1; int hist[256]; /* Find histogram for start of this line. */ memset( hist, 0, 256 * sizeof( int ) ); - for( p1 = p, j = 0; j < inf->ywin; j++, p1 += lsk ) - for( p2 = p1, i = 0; i < inf->xwin; i++, p2++ ) - hist[*p2]++; + p1 = p; + for( j = 0; j < inf->ywin; j++ ) { + for( i = 0; i < inf->xwin; i++ ) + hist[p1[i]] += 1; + + p1 += lsk; + } /* Loop for output pels. */ - for( x = le; x < ri; x++, p++ ) { + for( x = 0; x < r->width; x++ ) { /* Sum histogram up to current pel. */ - int target = p[coff]; - int sum = 0; + int target = p[centre]; + int sum; - for( sum = 0, i = 0; i < target; i++ ) + sum = 0; + for( i = 0; i < target; i++ ) sum += hist[i]; /* Transform. */ - *q++ = sum * 256 / inf->npels; + q[x] = sum * 256 / inf->npels; /* Adapt histogram - remove the pels from the left hand * column, add in pels for a new right-hand column. */ - for( p1 = p, j = 0; j < inf->ywin; j++, p1 += lsk ) { - hist[p1[0]]--; - hist[p1[inf->xwin]]++; + p1 = p; + for( j = 0; j < inf->ywin; j++ ) { + hist[p1[0]] -= 1; + hist[p1[inf->xwin]] += 1; + + p1 += lsk; } + + p += 1; } } @@ -153,22 +153,22 @@ im_lhisteq_raw( IMAGE *in, IMAGE *out, int xwin, int ywin ) { LhistInfo *inf; - if( im_piocheck( in, out ) ) + if( im_check_mono( "im_lhisteq", in ) || + im_check_uncoded( "im_lhisteq", in ) || + im_check_format( "im_lhisteq", in, IM_BANDFMT_UCHAR ) || + im_piocheck( in, out ) ) return( -1 ); - if( in->BandFmt != IM_BANDFMT_UCHAR || - in->Bands != 1 || in->Coding != IM_CODING_NONE ) { - im_error( "im_lhisteq", - "%s", _( "one band uchar uncoded only" ) ); - return( -1 ); - } - if( xwin > in->Xsize || ywin > in->Ysize ) { + if( xwin > in->Xsize || + ywin > in->Ysize ) { im_error( "im_lhisteq", "%s", _( "window too large" ) ); return( -1 ); } - if( xwin <= 0 || ywin <= 0 ) { + if( xwin <= 0 || + ywin <= 0 ) { im_error( "im_lhisteq", "%s", _( "window too small" ) ); return( -1 ); } + if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize -= xwin - 1; @@ -188,8 +188,6 @@ im_lhisteq_raw( IMAGE *in, IMAGE *out, int xwin, int ywin ) if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); - /* Write the hist. - */ if( im_generate( out, im_start_one, lhist_gen, im_stop_one, in, inf ) ) return( -1 ); @@ -200,14 +198,30 @@ im_lhisteq_raw( IMAGE *in, IMAGE *out, int xwin, int ywin ) return( 0 ); } -/* The above, with a border to make out the same size as in. +/** + * im_lhisteq: + * @in: input image + * @out: output image + * @xwin: width of region + * @hwin: height of region + * + * Performs local histogram equalisation on @in using a + * window of size @xwin by @ywin centered on the input pixel. Works only on + * monochrome images. + * + * The output image is the same size as the input image. The edge pixels are + * created by copy edge pixels of the input image outwards. + * + * See also: im_heq(). + * + * Returns: 0 on success, -1 on error */ int im_lhisteq( IMAGE *in, IMAGE *out, int xwin, int ywin ) { - IMAGE *t1 = im_open_local( out, "im_lhisteq:1", "p" ); + IMAGE *t1; - if( !t1 || + if( !(t1 = im_open_local( out, "im_lhisteq:1", "p" )) || im_embed( in, t1, 1, xwin / 2, ywin / 2, in->Xsize + xwin - 1, in->Ysize + ywin - 1 ) || diff --git a/libvips/histograms_lut/im_maplut.c b/libvips/histograms_lut/im_maplut.c index bcf3f600..fcaa4549 100644 --- a/libvips/histograms_lut/im_maplut.c +++ b/libvips/histograms_lut/im_maplut.c @@ -1,28 +1,4 @@ -/* @(#) 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 must be an unsigned integer types, that is, it must - * @(#) be one of IM_BANDFMT_UCHAR, IM_BANDFMT_USHORT or IM_BANDFMT_UINT. - * @(#) - * @(#) If the input is IM_BANDFMT_UCHAR, then the LUT must have 256 elements, - * @(#) in other words, lut->Xsize * lut->Ysize == 256. - * @(#) - * @(#) If the input is IM_BANDFMT_USHORT or IM_BANDFMT_UINT, then the lut - * @(#) may have any number of elements, and input pels whose value is - * @(#) greater than lut->Xsize * lut->Ysize are mapped with the last LUT - * @(#) element. - * @(#) - * @(#) If LUT has one band, then all bands of input pass through it. If LUT - * @(#) has same number of bands as input, then each band is LUTed - * @(#) separately. If input has one band, then LUT may have many bands and - * @(#) the output will have the same number of bands as the LUT. - * @(#) - * @(#) int - * @(#) im_maplut( in, out, lut ) - * @(#) IMAGE *in, *out, *lut; - * @(#) - * @(#) Returns 0 on success and -1 on error - * @(#) +/* map though a LUT * * Modified: * 18/6/93 JC @@ -50,6 +26,9 @@ * years :-) * 7/11/07 * - new eval start/end system + * 25/3/10 + * - gtkdoc + * - small cleanups */ /* @@ -130,11 +109,11 @@ lut_end( LutInfo *st ) static LutInfo * build_luts( IMAGE *out, IMAGE *lut ) { - LutInfo *st = IM_NEW( out, LutInfo ); + LutInfo *st; int i, x; PEL *q; - if( !st ) + if( !(st = IM_NEW( out, LutInfo )) ) return( NULL ); /* Make luts. We unpack the LUT image into a C 2D array to speed @@ -244,15 +223,15 @@ maplut_start( IMAGE *out, void *a, void *b ) for( y = to; y < bo; y++ ) { \ for( z = 0; z < b; z++ ) { \ PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y ) + z; \ - OUT *q = (OUT *) IM_REGION_ADDR( or, le, y ) + z*2; \ + OUT *q = (OUT *) IM_REGION_ADDR( or, le, y ) + z * 2; \ OUT *tlut = (OUT *) st->table[z]; \ \ for( x = 0; x < ne; x += b ) { \ - int n = p[x]*2; \ + int n = p[x] * 2; \ \ q[0] = tlut[n]; \ q[1] = tlut[n + 1]; \ - q += b*2; \ + q += b * 2; \ } \ } \ } \ @@ -287,7 +266,7 @@ maplut_start( IMAGE *out, void *a, void *b ) for( y = to; y < bo; y++ ) { \ for( z = 0; z < b; z++ ) { \ IN *p = (IN *) IM_REGION_ADDR( ir, le, y ) + z; \ - OUT *q = (OUT *) IM_REGION_ADDR( or, le, y ) + z*2; \ + OUT *q = (OUT *) IM_REGION_ADDR( or, le, y ) + z * 2; \ OUT *tlut = (OUT *) st->table[z]; \ \ for( x = 0; x < ne; x += b ) { \ @@ -298,10 +277,10 @@ maplut_start( IMAGE *out, void *a, void *b ) seq->overflow++; \ } \ \ - q[0] = tlut[ index*2 ]; \ - q[1] = tlut[ index*2+1 ]; \ + q[0] = tlut[index * 2]; \ + q[1] = tlut[index * 2 + 1]; \ \ - q += b*2; \ + q += b * 2; \ } \ } \ } \ @@ -378,8 +357,8 @@ maplut_start( IMAGE *out, void *a, void *b ) seq->overflow++; \ } \ \ - q[0] = tlut[index*2]; \ - q[1] = tlut[index*2 + 1]; \ + q[0] = tlut[index * 2]; \ + q[1] = tlut[index * 2 + 1]; \ q += 2; \ } \ } \ @@ -465,8 +444,8 @@ maplut_start( IMAGE *out, void *a, void *b ) } \ \ for( z = 0; z < st->nb; z++ ) { \ - q[0] = tlut[z][n*2]; \ - q[1] = tlut[z][n*2 + 1]; \ + q[0] = tlut[z][n * 2]; \ + q[1] = tlut[z][n * 2 + 1]; \ q += 2; \ } \ } \ @@ -481,8 +460,7 @@ maplut_start( IMAGE *out, void *a, void *b ) case IM_BANDFMT_USHORT: GEN( unsigned short, OUT ); break; \ case IM_BANDFMT_UINT: GEN( unsigned int, OUT ); break; \ default: \ - im_error( "im_maplut", "%s", _( "bad input file" ) ); \ - return( -1 ); \ + g_assert( 0 ); \ } /* Switch for LUT types. One function for non-complex images, a @@ -512,8 +490,7 @@ maplut_start( IMAGE *out, void *a, void *b ) case IM_BANDFMT_DPCOMPLEX: inner_switch( UCHAR_FC, GEN_FC, \ double ); break; \ default: \ - im_error( "im_maplut", "%s", _( "bad lut file" ) ); \ - return( -1 ); \ + g_assert( 0 ); \ } /* Do a map. @@ -529,8 +506,8 @@ maplut_gen( REGION *or, void *vseq, void *a, void *b ) int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); - int np = r->width; /* Pels across region */ - int ne = IM_REGION_N_ELEMENTS( or ); /* Number of elements */ + int np = r->width; /* Pels across region */ + int ne = IM_REGION_N_ELEMENTS( or ); /* Number of elements */ int x, y, z, i; /* Get input ready. @@ -557,51 +534,49 @@ maplut_gen( REGION *or, void *vseq, void *a, void *b ) return( 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 must be an unsigned integer types, that is, it must + * be one of 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 ) { LutInfo *st; - /* Check lut. - */ - if( lut->Coding != IM_CODING_NONE ) { - im_error( "im_maplut", "%s", _( "lut is not uncoded" ) ); - return( -1 ); - } - if( lut->Xsize * lut->Ysize > 100000 ) { - im_error( "im_maplut", "%s", _( "lut seems very large!" ) ); - return( -1 ); - } - /* Check input output. Old-style IO from lut, for simplicity. */ - if( im_piocheck( in, out ) || im_incheck( lut ) ) + 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_check_uint( "im_maplut", in ) || + im_piocheck( in, out ) || + im_incheck( lut ) ) return( -1 ); - /* Check args. - */ - if( in->Coding != IM_CODING_NONE ) { - im_error( "im_maplut", "%s", _( "input is not uncoded" ) ); - return( -1 ); - } - if( !vips_bandfmt_isuint( in->BandFmt ) ) { - im_error( "im_maplut", "%s", - _( "input is not some unsigned integer type" ) ); - return( -1 ); - } - if( in->Bands != 1 && lut->Bands != 1 && lut->Bands != in->Bands ) { - im_error( "im_maplut", "%s", _( "lut should have 1 band, " - "or same number of bands as input, " - "or any number of bands if input has 1 band" ) ); - return( -1 ); - } - if( in->BandFmt == IM_BANDFMT_UCHAR && - lut->Xsize * lut->Ysize != 256 ) { - im_error( "im_maplut", "%s", _( "input is uchar and lut " - "does not have 256 elements" ) ); - return( -1 ); - } - /* Prepare the output header. */ if( im_cp_descv( out, in, lut, NULL ) ) diff --git a/libvips/histograms_lut/im_mpercent.c b/libvips/histograms_lut/im_mpercent.c index 0c6dc56e..2f9bad7a 100644 --- a/libvips/histograms_lut/im_mpercent.c +++ b/libvips/histograms_lut/im_mpercent.c @@ -1,19 +1,4 @@ -/* @(#) Function which returns an int. This integer is the threshold - * @(#) above which there are percent values of the input images - * @(#) If for instance precent=.1, the number of pels of the input image - * @(#) with values greater than the returned int will correspond to - * @(#) 10% of all pels of the image. - * @(#) One band IM_BANDFMT_UCHAR images only. - * @(#) - * @(#) Function im_mpercent() assumes that input - * @(#) is either memory mapped or in a buffer. - * @(#) - * @(#) int im_percent(in, percent) - * @(#) IMAGE *in; - * @(#) double percent; - * @(#) - * @(#) Returns 0 on success and -1 on error - * +/* find percent of pixels * Copyright: 1990, N. Dessipris * * Author: N. Dessipris @@ -24,6 +9,8 @@ * - ANSIfied a little * 19/1/07 * - redone with the vips hist operators + * 25/3/10 + * - gtkdoc */ /* @@ -66,8 +53,23 @@ #include #endif /*WITH_DMALLOC*/ -/* What threshold will select a specified percentage of the pixels in the - * image. +/** + * im_mpercent: + * @in: input image + * @percent: threshold percentage + * @out: output threshold value + * + * im_mpercent() returns (through the @out parameter) the threshold above + * which there are @percent values of @in. If for example percent=.1, the + * number of pels of the input image with values greater than the returned + * int will correspond to 10% of all pels of the image. + * + * The function works for uchar and ushort images only. It can be used + * to threshold the scaled result of a filtering operation. + * + * See also: im_histgr(), im_profile(). + * + * Returns: 0 on success, -1 on error */ int im_mpercent( IMAGE *in, double percent, int *out )