示例#1
0
文件: im_grey.c 项目: alon/libvips
/**
 * im_fgrey:
 * @out: output image
 * @xsize: image size
 * @ysize: image size
 *
 * Create a one-band float image with the left-most column zero and the
 * right-most 1. Intermediate pixels are a linear ramp.
 *
 * See also: im_grey(), im_make_xy(), im_identity().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_fgrey( IMAGE *out, const int xsize, const int ysize )
{
	/* Check args.
	 */
	if( xsize <=0 || ysize <= 0 ) { 
		im_error( "im_fgrey", "%s", _( "bad size" ) ); 
		return( -1 ); 
	}
	if( im_poutcheck( out ) )
		return( -1 );

	/* Set image.
	 */
	im_initdesc( out, xsize, ysize, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT, 
		IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 );

	/* Set hints - ANY is ok with us.
	 */
	if( im_demand_hint( out, IM_ANY, NULL ) )
		return( -1 );
	
	/* Generate image.
	 */
	if( im_generate( out, NULL, fgrey_gen, NULL, NULL, NULL ) )
		return( -1 );

	return( 0 );
}
示例#2
0
/**
 * im_gaussnoise:
 * @out: output image
 * @x: output width
 * @y: output height
 * @mean: average value in output
 * @sigma: standard deviation in output
 *
 * Make a one band float image of gaussian noise with the specified
 * distribution. The noise distribution is created by averaging 12 random 
 * numbers with the appropriate weights.
 *
 * See also: im_addgnoise(), im_make_xy(), im_text(), im_black().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_gaussnoise( IMAGE *out, int x, int y, double mean, double sigma )
{	
	GnoiseInfo *gin;

	if( x <= 0 || y <= 0 ) {
		im_error( "im_gaussnoise", "%s", _( "bad parameter" ) );
		return( -1 );
	}

	if( im_poutcheck( out ) )
		return( -1 );
	im_initdesc( out, 
		x, y, 1, 
		IM_BBITS_FLOAT, IM_BANDFMT_FLOAT, IM_CODING_NONE, IM_TYPE_B_W,
		1.0, 1.0, 0, 0 );
	if( im_demand_hint( out, IM_ANY, NULL ) )
		return( -1 );
	
	/* Save parameters.
	 */
	if( !(gin = IM_NEW( out, GnoiseInfo )) )
		return( -1 );
	gin->mean = mean;
	gin->sigma = sigma;

	if( im_generate( out, NULL, gnoise_gen, NULL, gin, NULL ) )
		return( -1 );
	
	return( 0 );
}
示例#3
0
/**
 * im_buildlut:
 * @input: input mask
 * @output: output image
 *
 * This operation builds a lookup table from a set of points. Intermediate
 * values are generated by piecewise linear interpolation. 
 *
 * For example, consider this 2 x 2 matrix of (x, y) coordinates:
 *
 *   <tgroup cols='2' align='left' colsep='1' rowsep='1'>
 *     <tbody>
 *       <row>
 *         <entry>0</entry>
 *         <entry>0</entry>
 *       </row>
 *       <row>
 *         <entry>255</entry>
 *         <entry>100</entry>
 *       </row>
 *     </tbody>
 *   </tgroup>
 * 
 * We then generate:
 *
 *   <tgroup cols='2' align='left' colsep='1' rowsep='1'>
 *     <thead>
 *       <row>
 *         <entry>Index</entry>
 *         <entry>Value</entry>
 *       </row>
 *     </thead>
 *     <tbody>
 *       <row>
 *         <entry>0</entry>
 *         <entry>0</entry>
 *       </row>
 *       <row>
 *         <entry>1</entry>
 *         <entry>0.4</entry>
 *       </row>
 *       <row>
 *         <entry>...</entry>
 *         <entry>etc. by linear interpolation</entry>
 *       </row>
 *       <row>
 *         <entry>255</entry>
 *         <entry>100</entry>
 *       </row>
 *     </tbody>
 *   </tgroup>
 *
 * This is then written as the output image, with the left column giving the
 * index in the image to place the value.
 * 
 * The (x, y) points don't need to be sorted: we do that. You can have 
 * several Ys, each becomes a band in the output LUT. You don't need to
 * start at zero, any integer will do, including negatives.
 *
 * See also: im_identity(), im_invertlut().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_buildlut( DOUBLEMASK *input, IMAGE *output )
{
	State state;

	if( !input || input->xsize < 2 || input->ysize < 1 ) {
		im_error( "im_buildlut", "%s", _( "bad input matrix size" ) );
		return( -1 );
	}

	if( build_state( &state, input ) ||
		buildlut( &state ) ) {
		free_state( &state );
                return( -1 );
	}

        im_initdesc( output,
                state.lut_size, 1, input->xsize - 1, 
		IM_BBITS_DOUBLE, IM_BANDFMT_DOUBLE,
                IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 );
        if( im_setupout( output ) ||
		im_writeline( 0, output, (PEL *) state.buf ) ) {
		free_state( &state );
		return( -1 );
	}

	free_state( &state );

	return( 0 );
}
示例#4
0
static int
mat2vips_get_header( matvar_t *var, IMAGE *im )
{
	int width, height, bands, format, type;
	int i;

	width = 1;
	height = 1;
	bands = 1;
	switch( var->rank ) {
	case 3:
		bands = var->dims[2];

	case 2:
		height = var->dims[1];

	case 1:
		width = var->dims[0];
		break;

	default:
		im_error( "im_mat2vips", 
			_( "unsupported rank %d\n" ), var->rank );
		return( -1 );
	}

	if( bands > 1 )
		type = IM_TYPE_MULTIBAND;
	else
		type = IM_TYPE_B_W;

	for( i = 0; i < IM_NUMBER( mat2vips_formats ); i++ )
		if( mat2vips_formats[i][0] == var->class_type )
			break;
	if( i == IM_NUMBER( mat2vips_formats ) ) {
		im_error( "im_mat2vips", _( "unsupported class type %d\n" ),
			var->class_type );
		return( -1 );
	}
	format = mat2vips_formats[i][1];

	im_initdesc( im,
		 width, height, bands,
		 im_bits_of_fmt( format ), format,
		 IM_CODING_NONE, type, 1.0, 1.0, 0, 0 );

	return( 0 );
}
示例#5
0
static int
hist_write( IMAGE *out, Histogram *hist )
{
	if( im_cp_descv( out, hist->index, hist->value, NULL ) ) 
		return( -1 );
	im_initdesc( out,
		hist->mx + 1, 1, hist->value->Bands, 
		IM_BBITS_DOUBLE, IM_BANDFMT_DOUBLE, 
		IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 );
	if( im_setupout( out ) )
		return( -1 );

	if( im_writeline( 0, out, (PEL *) hist->bins ) )
		return( -1 );

	return( 0 );
}
示例#6
0
/**
 * im_mask2vips:
 * @in: input mask
 * @out: output image
 *
 * Write a one-band, %IM_BANDFMT_DOUBLE image to @out based on mask @in.
 *
 * See also: im_vips2mask().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_mask2vips( DOUBLEMASK *in, IMAGE *out )
{
	int x, y;
	double *buf, *p, *q;

	/* Check the mask.
	 */
	if( !in || !in->coeff ) {
		im_error( "im_mask2vips", "%s", _( "bad input mask" ) );
		return( -1 );
	}

	/* Make the output image.
	 */
	im_initdesc( out, in->xsize, in->ysize, 1, 
		IM_BBITS_DOUBLE, IM_BANDFMT_DOUBLE, 
		IM_CODING_NONE, 
		IM_TYPE_B_W, 
		1.0, 1.0, 
		0, 0 );
	if( im_setupout( out ) )
		return( -1 );

	/* Make an output buffer.
	 */
	if( !(buf = IM_ARRAY( out, in->xsize, double )) )
		return( -1 );

	/* Write!
	 */
	for( p = in->coeff, y = 0; y < out->Ysize; y++ ) {
		q = buf;

		for( x = 0; x < out->Xsize; x++ )
			*q++ = *p++;

		if( im_writeline( y, out, (void *) buf ) )
			return( -1 );
	}

	return( 0 );
}
示例#7
0
int
im_fzone( IMAGE *image, int size )
{
	int x, y;
	int i, j;

	float *buf;
	const int size2 = size/2;

	/* Check args.
	 */
	if( im_outcheck( image ) )
		return( -1 );
	if( size <= 0 || (size % 2) != 0 ) {
		im_error( "im_zone", "%s", 
			_( "size must be even and positive" ) );
		return( -1 );
	}

	/* Set up output image.
	 */
        im_initdesc( image, size, size, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT,
		IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 );
        if( im_setupout( image ) )
                return( -1 );

	/* Create output buffer.
	 */
        if( !(buf = IM_ARRAY( image, size, float )) )
                return( -1 );

	/* Make zone plate.
	 */
	for( y = 0, j = -size2; j < size2; j++, y++ ) {
		for( x = 0, i = -size2; i < size2; i++, x++ )
			buf[x] = cos( (IM_PI / size) * (i * i + j * j) );
		if( im_writeline( y, image, (PEL *) buf ) )
			return( -1 );
	}

	return( 0 );
}
示例#8
0
static int
lgrab_capture( LGrab *lg, IMAGE *im )
{
	int x, y;
	unsigned char *line;

	if( lgrab_capturen( lg ) )
		return( -1 );

	if( im_outcheck( im ) )
		return( -1 );
        im_initdesc( im, lg->c_width, lg->c_height, 3,
                IM_BBITS_BYTE, IM_BANDFMT_UCHAR,
                IM_CODING_NONE, IM_TYPE_MULTIBAND, 1.0, 1.0, 0, 0 );
        if( im_setupout( im ) )
                return( -1 );
	if( !(line = IM_ARRAY( im, 
		IM_IMAGE_SIZEOF_LINE( im ), unsigned char )) )
                return( -1 );

        for( y = 0; y < lg->c_height; y++ ) {
                unsigned char *p = (unsigned char *) lg->capture_buffer + 
			y * IM_IMAGE_SIZEOF_LINE( im );
                unsigned char *q = line;

		for( x = 0; x < lg->c_width; x++ ) {
			q[0] = p[2];
			q[1] = p[1];
			q[2] = p[0];

			p += 3;
			q += 3;
		}

                if( im_writeline( y, im, line ) )
                        return( -1 );
	}

	return( 0 );
}
示例#9
0
static int
read_header( FILE *fp, IMAGE *out, int *bits, int *ascii, int *msb_first )
{
	int width, height, bands, fmt, type;
	int index;
	char buf[IM_MAX_THING];

	/* ppm types.
	 */
	static char *magic_names[] = {
		"P1",	/* pbm ... 1 band 1 bit, ascii */
		"P2",	/* pgm ... 1 band many bit, ascii */
		"P3",	/* ppm ... 3 band many bit, ascii */
		"P4",	/* pbm ... 1 band 1 bit, binary */
		"P5",	/* pgm ... 1 band 8 bit, binary */
		"P6",	/* ppm ... 3 band 8 bit, binary */
		"PF",	/* pfm ... 3 band 32 bit, binary */
		"Pf"	/* pfm ... 1 band 32 bit, binary */
	};

	/* Characteristics, indexed by ppm type.
	 */
	static int lookup_bits[] = {
		1, 8, 8, 1, 8, 8, 32, 32
	};
	static int lookup_bands[] = {
		1, 1, 3, 1, 1, 3, 3, 1
	};
	static int lookup_ascii[] = {
		1, 1, 1, 0, 0, 0, 0, 0
	};

	/* Read in the magic number.
	 */
	buf[0] = fgetc( fp );
	buf[1] = fgetc( fp );
	buf[2] = '\0';

	for( index = 0; index < IM_NUMBER( magic_names ); index++ )
		if( strcmp( magic_names[index], buf ) == 0 ) 
			break;
	if( index == IM_NUMBER( magic_names ) ) {
		im_error( "im_ppm2vips", "%s", _( "bad magic number" ) );
		return( -1 );
	}
	*bits = lookup_bits[index];
	bands = lookup_bands[index];
	*ascii = lookup_ascii[index];

	/* Default ... can be changed below for PFM images.
	 */
	*msb_first = 0;

	/* Read in size.
	 */
	if( read_int( fp, &width ) ||
		read_int( fp, &height ) )
		return( -1 );

	/* Read in max value / scale for >1 bit images.
	 */
	if( *bits > 1 ) {
		if( index == 6 || index == 7 ) {
			float scale;

			if( read_float( fp, &scale ) )
				return( -1 );

			/* Scale > 0 means big-endian.
			 */
			*msb_first = scale > 0;
			im_meta_set_double( out, "pfm-scale", fabs( scale ) );
		}
		else {
			int max_value;

			if( read_int( fp, &max_value ) )
				return( -1 );

			if( max_value > 255 )
				*bits = 16;
			if( max_value > 65535 )
				*bits = 32;
		}
	}

	/* For binary images, there is always exactly 1 more whitespace
	 * character before the data starts.
	 */
	if( !*ascii && !isspace( fgetc( fp ) ) ) {
		im_error( "im_ppm2vips", "%s", 
			_( "not whitespace before start of binary data" ) );
		return( -1 );
	}

	/* Choose a VIPS bandfmt.
	 */
	switch( *bits ) {
	case 1:
	case 8:
		fmt = IM_BANDFMT_UCHAR;
		break;

	case 16:
		fmt = IM_BANDFMT_USHORT;
		break;

	case 32:
		if( index == 6 || index == 7 )
			fmt = IM_BANDFMT_FLOAT;
		else
			fmt = IM_BANDFMT_UINT;
		break;

	default:
		g_assert( 0 );
	}

	if( bands == 1 ) {
		if( fmt == IM_BANDFMT_USHORT )
			type = IM_TYPE_GREY16;
		else
			type = IM_TYPE_B_W;
	}
	else {
		if( fmt == IM_BANDFMT_USHORT )
			type = IM_TYPE_RGB16;
		else if( fmt == IM_BANDFMT_UINT )
			type = IM_TYPE_RGB;
		else 
			type = IM_TYPE_sRGB;
	}

	im_initdesc( out, width, height, bands, (*bits == 1) ? 8 : *bits, fmt, 
		IM_CODING_NONE, 
		type,
		1.0, 1.0,
		0, 0 );

	return( 0 );
}
示例#10
0
int 
im_histnD( IMAGE *in, IMAGE *out, int bins )
{
	int max_val;
	Histogram *mhist;
	int x, y, z, i;
	unsigned int *obuffer;

	/* Check images. PIO from in, WIO to out.
	 */
	if( im_pincheck( in ) || im_outcheck( out ) )
		return( -1 );
	if( in->Coding != IM_CODING_NONE ) {
		im_error( "im_histnD", _( " uncoded images only" ) );
		return( -1 );
	}
	if( in->BandFmt != IM_BANDFMT_UCHAR && 
		in->BandFmt != IM_BANDFMT_USHORT ) {
		im_error( "im_histnD", 
			_( " unsigned 8 or 16 bit images only" ) );
		return( -1 );
	}

	max_val = in->BandFmt == IM_BANDFMT_UCHAR ? 256 : 65536;
	if( bins < 1 || bins > max_val ) {
		im_error( "im_histnD", 
			_( " bins out of range [1,%d]" ), max_val );
		return( -1 );
	}

	/* Build main hist we accumulate to.
	 */
	if( !(mhist = build_hist( in, out, bins )) )
		return( -1 );

	/* Accumulate data.
	 */
	if( im_iterate( in, 
		build_subhist, find_hist, merge_subhist, mhist, NULL ) )
		return( -1 );

	/* Make the output image.
	 */
	if( im_cp_desc( out, in ) ) 
		return( -1 );
	im_initdesc( out,
		bins, in->Bands > 1 ? bins : 1, in->Bands > 2 ? bins : 1,
		IM_BBITS_INT, IM_BANDFMT_UINT, 
		IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 );
	if( im_setupout( out ) )
		return( -1 );

	/* Interleave to output buffer.
	 */
	if( !(obuffer = IM_ARRAY( out, 
		IM_IMAGE_N_ELEMENTS( out ), unsigned int )) )
		return( -1 );

	for( y = 0; y < out->Ysize; y++ ) {
		for( i = 0, x = 0; x < out->Xsize; x++ ) 
			for( z = 0; z < out->Bands; z++, i++ )
				obuffer[i] = mhist->data[z][y][x];

		if( im_writeline( y, out, (PEL *) obuffer ) )
			return( -1 );
	}

	return( 0 );
}
示例#11
0
/**
 * im_simcontr:
 * @out: output image
 * @xsize: image size
 * @ysize: image size
 *
 * Creates a pattern showing the similtaneous constrast effect.
 *
 * See also: im_eye().
 *
 * Returns: 0 on success, -1 on error
 */
