split vips_new_*() modes up

New modes and properties mean we can use _build() for all the vipsimage init
stuff now.
This commit is contained in:
John Cupitt 2011-03-01 14:49:16 +00:00
parent 17c5ab4383
commit 7257c5426a
14 changed files with 342 additions and 434 deletions

View File

@ -290,7 +290,7 @@ typedef struct _VipsImageClass {
/* An image has been modified in some way and downstream caches all
* need dropping.
*/
int (*invalidate)( VipsImage *image );
void (*invalidate)( VipsImage *image );
} VipsImageClass;
@ -348,11 +348,17 @@ int vips_image_get_yoffset( VipsImage *image );
size_t vips_image_size( VipsImage *image );
void vips_image_written( VipsImage *image );
void vips_image_invalidate_all( VipsImage *image );
void vips_image_preeval( VipsImage *image );
void vips_image_eval( VipsImage *image, int w, int h );
void vips_image_posteval( VipsImage *image );
VipsImage *vips_image_open( const char *filename, const char *mode );
VipsImage *vips_image_new( const char *mode );
VipsImage *vips_image_new_from_file( const char *filename, const char *mode );
VipsImage *vips_image_new_from_file_raw( const char *filename,
int xsize, int ysize, int bands, int offset );
VipsImage *vips_image_new_from_memory( void *buffer,
int xsize, int ysize, int bands, VipsBandFormat bandfmt );
gboolean vips_image_isMSBfirst( VipsImage *image );
gboolean vips_image_isfile( VipsImage *image );

View File

@ -80,7 +80,7 @@ typedef int (*im__fftproc_fn)( VipsImage *, VipsImage *, VipsImage * );
/* iofuncs
*/
int vips_open_input( VipsImage *image );
int vips_open_input_rw( VipsImage *image );
int vips_image_open_input( VipsImage *image );
int im_mapfile( VipsImage * );
int im_mapfilerw( VipsImage * );

View File

@ -96,7 +96,7 @@ void im_region_copy( REGION *reg, REGION *dest, Rect *r, int x, int y );
#define IM_REGION_N_ELEMENTS(R) \
((size_t)((R)->valid.width * (R)->im->Bands))
#define IM_REGION_SIZEOF_LINE(R) \
((size_t)((R)->valid.width * IM_IMAGE_SIZEOF_PEL((R)->im)))
((size_t)((R)->valid.width * VIPS_IMAGE_SIZEOF_PEL((R)->im)))
/* If DEBUG is defined, add bounds checking.
*/
@ -104,7 +104,7 @@ void im_region_copy( REGION *reg, REGION *dest, Rect *r, int x, int y );
#define IM_REGION_ADDR(R,X,Y) \
( (im_rect_includespoint( &(R)->valid, (X), (Y) ))? \
((R)->data + ((Y) - (R)->valid.top) * IM_REGION_LSKIP(R) + \
((X) - (R)->valid.left) * IM_IMAGE_SIZEOF_PEL((R)->im)): \
((X) - (R)->valid.left) * VIPS_IMAGE_SIZEOF_PEL((R)->im)): \
(fprintf( stderr, \
"IM_REGION_ADDR: point out of bounds, " \
"file \"%s\", line %d\n" \
@ -122,7 +122,7 @@ void im_region_copy( REGION *reg, REGION *dest, Rect *r, int x, int y );
#define IM_REGION_ADDR(R,X,Y) \
((R)->data + \
((Y)-(R)->valid.top) * IM_REGION_LSKIP(R) + \
((X)-(R)->valid.left) * IM_IMAGE_SIZEOF_PEL((R)->im))
((X)-(R)->valid.left) * VIPS_IMAGE_SIZEOF_PEL((R)->im))
#endif /*DEBUG*/
#define IM_REGION_ADDR_TOPLEFT(R) ( (R)->data )

View File

@ -15,9 +15,7 @@ libiofuncs_la_SOURCES = \
im_demand_hint.c \
im_generate.c \
im_histlin.c \
im_image.c \
im_mapfile.c \
im_partial.c \
im_prepare.c \
im_setbuf.c \
im_setupout.c \

View File

@ -113,7 +113,7 @@ input_image_init( im_object *obj, char *str )
{
IMAGE **im = (IMAGE **) obj;
return( !(*im = vips_image_open( str, "rd" )) );
return( !(*im = vips_image_new_from_file( str, "rd" )) );
}
/* Input image type.
@ -133,7 +133,7 @@ output_image_init( im_object *obj, char *str )
{
IMAGE **im = (IMAGE **) obj;
return( !(*im = vips_image_open( str, "w" )) );
return( !(*im = vips_image_new_from_file( str, "w" )) );
}
/* Output image type.
@ -153,7 +153,7 @@ rw_image_init( im_object *obj, char *str )
{
IMAGE **im = (IMAGE **) obj;
return( !(*im = vips_image_open( str, "rw" )) );
return( !(*im = vips_image_new_from_file( str, "rw" )) );
}
/* RW image type.
@ -215,7 +215,8 @@ input_imagevec_init( im_object *obj, char *str )
iv->vec[i] = NULL;
for( i = 0; i < nargs; i++ )
if( !(iv->vec[i] = vips_image_open( strv[i], "rd" )) ) {
if( !(iv->vec[i] =
vips_image_new_from_file( strv[i], "rd" )) ) {
g_strfreev( strv );
return( -1 );
}

View File

@ -170,7 +170,7 @@ im_cp_descv( IMAGE *out, IMAGE *in1, ... )
;
va_end( ap );
if( i == MAX_IMAGES ) {
im_error( "im_cp_descv",
vips_error( "im_cp_descv",
"%s", _( "too many images" ) );
return( -1 );
}

View File

@ -150,6 +150,19 @@ im__link_map( IMAGE *im, VSListMap2Fn fn, void *a, void *b )
{
static int serial = 0;
/* Invalidate callbacks might do anything, including removing images
* or invalidating other images, so we can't trigger them from within
* the image loop. Instead we collect a list of image to invalidate
* and trigger them all in one go, checking that they are not
* invalidated.
*/
/* im__link_mapp() needs to make the list, ref all the images, call
* the callbacks, then unref and free the list.
*/
FIXME
serial += 1;
return( im__link_mapp( im, fn, &serial, a, b ) );
}
@ -159,7 +172,7 @@ im__link_map( IMAGE *im, VSListMap2Fn fn, void *a, void *b )
static im_demand_type
find_least( im_demand_type a, im_demand_type b )
{
return( (im_demand_type) IM_MIN( (int) a, (int) b ) );
return( (im_demand_type) VIPS_MIN( (int) a, (int) b ) );
}
/**
@ -191,7 +204,7 @@ im_demand_hint_array( IMAGE *im, VipsDemandStyle hint, IMAGE **in )
/* How many input images are there? And how many are IM_ANY?
*/
for( i = 0, len = 0, nany = 0; in[i]; i++, len++ )
if( in[i]->dhint == IM_ANY )
if( in[i]->dhint == VIPS_DEMAND_STYLE_ANY )
nany++;
set_hint = hint;
@ -206,7 +219,7 @@ im_demand_hint_array( IMAGE *im, VipsDemandStyle hint, IMAGE **in )
/* Special case: if all the inputs are IM_ANY, then output can
* be IM_ANY regardless of what this function wants.
*/
set_hint = IM_ANY;
set_hint = VIPS_DEMAND_STYLE_ANY;
else
/* Find the most restrictive of all the hints available to us.
*/
@ -263,7 +276,7 @@ im_demand_hint( IMAGE *im, VipsDemandStyle hint, ... )
;
va_end( ap );
if( i == MAX_IMAGES ) {
im_error( "im_demand_hint", "%s", _( "too many images" ) );
vips_error( "im_demand_hint", "%s", _( "too many images" ) );
return( -1 );
}

