hist hacking

This commit is contained in:
John Cupitt 2010-03-25 14:41:27 +00:00
parent 81c6456b78
commit 05c5ae9734
8 changed files with 152 additions and 150 deletions

View File

@ -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

3
TODO
View File

@ -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

View File

@ -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 );

View File

@ -258,7 +258,6 @@ invfft1( IMAGE *dummy, IMAGE *in, IMAGE *out )
#endif /*HAVE_FFTW3*/
#endif /*HAVE_FFTW*/
/**
* im_invfft:
* @in: input image

View File

@ -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
*/

View File

@ -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 ) ||

View File

@ -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 ) )

View File

@ -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 <dmalloc.h>
#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 )