libvips/libvips/deprecated/rw_mask.c

1089 lines
23 KiB
C

/* read and write masks
*/
/* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 29/04/1991
* Modified on: 10/8/1992, J.Cupitt
* - Mask reading routines no longer fail if scale and offset are missing.
* Instead, they set default values of scale=1, offset=0.
* - Code tidied up, better error recovery.
* - Bugs fixed in im_dup_*mask. No longer coredump.
* - Bugs fixed in im_write_*mask. Now work for non-square matricies.
* - im_copy_*mask_matrix, im_copy_matrix_*mask added: copy VIPS mask
* structures into Numerical Recipies in C style matricies and vice
* versa. Both structures should have been built before copy attempted.
* See im_create_*mask, im_*mat_alloc. The matrix should be indexed by 0
* to size-1.
* 9/7/93 JC
* - some ANSIfication and tidies
* - im_free_*mask() now return zero, so they can be used as close
* callbacks.
* 7/10/94 JC
* - new IM_NEW(), IM_ARRAY() macros added
* 27/4/95 JC
* - oops! forgot to init IM_ARRAY() memory to zero
* 7/8/96 JC
* - im_scale_dmask() rewritten
* 7/5/98 JC
* - im_read_*mask() rewritten, now more robust
* - im_write_*mask() rewritten
* - new functions im_write_*mask_name()
* 28/7/99 JC
* - im_create_imaskv(), im_create_dmaskv() make masks and init from
* varargs
* - tabs allowed as column separators
* 9/2/05
* - "," allowed as column separator ... helps CSV read
* 31/5/06
* - use g_ascii_strtod() and friends
* 2006-09-08 tcv
* - add im_norm_dmask()
* 1/9/09
* - move im_print_*mask() here
* 12/11/09
* - reading a float mask with im_read_imask() produced an incorrect
* error messagge
* 21/10/10
* - gtk-doc
* - you can use commas to separate header fields
* - small cleanups
* 30/11/10
* - im_scale_dmask() normalises to 20, not 100 ... we hit the fast
* conv path more often
* 24/1/10
* - oops, missing braces in write dmask removed spaces between items
*/
/*
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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <glib/gi18n-lib.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/vips7compat.h>
/**
* INTMASK:
* @xsize: mask width
* @ysize: mask height
* @scale: mask scale factor
* @offset: mask offset
* @coeff: array of mask elements
* @filename: the file this mask was read from, or should be written to
*
* An integer mask.
*
* @scale lets the mask represent fractional values: for
* example, in integer convolution (see im_conv()) the result of the
* convolution is divided by @scale and then added to @offset before being
* written to the output image.
*
* @scale and @offset default to 1 and 0. Various functions, such as
* im_conv(), will fail if @scale is zero.
*
* You can read and write the matrix elements in @coeff.
*/
/**
* DOUBLEMASK:
* @xsize: mask width
* @ysize: mask height
* @scale: mask scale factor
* @offset: mask offset
* @coeff: array of mask elements
* @filename: the file this mask was read from, or should be written to
*
* A floating-point mask.
*
* As with #INTMASK, in convolution (see im_convf()) the result of the
* convolution is divided by @scale and then added to @offset before being
* written to the output image.
*
* @scale and @offset default to 1.0 and 0.0. Various functions, such as
* im_conv(), will fail if @scale is zero.
*
* You can read and write the matrix elements in @coeff.
*/
/* Size of line buffer for reading.
*/
#define MAX_LINE (32768)
/**
* im_free_imask:
* @in: mask to free
*
* Free mask structure and any attached arrays. Return zero, so we can use
* these functions as close callbacks.
*
* See also: im_free_dmask().
*
* Returns: zero.
*/
int
im_free_imask( INTMASK *in )
{
if( !in )
return( 0 );
IM_FREE( in->coeff );
IM_FREE( in->filename );
IM_FREE( in );
return( 0 );
}
/**
* im_free_dmask:
* @in: mask to free
*
* Free mask structure and any attached arrays. Return zero, so we can use
* these functions as close callbacks.
*
* See also: im_free_dmask().
*
* Returns: zero.
*/
int
im_free_dmask( DOUBLEMASK *in )
{
if( !in )
return( 0 );
IM_FREE( in->coeff );
IM_FREE( in->filename );
IM_FREE( in );
return( 0 );
}
/**
* im_create_imask:
* @filename: set mask filename to this
* @xsize: mask width
* @ysize: mask height
*
* Create an empty imask. You need to loop over @coeff to set the values.
*
* See also: im_create_imaskv().
*
* Returns: The newly-allocated mask.
*/
INTMASK *
im_create_imask( const char *filename, int xsize, int ysize )
{
INTMASK *out;
int size = xsize * ysize;
/* Check args.
*/
if( xsize <= 0 || ysize <= 0 || filename == NULL ) {
im_error( "im_create_imask", "%s", _( "bad arguments" ) );
return( NULL );
}
/* Allocate and initialise structure.
*/
if( !(out = IM_NEW( NULL, INTMASK )) )
return( NULL );
out->coeff = NULL;
out->filename = NULL;
out->scale = 1;
out->offset = 0;
out->xsize = 0;
out->ysize = 0;
if( !(out->coeff = IM_ARRAY( NULL, size, int )) ) {
im_free_imask( out );
return( NULL );
}
(void) memset( (char *) out->coeff, 0, size * sizeof( int ) );
if( !(out->filename = im_strdup( NULL, filename )) ) {
im_free_imask( out );
return( NULL );
}
out->xsize = xsize;
out->ysize = ysize;
return( out );
}
/**
* im_create_imaskv:
* @filename: set mask filename to this
* @xsize: mask width
* @ysize: mask height
* @...: values to set for the mask
*
* Create an imask and initialise it from the function parameter list.
*
* See also: im_create_imask().
*
* Returns: The newly-allocated mask.
*/
INTMASK *
im_create_imaskv( const char *filename, int xsize, int ysize, ... )
{
va_list ap;
INTMASK *out;
int i;
if( !(out = im_create_imask( filename, xsize, ysize )) )
return( NULL );
va_start( ap, ysize );
for( i = 0; i < xsize * ysize; i++ )
out->coeff[i] = va_arg( ap, int );
va_end( ap );
return( out );
}
/**
* im_create_dmask:
* @filename: set mask filename to this
* @xsize: mask width
* @ysize: mask height
*
* Create an empty dmask. You need to loop over @coeff to set the values.
*
* See also: im_create_dmaskv(), im_vips2mask().
*
* Returns: The newly-allocated mask.
*/
DOUBLEMASK *
im_create_dmask( const char *filename, int xsize, int ysize )
{
DOUBLEMASK *out;
int size = xsize * ysize;
/* Check args.
*/
if( xsize <= 0 || ysize <= 0 || filename == NULL ) {
im_error( "im_create_dmask", "%s", _( "bad arguments" ) );
return( NULL );
}
/* Allocate and initialise structure.
*/
if( !(out = IM_NEW( NULL, DOUBLEMASK )) )
return( NULL );
out->coeff = NULL;
out->filename = NULL;
out->scale = 1.0;
out->offset = 0.0;
out->xsize = 0;
out->ysize = 0;
if( !(out->coeff = IM_ARRAY( NULL, size, double )) ) {
im_free_dmask( out );
return( NULL );
}
(void) memset( (char *) out->coeff, 0, size * sizeof( double ) );
if( !(out->filename = im_strdup( NULL, filename )) ) {
im_free_dmask( out );
return( NULL );
}
out->xsize = xsize;
out->ysize = ysize;
return( out );
}
/**
* im_create_dmaskv:
* @filename: set mask filename to this
* @xsize: mask width
* @ysize: mask height
* @...: values to set for the mask
*
* Create a dmask and initialise it from the function parameter list.
*
* See also: im_create_dmask().
*
* Returns: The newly-allocated mask.
*/
DOUBLEMASK *
im_create_dmaskv( const char *filename, int xsize, int ysize, ... )
{
va_list ap;
DOUBLEMASK *out;
int i;
if( !(out = im_create_dmask( filename, xsize, ysize )) )
return( NULL );
va_start( ap, ysize );
for( i = 0; i < xsize * ysize; i++ )
out->coeff[i] = va_arg( ap, double );
va_end( ap );
return( out );
}
/* Read a line from a file!
*/
static int
get_line( FILE *fp, char *buf )
{
if( !fgets( buf, MAX_LINE, fp ) ) {
im_error( "read_mask", "%s", _( "unexpected EOF" ) );
return( -1 );
}
return( 0 );
}
/* width, height, optional scale, optional offset.
*/
static int
read_header( FILE *fp, int *xs, int *ys, double *scale, double *offset )
{
char buf[MAX_LINE];
char *p, *q;
double v[4];
int i;
/* Read the first line: should contain size and optional
* scale + offset.
*/
if( get_line( fp, buf ) )
return( -1 );
/* Read as space separated doubles. \n is in the break list because
* our line will (usually) have a trailing \n which we want to count
* as whitespace.
*/
p = buf;
for( i = 0, p = buf;
i < 4 && (q = im_break_token( p, " \";,\t\n" ));
i++, p = q )
v[i] = g_ascii_strtod( p, NULL );
if( (i != 2 && i != 4) ||
ceil( v[0] ) != v[0] ||
ceil( v[1] ) != v[1] ||
v[0] <= 0 ||
v[1] <= 0 ) {
im_error( "read_header",
"%s", _( "error reading matrix header" ) );
return( -1 );
}
if( i == 4 && v[2] == 0 ) {
im_error( "read_header",
"%s", _( "scale should be non-zero" ) );
return( -1 );
}
*xs = v[0];
*ys = v[1];
if( i == 2 ) {
*scale = 1.0;
*offset = 0.0;
}
else {
*scale = v[2];
*offset = v[3];
}
return( 0 );
}
/**
* im_read_dmask:
* @filename: read matrix from this file
*
* Reads a matrix from a file.
*
* Matrix files have a simple format that's supposed to be easy to create with
* a text editor or a spreadsheet.
*
* The first line has four numbers for width, height, scale and
* offset (scale and offset may be omitted, in which case they default to 1.0
* and 0.0). Scale must be non-zero. Width and height must be positive
* integers. The numbers are separated by any mixture of spaces, commas,
* tabs and quotation marks ("). The scale and offset fields may be
* floating-point, and must use '.'
* as a decimal separator.
*
* Subsequent lines each hold one line of matrix data, with numbers again
* separated by any mixture of spaces, commas,
* tabs and quotation marks ("). The numbers may be floating-point, and must
* use '.'
* as a decimal separator.
*
* Extra characters at the ends of lines or at the end of the file are
* ignored.
*
* See also: im_read_imask(), im_gauss_dmask().
*
* Returns: the loaded mask on success, or NULL on error.
*/
DOUBLEMASK *
im_read_dmask( const char *filename )
{
FILE *fp;
double sc, off;
int xs, ys;
DOUBLEMASK *out;
int x, y, i;
char buf[MAX_LINE];
if( !(fp = im__file_open_read( filename, NULL, TRUE )) )
return( NULL );
if( read_header( fp, &xs, &ys, &sc, &off ) ) {
fclose( fp );
return( NULL );
}
if( !(out = im_create_dmask( filename, xs, ys )) ) {
fclose( fp );
return( NULL );
}
out->scale = sc;
out->offset = off;
for( i = 0, y = 0; y < ys; y++ ) {
char *p;
if( get_line( fp, buf ) ) {
im_free_dmask( out );
fclose( fp );
return( NULL );
}
for( p = buf, x = 0; p && x < xs;
x++, i++, p = im_break_token( p, " \t,\";" ) )
out->coeff[i] = g_ascii_strtod( p, NULL );
}
fclose( fp );
return( out );
}
/**
* im_read_imask:
* @filename: read matrix from this file
*
* Reads an integer matrix from a file.
*
* This function works exactly as im_read_dmask(), but the loaded matrix is
* checked for 'int-ness'. All coefficients must be integers, and scale and
* offset must be integers.
*
* See also: im_read_dmask().
*
* Returns: the loaded mask on success, or NULL on error.
*/
INTMASK *
im_read_imask( const char *filename )
{
DOUBLEMASK *dmask;
INTMASK *imask;
int i;
if( !(dmask = im_read_dmask( filename )) )
return( NULL );
if( ceil( dmask->scale ) != dmask->scale ||
ceil( dmask->offset ) != dmask->offset ) {
im_error( "im_read_imask",
"%s", _( "scale and offset should be int" ) );
im_free_dmask( dmask );
return( NULL );
}
for( i = 0; i < dmask->xsize * dmask->ysize; i++ )
if( ceil( dmask->coeff[i] ) != dmask->coeff[i] ) {
im_error( "im_read_imask", _( "ceofficient at "
"position (%d, %d) is not int" ),
i % dmask->xsize,
i / dmask->xsize );
im_free_dmask( dmask );
return( NULL );
}
if( !(imask = im_create_imask( filename,
dmask->xsize, dmask->ysize )) ) {
im_free_dmask( dmask );
return( NULL );
}
imask->scale = dmask->scale;
imask->offset = dmask->offset;
for( i = 0; i < dmask->xsize * dmask->ysize; i++ )
imask->coeff[i] = dmask->coeff[i];
im_free_dmask( dmask );
return( imask );
}
/**
* im_scale_dmask:
* @in: mask to scale
* @filename: filename for returned mask
*
* Scale the dmask to make an imask with a maximum value of 20.
*
* See also: im_norm_dmask().
*
* Returns: the converted mask, or NULL on error.
*/
INTMASK *
im_scale_dmask( DOUBLEMASK *in, const char *filename )
{
const int size = in->xsize * in->ysize;
INTMASK *out;
double maxval, dsum;
int i;
int isum;
if( im_check_dmask( "im_scale_dmask", in ) ||
!(out = im_create_imask( filename, in->xsize, in->ysize )) )
return( NULL );
/* Find mask max.
*/
maxval = in->coeff[0];
for( i = 0; i < size; i++ )
if( in->coeff[i] > maxval )
maxval = in->coeff[i];
/* Copy and scale, setting max to 20.
*/
for( i = 0; i < size; i++ )
out->coeff[i] = IM_RINT( in->coeff[i] * 20.0 / maxval );
out->offset = in->offset;
/* Set the scale to match the adjustment to max.
*/
isum = 0;
dsum = 0.0;
for( i = 0; i < size; i++ ) {
isum += out->coeff[i];
dsum += in->coeff[i];
}
if( dsum == in->scale )
out->scale = isum;
else if( dsum == 0.0 )
out->scale = 1.0;
else
out->scale = IM_RINT( in->scale * isum / dsum );
return( out );
}
/**
* im_dmask2imask:
* @in: mask to convert
* @filename: filename for returned mask
*
* 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 )
{
const int n = mask->xsize * mask->ysize;
const double scale = (mask->scale == 0) ? 0 : (1.0 / mask->scale);
int i;
if( im_check_dmask( "im_norm_dmask", mask ) ||
(1.0 == scale && 0.0 == mask->offset) )
return;
for( i = 0; i < n; i++ )
mask->coeff[i] = mask->coeff[i] * scale + mask->offset;
mask->scale = 1.0;
mask->offset = 0.0;
}
/**
* im_dup_imask:
* @in: mask to duplicate
* @filename: filename to set for the new mask
*
* Duplicate an imask.
*
* See also: im_dup_dmask().
*
* Returns: the mask copy, or NULL on error.
*/
INTMASK *
im_dup_imask( INTMASK *in, const char *filename )
{
INTMASK *out;
int i;
if( im_check_imask( "im_dup_imask", in ) ||
!(out = im_create_imask( filename, in->xsize, in->ysize )) )
return( NULL );
out->offset = in->offset;
out->scale = in->scale;
for( i = 0; i < in->xsize * in->ysize; i++ )
out->coeff[i] = in->coeff[i];
return( out );
}
/**
* im_dup_dmask:
* @in: mask to duplicate
* @filename: filename to set for the new mask
*
* Duplicate a dmask.
*
* See also: im_dup_imask().
*
* Returns: the mask copy, or NULL on error.
*/
DOUBLEMASK *
im_dup_dmask( DOUBLEMASK *in, const char *filename )
{
DOUBLEMASK *out;
int i;
if( im_check_dmask( "im_dup_dmask", in ) ||
!(out = im_create_dmask( filename, in->xsize, in->ysize )) )
return( NULL );
out->offset = in->offset;
out->scale = in->scale;
for( i = 0; i < in->xsize * in->ysize; i++ )
out->coeff[i] = in->coeff[i];
return( out );
}
/* Write to file.
*/
static int
write_line( FILE *fp, const char *fmt, ... )
{
va_list ap;
va_start( ap, fmt );
if( !vfprintf( fp, fmt, ap ) ) {
im_error( "write_mask", "%s", _( "write error, disc full?" ) );
return( -1 );
}
va_end( ap );
return( 0 );
}
static int
write_double( FILE *fp, double d )
{
char buf[G_ASCII_DTOSTR_BUF_SIZE];
fprintf( fp, "%s", g_ascii_dtostr( buf, sizeof( buf ), d ) );
return( 0 );
}
/**
* im_write_imask_name:
* @in: mask to write
* @filename: filename to write to
*
* Write an imask to a file. See im_read_dmask() for a description of the mask
* file format.
*
* See also: im_write_imask().
*
* Returns: 0 on success, or -1 on error.
*/
int
im_write_imask_name( INTMASK *in, const char *filename )
{
FILE *fp;
int x, y, i;
if( im_check_imask( "im_write_imask_name", in ) ||
!(fp = im__file_open_write( filename, TRUE )) )
return( -1 );
if( write_line( fp, "%d %d", in->xsize, in->ysize ) ) {
fclose( fp );
return( -1 );
}
if( in->scale != 1 || in->offset != 0 )
write_line( fp, " %d %d", in->scale, in->offset );
write_line( fp, "\n" );
for( i = 0, y = 0; y < in->ysize; y++ ) {
for( x = 0; x < in->xsize; x++, i++ )
write_line( fp, "%d ", in->coeff[i] );
if( write_line( fp, "\n" ) ) {
fclose( fp );
return( -1 );
}
}
fclose( fp );
return( 0 );
}
/**
* im_write_imask:
* @in: mask to write
*
* Write an imask to a file.
*
* See also: im_write_imask_name().
*
* Returns: 0 on success, or -1 on error.
*/
int
im_write_imask( INTMASK *in )
{
if( !in->filename ) {
im_error( "im_write_imask", "%s", _( "filename not set" ) );
return( -1 );
}
return( im_write_imask_name( in, in->filename ) );
}
/**
* im_write_dmask_name:
* @in: mask to write
* @filename: filename to write to
*
* Write a dmask to a file. See im_read_dmask() for a description of the mask
* file format.
*
* See also: im_write_dmask().
*
* Returns: 0 on success, or -1 on error.
*/
int
im_write_dmask_name( DOUBLEMASK *in, const char *filename )
{
FILE *fp;
int x, y, i;
if( im_check_dmask( "im_write_dmask_name", in ) ||
!(fp = im__file_open_write( filename, TRUE )) )
return( -1 );
if( write_line( fp, "%d %d", in->xsize, in->ysize ) ) {
fclose( fp );
return( -1 );
}
if( in->scale != 1.0 || in->offset != 0.0 ) {
write_line( fp, " " );
write_double( fp, in->scale );
write_line( fp, " " );
write_double( fp, in->offset );
}
write_line( fp, "\n" );
for( i = 0, y = 0; y < in->ysize; y++ ) {
for( x = 0; x < in->xsize; x++, i++ ) {
write_double( fp, in->coeff[i] );
write_line( fp, " " );
}
if( write_line( fp, "\n" ) ) {
fclose( fp );
return( -1 );
}
}
fclose( fp );
return( 0 );
}
/**
* im_write_dmask:
* @in: mask to write
*
* Write a dmask to a file. See im_read_dmask() for a description of the mask
* file format.
*
* See also: im_write_dmask_name().
*
* Returns: 0 on success, or -1 on error.
*/
int
im_write_dmask( DOUBLEMASK *in )
{
if( !in->filename ) {
im_error( "im_write_dmask", "%s", _( "filename not set" ) );
return( -1 );
}
return( im_write_dmask_name( in, in->filename ) );
}
/* Copy an imask into a matrix. Only used internally by matrix package for
* invert.
*/
void
im_copy_imask_matrix( INTMASK *mask, int **matrix )
{
int x, y;
int *p = mask->coeff;
for( y = 0; y < mask->ysize; y++ )
for( x = 0; x < mask->xsize; x++ )
matrix[x][y] = *p++;
}
/* Copy a matrix into an imask.
*/
void
im_copy_matrix_imask( int **matrix, INTMASK *mask )
{
int x, y;
int *p = mask->coeff;
for( y = 0; y < mask->ysize; y++ )
for( x = 0; x < mask->xsize; x++ )
*p++ = matrix[x][y];
}
/* Copy a dmask into a matrix.
*/
void
im_copy_dmask_matrix( DOUBLEMASK *mask, double **matrix )
{
int x, y;
double *p = mask->coeff;
for( y = 0; y < mask->ysize; y++ )
for( x = 0; x < mask->xsize; x++ )
matrix[x][y] = *p++;
}
/* Copy a matrix to a dmask.
*/
void
im_copy_matrix_dmask( double **matrix, DOUBLEMASK *mask )
{
int x, y;
double *p = mask->coeff;
for( y = 0; y < mask->ysize; y++ )
for( x = 0; x < mask->xsize; x++ )
*p++ = matrix[x][y];
}
/**
* im_print_imask:
* @in: mask to print
*
* Print an imask to stdout.
*
* See also: im_print_dmask().
*/
void
im_print_imask( INTMASK *in )
{
int i, j, k;
printf( "%s: %d %d %d %d\n",
in->filename, in->xsize, in->ysize, in->scale, in->offset );
for( k = 0, j = 0; j < in->ysize; j++ ) {
for( i = 0; i < in->xsize; i++, k++ )
printf( "%d\t", in->coeff[k] );
printf( "\n" );
}
}
/**
* im_print_dmask:
* @in: mask to print
*
* Print a dmask to stdout.
*
* See also: im_print_imask().
*/
void
im_print_dmask( DOUBLEMASK *in )
{
int i, j, k;
printf( "%s: %d %d %f %f\n",
in->filename, in->xsize, in->ysize, in->scale, in->offset );
for( k = 0, j = 0; j < in->ysize; j++ ) {
for( i = 0; i < in->xsize; i++, k++ )
printf( "%f\t", in->coeff[k] );
printf( "\n" );
}
}
/**
* im_local_dmask:
* @out: image to make the mask local to
* @mask: mask to local-ize
*
* @out takes ownership of @mask: when @out is closed, @mask will be closed
* for you. If im_local_dmask() itself fails, the mask is also freed.
*
* See also: im_local_imask().
*
* Returns: the mask, or NULL on error.
*/
DOUBLEMASK *
im_local_dmask( VipsImage *out, DOUBLEMASK *mask )
{
if( im_check_dmask( "im_local_dmask", mask ) )
return( NULL );
if( im_add_close_callback( out,
(im_callback_fn) im_free_dmask, mask, NULL ) ) {
im_free_dmask( mask );
return( NULL );
}
return( mask );
}
/**
* im_local_imask:
* @out: image to make the mask local to
* @mask: mask to local-ize
*
* @out takes ownership of @mask: when @out is closed, @mask will be closed
* for you. If im_local_imask() itself fails, the mask is also freed.
*
* See also: im_local_dmask().
*
* Returns: the mask, or NULL on error.
*/
INTMASK *
im_local_imask( VipsImage *out, INTMASK *mask )
{
if( im_check_imask( "im_local_dmask", mask ) )
return( NULL );
if( im_add_close_callback( out,
(im_callback_fn) im_free_imask, mask, NULL ) ) {
im_free_imask( mask );
return( NULL );
}
return( mask );
}