blob: 794e0aadf7f10f9ea13c81f74b1f37d294fbeb9b [file] [log] [blame]
/* VIPS mask class.
*
* Just like VImage, but we don't need dependency stuff. Instead, have a base
* wrapper over *MASK, derive VMaskD and VMaskI from that, and then put
* refcounting over all of them.
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifndef IM_VMASK_H
#define IM_VMASK_H
/* SWIG includes this file directly rather than going through vipscpp.h ... so
* we have to define these macros here as well.
*/
#ifdef SWIG
# define VIPS_NAMESPACE_START namespace vips {
# define VIPS_NAMESPACE_END }
#endif /*SWIG*/
/* Don't include these when parsing for SWIG.
*/
#ifndef SWIG
# include <cstdarg>
# include <iosfwd>
# include <vector>
#endif /*!SWIG*/
/* Wrap pointers to these, but we don't want to import all the old C API. Just
* declare them.
*/
extern "C" {
struct im__INTMASK;
struct im__DOUBLEMASK;
}
VIPS_NAMESPACE_START
/* This first section is private. Only expose the non-P versions of these
* classes later on. Don't need to wrap then in SWIG either.
*/
#ifndef SWIG
namespace _private_detail {
union MASKUNION {
im__INTMASK *iptr;
im__DOUBLEMASK *dptr;
};
// Private wrapper over *MASK - user does not see this
class VPMask {
friend class VMask;
public:
// Track type of mask with this
enum VMaskType {
UNASSIGNED, // Not yet set
INT, // mask points to INTMASK
DOUBLE // mask points to DOUBLEMASK
};
MASKUNION data; // Mask pointer - INT or DOUBLE
VMaskType type; // Track type too, for safety
virtual ~VPMask() {};
// Duplicate
virtual VPMask *dup() const = 0;
// Projection functions to get MASK fields
virtual int xsize() const = 0;
virtual int ysize() const = 0;
virtual const char *filename() const = 0;
// Output
virtual void ostream_print( std::ostream & ) const = 0;
};
// Specialise for INTMASK
class VPIMask : public VPMask {
public:
VPIMask( int xsize, int ysize );
VPIMask( int xsize, int ysize, int scale, int offset,
std::vector<int> coeff );
VPIMask( const char * )
throw( VError );
VPIMask( im__INTMASK * );
VPIMask();
virtual ~VPIMask();
VPMask *dup() const;
void embed( im__INTMASK * );
int xsize() const;
int ysize() const;
int scale() const;
int offset() const;
const char *filename() const;
// Output
virtual void ostream_print( std::ostream & ) const;
// Extract start of array of ints
int *array() const;
};
// Specialise for DOUBLEMASK
class VPDMask : public VPMask {
public:
VPDMask( int xsize, int ysize );
VPDMask( int xsize, int ysize,
double scale, double offset, std::vector<double> coeff )
throw( VError );
VPDMask( const char * );
VPDMask( im__DOUBLEMASK * );
VPDMask();
virtual ~VPDMask();
VPMask *dup() const;
void embed( im__DOUBLEMASK * );
int xsize() const;
int ysize() const;
double scale() const;
double offset() const;
const char *filename() const;
// Output
virtual void ostream_print( std::ostream & ) const;
// Extract start of array of doubles
double *array() const;
};
} // end of namespace _private_detail
inline std::ostream &operator<<( std::ostream &file,
const _private_detail::VPMask &msk )
{
msk.ostream_print( file );
return( file );
}
#endif /*!SWIG*/
// Wrapper over VP?Mask with ref counting
class VMask {
protected:
struct refblock {
_private_detail::VPMask *pmask; // Mask: double or int
int nrefs; // Refs to us
refblock() : pmask(0), nrefs(1) {}
virtual ~refblock() { delete pmask; }
};
refblock *ref;
// Make sure this is a private copy of pmask --- dup if nrefs != 1
void make_private();
public:
// Constructor leaves msk uninitialised
VMask() { ref = new refblock; }
// Copy constructor
VMask( const VMask &a ) { ref = a.ref; ref->nrefs++; }
// Assignment
VMask &operator=( const VMask &a );
// Destructor
virtual ~VMask();
int xsize() const
{ return( ref->pmask->xsize() ); }
int ysize() const
{ return( ref->pmask->ysize() ); }
int size() const
{ return( xsize() * ysize() ); }
const char *filename() const
{ return( ref->pmask->filename() ); }
// Extract underlying type
_private_detail::VPMask::VMaskType type() const
{ return( ref->pmask->type ); }
// Extract underlying VIPS pointer
_private_detail::MASKUNION mask() const { return( ref->pmask->data ); }
void ostream_print( std::ostream & ) const;
};
inline std::ostream &operator<<( std::ostream &file, const VMask &msk )
{
msk.ostream_print( file );
return( file );
}
// Need to forward ref these
class VDMask;
class VImage;
// Wrapper over _private_detail::VPIMask with ref counting
class VIMask : public VMask {
public:
VIMask( int xsize, int ysize )
{
ref->pmask = new _private_detail::VPIMask( xsize, ysize );
}
/* Don't wrap the varargs constructor. We want Python to use the vector one.
*/
#ifndef SWIG
VIMask( int xsize, int ysize, int scale, int offset, ... )
{
va_list ap;
int i;
std::vector<int> coeff( xsize * ysize );
va_start( ap, offset );
for( i = 0; i < xsize * ysize; i++ )
coeff[i] = va_arg( ap, int );
va_end( ap );
ref->pmask = new _private_detail::VPIMask( xsize, ysize,
scale, offset, coeff );
}
#endif /*!SWIG*/
VIMask( int xsize, int ysize, int scale, int offset,
std::vector<int> coeff )
{
ref->pmask = new _private_detail::VPIMask( xsize, ysize,
scale, offset, coeff );
}
VIMask( const char *name )
{
ref->pmask = new _private_detail::VPIMask( name );
}
// No mask there yet
VIMask() {}
int scale()
{
return( ((_private_detail::VPIMask *)ref->pmask)->scale() );
}
int offset()
{
return( ((_private_detail::VPIMask *)ref->pmask)->offset() );
}
// Embed INTMASK in VIMask
void embed( im__INTMASK * );
// Overload [] to get linear array subscript.
int &operator[]( int );
// Overload () to get matrix subscript.
int &operator()( int x, int y )
{ return( (*this)[x + y*xsize()] ); }
// and as a function call that SWIG can wrap
int get( int i )
{ return( (*this)[i] ); }
// Type conversion: INTMASK->DOUBLEMASK
operator VDMask();
// Type conversion: INTMASK->image
operator VImage();
// VIMask build functions
static VIMask gauss( double, double );
static VIMask gauss_sep( double, double );
static VIMask log( double, double );
// VIMask manipulation
VIMask rotate45();
VIMask rotate90();
// Arithmetic ... cast to double, and use VDMask funcs. For some
// reason, the compiler won't let us do casts to VDImage yet, so no
// inlines.
VDMask trn();
VDMask inv();
VDMask cat( VDMask );
VDMask mul( VDMask );
};
// Wrapper over _private_detail::VPDMask with ref counting
class VDMask : public VMask {
public:
VDMask( int xsize, int ysize )
{
ref->pmask = new _private_detail::VPDMask( xsize, ysize );
}
/* Don't wrap the varargs constructor. We want Python to use the vector one.
*/
#ifndef SWIG
VDMask( int xsize, int ysize, double scale, double offset, ... )
{
va_list ap;
int i;
std::vector<double> coeff( xsize * ysize );
va_start( ap, offset );
for( i = 0; i < xsize * ysize; i++ )
coeff[i] = va_arg( ap, double );
va_end( ap );
ref->pmask = new _private_detail::VPDMask( xsize, ysize,
scale, offset, coeff );
}
#endif /*!SWIG*/
VDMask( int xsize, int ysize, double scale, double offset,
std::vector<double> coeff )
{
ref->pmask = new _private_detail::VPDMask( xsize, ysize,
scale, offset, coeff );
}
VDMask( const char *name )
{
ref->pmask = new _private_detail::VPDMask( name );
}
// No mask yet
VDMask() { }
// Embed DOUBLEMASK in VDMask
void embed( im__DOUBLEMASK * );
double scale()
{
return( ((_private_detail::VPDMask *)ref->pmask)->scale() );
}
double offset()
{
return( ((_private_detail::VPDMask *)ref->pmask)->offset() );
}
// Overload [] to get linear array subscript.
double &operator[]( int );
// Overload () to get matrix subscript.
double &operator()( int x, int y )
{ return( (*this)[x + y*xsize()] ); }
// and as a function call that SWIG can wrap
double get( int i )
{ return( (*this)[i] ); }
// Type conversion: double->int
operator VIMask();
// Type conversion: DOUBLEMASK->image
operator VImage();
// VDMask build functions
static VDMask gauss( double, double );
static VDMask log( double, double );
// VDMask manipulation
VDMask rotate45();
VDMask rotate90();
// Scale to intmask
VIMask scalei();
// Simple arithmetic
VDMask trn();
VDMask inv();
VDMask cat( VDMask );
VDMask mul( VDMask );
};
VIPS_NAMESPACE_END
#endif /*IM_VMASK_H*/