8cc76a6ba3
Also update LGPLv2.1 license text from the copy currently on the GNU website.
412 lines
9.9 KiB
C++
412 lines
9.9 KiB
C++
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301 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 ) throw( VError );
|
|
VPIMask( int xsize, int ysize, int scale, int offset,
|
|
std::vector<int> coeff ) throw( VError );
|
|
VPIMask( const char * )
|
|
throw( VError );
|
|
VPIMask( im__INTMASK * );
|
|
VPIMask();
|
|
virtual ~VPIMask();
|
|
|
|
VPMask *dup() const throw( VError );
|
|
void embed( im__INTMASK * ) throw( VError );
|
|
|
|
int xsize() const throw( VError );
|
|
int ysize() const throw( VError );
|
|
int scale() const throw( VError );
|
|
int offset() const throw( VError );
|
|
const char *filename() const throw( VError );
|
|
|
|
// Output
|
|
virtual void ostream_print( std::ostream & ) const throw( VError );
|
|
|
|
// Extract start of array of ints
|
|
int *array() const;
|
|
};
|
|
|
|
// Specialise for DOUBLEMASK
|
|
class VPDMask : public VPMask {
|
|
public:
|
|
VPDMask( int xsize, int ysize ) throw( VError );
|
|
VPDMask( int xsize, int ysize,
|
|
double scale, double offset, std::vector<double> coeff )
|
|
throw( VError );
|
|
VPDMask( const char * ) throw( VError );
|
|
VPDMask( im__DOUBLEMASK * );
|
|
VPDMask();
|
|
virtual ~VPDMask();
|
|
|
|
VPMask *dup() const throw( VError );
|
|
void embed( im__DOUBLEMASK * ) throw( VError );
|
|
|
|
int xsize() const throw( VError );
|
|
int ysize() const throw( VError );
|
|
double scale() const throw( VError );
|
|
double offset() const throw( VError );
|
|
const char *filename() const throw( VError );
|
|
|
|
// Output
|
|
virtual void ostream_print( std::ostream & ) const throw( VError );
|
|
|
|
// 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 throw( VError )
|
|
{ return( ref->pmask->xsize() ); }
|
|
int ysize() const throw( VError )
|
|
{ return( ref->pmask->ysize() ); }
|
|
int size() const throw( VError )
|
|
{ return( xsize() * ysize() ); }
|
|
const char *filename() const throw( VError )
|
|
{ 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 * ) throw( VError );
|
|
|
|
// Overload [] to get linear array subscript.
|
|
int &operator[]( int ) throw( VError );
|
|
|
|
// Overload () to get matrix subscript.
|
|
int &operator()( int x, int y ) throw( VError )
|
|
{ return( (*this)[x + y*xsize()] ); }
|
|
|
|
// and as a function call that SWIG can wrap
|
|
int get( int i ) throw( VError )
|
|
{ return( (*this)[i] ); }
|
|
|
|
// Type conversion: INTMASK->DOUBLEMASK
|
|
operator VDMask();
|
|
|
|
// Type conversion: INTMASK->image
|
|
operator VImage();
|
|
|
|
// VIMask build functions
|
|
static VIMask gauss( double, double ) throw( VError );
|
|
static VIMask gauss_sep( double, double ) throw( VError );
|
|
static VIMask log( double, double ) throw( VError );
|
|
|
|
// VIMask manipulation
|
|
VIMask rotate45() throw( VError );
|
|
VIMask rotate90() throw( VError );
|
|
|
|
// 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() throw( VError );
|
|
VDMask inv() throw( VError );
|
|
VDMask cat( VDMask ) throw( VError );
|
|
VDMask mul( VDMask ) throw( VError );
|
|
};
|
|
|
|
// 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 * ) throw( VError );
|
|
|
|
double scale() throw( VError )
|
|
{
|
|
return( ((_private_detail::VPDMask *)ref->pmask)->scale() );
|
|
}
|
|
|
|
double offset() throw( VError )
|
|
{
|
|
return( ((_private_detail::VPDMask *)ref->pmask)->offset() );
|
|
}
|
|
|
|
// Overload [] to get linear array subscript.
|
|
double &operator[]( int ) throw( VError );
|
|
|
|
// Overload () to get matrix subscript.
|
|
double &operator()( int x, int y ) throw( VError )
|
|
{ return( (*this)[x + y*xsize()] ); }
|
|
|
|
// and as a function call that SWIG can wrap
|
|
double get( int i ) throw( VError )
|
|
{ return( (*this)[i] ); }
|
|
|
|
// Type conversion: double->int
|
|
operator VIMask();
|
|
|
|
// Type conversion: DOUBLEMASK->image
|
|
operator VImage() throw( VError );
|
|
|
|
// VDMask build functions
|
|
static VDMask gauss( double, double ) throw( VError );
|
|
static VDMask log( double, double ) throw( VError );
|
|
|
|
// VDMask manipulation
|
|
VDMask rotate45() throw( VError );
|
|
VDMask rotate90() throw( VError );
|
|
|
|
// Scale to intmask
|
|
VIMask scalei() throw( VError );
|
|
|
|
// Simple arithmetic
|
|
VDMask trn() throw( VError );
|
|
VDMask inv() throw( VError );
|
|
VDMask cat( VDMask ) throw( VError );
|
|
VDMask mul( VDMask ) throw( VError );
|
|
};
|
|
|
|
VIPS_NAMESPACE_END
|
|
|
|
#endif /*IM_VMASK_H*/
|