View File

@ -207,7 +207,7 @@ im_start_many( IMAGE *out, void *a, void *b )
/* Alocate space for region array.
*/
if( !(ar = IM_ARRAY( NULL, n + 1, REGION * )) )
if( !(ar = VIPS_ARRAY( NULL, n + 1, REGION * )) )
return( NULL );
/* Create a set of regions.
@ -251,7 +251,7 @@ im_allocate_input_array( IMAGE *out, ... )
/* Allocate array.
*/
if( !(ar = IM_ARRAY( out, n + 1, IMAGE * )) )
if( !(ar = VIPS_ARRAY( out, n + 1, IMAGE * )) )
return( NULL );
/* Fill array.
@ -365,13 +365,13 @@ im_generate( IMAGE *im,
g_assert( !im_image_sanity( im ) );
if( !im->hint_set ) {
im_error( "im_generate",
vips_error( "im_generate",
"%s", _( "im_demand_hint() not set" ) );
return( -1 );
}
if( im->Xsize <= 0 || im->Ysize <= 0 || im->Bands <= 0 ) {
im_error( "im_generate",
vips_error( "im_generate",
"%s", _( "bad dimensions" ) );
return( -1 );
}
@ -384,11 +384,11 @@ im_generate( IMAGE *im,
/* Look at output type to decide our action.
*/
switch( im->dtype ) {
case IM_PARTIAL:
case VIPS_IMAGE_PARTIAL:
/* Output to partial image. Just attach functions and return.
*/
if( im->generate || im->start || im->stop ) {
im_error( "im_generate",
vips_error( "im_generate",
"%s", _( "func already attached" ) );
return( -1 );
}
@ -405,14 +405,14 @@ im_generate( IMAGE *im,
break;
case IM_SETBUF:
case IM_SETBUF_FOREIGN:
case IM_MMAPINRW:
case IM_OPENOUT:
case VIPS_IMAGE_SETBUF:
case VIPS_IMAGE_SETBUF_FOREIGN:
case VIPS_IMAGE_MMAPINRW:
case VIPS_IMAGE_OPENOUT:
/* Eval now .. sanity check.
*/
if( im->generate || im->start || im->stop ) {
im_error( "im_generate",
vips_error( "im_generate",
"%s", _( "func already attached" ) );
return( -1 );
}
@ -430,7 +430,7 @@ im_generate( IMAGE *im,
im->client1 = a;
im->client2 = b;
if( im->dtype == IM_OPENOUT )
if( im->dtype == VIPS_IMAGE_OPENOUT )
res = vips_sink_disc( im,
(VipsRegionWrite) write_vips, NULL );
else
@ -446,15 +446,12 @@ im_generate( IMAGE *im,
default:
/* Not a known output style.
*/
im_error( "im_generate", _( "unable to output to a %s image" ),
vips_error( "im_generate", _( "unable to output to a %s image" ),
im_dtype2char( im->dtype ) );
return( -1 );
}
/* Successful write: trigger "written".
*/
if( im__trigger_callbacks( im->writtenfns ) )
return( -1 );
vips_image_written( im );
return( 0 );
}

View File

@ -1,102 +0,0 @@
/* im_image.c ... area of memory as an image
*
* Written on: 11/7/00
* Modified on:
* 20/3/01 JC
* - oops, broken for IM_BANDFMT_UCHAR
*/
/*
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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/**
* im_image:
* @buffer: start of memory area
* @xsize: image width
* @ysize: image height
* @bands: image bands (or bytes per pixel)
* @bandfmt: image format
*
* This function wraps an #IMAGE around a memory buffer. VIPS does not take
* responsibility for the area of memory, it's up to you to make sure it's
* freed when the image is closed. See for example im_add_close_callback().
*
* See also: im_binfile(), im_raw2vips(), im_open().
*
* Returns: the new #IMAGE, or %NULL on error.
*/
IMAGE *
im_image( void *buffer, int xsize, int ysize, int bands, VipsBandFmt bandfmt )
{
IMAGE *im;
if( xsize <= 0 || ysize <= 0 || bands <= 0 ||
bandfmt < 0 || bandfmt > IM_BANDFMT_DPCOMPLEX ) {
im_error( "im_image", "%s", _( "bad parameters" ) );
return( NULL );
}
/* Make new output image for us.
*/
if( !(im = im_init( "untitled" )) )
return( NULL );
/* Set header fields.
*/
im->Xsize = xsize;
im->Ysize = ysize;
im->Bands = bands;
im->BandFmt = bandfmt;
im->Bbits = im_bits_of_fmt( bandfmt );
im->Coding = IM_CODING_NONE;
if( bands == 1 )
im->Type = IM_TYPE_B_W;
else if( bands == 3 )
im->Type = IM_TYPE_RGB;
else
im->Type = IM_TYPE_MULTIBAND;
im->data = (char *) buffer;
im->dtype = IM_SETBUF_FOREIGN;
return( im );
}

View File

@ -138,17 +138,17 @@ im__mmap( int fd, int writeable, size_t length, gint64 offset )
if( !(hMMFile = CreateFileMapping( hFile,
NULL, flProtect, 0, 0, NULL )) ) {
im_error_system( GetLastError(), "im_mapfile",
vips_error_system( GetLastError(), "im_mapfile",
"%s", _( "unable to CreateFileMapping" ) );
printf( "CreateFileMapping failed: %s\n", im_error_buffer() );
printf( "CreateFileMapping failed: %s\n", vips_error_buffer() );
return( NULL );
}
if( !(baseaddr = (char *)MapViewOfFile( hMMFile, dwDesiredAccess,
dwFileOffsetHigh, dwFileOffsetLow, length )) ) {
im_error_system( GetLastError(), "im_mapfile",
vips_error_system( GetLastError(), "im_mapfile",
"%s", _( "unable to MapViewOfFile" ) );
printf( "MapViewOfFile failed: %s\n", im_error_buffer() );
printf( "MapViewOfFile failed: %s\n", vips_error_buffer() );
CloseHandle( hMMFile );
return( NULL );
}
@ -186,9 +186,9 @@ im__mmap( int fd, int writeable, size_t length, gint64 offset )
baseaddr = mmap( 0, length, prot, MAP_SHARED, fd, (off_t) offset );
if( baseaddr == MAP_FAILED ) {
im_error_system( errno, "im_mapfile",
vips_error_system( errno, "im_mapfile",
"%s", _( "unable to mmap" ) );
im_warn( "im_mapfile", _( "map failed (%s), "
vips_warn( "im_mapfile", _( "map failed (%s), "
"running very low on system resources, "
"expect a crash soon" ), strerror( errno ) );
return( NULL );
@ -204,13 +204,13 @@ im__munmap( void *start, size_t length )
{
#ifdef OS_WIN32
if( !UnmapViewOfFile( start ) ) {
im_error_system( GetLastError(), "im_mapfile",
vips_error_system( GetLastError(), "im_mapfile",
"%s", _( "unable to UnmapViewOfFile" ) );
return( -1 );
}
#else /*!OS_WIN32*/
if( munmap( start, length ) < 0 ) {
im_error_system( errno, "im_mapfile",
vips_error_system( errno, "im_mapfile",
"%s", _( "unable to munmap file" ) );
return( -1 );
}
@ -232,18 +232,18 @@ im_mapfile( IMAGE *im )
*/
g_assert( im->file_length > 0 );
if( im->file_length < 64 ) {
im_error( "im_mapfile",
vips_error( "im_mapfile",
"%s", _( "file is less than 64 bytes" ) );
return( -1 );
}
if( fstat( im->fd, &st ) == -1 ) {
im_error( "im_mapfile",
vips_error( "im_mapfile",
"%s", _( "unable to get file status" ) );
return( -1 );
}
m = (mode_t) st.st_mode;
if( !S_ISREG( m ) ) {
im_error( "im_mapfile",
vips_error( "im_mapfile",
"%s", _( "not a regular file" ) );
return( -1 );
}
@ -271,13 +271,13 @@ im_mapfilerw( IMAGE *im )
*/
g_assert( im->file_length > 0 );
if( fstat( im->fd, &st ) == -1 ) {
im_error( "im_mapfilerw",
vips_error( "im_mapfilerw",
"%s", _( "unable to get file status" ) );
return( -1 );
}
m = (mode_t) st.st_mode;
if( im->file_length < 64 || !S_ISREG( m ) ) {
im_error( "im_mapfile",
vips_error( "im_mapfile",
"%s", _( "unable to read data" ) );
return( -1 );
}
@ -305,19 +305,19 @@ im_remapfilerw( IMAGE *image )
if( !(hMMFile = CreateFileMapping( hFile,
NULL, PAGE_READWRITE, 0, 0, NULL )) ) {
im_error_system( GetLastError(), "im_mapfile",
vips_error_system( GetLastError(), "im_mapfile",
"%s", _( "unable to CreateFileMapping" ) );
return( -1 );
}
if( !UnmapViewOfFile( image->baseaddr ) ) {
im_error_system( GetLastError(), "im_mapfile",
vips_error_system( GetLastError(), "im_mapfile",
"%s", _( "unable to UnmapViewOfFile" ) );
return( -1 );
}
if( !(baseaddr = (char *)MapViewOfFileEx( hMMFile, FILE_MAP_WRITE,
0, 0, 0, image->baseaddr )) ) {
im_error_system( GetLastError(), "im_mapfile",
vips_error_system( GetLastError(), "im_mapfile",
"%s", _( "unable to MapViewOfFile" ) );
CloseHandle( hMMFile );
return( -1 );
@ -332,23 +332,23 @@ im_remapfilerw( IMAGE *image )
}
#else /*!OS_WIN32*/
{
assert( image->dtype == IM_MMAPIN );
assert( image->dtype == VIPS_IMAGE_MMAPIN );
baseaddr = mmap( image->baseaddr, image->length,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
image->fd, 0 );
if( baseaddr == (void *)-1 ) {
im_error( "im_mapfile", _( "unable to mmap: \"%s\" - %s" ),
vips_error( "im_mapfile", _( "unable to mmap: \"%s\" - %s" ),
image->filename, strerror( errno ) );
return( -1 );
}
}
#endif /*OS_WIN32*/
image->dtype = IM_MMAPINRW;
image->dtype = VIPS_IMAGE_MMAPINRW;
if( baseaddr != image->baseaddr ) {
im_error( "im_mapfile", _( "unable to mmap \"%s\" to same "
vips_error( "im_mapfile", _( "unable to mmap \"%s\" to same "
"address" ), image->filename );
image->baseaddr = baseaddr;
return( -1 );

View File

@ -1,65 +0,0 @@
/* @(#) im_partial: initialise a partial IMAGE. Just set im->dtype.
* @(#)
* @(#) IMAGE *
* @(#) im_partial( file_name )
* @(#) char *file_name;
* @(#)
*/
/*
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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
IMAGE *
im_partial( const char *filename )
{
IMAGE *im = im_init( filename );
if( !im )
return(NULL);
im->dtype = IM_PARTIAL;
/* No need to set demand style - im_demand_hint() from application
* will do this.
*/
return( im );
}

View File

@ -99,7 +99,7 @@ im__test_kill( IMAGE *im )
/* Has kill been set for this image? If yes, abort evaluation.
*/
if( im->kill ) {
im_error( "im__test_kill", _( "killed for image \"%s\"" ),
vips_error( "im__test_kill", _( "killed for image \"%s\"" ),
im->filename );
return( -1 );
}
@ -162,18 +162,18 @@ im_prepare( REGION *reg, Rect *r )
#endif /*DEBUG*/
switch( im->dtype ) {
case IM_PARTIAL:
case VIPS_IMAGE_PARTIAL:
if( im_region_fill( reg, r,
(im_region_fill_fn) fill_region, NULL ) )
return( -1 );
break;
case IM_SETBUF:
case IM_SETBUF_FOREIGN:
case IM_MMAPIN:
case IM_MMAPINRW:
case IM_OPENIN:
case VIPS_IMAGE_SETBUF:
case VIPS_IMAGE_SETBUF_FOREIGN:
case VIPS_IMAGE_MMAPIN:
case VIPS_IMAGE_MMAPINRW:
case VIPS_IMAGE_OPENIN:
/* Attach to existing buffer.
*/
if( im_region_image( reg, r ) )
@ -182,7 +182,7 @@ im_prepare( REGION *reg, Rect *r )
break;
default:
im_error( "im_prepare", _( "unable to input from a %s image" ),
vips_error( "im_prepare", _( "unable to input from a %s image" ),
im_dtype2char( im->dtype ) );
return( -1 );
}
@ -204,7 +204,7 @@ im_prepare_to_generate( REGION *reg, REGION *dest, Rect *r, int x, int y )
char *p;
if( !im->generate ) {
im_error( "im_prepare_to", "%s", _( "incomplete header" ) );
vips_error( "im_prepare_to", "%s", _( "incomplete header" ) );
return( -1 );
}
@ -271,7 +271,7 @@ im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
if( !dest->data ||
dest->im->BandFmt != reg->im->BandFmt ||
dest->im->Bands != reg->im->Bands ) {
im_error( "im_prepare_to",
vips_error( "im_prepare_to",
"%s", _( "inappropriate region type" ) );
return( -1 );
}
@ -297,7 +297,7 @@ im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
/* Test that dest->valid is large enough.
*/
if( !im_rect_includesrect( &dest->valid, &wanted ) ) {
im_error( "im_prepare_to", "%s", _( "dest too small" ) );
vips_error( "im_prepare_to", "%s", _( "dest too small" ) );
return( -1 );
}
@ -314,7 +314,7 @@ im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
y = clipped2.top;
if( im_rect_isempty( &final ) ) {
im_error( "im_prepare_to",
vips_error( "im_prepare_to",
"%s", _( "valid clipped to nothing" ) );
return( -1 );
}
@ -327,8 +327,8 @@ im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
/* Input or output image type?
*/
switch( im->dtype ) {
case IM_OPENOUT:
case IM_PARTIAL:
case VIPS_IMAGE_OPENOUT:
case VIPS_IMAGE_PARTIAL:
/* We are generating with a sequence.
*/
if( im_prepare_to_generate( reg, dest, &final, x, y ) )
@ -336,9 +336,9 @@ im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
break;
case IM_MMAPIN:
case IM_MMAPINRW:
case IM_OPENIN:
case VIPS_IMAGE_MMAPIN:
case VIPS_IMAGE_MMAPINRW:
case VIPS_IMAGE_OPENIN:
/* Attach to existing buffer and copy to dest.
*/
if( im_region_image( reg, &final ) )
@ -347,8 +347,8 @@ im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
break;
case IM_SETBUF:
case IM_SETBUF_FOREIGN:
case VIPS_IMAGE_SETBUF:
case VIPS_IMAGE_SETBUF_FOREIGN:
/* Could be either input or output. If there is a generate
* function, we are outputting.
*/
@ -365,7 +365,7 @@ im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y )
break;
default:
im_error( "im_prepare_to", _( "unable to input from a "
vips_error( "im_prepare_to", _( "unable to input from a "
"%s image" ), im_dtype2char( im->dtype ) );
return( -1 );
}
@ -390,87 +390,3 @@ im_prepare_many( REGION **reg, Rect *r )
return( 0 );
}
static void *
im_invalidate_region( REGION *reg )
{
reg->invalid = TRUE;
return( NULL );
}
static void *
im_invalidate_image( IMAGE *im, GSList **to_be_invalidated )
{
g_mutex_lock( im->sslock );
(void) im_slist_map2( im->regions,
(VSListMap2Fn) im_invalidate_region, NULL, NULL );
g_mutex_unlock( im->sslock );
*to_be_invalidated = g_slist_prepend( *to_be_invalidated, im );
return( NULL );
}
/* Trigger a callbacks on a list of images, where the callbacks might create
* or destroy the images.
*
* We make a set of temp regions to hold the images open, but when we switch
* to VipsObject we should incr/decr ref count.
*/
static void
im_invalidate_trigger( GSList *images )
{
GSList *regions;
GSList *p;
regions = NULL;
for( p = images; p; p = p->next ) {
IMAGE *im = (IMAGE *) p->data;
regions = g_slist_prepend( regions, im_region_create( im ) );
}
for( p = images; p; p = p->next ) {
IMAGE *im = (IMAGE *) p->data;
(void) im__trigger_callbacks( im->invalidatefns );
}
for( p = regions; p; p = p->next ) {
REGION *r = (REGION *) p->data;
im_region_free( r );
}
g_slist_free( regions );
}
/**
* im_invalidate:
* @im: #IMAGE to invalidate
*
* Invalidate all pixel caches on an #IMAGE and any derived images. The
* "invalidate" callback is triggered for all invalidated images.
*
* See also: im_add_invalidate_callback().
*/
void
im_invalidate( IMAGE *im )
{
GSList *to_be_invalidated;
/* Invalidate callbacks might do anything, including removing images
* or invalidating other images, so we can't trigger them from within
* the image loop. Instead we collect a list of image to invalidate
* and trigger them all in one go, checking that they are not
* invalidated.
*/
to_be_invalidated = NULL;
(void) im__link_map( im,
(VSListMap2Fn) im_invalidate_image, &to_be_invalidated, NULL );
im_invalidate_trigger( to_be_invalidated );
g_slist_free( to_be_invalidated );
}

View File

@ -296,6 +296,8 @@ enum {
PROP_KILL,
PROP_MODE,
PROP_DEMAND,
PROP_SIZEOF_HEADER,
PROP_FOREIGN_BUFFER,
PROP_LAST
};
@ -306,6 +308,7 @@ enum {
SIG_EVAL,
SIG_POSTEVAL,
SIG_WRITTEN,
SIG_INVALIDATE,
SIG_LAST
};
@ -597,7 +600,7 @@ lazy_real_image( Lazy *lazy )
/* Otherwise, fall back to a "p".
*/
if( !real &&
!(real = vips_image_open( lazy->filename, "p" )) )
!(real = vips_image_new( "p" )) )
return( NULL );
return( real );
@ -831,7 +834,7 @@ vips_image_build( VipsObject *object )
else {
VipsImage *x;
if( !(x = vips_image_open( filename, "p" )) )
if( !(x = vips_image_new( "p" )) )
return( -1 );
vips_object_local( image, x );
if( vips_image_open_input( x ) )
@ -871,6 +874,63 @@ vips_image_build( VipsObject *object )
image->dtype = VIPS_IMAGE_PARTIAL;
break;
case 'a':
/* Check parameters.
*/
if( image->sizeof_header < 0 ) {
vips_error( "vips_image_open_raw",
"%s", _( "bad parameters" ) );
return( -1 );
}
if( (image->fd = im__open_image_file( filename )) == -1 )
return( -1 );
image->dtype = VIPS_IMAGE_OPENIN;
image->dhint = VIPS_DEMAND_STYLE_THINSTRIP;
if( image->Bands == 1 )
image->Type = VIPS_INTERPRETATION_B_W;
else if( image->Bands == 3 )
image->Type = VIPS_INTERPRETATION_RGB;
else
image->Type = VIPS_INTERPRETATION_MULTIBAND;
/* Read the real file length and check against what we think
* the size should be.
*/
if( (image->file_length = im_file_length( image->fd )) == -1 )
return( -1 );
/* Very common, so a special message.
*/
if( image->file_length < vips_image_size( image ) ) {
vips_error( "VipsImage",
_( "unable to open %s: file too short" ),
image->filename );
return( -1 );
}
/* Just weird. Only print a warning for this, since we should
* still be able to process it without coredumps.
*/
if( image->file_length > vips_image_size( image ) )
vips_warn( "VipsImage",
_( "%s is longer than expected" ),
image->filename );
break;
case 'm':
if( image->Bands == 1 )
image->Type = VIPS_INTERPRETATION_B_W;
else if( image->Bands == 3 )
image->Type = VIPS_INTERPRETATION_RGB;
else
image->Type = VIPS_INTERPRETATION_MULTIBAND;
image->dtype = VIPS_IMAGE_SETBUF_FOREIGN;
break;
default:
vips_error( "VipsImage", _( "bad mode \"%s\"" ), mode );
@ -887,6 +947,28 @@ vips_image_build( VipsObject *object )
return( 0 );
}
static void *
vips_region_invalidate( REGION *reg )
{
reg->invalid = TRUE;
return( NULL );
}
static void
vips_image_real_invalidate( VipsImage *image )
{
#ifdef DEBUG_VIPS
printf( "vips_image_real_invalidate: " );
vips_object_dump( VIPS_OBJECT( image ) );
#endif /*DEBUG_VIPS*/
g_mutex_lock( image->sslock );
(void) im_slist_map2( image->regions,
(VSListMap2Fn) vips_region_invalidate, NULL, NULL );
g_mutex_unlock( image->sslock );
}
static void
vips_image_class_init( VipsImageClass *class )
{
@ -909,11 +991,13 @@ vips_image_class_init( VipsImageClass *class )
vobject_class->print = vips_image_print;
vobject_class->build = vips_image_build;
class->invalidate = vips_image_real_invalidate;
/* Create properties.
*/
pspec = g_param_spec_int( "width", "Width",
_( "Image width in pixels" ),
0, 1000000, 0,
1, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_WIDTH, pspec );
vips_object_class_install_argument( vobject_class, pspec,
@ -922,7 +1006,7 @@ vips_image_class_init( VipsImageClass *class )
pspec = g_param_spec_int( "height", "Height",
_( "Image height in pixels" ),
0, 1000000, 0,
1, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_HEIGHT, pspec );
vips_object_class_install_argument( vobject_class, pspec,
@ -931,7 +1015,7 @@ vips_image_class_init( VipsImageClass *class )
pspec = g_param_spec_int( "bands", "Bands",
_( "Number of bands in image" ),
0, 1000000, 0,
1, 1000000, 0,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class, PROP_BANDS, pspec );
vips_object_class_install_argument( vobject_class, pspec,
@ -965,7 +1049,7 @@ vips_image_class_init( VipsImageClass *class )
VIPS_ARGUMENT_CONSTRUCT,
G_STRUCT_OFFSET( VipsImage, mode ) );
pspec = g_param_spec_boolean("kill", "Kill",
pspec = g_param_spec_boolean( "kill", "Kill",
_( "Block evaluation on this image" ),
FALSE,
G_PARAM_READWRITE );
@ -983,6 +1067,25 @@ vips_image_class_init( VipsImageClass *class )
VIPS_ARGUMENT_NONE,
G_STRUCT_OFFSET( VipsImage, dhint ) );
pspec = g_param_spec_int( "sizeof_header", "Size of header",
_( "Offset in bytes from start of file" ),
0, 1000000, IM_SIZEOF_HEADER,
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_SIZEOF_HEADER, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE | VIPS_ARGUMENT_CONSTRUCT,
G_STRUCT_OFFSET( VipsImage, sizeof_header ) );
pspec = g_param_spec_pointer( "foreign_buffer", "Foreign buffer",
"Pointer to foreign pixels",
G_PARAM_READWRITE );
g_object_class_install_property( gobject_class,
PROP_FOREIGN_BUFFER, pspec );
vips_object_class_install_argument( vobject_class, pspec,
VIPS_ARGUMENT_SET_ONCE | VIPS_ARGUMENT_CONSTRUCT,
G_STRUCT_OFFSET( VipsImage, data ) );
/* Create signals.
*/
@ -1015,6 +1118,14 @@ vips_image_class_init( VipsImageClass *class )
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0 );
vips_image_signals[SIG_INVALIDATE] = g_signal_new( "invalidate",
G_TYPE_FROM_CLASS( class ),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET( VipsImageClass, invalidate ),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0 );
}
static void
@ -1029,7 +1140,6 @@ vips_image_init( VipsImage *image )
image->magic = im_amiMSBfirst() ? VIPS_MAGIC_SPARC : VIPS_MAGIC_INTEL;
image->fd = -1; /* since 0 is stdout */
image->sizeof_header = IM_SIZEOF_HEADER;
image->sslock = g_mutex_new ();
}
@ -1113,6 +1223,39 @@ vips_image_written( VipsImage *image )
g_signal_emit( image, vips_image_signals[SIG_WRITTEN], 0 );
}
void
vips_image_invalidate( VipsImage *image )
{
#ifdef DEBUG
printf( "vips_image_invalidate: " );
vips_object_print( object );
#endif /*DEBUG*/
g_signal_emit( image, vips_image_signals[SIG_INVALIDATE], 0 );
}
static void *
vips_image_invalidate_all_cb( VipsImage *image )
{
vips_image_invalidate( image );
return( NULL );
}
/**
* vips_image_invalidate_all:
* @image: #VipsImage to invalidate
*
* Invalidate all pixel caches on an @image and any derived images. The
* "invalidate" callback is triggered for all invalidated images.
*/
void
vips_image_invalidate_all( VipsImage *image )
{
(void) im__link_map( image,
(VSListMap2Fn) vips_image_invalidate_all_cb, NULL, NULL );
}
/* Attach a new time struct, if necessary, and reset it.
*/
static int
@ -1202,20 +1345,62 @@ vips_image_posteval( VipsImage *image )
}
/**
* vips_image_open:
* vips_image_new:
* @mode: mode to open with
*
* vips_image_new() examines the mode string and creates an
* appropriate #VipsImage.
*
* <itemizedlist>
* <listitem>
* <para>
* <emphasis>"t"</emphasis>
* creates a temporary memory buffer image.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"p"</emphasis>
* creates a "glue" descriptor you can use to join two image
* processing operations together.
* </para>
* </listitem>
* </itemizedlist>
*
* Returns: the image descriptor on success and NULL on error.
*/
VipsImage *
vips_image_new( const char *mode )
{
VipsImage *image;
image = VIPS_IMAGE( g_object_new( VIPS_TYPE_IMAGE, NULL ) );
g_object_set( image,
"mode", mode,
NULL );
if( vips_object_build( VIPS_OBJECT( image ) ) ) {
VIPS_UNREF( image );
return( NULL );
}
return( image );
}
/**
* vips_image_new_from_file:
* @filename: file to open
* @mode: mode to open with
*
* vips_image_open() examines the mode string, and creates an appropriate
* #VipsImage.
* vips_image_new_from_file() examines the mode string and creates an
* appropriate #VipsImage.
*
* <itemizedlist>
* <listitem>
* <para>
* <emphasis>"r"</emphasis>
* opens the named file for reading. If the file is not in the native
* VIPS format for your machine, vips_image_open() automatically converts the
* file for you in memory.
* VIPS format for your machine, vips_image_new_from_file()
* automatically converts the file for you in memory.
*
* For some large files (eg. TIFF) this may
* not be what you want, it can fill memory very quickly. Instead, you
@ -1223,7 +1408,7 @@ vips_image_posteval( VipsImage *image )
* API and control the loading process yourself. See
* #VipsBandFormat.
*
* vips_image_open() can read files in most formats.
* vips_image_new_from_file() can read files in most formats.
*
* Note that <emphasis>"r"</emphasis> mode works in at least two stages.
* It should return quickly and let you check header fields. It will
@ -1235,9 +1420,9 @@ vips_image_posteval( VipsImage *image )
* <emphasis>"rd"</emphasis>
* opens the named file for reading. If the uncompressed image is larger
* than a threshold and the file format does not support random access,
* rather than uncompressing to memory, vips_image_open() will uncompress to a
* temporary disc file. This file will be automatically deleted when the
* IMAGE is closed.
* rather than uncompressing to memory, vips_image_new_from_file() will
* uncompress to a temporary disc file. This file will be automatically
* deleted when the IMAGE is closed.
*
* See im_system_image() for an explanation of how VIPS selects a
* location for the temporary file.
@ -1264,7 +1449,7 @@ vips_image_posteval( VipsImage *image )
* suffix to determine the type to write -- for example:
*
* |[
* vips_image_open( "fred.tif", "w" )
* vips_image_new_from_file( "fred.tif", "w" )
* ]|
*
* will write in TIFF format.
@ -1272,19 +1457,6 @@ vips_image_posteval( VipsImage *image )
* </listitem>
* <listitem>
* <para>
* <emphasis>"t"</emphasis>
* creates a temporary memory buffer image.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"p"</emphasis>
* creates a "glue" descriptor you can use to join two image
* processing operations together.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"rw"</emphasis>
* opens the named file for reading and writing. This will only work for
* VIPS files in a format native to your machine. It is only for
@ -1296,7 +1468,7 @@ vips_image_posteval( VipsImage *image )
* Returns: the image descriptor on success and NULL on error.
*/
VipsImage *
vips_image_open( const char *filename, const char *mode )
vips_image_new_from_file( const char *filename, const char *mode )
{
VipsImage *image;
@ -1314,7 +1486,7 @@ vips_image_open( const char *filename, const char *mode )
}
/**
* vips_image_open_raw:
* vips_image_new_from_file_raw:
* @filename: filename to open
* @xsize: image width
* @ysize: image height
@ -1327,98 +1499,70 @@ vips_image_open( const char *filename, const char *mode )
* It returns an 8-bit image with @bands bands. If the image is not 8-bit, use
* im_copy_set() to transform the descriptor after loading it.
*
* See also: im_copy_set(), im_raw2vips(), vips_image_open().
* See also: im_copy_set(), im_raw2vips(), vips_image_new_from_file().
*
* Returns: the new #VipsImage, or %NULL on error.
*/
VipsImage *
vips_image_open_raw( const char *filename,
vips_image_new_from_file_raw( const char *filename,
int xsize, int ysize, int bands, int offset )
{
VipsImage *image;
/* Check parameters.
*/
if( xsize <= 0 || ysize <= 0 ||
bands <= 0 || offset <= 0 ) {
vips_error( "vips_image_open_raw",
"%s", _( "bad parameters" ) );
image = VIPS_IMAGE( g_object_new( VIPS_TYPE_IMAGE, NULL ) );
g_object_set( image,
"filename", filename,
"mode", "a",
"width", xsize,
"height", ysize,
"bands", bands,
"sizeof_header", offset,
NULL );
if( vips_object_build( VIPS_OBJECT( image ) ) ) {
VIPS_UNREF( image );
return( NULL );
}
if( !(image = vips_image_open( filename, "p" )) )
return( NULL );
return( image );
}
if( (im->fd = im__open_image_file( name )) == -1 ) {
im_close( im );
return( NULL );
}
im->dtype = IM_OPENIN;
im->sizeof_header = offset;
/**
* vips_image_new_from_memory:
* @buffer: start of memory area
* @xsize: image width
* @ysize: image height
* @bands: image bands (or bytes per pixel)
* @bandfmt: image format
*
* This function wraps an #IMAGE around a memory buffer. VIPS does not take
* responsibility for the area of memory, it's up to you to make sure it's
* freed when the image is closed. See for example im_add_close_callback().
*
* See also: im_binfile(), im_raw2vips(), im_open().
*
* Returns: the new #IMAGE, or %NULL on error.
*/
VipsImage *
vips_image_new_from_memory( void *buffer,
int xsize, int ysize, int bands, VipsBandFormat bandfmt )
{
VipsImage *image;
/* Predict file size.
*/
psize = (gint64) xsize * ysize * bands + offset;
/* Read the real file length and check against what we think
* the size should be.
*/
if( (rsize = im_file_length( im->fd )) == -1 ) {
im_close( im );
return( NULL );
}
im->file_length = rsize;
/* Very common, so a special message.
*/
if( psize > rsize ) {
vips_error( "im_binfile", _( "unable to open %s: "
"file has been truncated" ), im->filename );
im_close( im );
image = VIPS_IMAGE( g_object_new( VIPS_TYPE_IMAGE, NULL ) );
g_object_set( image,
"foreign_buffer", buffer,
"mode", "m",
"width", xsize,
"height", ysize,
"bands", bands,
"format", bandfmt,
NULL );
if( vips_object_build( VIPS_OBJECT( image ) ) ) {
VIPS_UNREF( image );
return( NULL );
}
/* Just wierd. Only print a warning for this, since we should
* still be able to process it without coredumps.
*/
if( psize < rsize )
im_warn( "im_binfile", _( "%s is longer than expected" ),
im->filename );
/* Set header fields.
*/
im->Xsize = xsize;
im->Ysize = ysize;
im->Bands = bands;
/* Set others to standard values.
*/
im->BandFmt = IM_BANDFMT_UCHAR;
im->Bbits = im_bits_of_fmt( im->BandFmt );
im->Coding = IM_CODING_NONE;
if( bands == 1 )
im->Type = IM_TYPE_B_W;
else if( bands == 3 )
im->Type = IM_TYPE_RGB;
else
im->Type = IM_TYPE_MULTIBAND;
im->Xres = 1.0;
im->Yres = 1.0;
im->Length = 0;
im->Compression = 0;
im->Level = 0;
im->Xoffset = 0;
im->Yoffset = 0;
/* Init others too.
*/
im->dhint = IM_THINSTRIP;
return( im );
return( image );
}
/**

View File

@ -902,7 +902,7 @@ im__writehist( IMAGE *im )
/* Open the filename, read the header, some sanity checking.
*/
int
vips_open_input( VipsImage *image )
vips_image_open_input( VipsImage *image )
{
/* We don't use im->sizeof_header here, but we know we're reading a
* VIPS image anyway.