diff --git a/ChangeLog b/ChangeLog index 753a7cfe..745496df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,8 @@ - im_histplot() could fail for signed int histograms - im_fwfft() and im_invfft() could free their output image too early - added im_local_imask(), im_local_dmask() +- added im_mpercent_hist() +- im_maplut() casts the index image to one of the uint types 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 5f459b09..2f178fd8 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,9 @@ +- expose more of the tone funcs in nip2 + +- quite a few hist operations have no GUI ... lhisteq, for example? or + histspec? + - conv with scale == 0 gives /0 error - added im_local_imask(), im_local_dmask(), needs docs? @@ -7,22 +12,20 @@ is local_imask() in the best place? shouldn't it be in mask.h? -- im_tone_analyse() needs docs and testing - - also im_tone_map() - -- im_rotate_imask90 only works for square, odd-sized massks, argh +- im_rotate_imask90 only works for square, odd-sized masks, argh - 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 + + + + + - im_render() should be renamed as vips_sink_screen()? also vips_sink_disc() instead of vips_discsink()? diff --git a/libvips/histograms_lut/im_maplut.c b/libvips/histograms_lut/im_maplut.c index fcaa4549..f0e43a9e 100644 --- a/libvips/histograms_lut/im_maplut.c +++ b/libvips/histograms_lut/im_maplut.c @@ -534,6 +534,19 @@ maplut_gen( REGION *or, void *vseq, void *a, void *b ) return( 0 ); } +/* Save a bit of typing. + */ +#define UC IM_BANDFMT_UCHAR +#define US IM_BANDFMT_USHORT +#define UI IM_BANDFMT_UINT + +/* Type mapping: go to uchar or ushort. + */ +static int bandfmt_maplut[10] = { +/* UC C US S UI I F X D DX */ + UC, UC, US, US, UI, UI, UI, UI, UI, UI +}; + /** * im_maplut: * @in: input image @@ -543,8 +556,8 @@ maplut_gen( REGION *or, void *vseq, void *a, void *b ) * 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. + * The input image will be cast to one of the unsigned integer types, that is, + * IM_BANDFMT_UCHAR, IM_BANDFMT_USHORT or IM_BANDFMT_UINT. * * If @lut is too small for the input type (for example, if @in is * IM_BANDFMT_UCHAR but @lut only has 100 elements), the lut is padded out @@ -564,6 +577,7 @@ maplut_gen( REGION *or, void *vseq, void *a, void *b ) int im_maplut( IMAGE *in, IMAGE *out, IMAGE *lut ) { + IMAGE *t; LutInfo *st; /* Check input output. Old-style IO from lut, for simplicity. @@ -572,14 +586,19 @@ im_maplut( IMAGE *in, IMAGE *out, IMAGE *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 ); + /* Cast in to u8/u16. + */ + if( !(t = im_open_local( out, "im_maplut", "p" )) || + im_clip2fmt( in, t, bandfmt_maplut[in->BandFmt] ) ) + return( -1 ); + /* Prepare the output header. */ - if( im_cp_descv( out, in, lut, NULL ) ) + if( im_cp_descv( out, t, lut, NULL ) ) return( -1 ); /* Force output to be the same type as lut. @@ -599,12 +618,12 @@ im_maplut( IMAGE *in, IMAGE *out, IMAGE *lut ) /* Set demand hints. */ - if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) ) + if( im_demand_hint( out, IM_THINSTRIP, t, NULL ) ) return( -1 ); /* Process! */ - if( im_generate( out, maplut_start, maplut_gen, maplut_stop, in, st ) ) + if( im_generate( out, maplut_start, maplut_gen, maplut_stop, t, st ) ) return( -1 ); return( 0 ); diff --git a/libvips/histograms_lut/im_mpercent.c b/libvips/histograms_lut/im_mpercent.c index 2f9bad7a..4f133d8d 100644 --- a/libvips/histograms_lut/im_mpercent.c +++ b/libvips/histograms_lut/im_mpercent.c @@ -53,6 +53,53 @@ #include #endif /*WITH_DMALLOC*/ +/** + * im_mpercent_hist: + * @hist: input histogram image + * @percent: threshold percentage + * @out: output threshold value + * + * Just like im_mpercent(), except it works on an image histogram. Handy if + * you want to run im_mpercent() several times without having to recompute the + * histogram each time. + * + * See also: im_mpercent(). + * + * Returns: 0 on success, -1 on error + */ +int +im_mpercent_hist( IMAGE *hist, double percent, int *out ) +{ + IMAGE *base; + IMAGE *t[6]; + double pos; + + if( im_check_hist( "im_mpercent", hist ) ) + return( -1 ); + + if( !(base = im_open( "im_mpercent", "p" )) ) + return( -1 ); + if( im_open_local_array( base, t, 6, "im_mpercent", "p" ) ) { + im_close( base ); + return( -1 ); + } + + if( im_histcum( hist, t[1] ) || + im_histnorm( t[1], t[2] ) || + im_lessconst( t[2], t[3], percent * t[2]->Xsize ) || + im_fliphor( t[3], t[4] ) || + im_profile( t[4], t[5], 1 ) || + im_avg( t[5], &pos ) ) { + im_close( base ); + return( -1 ); + } + im_close( base ); + + *out = pos; + + return( 0 ); +} + /** * im_mpercent: * @in: input image @@ -73,31 +120,17 @@ */ int im_mpercent( IMAGE *in, double percent, int *out ) -{ - IMAGE *base; - IMAGE *t[6]; - double pos; +{ + IMAGE *t; - if( !(base = im_open( "im_mpercent1", "p" )) ) + if( !(t = im_open( "im_mpercent1", "p" )) ) return( -1 ); - if( im_open_local_array( base, t, 6, "im_mpercent", "p" ) ) { - im_close( base ); + if( im_histgr( in, t, -1 ) || + im_mpercent_hist( t, percent, out ) ) { + im_close( t ); return( -1 ); } - - if( im_histgr( in, t[0], -1 ) || - im_histcum( t[0], t[1] ) || - im_histnorm( t[1], t[2] ) || - im_lessconst( t[2], t[3], percent * t[2]->Xsize ) || - im_fliphor( t[3], t[4] ) || - im_profile( t[4], t[5], 1 ) || - im_avg( t[5], &pos ) ) { - im_close( base ); - return( -1 ); - } - im_close( base ); - - *out = pos; + im_close( t ); return( 0 ); } diff --git a/libvips/histograms_lut/tone.c b/libvips/histograms_lut/tone.c index 40c51809..b3f7bd72 100644 --- a/libvips/histograms_lut/tone.c +++ b/libvips/histograms_lut/tone.c @@ -427,9 +427,23 @@ im_tone_map( IMAGE *in, IMAGE *out, IMAGE *lut ) return( im_copy( t[4], out ) ); } -/* Find histogram of in, and use that to set Lb, Lw levels. - * @(#) im_tone_analyse: find the histogram of a LabS or LabQ image and use - * @(#) that to set the Ln and Lw parameters of im_tone_build() +/** + * im_tone_analyse: + * in: input image + * out: output image + * Ps: shadow point (eg. 0.2) + * Pm: mid-tone point (eg. 0.5) + * Ph: highlight point (eg. 0.8) + * S: shadow adjustment (+/- 30) + * M: mid-tone adjustment (+/- 30) + * H: highlight adjustment (+/- 30) + * + * As im_tone_build(), but analyse the histogram of @in and use it to + * pick the 0.1% and 99.9% points for @Lb and @Lw. + * + * See also: im_tone_build(). + * + * Returns: 0 on success, -1 on error */ int im_tone_analyse( @@ -466,8 +480,8 @@ im_tone_analyse( im_histgr( t[2], t[3], -1 ) ) return( -1 ); - if( im_mpercent( t[3], 0.1 / 100.0, &low ) || - im_mpercent( t[3], 99.9 / 100.0, &high ) ) + if( im_mpercent_hist( t[3], 0.1 / 100.0, &high ) || + im_mpercent_hist( t[3], 99.9 / 100.0, &low ) ) return( -1 ); Lb = 100 * low / 32768; diff --git a/libvips/include/vips/histograms_lut.h b/libvips/include/vips/histograms_lut.h index 853e1cb0..9ca8b8e8 100644 --- a/libvips/include/vips/histograms_lut.h +++ b/libvips/include/vips/histograms_lut.h @@ -70,6 +70,7 @@ int im_ismonotonic( IMAGE *lut, int *out ); int im_tone_map( IMAGE *in, IMAGE *out, IMAGE *lut ); int im_project( IMAGE *in, IMAGE *hout, IMAGE *vout ); int im_mpercent( IMAGE *in, double percent, int *out ); +int im_mpercent_hist( IMAGE *hist, double percent, int *out ); #ifdef __cplusplus }