pkg://vips-7.10.10.tar.gz:3320069/
vips-7.10.10/
libsrcCC/VImage.cc
downloads
// Object part of VImage class
/*
Copyright (C) 1991-2001 The National Gallery
This program 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdlib.h>
#include <stdio.h>
#include <vips/vips.h>
#include <vips/vipscpp.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/*
#define DEBUG
*/
void VImage::refblock::print()
{
std::list<refblock *>::iterator i;
printf( "refblock 0x%x:\n", GPOINTER_TO_UINT( this ) );
printf( " im = 0x%x", GPOINTER_TO_UINT( im ) );
if( im && ((IMAGE*)im)->filename )
printf( " (im->filename = \"%s\")", ((IMAGE*)im)->filename );
printf( "\n" );
printf( " close_on_delete = %d\n", close_on_delete );
printf( " nrefs (refs to us) = %d\n", nrefs );
printf( " orefs (refs we make) = refblocks " );
for( i = orefs.begin(); i != orefs.end(); i++ )
printf( "0x%x ", GPOINTER_TO_UINT( *i ) );
printf( "\n" );
}
// dump all refblocks for debugging
void VImage::print_all()
{
#ifdef DEBUG
std::list<VImage::refblock *>::iterator i;
printf( "*** VImage::refblock::print_all() start\n" );
for( i = all_refblock.begin(); i != all_refblock.end(); i++ )
(*i)->print();
printf( "*** VImage::refblock::print_all() end\n" );
#endif /*DEBUG*/
}
// easy call from C version
void im__ccp_print_all()
{
VImage::print_all();
}
// constructor
VImage::refblock::refblock()
{
im = 0;
close_on_delete = 1;
nrefs = 1;
#ifdef DEBUG
all_refblock.push_front( this );
#endif /*DEBUG*/
}
// Add a ref - this (output image) depends upon IMAGE in
void VImage::refblock::addref( refblock *in )
{
if( this == in )
verror( "sanity failure" );
in->nrefs++;
orefs.push_front( in );
}
VImage::refblock::~refblock()
{
#ifdef DEBUG
printf( "VImage::refblock::removeref(): death!\n" );
print();
#endif /*DEBUG*/
std::list<refblock *>::iterator i;
if( close_on_delete && im ) {
if( im_close( (IMAGE *) im ) )
verror();
im = 0;
}
// remove any refs we have ... may trigger other destructs in turn
for( i = orefs.begin(); i != orefs.end(); i++ )
(*i)->removeref();
#ifdef DEBUG
all_refblock.remove( this );
#endif /*DEBUG*/
}
// Remove a ref
void VImage::refblock::removeref()
{
nrefs--;
if( nrefs < 0 )
verror( "too many closes!" );
if( nrefs == 0 )
delete this;
}
// Init with name ... means open for read.
VImage::VImage( const char *name, const char *mode )
{
_ref = new refblock;
if( !(_ref->im = im_open( name, mode )) )
verror();
_ref->close_on_delete = 1;
#ifdef DEBUG
printf( "VImage::VImage( \"%s\", \"%s\" )\n", name, mode );
_ref->print();
#endif /*DEBUG*/
}
// Build a VImage from an IMAGE structure
VImage::VImage( void *in )
{
_ref = new refblock;
_ref->im = in;
_ref->close_on_delete = 0;
#ifdef DEBUG
printf( "VImage::VImage( IMAGE* 0x%x )\n", (unsigned long) in );
_ref->print();
#endif /*DEBUG*/
}
// Build from memory buffer
VImage::VImage( void *buffer, int width, int height,
int bands, TBandFmt format )
{
_ref = new refblock;
if( !(_ref->im = im_image( buffer, width, height,
bands, int( format ) )) )
verror();
_ref->close_on_delete = 1;
#ifdef DEBUG
printf( "VImage::VImage( void* 0x%x, %d, %d )\n",
(unsigned long) buffer, width, height );
_ref->print();
#endif /*DEBUG*/
}
// Empty init ... means open intermediate
VImage::VImage()
{
static GStaticMutex lock = G_STATIC_MUTEX_INIT;
volatile static int id = 0;
char filename[256];
_ref = new refblock;
/* This is not 100% safe if VIPS threading is not implemented on this
* platform ... but it doesn't really matter.
*/
g_static_mutex_lock( &lock );
im_snprintf( filename, 256, "intermediate image #%d", id++ );
g_static_mutex_unlock( &lock );
if( !(_ref->im = im_open( filename, "p" )) )
verror();
_ref->close_on_delete = 1;
#ifdef DEBUG
printf( "VImage::VImage()\n" );
_ref->print();
#endif /*DEBUG*/
}
// Copy constructor
VImage::VImage( const VImage &a )
{
_ref = a._ref;
_ref->nrefs++;
}
// Assignment
VImage &VImage::operator=( const VImage &a )
{
_ref->removeref();
_ref = a._ref;
_ref->nrefs++;
return( *this );
}
// Extract underlying data pointer
void *VImage::data() const
{
if( im_incheck( (IMAGE *) _ref->im ) )
verror();
return( (void *) ((IMAGE *) _ref->im)->data );
}
void VImage::print()
{
im_printdesc( (IMAGE *) image() );
}
// Write this to a VImage
VImage VImage::write( VImage out )
{
if( im_copy( (IMAGE *) _ref->im, (IMAGE *) out._ref->im ) )
verror();
out._ref->addref( _ref );
return( out );
}
VImage VImage::write( const char *name )
{
VImage out( name, "w" );
if( im_copy( (IMAGE *) _ref->im, (IMAGE *) out._ref->im ) )
verror();
out._ref->addref( _ref );
return( out );
}
VImage VImage::write()
{
VImage out( "VImage:w1", "t" );
if( im_copy( (IMAGE *) _ref->im, (IMAGE *) out._ref->im ) )
verror();
out._ref->addref( _ref );
return( out );
}
// Projection functions to get header fields
int VImage::Xsize() { return( ((IMAGE *) _ref->im)->Xsize ); }
int VImage::Ysize() { return( ((IMAGE *) _ref->im)->Ysize ); }
int VImage::Bands() { return( ((IMAGE *) _ref->im)->Bands ); }
VImage::TBandFmt VImage::BandFmt()
{ return( (TBandFmt) ((((IMAGE *) _ref->im)->BandFmt)) ); }
VImage::TCoding VImage::Coding()
{ return( (TCoding) ((((IMAGE *) _ref->im)->Coding)) ); }
VImage::TType VImage::Type()
{ return( (TType) ((((IMAGE *) _ref->im)->Type)) ); }
float VImage::Xres() { return( ((IMAGE *) _ref->im)->Xres ); }
float VImage::Yres() { return( ((IMAGE *) _ref->im)->Yres ); }
int VImage::Length() { return( ((IMAGE *) _ref->im)->Length ); }
VImage::TCompression VImage::Compression()
{ return( (TCompression) ((((IMAGE *) _ref->im)->Compression)) ); }
short VImage::Level() { return( ((IMAGE *) _ref->im)->Level ); }
int VImage::Xoffset() { return( ((IMAGE *) _ref->im)->Xoffset ); }
int VImage::Yoffset() { return( ((IMAGE *) _ref->im)->Yoffset ); }
// Derived fields
char *VImage::filename() { return( ((IMAGE *) _ref->im)->filename ); }
char *VImage::Hist() { return( ((IMAGE *) _ref->im)->Hist ); }
// Set header fields and setbuf() in one go.
void VImage::initdesc( int x, int y, int b,
TBandFmt f, TCoding c, TType t, float xr, float yr, int xo, int yo )
{
static int fmt[] = {
0, // NOTSET
IM_BBITS_BYTE, IM_BBITS_BYTE, // uchar/char
IM_BBITS_SHORT, IM_BBITS_SHORT, // ushort/short
IM_BBITS_INT, IM_BBITS_INT, // uint/int
IM_BBITS_FLOAT, // float types ...
IM_BBITS_COMPLEX,
IM_BBITS_DOUBLE,
IM_BBITS_DPCOMPLEX
};
im_initdesc( (IMAGE *) (_ref->im), x, y, b,
fmt[(int)f + 1], f, c, t, xr, yr, xo, yo );
if( im_setupout( (IMAGE *) _ref->im ) )
verror();
}
// Class wrapping up a vargv
class Vargv {
// Function we are args to
im_function *fn;
// Base of object vector
im_object *base;
public:
Vargv( const char *name );
~Vargv();
// Reference to element of base
im_object &data( int i = 0 ) { return( base[i] ); };
// Invoke function
void call();
};
// Create a Vargv from a name
Vargv::Vargv( const char *name )
{
im_function *f = im_find_function( (char *) name );
if( !f )
verror();
fn = f;
base = new im_object[ fn->argc ];
if( im_allocate_vargv( fn, base ) ) {
delete[] base;
verror();
}
}
// Destroy a Vargv
Vargv::~Vargv()
{
im_free_vargv( fn, base );
delete[] base;
}
// Call the function
void
Vargv::call()
{
if( fn->disp( base ) )
verror();
}
/* Insert automatically generated wrappers for VIPS image processing
* functions.
*/
#include "vipsc++.cc"