int 
im_simcontr( IMAGE *out, int xsize, int ysize )
{
	int x, y;
	unsigned char *line1, *line2, *cpline;


/* Check input args */
	if( im_outcheck( out ) )
		return( -1 );

/* Set now image properly */
        im_initdesc(out, xsize, ysize, 1, IM_BBITS_BYTE, IM_BANDFMT_UCHAR,
		IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 );

/* Set up image checking whether the output is a buffer or a file */
        if (im_setupout( out ) == -1 )
                return( -1 );
/* Create data */
        line1 = (unsigned char *)calloc((unsigned)xsize, sizeof(char));
        line2 = (unsigned char *)calloc((unsigned)xsize, sizeof(char));
        if ( (line1 == NULL) || (line2 == NULL) ) { 
		im_error( "im_simcontr", "%s", _( "calloc failed") ); 
		return(-1); }

	cpline = line1;
	for (x=0; x<xsize; x++)
		*cpline++ = (PEL)255;
	cpline = line1;
	for (x=0; x<xsize/2; x++)
		*cpline++ = (PEL)0;
	
	cpline = line2;
	for (x=0; x<xsize; x++)
		*cpline++ = (PEL)255;
	cpline = line2;
	for (x=0; x<xsize/8; x++)
		*cpline++ = (PEL)0;
	for (x=0; x<xsize/4; x++)
		*cpline++ = (PEL)128;
	for (x=0; x<xsize/8; x++)
		*cpline++ = (PEL)0;
	for (x=0; x<xsize/8; x++)
		*cpline++ = (PEL)255;
	for (x=0; x<xsize/4; x++)
		*cpline++ = (PEL)128;

	for (y=0; y<ysize/4; y++)
		{
		if ( im_writeline( y, out, (PEL *)line1 ) == -1 )
			{
			free ( (char *)line1 ); free ( (char *)line2 );
			return( -1 );
			}
		}
	for (y=ysize/4; y<(ysize/4+ysize/2); y++)
		{
		if ( im_writeline( y, out, (PEL *)line2 ) == -1 )
			{
			free ( (char *)line1 ); free ( (char *)line2 );
			return( -1 );
			}
		}
	for (y=(ysize/4 + ysize/2); y<ysize; y++)
		{
		if ( im_writeline( y, out, (PEL *)line1 ) == -1 )
			{
			free ( (char *)line1 ); free ( (char *)line2 );
			return( -1 );
			}
		}
	free ( (char *)line1 ); free ( (char *)line2 );
	return(0);
}
示例#12
0
/* Plot image.
 */
