0337c09700
Use GLib's i18n support instead of copying and pasting that logic into its own header. This deprecates the vips/intl.h header in favour of glib/gi18n.h.
248 lines
5.7 KiB
C
248 lines
5.7 KiB
C
/* im_vips2mask
|
|
*
|
|
* Author: J.Cupitt
|
|
* Written on: 6/6/94
|
|
* Modified on:
|
|
*
|
|
* 16/10/06
|
|
* - allow 1xn-band images too
|
|
* 23/2/07
|
|
* - oop, broken for nx1 m-band images
|
|
* - now casts to double for you
|
|
* 1/2/10
|
|
* - gtkdoc
|
|
*/
|
|
|
|
/*
|
|
|
|
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 <string.h>
|
|
|
|
#include <vips/vips.h>
|
|
#include <vips/vips7compat.h>
|
|
|
|
/**
|
|
* im_vips2mask:
|
|
* @in: input image
|
|
* @filename: name for output mask
|
|
*
|
|
* Make a mask from an image. All images are cast to %IM_BANDFMT_DOUBLE
|
|
* before processing. There are two cases for handling bands:
|
|
*
|
|
* If the image has a single band, im_vips2mask() will write a mask the same
|
|
* size as the image.
|
|
*
|
|
* If the image has more than one band, it must be one pixel high or wide. In
|
|
* this case the output mask uses that axis to represent band values.
|
|
*
|
|
* See also: im_mask2vips(), im_measure_area().
|
|
*
|
|
* Returns: a #DOUBLEMASK with @outname set as the name, or NULL on error
|
|
*/
|
|
DOUBLEMASK *
|
|
im_vips2mask( IMAGE *in, const char *filename )
|
|
{
|
|
int width, height;
|
|
DOUBLEMASK *out;
|
|
|
|
/* double* only: cast if necessary.
|
|
*/
|
|
if( in->BandFmt != IM_BANDFMT_DOUBLE ) {
|
|
IMAGE *t;
|
|
|
|
if( !(t = im_open( "im_vips2mask", "p" )) )
|
|
return( NULL );
|
|
if( im_clip2fmt( in, t, IM_BANDFMT_DOUBLE ) ||
|
|
!(out = im_vips2mask( t, filename )) ) {
|
|
im_close( t );
|
|
return( NULL );
|
|
}
|
|
im_close( t );
|
|
|
|
return( out );
|
|
}
|
|
|
|
/* Check the image.
|
|
*/
|
|
if( im_incheck( in ) ||
|
|
im_check_uncoded( "im_vips2mask", in ) )
|
|
return( NULL );
|
|
|
|
if( in->Bands == 1 ) {
|
|
width = in->Xsize;
|
|
height = in->Ysize;
|
|
}
|
|
else if( in->Xsize == 1 ) {
|
|
width = in->Bands;
|
|
height = in->Ysize;
|
|
}
|
|
else if( in->Ysize == 1 ) {
|
|
width = in->Xsize;
|
|
height = in->Bands;
|
|
}
|
|
else {
|
|
im_error( "im_vips2mask",
|
|
"%s", _( "one band, nx1, or 1xn images only" ) );
|
|
return( NULL );
|
|
}
|
|
|
|
if( !(out = im_create_dmask( filename, width, height )) )
|
|
return( NULL );
|
|
if( in->Bands > 1 && in->Ysize == 1 ) {
|
|
double *data = (double *) in->data;
|
|
int x, y;
|
|
|
|
/* Need to transpose: the image is RGBRGBRGB, we need RRRGGGBBB.
|
|
*/
|
|
for( y = 0; y < height; y++ )
|
|
for( x = 0; x < width; x++ )
|
|
out->coeff[x + y * width] =
|
|
data[x * height + y];
|
|
}
|
|
else
|
|
memcpy( out->coeff, in->data,
|
|
width * height * sizeof( double ) );
|
|
|
|
out->scale = vips_image_get_scale( in );
|
|
out->offset = vips_image_get_offset( in );
|
|
|
|
return( out );
|
|
}
|
|
|
|
INTMASK *
|
|
im_vips2imask( IMAGE *in, const char *filename )
|
|
{
|
|
int width, height;
|
|
INTMASK *out;
|
|
|
|
double *data;
|
|
int x, y;
|
|
double double_result;
|
|
int int_result;
|
|
|
|
/* double* only: cast if necessary.
|
|
*/
|
|
if( in->BandFmt != IM_BANDFMT_DOUBLE ) {
|
|
IMAGE *t;
|
|
|
|
if( !(t = im_open( "im_vips2imask", "p" )) )
|
|
return( NULL );
|
|
if( im_clip2fmt( in, t, IM_BANDFMT_DOUBLE ) ||
|
|
!(out = im_vips2imask( t, filename )) ) {
|
|
im_close( t );
|
|
return( NULL );
|
|
}
|
|
im_close( t );
|
|
|
|
return( out );
|
|
}
|
|
|
|
/* Check the image.
|
|
*/
|
|
if( im_incheck( in ) ||
|
|
im_check_uncoded( "im_vips2imask", in ) )
|
|
return( NULL );
|
|
|
|
if( in->Bands == 1 ) {
|
|
width = in->Xsize;
|
|
height = in->Ysize;
|
|
}
|
|
else if( in->Xsize == 1 ) {
|
|
width = in->Bands;
|
|
height = in->Ysize;
|
|
}
|
|
else if( in->Ysize == 1 ) {
|
|
width = in->Xsize;
|
|
height = in->Bands;
|
|
}
|
|
else {
|
|
im_error( "im_vips2imask",
|
|
"%s", _( "one band, nx1, or 1xn images only" ) );
|
|
return( NULL );
|
|
}
|
|
|
|
data = (double *) in->data;
|
|
if( !(out = im_create_imask( filename, width, height )) )
|
|
return( NULL );
|
|
|
|
/* We want to make an intmask which has the same input to output ratio
|
|
* as the double image.
|
|
*
|
|
* Imagine convolving with the double image, what's the ratio of
|
|
* brightness between input and output? We want the same ratio for the
|
|
* int version, if we can.
|
|
*
|
|
* Imagine an input image where every pixel is 1, what will the output
|
|
* be?
|
|
*/
|
|
double_result = 0;
|
|
for( y = 0; y < height; y++ )
|
|
for( x = 0; x < width; x++ )
|
|
double_result += data[x + width * y];
|
|
double_result /= vips_image_get_scale( in );
|
|
|
|
for( y = 0; y < height; y++ )
|
|
for( x = 0; x < width; x++ )
|
|
if( in->Bands > 1 && in->Ysize == 1 )
|
|
/* Need to transpose: the image is RGBRGBRGB,
|
|
* we need RRRGGGBBB.
|
|
*/
|
|
out->coeff[x + y * width] =
|
|
VIPS_RINT( data[x * height + y] );
|
|
else
|
|
out->coeff[x + y * width] =
|
|
VIPS_RINT( data[x + y * width] );
|
|
|
|
out->scale = VIPS_RINT( vips_image_get_scale( in ) );
|
|
if( out->scale == 0 )
|
|
out->scale = 1;
|
|
out->offset = VIPS_RINT( vips_image_get_offset( in ) );
|
|
|
|
/* Now convolve a 1 everywhere image with the int version we've made,
|
|
* what do we get?
|
|
*/
|
|
int_result = 0;
|
|
for( y = 0; y < height; y++ )
|
|
for( x = 0; x < width; x++ )
|
|
int_result += out->coeff[x + width * y];
|
|
int_result /= out->scale;
|
|
|
|
/* And adjust the scale to get as close to a match as we can.
|
|
*/
|
|
out->scale = VIPS_RINT( out->scale + (int_result - double_result) );
|
|
if( out->scale == 0 )
|
|
out->scale = 1;
|
|
|
|
return( out );
|
|
}
|
|
|