any size mask for rot90

This commit is contained in:
John Cupitt 2010-12-01 10:02:40 +00:00
parent 97a5ff1607
commit c93443aaca
5 changed files with 232 additions and 178 deletions

View File

@ -1,5 +1,7 @@
30/11/10 started 7.24.0
- bump for new stable
- added im_dmask2imask(), im_imask2dmask()
- im_rotate_*mask90() can do masks of any size (thanks Adam)
18/7/10 started 7.23.0
- im_vips2bufjpeg() writes to a linked list, so it will work for any size

5
TODO
View File

@ -118,11 +118,6 @@ g++ -shared -nostdlib /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crti.o
- quite a few hist operations have no GUI ... lhisteq, for example? or
histspec?
- im_rotate_imask90 only works for square, odd-sized masks, argh
just use im_rot90? have a small wrapper to let you use image functions on
masks

View File

@ -88,6 +88,9 @@ DOUBLEMASK *im_dup_dmask( DOUBLEMASK *in, const char *filename );
INTMASK *im_scale_dmask( DOUBLEMASK *in, const char *filename );
void im_norm_dmask( DOUBLEMASK *mask );
DOUBLEMASK *im_imask2dmask( INTMASK *in, const char *filename );
INTMASK *im_dmask2imask( DOUBLEMASK *in, const char *filename );
INTMASK *im_rotate_imask90( INTMASK *in, const char *filename );
INTMASK *im_rotate_imask45( INTMASK *in, const char *filename );
DOUBLEMASK *im_rotate_dmask90( DOUBLEMASK *in, const char *filename );

View File