static int
plot( IMAGE *in, IMAGE *out )
{
	double max;
	int tsize;
	int xsize;
	int ysize;

	if( im_incheck( in ) ||
		im_poutcheck( out ) )
		return( -1 );

	/* Find range we will plot.
	 */
	if( im_max( in, &max ) )
		return( -1 );
	g_assert( max >= 0 );
	if( in->BandFmt == IM_BANDFMT_UCHAR )
		tsize = 256;
	else
		tsize = ceil( max );

	/* Make sure we don't make a zero height image.
	 */
	if( tsize == 0 )
		tsize = 1;

	if( in->Xsize == 1 ) {
		/* Vertical graph.
		 */
		xsize = tsize;
		ysize = in->Ysize;
	}
	else {
		/* Horizontal graph.
		 */
		xsize = in->Xsize;
		ysize = tsize;
	}

	/* Set image.
	 */
	im_initdesc( out, xsize, ysize, in->Bands, 
		IM_BBITS_BYTE, IM_BANDFMT_UCHAR, 
		IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 );

	/* Set hints - ANY is ok with us.
	 */
	if( im_demand_hint( out, IM_ANY, NULL ) )
		return( -1 );
	
	/* Generate image.
	 */
	if( in->Xsize == 1 ) {
		if( im_generate( out, NULL, make_vert_gen, NULL, in, NULL ) )
			return( -1 );
	}
	else {
		if( im_generate( out, NULL, make_horz_gen, NULL, in, NULL ) )
			return( -1 );
	}

	return( 0 );
}
示例#13
0
/**
 * im_sines:
 * @out: output image
 * @xsize: image size
 * @ysize: image size
 * @horfreq: horizontal frequency
 * @verfreq: vertical frequency
 *
 * im_sines() creates a float one band image of the a sine waveform in two
 * dimensions.  
 *
 * The number of horizontal and vertical spatial frequencies are
 * determined by the variables @horfreq and @verfreq respectively.  The
 * function is useful for creating displayable sine waves and
 * square waves in two dimensions.
 *
 * If horfreq and verfreq are integers the resultant image is periodical
 * and therfore the Fourier transform doesnot present spikes
 * 
 * See also: im_grey(), im_make_xy(). 
 *
 * Returns: 0 on success, -1 on error
 */
