any number of bands for hist_local
This commit is contained in:
parent
05bab10fb8
commit
f1c3e1a434
@ -6,6 +6,7 @@
|
|||||||
im_gammacorrect(), im_histgr(), im_histcum(), im_histnorm(), im_heq(),
|
im_gammacorrect(), im_histgr(), im_histcum(), im_histnorm(), im_heq(),
|
||||||
im_histnD(), im_histindexed(), im_histspec(), im_invertlut(), im_lhisteq()
|
im_histnD(), im_histindexed(), im_histspec(), im_invertlut(), im_lhisteq()
|
||||||
as classes
|
as classes
|
||||||
|
- vips_hist_local() does any number of bands
|
||||||
- thin vips8 wrapper for im_histplot()
|
- thin vips8 wrapper for im_histplot()
|
||||||
- added vips_error_freeze() / vips_error_thaw()
|
- added vips_error_freeze() / vips_error_thaw()
|
||||||
- used freeze() / thaw() to stop file format sniffers logging spurious errors
|
- used freeze() / thaw() to stop file format sniffers logging spurious errors
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
* - small cleanups
|
* - small cleanups
|
||||||
* 5/9/13
|
* 5/9/13
|
||||||
* - redo as a class
|
* - redo as a class
|
||||||
|
* 9/9/13
|
||||||
|
* - any number of bands
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -74,13 +76,72 @@ typedef VipsOperationClass VipsHistLocalClass;
|
|||||||
|
|
||||||
G_DEFINE_TYPE( VipsHistLocal, vips_hist_local, VIPS_TYPE_OPERATION );
|
G_DEFINE_TYPE( VipsHistLocal, vips_hist_local, VIPS_TYPE_OPERATION );
|
||||||
|
|
||||||
|
/* Our sequence value: the region this sequence is using, and local stats.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
VipsRegion *ir; /* Input region */
|
||||||
|
|
||||||
|
/* A 256-element hist for evry band.
|
||||||
|
*/
|
||||||
|
unsigned int **hist;
|
||||||
|
} VipsHistLocalSequence;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_hist_local_gen( VipsRegion *or,
|
vips_hist_local_stop( void *vseq, void *a, void *b )
|
||||||
void *seq, void *a, void *b, gboolean *stop )
|
|
||||||
{
|
{
|
||||||
VipsRegion *ir = (VipsRegion *) seq;
|
VipsHistLocalSequence *seq = (VipsHistLocalSequence *) vseq;
|
||||||
|
VipsImage *in = (VipsImage *) a;
|
||||||
|
|
||||||
|
VIPS_UNREF( seq->ir );
|
||||||
|
if( seq->hist ) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < in->Bands; i++ )
|
||||||
|
VIPS_FREE( seq->hist[i] );
|
||||||
|
VIPS_FREE( seq->hist );
|
||||||
|
}
|
||||||
|
VIPS_FREE( seq );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vips_hist_local_start( VipsImage *out, void *a, void *b )
|
||||||
|
{
|
||||||
|
VipsImage *in = (VipsImage *) a;
|
||||||
|
VipsHistLocalSequence *seq;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if( !(seq = VIPS_NEW( NULL, VipsHistLocalSequence )) )
|
||||||
|
return( NULL );
|
||||||
|
seq->ir = NULL;
|
||||||
|
seq->hist = NULL;
|
||||||
|
|
||||||
|
if( !(seq->ir = vips_region_new( in )) ||
|
||||||
|
!(seq->hist = VIPS_ARRAY( NULL, in->Bands, unsigned int * )) ) {
|
||||||
|
vips_hist_local_stop( seq, NULL, NULL );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < in->Bands; i++ )
|
||||||
|
if( !(seq->hist[i] = VIPS_ARRAY( NULL, 256, unsigned int )) ) {
|
||||||
|
vips_hist_local_stop( seq, NULL, NULL );
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( seq );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_hist_local_generate( VipsRegion *or,
|
||||||
|
void *vseq, void *a, void *b, gboolean *stop )
|
||||||
|
{
|
||||||
|
VipsHistLocalSequence *seq = (VipsHistLocalSequence *) vseq;
|
||||||
|
VipsImage *in = (VipsImage *) a;
|
||||||
const VipsHistLocal *local = (VipsHistLocal *) b;
|
const VipsHistLocal *local = (VipsHistLocal *) b;
|
||||||
VipsRect *r = &or->valid;
|
VipsRect *r = &or->valid;
|
||||||
|
int bands = in->Bands;
|
||||||
|
|
||||||
VipsRect irect;
|
VipsRect irect;
|
||||||
int y;
|
int y;
|
||||||
@ -93,29 +154,31 @@ vips_hist_local_gen( VipsRegion *or,
|
|||||||
irect.top = r->top;
|
irect.top = r->top;
|
||||||
irect.width = r->width + local->width;
|
irect.width = r->width + local->width;
|
||||||
irect.height = r->height + local->height;
|
irect.height = r->height + local->height;
|
||||||
if( vips_region_prepare( ir, &irect ) )
|
if( vips_region_prepare( seq->ir, &irect ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
lsk = VIPS_REGION_LSKIP( ir );
|
lsk = VIPS_REGION_LSKIP( seq->ir );
|
||||||
centre = lsk * (local->height / 2) + local->width / 2;
|
centre = lsk * (local->height / 2) + bands * local->width / 2;
|
||||||
|
|
||||||
for( y = 0; y < r->height; y++ ) {
|
for( y = 0; y < r->height; y++ ) {
|
||||||
/* Get input and output pointers for this line.
|
/* Get input and output pointers for this line.
|
||||||
*/
|
*/
|
||||||
VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y );
|
VipsPel *p = VIPS_REGION_ADDR( seq->ir, r->left, r->top + y );
|
||||||
VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y );
|
VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y );
|
||||||
|
|
||||||
VipsPel *p1;
|
VipsPel *p1;
|
||||||
int hist[256];
|
int x, i, j, b;
|
||||||
int x, i, j;
|
|
||||||
|
|
||||||
/* Find histogram for start of this line.
|
/* Find histogram for start of this line.
|
||||||
*/
|
*/
|
||||||
memset( hist, 0, 256 * sizeof( int ) );
|
for( b = 0; b < bands; b++ )
|
||||||
|
memset( seq->hist[b], 0, 256 * sizeof( unsigned int ) );
|
||||||
p1 = p;
|
p1 = p;
|
||||||
for( j = 0; j < local->height; j++ ) {
|
for( j = 0; j < local->height; j++ ) {
|
||||||
for( i = 0; i < local->width; i++ )
|
i = 0;
|
||||||
hist[p1[i]] += 1;
|
for( x = 0; x < local->width; x++ )
|
||||||
|
for( b = 0; b < bands; b++ )
|
||||||
|
seq->hist[b][p1[i++]] += 1;
|
||||||
|
|
||||||
p1 += lsk;
|
p1 += lsk;
|
||||||
}
|
}
|
||||||
@ -123,30 +186,34 @@ vips_hist_local_gen( VipsRegion *or,
|
|||||||
/* Loop for output pels.
|
/* Loop for output pels.
|
||||||
*/
|
*/
|
||||||
for( x = 0; x < r->width; x++ ) {
|
for( x = 0; x < r->width; x++ ) {
|
||||||
/* Sum histogram up to current pel.
|
for( b = 0; b < bands; b++ ) {
|
||||||
*/
|
/* Sum histogram up to current pel.
|
||||||
int target = p[centre];
|
*/
|
||||||
int sum;
|
unsigned int *hist = seq->hist[b];
|
||||||
|
int target = p[centre];
|
||||||
|
int sum;
|
||||||
|
|
||||||
sum = 0;
|
sum = 0;
|
||||||
for( i = 0; i < target; i++ )
|
for( i = 0; i < target; i++ )
|
||||||
sum += hist[i];
|
sum += hist[i];
|
||||||
|
|
||||||
q[x] = 256 * sum / (local->width * local->height);
|
*q++ = 256 * sum /
|
||||||
|
(local->width * local->height);
|
||||||
|
|
||||||
/* Adapt histogram --- remove the pels from the left
|
/* Adapt histogram --- remove the pels from
|
||||||
* hand column, add in pels for a new right-hand
|
* the left hand column, add in pels for a
|
||||||
* column.
|
* new right-hand column.
|
||||||
*/
|
*/
|
||||||
p1 = p;
|
p1 = p;
|
||||||
for( j = 0; j < local->height; j++ ) {
|
for( j = 0; j < local->height; j++ ) {
|
||||||
hist[p1[0]] -= 1;
|
hist[p1[0]] -= 1;
|
||||||
hist[p1[local->width]] += 1;
|
hist[p1[bands * local->width]] += 1;
|
||||||
|
|
||||||
p1 += lsk;
|
p1 += lsk;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,8 +234,7 @@ vips_hist_local_build( VipsObject *object )
|
|||||||
|
|
||||||
in = local->in;
|
in = local->in;
|
||||||
|
|
||||||
if( vips_check_mono( class->nickname, in ) ||
|
if( vips_check_uncoded( class->nickname, in ) ||
|
||||||
vips_check_uncoded( class->nickname, in ) ||
|
|
||||||
vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
vips_check_format( class->nickname, in, VIPS_FORMAT_UCHAR ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -207,7 +273,9 @@ vips_hist_local_build( VipsObject *object )
|
|||||||
VIPS_DEMAND_STYLE_FATSTRIP, in, NULL );
|
VIPS_DEMAND_STYLE_FATSTRIP, in, NULL );
|
||||||
|
|
||||||
if( vips_image_generate( local->out,
|
if( vips_image_generate( local->out,
|
||||||
vips_start_one, vips_hist_local_gen, vips_stop_one,
|
vips_hist_local_start,
|
||||||
|
vips_hist_local_generate,
|
||||||
|
vips_hist_local_stop,
|
||||||
in, local ) )
|
in, local ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -271,8 +339,7 @@ vips_hist_local_init( VipsHistLocal *local )
|
|||||||
* @...: %NULL-terminated list of optional named arguments
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
*
|
*
|
||||||
* Performs local histogram equalisation on @in using a
|
* Performs local histogram equalisation on @in using a
|
||||||
* window of size @xwin by @ywin centered on the input pixel. Works only on
|
* window of size @xwin by @ywin centered on the input pixel.
|
||||||
* monochrome images.
|
|
||||||
*
|
*
|
||||||
* The output image is the same size as the input image. The edge pixels are
|
* 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.
|
* created by copy edge pixels of the input image outwards.
|
||||||
|
Loading…
Reference in New Issue
Block a user