@ -1,54 +1,5 @@
/* @(#) Functions to create offsets for rotating square masks.
* @(#) Usage
* @(#) int *im_offsets45( size )
* @(#) int size;
* @(#)
* @(#) Returns an int pointer to valid offsets on sucess and -1 on error
* @(#)
*
* @(#) Usage
* @(#) int *im_offsets90( size )
* @(#) int size;
* @(#)
* @(#) Returns an int pointer to valid offsets on sucess and -1 on error
* @(#)
/* Functions to create offsets for rotating square masks.
*
* @(#) Functions to rotate square masks
* @(#)
* @(#) Usage
* @(#) INTMASK *im_rotate_imask45( mask, name )
* @(#) INTMASK *mask;
* @(#)
* @(#) Returns an pointer to INTMASK which keeps the original mask rotated
* @(#) by 45 degrees clockwise.
* @(#) The filename member of the returned mask is set to name
* @(#)
* @(#) Usage
* @(#) DOUBLEMASK *im_rotate_dmask45( mask, name )
* @(#) DOUBLEMASK *mask;
* @(#)
* @(#) Returns an pointer to INTMASK which keeps the original mask rotated
* @(#) by 45 degrees clockwise.
* @(#) The filename member of the returned mask is set to name
* @(#)
* @(#) Usage
* @(#) INTMASK *im_rotate_imask90( mask, name )
* @(#) INTMASK *mask;
* @(#)
* @(#) Returns an pointer to INTMASK which keeps the original mask rotated
* @(#) by 90 degrees clockwise.
* @(#) The filename member of the returned mask is set to name
* @(#)
* @(#) Usage
* @(#) DOUBLEMASK *im_rotate_dmask90( mask, name )
* @(#) DOUBLEMASK *mask;
* @(#)
* @(#) Returns an pointer to DOUBLEMASK which keeps the original mask rotated
* @(#) by 90 degrees clockwise.
* @(#) The filename member of the returned mask is set to name
* @(#)
*
*
* Author: N. Dessipris (Copyright, N. Dessipris 1991)
* Written on: 08/05/1991
* Modified on: 28/05/1991
@ -59,6 +10,8 @@
* - many bugs and mem leaks fixed
* 1/3/99 JC
* - oops, fns were not preserving scale and offset
* 1/12/10
* - allow any size mask for the 90 degree rotates by using im_rot90().
*/
/*
@ -191,7 +144,7 @@ im_offsets90( int size )
int x, y, k;
int *offsets;
if( !(offsets = IM_ARRAY( NULL, size*size, int )) )
if( !(offsets = IM_ARRAY( NULL, size * size, int )) )
return( NULL );
for( k = 0, y = 0; y < size; y++ ) {
@ -206,92 +159,6 @@ im_offsets90( int size )
return( offsets );
}
/* Tye pf offset-generating function.
*/
typedef int *(*offset_fn)( int );
/* Rotate a dmask with a set of offsets.
*/
static DOUBLEMASK *
rotdmask( offset_fn fn, DOUBLEMASK *m, const char *name )
{
DOUBLEMASK *out;
int size = m->xsize * m->ysize;
int *offsets;
int i;
if( m->xsize != m->ysize || (m->xsize % 2) == 0 ) {
im_error( "im_rotate_mask", "%s",
_( "mask should be square of even size" ) );
return( NULL );
}
if( !(offsets = fn( m->xsize )) )
return( NULL );
if( !(out = im_create_dmask( name, m->xsize, m->ysize )) ) {
im_free( offsets );
return( NULL );
}
out->scale = m->scale;
out->offset = m->offset;
for( i = 0; i < size; i++ )
out->coeff[i] = m->coeff[offsets[i]];
im_free( offsets );
return( out );
}
/* Rotate an imask with a set of offsets.
*/
static INTMASK *
rotimask( offset_fn fn, INTMASK *m, const char *name )
{
INTMASK *out;
int size = m->xsize * m->ysize;
int *offsets;
int i;
if( m->xsize != m->ysize || (m->xsize % 2) == 0 ) {
im_error( "im_rotate_mask", "%s",
_( "mask should be square of even size" ) );
return( NULL );
}
if( !(offsets = fn( m->xsize )) )
return( NULL );
if( !(out = im_create_imask( name, m->xsize, m->ysize )) ) {
im_free( offsets );
return( NULL );
}
out->scale = m->scale;
out->offset = m->offset;
for( i = 0; i < size; i++ )
out->coeff[i] = m->coeff[offsets[i]];
im_free( offsets );
return( out );
}
/**
* im_rotate_dmask90:
* @in: input matrix
* @filename: name for output matrix
*
* Returns a mask which is the argument mask rotated by 90 degrees.
* Pass the filename to set for the output.
*
* See also: im_rotate_dmask45().
*
* Returns: the result matrix on success, or %NULL on error.
*/
DOUBLEMASK *
im_rotate_dmask90( DOUBLEMASK *in, const char *filename )
{
return( rotdmask( im_offsets90, in, filename ) );
}
/**
* im_rotate_dmask45:
* @in: input matrix
@ -307,25 +174,31 @@ im_rotate_dmask90( DOUBLEMASK *in, const char *filename )
DOUBLEMASK *
im_rotate_dmask45( DOUBLEMASK *in, const char *filename )
{
return( rotdmask( im_offsets45, in, filename ) );
}
DOUBLEMASK *out;
int size = in->xsize * in->ysize;
int *offsets;
int i;
/**
* im_rotate_imask90:
* @in: input matrix
* @filename: name for output matrix
*
* Returns a mask which is the argument mask rotated by 90 degrees.
* Pass the filename to set for the output.
*
* See also: im_rotate_imask45().
*
* Returns: the result matrix on success, or %NULL on error.
*/
INTMASK *
im_rotate_imask90( INTMASK *in, const char *filename )
{
return( rotimask( im_offsets90, in, filename ) );
if( in->xsize != in->ysize || (in->xsize % 2) == 0 ) {
im_error( "im_rotate_dmask45", "%s",
_( "mask should be square of odd size" ) );
return( NULL );
}
if( !(offsets = im_offsets45( in->xsize )) )
return( NULL );
if( !(out = im_create_dmask( filename, in->xsize, in->ysize )) ) {
im_free( offsets );
return( NULL );
}
out->scale = in->scale;
out->offset = in->offset;
for( i = 0; i < size; i++ )
out->coeff[i] = in->coeff[offsets[i]];
im_free( offsets );
return( out );
}
/**
@ -343,5 +216,122 @@ im_rotate_imask90( INTMASK *in, const char *filename )
INTMASK *
im_rotate_imask45( INTMASK *in, const char *filename )
{
return( rotimask( im_offsets45, in, filename ) );
INTMASK *out;
int size = in->xsize * in->ysize;
int *offsets;
int i;
if( in->xsize != in->ysize || (in->xsize % 2) == 0 ) {
im_error( "im_rotate_imask45", "%s",
_( "mask should be square of odd size" ) );
return( NULL );
}
if( !(offsets = im_offsets45( in->xsize )) )
return( NULL );
if( !(out = im_create_imask( filename, in->xsize, in->ysize )) ) {
im_free( offsets );
return( NULL );
}
out->scale = in->scale;
out->offset = in->offset;
for( i = 0; i < size; i++ )
out->coeff[i] = in->coeff[offsets[i]];
im_free( offsets );
return( out );
}
/* The type of the vips operations we support.
*/
typedef int (*vips_fn)( IMAGE *in, IMAGE *out );
/* Pass a mask through a vips operation, eg. im_rot90().
*/
static INTMASK *
vapplyimask( INTMASK *in, const char *name, vips_fn fn )
{
IMAGE *x;
IMAGE *t[2];
DOUBLEMASK *d[2];
INTMASK *out;
if( !(x = im_open( name, "p" )) )
return( NULL );
if( !(d[0] = im_local_dmask( x, im_imask2dmask( in, name ) )) ||
im_open_local_array( x, t, 2, name, "p" ) ||
im_mask2vips( d[0], t[0] ) ||
fn( t[0], t[1] ) ||
!(d[1] = im_local_dmask( x, im_vips2mask( t[1], name ) )) ||
!(out = im_dmask2imask( d[1], name )) ) {
im_close( x );
return( NULL );
}
im_close( x );
out->scale = in->scale;
out->offset = in->offset;
return( out );
}
static DOUBLEMASK *
vapplydmask( DOUBLEMASK *in, const char *name, vips_fn fn )
{
IMAGE *x;
IMAGE *t[2];
DOUBLEMASK *out;
if( !(x = im_open( name, "p" )) )
return( NULL );
if( im_open_local_array( x, t, 2, name, "p" ) ||
im_mask2vips( in, t[0] ) ||
fn( t[0], t[1] ) ||
!(out = im_vips2mask( t[1], name )) ) {
im_close( x );
return( NULL );
}
im_close( x );
out->scale = in->scale;
out->offset = in->offset;
return( out );
}
/**
* im_rotate_imask90:
* @in: input matrix
* @filename: name for output matrix
*
* Returns a mask which is the argument mask rotated by 90 degrees.
* Pass the filename to set for the output.
*
* See also: im_rotate_imask45().
*
* Returns: the result matrix on success, or %NULL on error.
*/
INTMASK *
im_rotate_imask90( INTMASK *in, const char *filename )
{
return( vapplyimask( in, filename, im_rot90 ) );
}
/**
* im_rotate_dmask90:
* @in: input matrix
* @filename: name for output matrix
*
* Returns a mask which is the argument mask rotated by 90 degrees.
* Pass the filename to set for the output.
*
* See also: im_rotate_dmask45().
*
* Returns: the result matrix on success, or %NULL on error.
*/
DOUBLEMASK *
im_rotate_dmask90( DOUBLEMASK *in, const char *filename )
{
return( vapplydmask( in, filename, im_rot90 ) );
}