int 
im_sines( IMAGE *out, int xsize, int ysize, double horfreq, double verfreq )
{
	int x, y;
	float *line, *cpline;
	int size;
	double cons, factor;
	double theta_rad, costheta, sintheta, ysintheta;

/* Check input args */
	if( im_outcheck( out ) )
		return( -1 );
        if ( xsize <= 0 || ysize <= 0 ) { 
		im_error( "im_sines", "%s", _( "wrong sizes") ); 
		return(-1); }

/* Set now out properly */
        im_initdesc(out, xsize, ysize, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT,
		IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0);

/* Set up out checking whether the output is a buffer or a file */
        if (im_setupout( out ) == -1 )
                return( -1 );
/* Create data */
	size = out->Xsize;
        if ( (line=(float *)calloc((unsigned)size, sizeof(float))) == NULL ) { 
		im_error( "im_sines", "%s", _( "calloc failed") ); 
		return(-1); }

/* make angle in rad */
	if (horfreq == 0)
		theta_rad = IM_PI/2.0;
	else
		theta_rad = atan(verfreq/horfreq);
	costheta = cos(theta_rad); sintheta = sin(theta_rad);
	factor = sqrt ((double)(horfreq*horfreq + verfreq*verfreq));
	cons =  factor * IM_PI * 2.0/(double)out->Xsize;
/* There is a bug (rounding error ?) for horfreq=0,
 *so do this calculation independantly */
	if ( horfreq != 0 )
		{
		for (y=0; y<out->Ysize; y++)
			{
			ysintheta = y * sintheta;
			cpline = line;
			for (x=0; x<out->Xsize; x++)
				*cpline++ =
				(float)(cos(cons*(x*costheta-ysintheta)));
			if ( im_writeline( y, out, (PEL *)line ) == -1 )
				{
				free ( (char *)line );
				return( -1 );
				}
			}
		}
	else
		{
		for (y=0; y<out->Ysize; y++)
			{
			cpline = line;
			ysintheta = cos (- cons * y * sintheta);
			for (x=0; x<out->Xsize; x++)
				*cpline++ = (float)ysintheta;
			if ( im_writeline( y, out, (PEL *)line ) == -1 )
				{
				free ( (char *)line );
				return( -1 );
				}
			}
		}
	free ( (char *)line );
	return(0);
}
示例#14
0
/* Read a cinfo to a VIPS image. Set invert_pels if the pixel reader needs to
 * do 255-pel.
 */
static int
read_jpeg_header( struct jpeg_decompress_struct *cinfo, 
	IMAGE *out, gboolean *invert_pels, int shrink )
{
	jpeg_saved_marker_ptr p;
	int type;

	/* Capture app2 sections here for assembly.
	 */
	void *app2_data[MAX_APP2_SECTIONS] = { 0 };
	int app2_data_length[MAX_APP2_SECTIONS] = { 0 };
	int data_length;
	int i;

	/* Read JPEG header. libjpeg will set out_color_space sanely for us 
	 * for YUV YCCK etc.
	 */
	jpeg_read_header( cinfo, TRUE );
	cinfo->scale_denom = shrink;
	cinfo->scale_num = 1;
	jpeg_calc_output_dimensions( cinfo );

	*invert_pels = FALSE;
	switch( cinfo->out_color_space ) {
	case JCS_GRAYSCALE:
		type = IM_TYPE_B_W;
		break;

	case JCS_CMYK:
		type = IM_TYPE_CMYK;
		/* Photoshop writes CMYK JPEG inverted :-( Maybe this is a
		 * way to spot photoshop CMYK JPGs.
		 */
		if( cinfo->saw_Adobe_marker ) 
			*invert_pels = TRUE;
		break;

	case JCS_RGB:
	default:
		type = IM_TYPE_sRGB;
		break;
	}

	/* Set VIPS header.
	 */
	im_initdesc( out,
		 cinfo->output_width, cinfo->output_height,
		 cinfo->output_components,
		 IM_BBITS_BYTE, IM_BANDFMT_UCHAR, IM_CODING_NONE, type,
		 1.0, 1.0, 0, 0 );

	/* Interlaced jpegs need lots of memory to read, so our caller needs
	 * to know.
	 */
	(void) im_meta_set_int( out, "jpeg-multiscan", 
		jpeg_has_multiple_scans( cinfo ) );

	/* Look for EXIF and ICC profile.
	 */
	for( p = cinfo->marker_list; p; p = p->next ) {
		switch( p->marker ) {
		case JPEG_APP0 + 1:
			/* EXIF data.
			 */
#ifdef DEBUG
			printf( "read_jpeg_header: seen %d bytes of APP1\n",
				p->data_length );
#endif /*DEBUG*/
			if( read_exif( out, p->data, p->data_length ) )
				return( -1 );
			break;

		case JPEG_APP0 + 2:
			/* ICC profile.
			 */
#ifdef DEBUG
			printf( "read_jpeg_header: seen %d bytes of APP2\n",
				p->data_length );
#endif /*DEBUG*/

			if( p->data_length > 14 &&
				im_isprefix( "ICC_PROFILE", 
					(char *) p->data ) ) {
				/* cur_marker numbers from 1, according to
				 * spec.
				 */
				int cur_marker = p->data[12] - 1;

				if( cur_marker >= 0 &&
					cur_marker < MAX_APP2_SECTIONS ) {
					app2_data[cur_marker] = p->data + 14;
					app2_data_length[cur_marker] = 
						p->data_length - 14;
				}
			}
			break;

		default:
#ifdef DEBUG
			printf( "read_jpeg_header: seen %d bytes of data\n",
				p->data_length );
#endif /*DEBUG*/
			break;
		}
	}

	/* Assemble ICC sections.
	 */
	data_length = 0;
	for( i = 0; i < MAX_APP2_SECTIONS && app2_data[i]; i++ )
		data_length += app2_data_length[i];
	if( data_length ) {
		unsigned char *data;
		int p;

#ifdef DEBUG
		printf( "read_jpeg_header: assembled %d byte ICC profile\n",
			data_length );
#endif /*DEBUG*/

		if( !(data = im_malloc( NULL, data_length )) ) 
			return( -1 );

		p = 0;
		for( i = 0; i < MAX_APP2_SECTIONS && app2_data[i]; i++ ) {
			memcpy( data + p, app2_data[i], app2_data_length[i] );
			p += app2_data_length[i];
		}

		if( im_meta_set_blob( out, IM_META_ICC_NAME, 
			(im_callback_fn) im_free, data, data_length ) ) {
			im_free( data );
			return( -1 );
		}
	}

	return( 0 );
}
示例#15
0
/* Read a PNG file (header) into a VIPS (header).
 */