View File

@ -25,7 +25,7 @@
* 27/4/95 JC
* - oops! forgot to init IM_ARRAY() memory to zero
* 7/8/96 JC
* - im_scale_dmask rewritten
* - im_scale_dmask() rewritten
* 7/5/98 JC
* - im_read_*mask() rewritten, now more robust
* - im_write_*mask() rewritten
@ -594,11 +594,8 @@ im_scale_dmask( DOUBLEMASK *in, const char *filename )
int i;
int isum;
if( !filename || in->xsize <= 0 || in->ysize <= 0 ) {
im_error( "im_scale_dmask", "%s", _( "bad arguments" ) );
return( NULL );
}
if( !(out = im_create_imask( filename, in->xsize, in->ysize )) )
if( im_check_dmask( "im_scale_dmask", in ) ||
!(out = im_create_imask( filename, in->xsize, in->ysize )) )
return( NULL );
/* Find mask max.
@ -634,16 +631,78 @@ im_scale_dmask( DOUBLEMASK *in, const char *filename )
}
/**
* im_norm_dmask:
* @mask: mask to scale
* im_dmask2imask:
* @in: mask to convert
* @filename: filename for returned mask
*
* Normalise the dmask. Apply the scale and offset to each element and return
* a mask with scale 1, offset zero.
* Make an imask from the dmask, rounding to nearest.
*
* See also: im_scale_dmask().
*
* Returns: the converted mask, or NULL on error.
*/
INTMASK *
im_dmask2imask( DOUBLEMASK *in, const char *filename )
{
const int size = in->xsize * in->ysize;
INTMASK *out;
int i;
if( im_check_dmask( "im_dmask2imask", in ) ||
!(out = im_create_imask( filename, in->xsize, in->ysize )) )
return( NULL );
for( i = 0; i < size; i++ )
out->coeff[i] = IM_RINT( in->coeff[i] );
out->offset = IM_RINT( in->offset );
out->scale = IM_RINT( in->scale );
return( out );
}
/**
* im_imask2dmask:
* @in: mask to convert
* @filename: filename for returned mask
*
* Make a dmask from the imask.
*
* See also: im_dmask2imask().
*
* Returns: the converted mask, or NULL on error.
*/
DOUBLEMASK *
im_imask2dmask( INTMASK *in, const char *filename )
{
const int size = in->xsize * in->ysize;
DOUBLEMASK *out;
int i;
if( im_check_imask( "im_imask2dmask", in ) ||
!(out = im_create_dmask( filename, in->xsize, in->ysize )) )
return( NULL );
for( i = 0; i < size; i++ )
out->coeff[i] = in->coeff[i];
out->offset = in->offset;
out->scale = in->scale;
return( out );
}
/**
* im_norm_dmask:
* @mask: mask to scale
*
* Normalise the dmask. Apply the scale and offset to each element to make
* a mask with scale 1, offset zero.
*
* See also: im_scale_dmask().
*
* Returns: 0 on success, or -1 on error.
*/
void
im_norm_dmask( DOUBLEMASK *mask )
{
@ -652,7 +711,8 @@ im_norm_dmask( DOUBLEMASK *mask )
int i;
if( 1.0 == scale && 0.0 == mask->offset )
if( im_check_dmask( "im_norm_dmask", mask ) ||
(1.0 == scale && 0.0 == mask->offset) )
return;
for( i = 0; i < n; i++ )
@ -679,7 +739,8 @@ im_dup_imask( INTMASK *in, const char *filename )
INTMASK *out;
int i;
if( !(out = im_create_imask( filename, in->xsize, in->ysize )) )
if( im_check_imask( "im_dup_imask", in ) ||
!(out = im_create_imask( filename, in->xsize, in->ysize )) )
return( NULL );
out->offset = in->offset;
@ -708,7 +769,8 @@ im_dup_dmask( DOUBLEMASK *in, const char *filename )
DOUBLEMASK *out;
int i;
if( !(out = im_create_dmask( filename, in->xsize, in->ysize )) )
if( im_check_dmask( "im_dup_dmask", in ) ||
!(out = im_create_dmask( filename, in->xsize, in->ysize )) )
return( NULL );
out->offset = in->offset;
@ -781,7 +843,8 @@ im_write_imask_name( INTMASK *in, const char *filename )
FILE *fp;
int x, y, i;
if( !(fp = open_write( filename )) )
if( im_check_imask( "im_write_imask_name", in ) ||
!(fp = open_write( filename )) )
return( -1 );
if( write_line( fp, "%d %d", in->xsize, in->ysize ) ) {
@ -845,7 +908,8 @@ im_write_dmask_name( DOUBLEMASK *in, const char *filename )
FILE *fp;
int x, y, i;
if( !(fp = open_write( filename )) )
if( im_check_dmask( "im_write_dmask_name", in ) ||
!(fp = open_write( filename )) )
return( -1 );
if( write_line( fp, "%d %d", in->xsize, in->ysize ) ) {
@ -1014,7 +1078,7 @@ im_print_dmask( DOUBLEMASK *in )
DOUBLEMASK *
im_local_dmask( VipsImage *out, DOUBLEMASK *mask )
{
if( !mask )
if( im_check_dmask( "im_local_dmask", mask ) )
return( NULL );
if( im_add_close_callback( out,
@ -1041,7 +1105,7 @@ im_local_dmask( VipsImage *out, DOUBLEMASK *mask )
INTMASK *
im_local_imask( VipsImage *out, INTMASK *mask )
{
if( !mask )
if( im_check_imask( "im_local_dmask", mask ) )
return( NULL );
if( im_add_close_callback( out,