static int
png2vips( Read *read, int header_only )
{
	int bands, bpp, type;

	if( setjmp( read->pPng->jmpbuf ) ) 
		return( -1 );

	png_init_io( read->pPng, read->fp );
	png_read_info( read->pPng, read->pInfo );

	/* png_get_channels() gives us 1 band for palette images ... so look
	 * at colour_type for output bands.
	 */
	switch( read->pInfo->color_type ) {
	case PNG_COLOR_TYPE_PALETTE: 
		bands = 3; 

		/* Don't know if this is really correct. If there are
		 * transparent pixels, assume we're going to output RGBA.
		 */
		if( read->pInfo->num_trans )
			bands = 4; 

		break;

	case PNG_COLOR_TYPE_GRAY: bands = 1; break;
	case PNG_COLOR_TYPE_GRAY_ALPHA: bands = 2; break;
	case PNG_COLOR_TYPE_RGB: bands = 3; break;
	case PNG_COLOR_TYPE_RGB_ALPHA: bands = 4; break;

	default:
		im_error( "im_png2vips", "%s", _( "unsupported color type" ) );
		return( -1 );
	}

	/* 8 or 16 bit.
	 */
	bpp = read->pInfo->bit_depth > 8 ? 2 : 1;

	if( bpp > 1 ) {
		if( bands < 3 )
			type = IM_TYPE_GREY16;
		else
			type = IM_TYPE_RGB16;
	}
	else {
		if( bands < 3 )
			type = IM_TYPE_B_W;
		else
			type = IM_TYPE_sRGB;
	}

	/* Expand palette images.
	 */
	if( read->pInfo->color_type == PNG_COLOR_TYPE_PALETTE )
	        png_set_expand( read->pPng );

	/* Expand <8 bit images to full bytes.
	 */
	if( read->pInfo->bit_depth < 8 ) {
		png_set_packing( read->pPng );
	        png_set_shift( read->pPng, &(read->pInfo->sig_bit) );
	}

	/* If we're an INTEL byte order machine and this is 16bits, we need
	 * to swap bytes.
	 */
	if( read->pInfo->bit_depth > 8 && !im_amiMSBfirst() )
		png_set_swap( read->pPng );

	/* Set VIPS header.
	 */
	im_initdesc( read->out,
		 read->pInfo->width, read->pInfo->height, bands,
		 bpp == 1 ? IM_BBITS_BYTE : IM_BBITS_SHORT, 
		 bpp == 1 ? IM_BANDFMT_UCHAR : IM_BANDFMT_USHORT,
		 IM_CODING_NONE, type, 1.0, 1.0, 0, 0 );

	if( !header_only ) {
		if( png_set_interlace_handling( read->pPng ) > 1 ) {
			if( png2vips_interlace( read ) )
				return( -1 );
		}
		else {
			if( png2vips_noninterlace( read ) )
				return( -1 );
		}
	}

	return( 0 );
}
示例#16
0
文件: fits.c 项目: nrobidoux/libvips
static int
vips_fits_get_header( VipsFits *fits, VipsImage *out )
{
	int status;
	int bitpix;

	int width, height, bands, format, type;
	int keysexist;
	int i;

	status = 0;

	if( fits_get_img_paramll( fits->fptr, 
		10, &bitpix, &fits->naxis, fits->naxes, &status ) ) {
		vips_fits_error( status );
		return( -1 );
	}

#ifdef VIPS_DEBUG
	VIPS_DEBUG_MSG( "naxis = %d\n", fits->naxis );
	for( i = 0; i < fits->naxis; i++ )
		VIPS_DEBUG_MSG( "%d) %lld\n", i, fits->naxes[i] );
#endif /*VIPS_DEBUG*/

	width = 1;
	height = 1;
	bands = 1;
	switch( fits->naxis ) {
	/* If you add more dimensions here, adjust data read below. See also
	 * the definition of MAX_DIMENSIONS above.
	 */
	case 10:
	case 9:
	case 8:
	case 7:
	case 6:
	case 5:
	case 4:
		for( i = fits->naxis; i > 3; i-- )
			if( fits->naxes[i - 1] != 1 ) {
				im_error( "fits", "%s", _( "dimensions above 3 "
					"must be size 1" ) );
				return( -1 );
			}

	case 3:
		bands = fits->naxes[2];

	case 2:
		height = fits->naxes[1];

	case 1:
		width = fits->naxes[0];
		break;

	default:
		im_error( "fits", _( "bad number of axis %d" ), fits->naxis );
		return( -1 );
	}

	/* Are we in one-band mode?
	 */
	if( fits->band_select != -1 )
		bands = 1;

	/* Get image format. We want the 'raw' format of the image, our caller
	 * can convert using the meta info if they want.
	 */
	for( i = 0; i < VIPS_NUMBER( fits2vips_formats ); i++ )
		if( fits2vips_formats[i][0] == bitpix )
			break;
	if( i == VIPS_NUMBER( fits2vips_formats ) ) {
		im_error( "fits", _( "unsupported bitpix %d\n" ),
			bitpix );
		return( -1 );
	}
	format = fits2vips_formats[i][1];
	fits->datatype = fits2vips_formats[i][2];

	if( bands == 1 ) {
		if( format == VIPS_FORMAT_USHORT )
			type = VIPS_INTERPRETATION_GREY16;
		else
			type = VIPS_INTERPRETATION_B_W;
	}
	else if( bands == 3 ) {
		if( format == VIPS_FORMAT_USHORT )
			type = VIPS_INTERPRETATION_RGB16;
		else
			type = VIPS_INTERPRETATION_RGB;
	}
	else
		type = VIPS_INTERPRETATION_MULTIBAND;

	im_initdesc( out,
		 width, height, bands,
		 im_bits_of_fmt( format ), format,
		 VIPS_CODING_NONE, type, 1.0, 1.0, 0, 0 );

	/* Read all keys into meta.
	 */
	if( fits_get_hdrspace( fits->fptr, &keysexist, NULL, &status ) ) {
		vips_fits_error( status );
		return( -1 );
	}

	for( i = 0; i < keysexist; i++ ) {
		char record[81];
		char vipsname[100];

		if( fits_read_record( fits->fptr, i + 1, record, &status ) ) {
			vips_fits_error( status );
			return( -1 );
		}

		VIPS_DEBUG_MSG( "fits2vips: setting meta on vips image:\n" );
		VIPS_DEBUG_MSG( " record == \"%s\"\n", record );

		/* FITS lets keys repeat. For example, HISTORY appears many
		 * times, each time with a fresh line of history attached. We
		 * have to include the key index in the vips name we assign.
		 */

		im_snprintf( vipsname, 100, "fits-%d", i );
		if( im_meta_set_string( out, vipsname, record ) ) 
			return( -1 );
	}

	return( 0 );
}
示例#17
0
文件: tone.c 项目: sepastian/libvips
/**
 * im_tone_build_range:
 * @out: output image
 * @in_max: input range
 * @out_max: output range
 * @Lb: black-point [0-100]
 * @Lw: white-point [0-100]
 * @Ps: shadow point (eg. 0.2)
 * @Pm: mid-tone point (eg. 0.5)
 * @Ph: highlight point (eg. 0.8)
 * @S: shadow adjustment (+/- 30)
 * @M: mid-tone adjustment (+/- 30)
 * @H: highlight adjustment (+/- 30)
 *
 * im_tone_build_range() generates a tone curve for the adjustment of image
 * levels. It is mostly designed for adjusting the L* part of a LAB image in
 * way suitable for print work, but you can use it for other things too.
 *
 * The curve is an unsigned 16-bit image with (@in_max + 1) entries,
 * each in the range [0, @out_max].
 *
 * @Lb, @Lw are expressed as 0-100, as in LAB colour space. You
 * specify the scaling for the input and output images with the @in_max and
 * @out_max parameters.
 *
 * See also: im_ismonotonic(), im_tone_map(), im_tone_analyse().
 *
 * Returns: 0 on success, -1 on error
 */
int
im_tone_build_range( IMAGE *out,
                     int in_max, int out_max,
                     double Lb, double Lw,
                     double Ps, double Pm, double Ph,
                     double S, double M, double H )
{
    ToneShape *ts;
    unsigned short lut[65536];
    int i;

    /* Check args.
     */
    if( !(ts = IM_NEW( out, ToneShape )) ||
            im_outcheck( out ) )
        return( -1 );
    if( in_max < 0 || in_max > 65535 ||
            out_max < 0 || out_max > 65535 ) {
        im_error( "im_tone_build",
                  "%s", _( "bad in_max, out_max parameters" ) );
        return( -1 );
    }
    if( Lb < 0 || Lb > 100 || Lw < 0 || Lw > 100 || Lb > Lw ) {
        im_error( "im_tone_build",
                  "%s", _( "bad Lb, Lw parameters" ) );
        return( -1 );
    }
    if( Ps < 0.0 || Ps > 1.0 ) {
        im_error( "im_tone_build",
                  "%s", _( "Ps not in range [0.0,1.0]" ) );
        return( -1 );
    }
    if( Pm < 0.0 || Pm > 1.0 ) {
        im_error( "im_tone_build",
                  "%s", _( "Pm not in range [0.0,1.0]" ) );
        return( -1 );
    }
    if( Ph < 0.0 || Ph > 1.0 ) {
        im_error( "im_tone_build",
                  "%s", _( "Ph not in range [0.0,1.0]" ) );
        return( -1 );
    }
    if( S < -30 || S > 30 ) {
        im_error( "im_tone_build",
                  "%s", _( "S not in range [-30,+30]" ) );
        return( -1 );
    }
    if( M < -30 || M > 30 ) {
        im_error( "im_tone_build",
                  "%s", _( "M not in range [-30,+30]" ) );
        return( -1 );
    }
    if( H < -30 || H > 30 ) {
        im_error( "im_tone_build",
                  "%s", _( "H not in range [-30,+30]" ) );
        return( -1 );
    }

    /* Note params.
     */
    ts->Lb = Lb;
    ts->Lw = Lw;
    ts->Ps = Ps;
    ts->Pm = Pm;
    ts->Ph = Ph;
    ts->S = S;
    ts->M = M;
    ts->H = H;

    /* Note derived params.
     */
    ts->Ls = Lb + Ps * (Lw - Lb);
    ts->Lm = Lb + Pm * (Lw - Lb);
    ts->Lh = Lb + Ph * (Lw - Lb);

    /* Generate curve.
     */
    for( i = 0; i <= in_max; i++ ) {
        int v = (out_max / 100.0) *
                tone_curve( ts, 100.0 * i / in_max );

        if( v < 0 )
            v = 0;
        else if( v > out_max )
            v = out_max;

        lut[i] = v;
    }

    /* Make the output image.
     */
    im_initdesc( out,
                 in_max + 1, 1, 1, IM_BBITS_SHORT, IM_BANDFMT_USHORT,
                 IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 );
    if( im_setupout( out ) )
        return( -1 );

    if( im_writeline( 0, out, (VipsPel *) lut ) )
        return( -1 );

    return( 0 );
}