Exemple #1
0
static void
vips_round_buffer( VipsArithmetic *arithmetic, 
	VipsPel *out, VipsPel **in, int width )
{
	VipsRound *round = (VipsRound *) arithmetic;
	VipsImage *im = arithmetic->ready[0];

	/* Complex just doubles the size.
	 */
	const int sz = width * im->Bands * 
		(vips_band_format_iscomplex( im->BandFmt ) ? 2 : 1);

	int x;

	switch( round->round ) {
	case VIPS_OPERATION_ROUND_RINT:		SWITCH( VIPS_RINT ); break;
	case VIPS_OPERATION_ROUND_CEIL:		SWITCH( VIPS_CEIL ); break;
	case VIPS_OPERATION_ROUND_FLOOR:	SWITCH( VIPS_FLOOR ); break;

	default: 
		g_assert_not_reached(); 
	} 
}
Exemple #2
0
static void
vips_bandmean_buffer( VipsBandary *bandary, 
	VipsPel *out, VipsPel **in, int width )
{
	VipsImage *im = bandary->ready[0];
	const int bands = im->Bands;
	const int sz = width * 
		(vips_band_format_iscomplex( im->BandFmt ) ? 2 : 1);

	int i, j;

	switch( vips_image_get_format( im ) ) {
	case VIPS_FORMAT_CHAR: 	
		SILOOP( signed char, int ); break; 
	case VIPS_FORMAT_UCHAR:	
		UILOOP( unsigned char, unsigned int ); break; 
	case VIPS_FORMAT_SHORT: 	
		SILOOP( signed short, int ); break; 
	case VIPS_FORMAT_USHORT:	
		UILOOP( unsigned short, unsigned int ); break; 
	case VIPS_FORMAT_INT: 	
		SILOOP( signed int, int ); break; 
	case VIPS_FORMAT_UINT: 	
		UILOOP( unsigned int, unsigned int ); break; 
	case VIPS_FORMAT_FLOAT: 	
		FLOOP( float ); break; 
	case VIPS_FORMAT_DOUBLE:	
		FLOOP( double ); break; 
	case VIPS_FORMAT_COMPLEX:
		FLOOP( float ); break;
	case VIPS_FORMAT_DPCOMPLEX:
		FLOOP( double ); break;

	default:
		g_assert( 0 );
	}
}
Exemple #3
0
  const double relative_x = absolute_x - ix;
  const double relative_y = absolute_y - iy;

  /*
   * VIPS versions of Nicolas's pixel addressing values.
   */
  const int lskip = VIPS_REGION_LSKIP( in ) / 
	  VIPS_IMAGE_SIZEOF_ELEMENT( in->im );

  /*
   * Double the bands for complex images to account for the real and
   * imaginary parts being computed independently:
   */
  const int actual_bands = in->im->Bands;
  const int bands =
    vips_band_format_iscomplex( in->im->BandFmt ) ? 
      2 * actual_bands : actual_bands;

  /* Confirm that absolute_x and absolute_y are >= 1, see above. 
   */
  g_assert( absolute_x >= 1.0 );
  g_assert( absolute_y >= 1.0 );

  switch( in->im->BandFmt ) {
  case VIPS_FORMAT_UCHAR:
    CALL( unsigned char, nosign );
    break;

  case VIPS_FORMAT_CHAR:
    CALL( signed char, withsign );
    break;
/* Make and init a Write.
 */
static Write *
write_new( VipsImage *im, const char *filename,
	VipsForeignTiffCompression compression, int Q, 
		VipsForeignTiffPredictor predictor,
	char *profile,
	gboolean tile, int tile_width, int tile_height,
	gboolean pyramid,
	gboolean squash,
	gboolean miniswhite,
	VipsForeignTiffResunit resunit, double xres, double yres,
	gboolean bigtiff,
	gboolean rgbjpeg,
	gboolean properties,
	gboolean strip )
{
	Write *write;

	if( !(write = VIPS_NEW( im, Write )) )
		return( NULL );
	write->im = im;
	write->filename = vips_strdup( VIPS_OBJECT( im ), filename );
	write->layer = NULL;
	write->tbuf = NULL;
	write->compression = get_compression( compression );
	write->jpqual = Q;
	write->predictor = predictor;
	write->tile = tile;
	write->tilew = tile_width;
	write->tileh = tile_height;
	write->pyramid = pyramid;
	write->onebit = squash;
	write->miniswhite = miniswhite;
	write->icc_profile = vips_strdup( NULL, profile );
	write->bigtiff = bigtiff;
	write->rgbjpeg = rgbjpeg;
	write->properties = properties;
	write->strip = strip;

	write->resunit = get_resunit( resunit );
	write->xres = xres;
	write->yres = yres;

	/* In strip mode we use tileh to set rowsperstrip, and that does not
	 * have the multiple-of-16 restriction.
	 */
	if( tile ) { 
		if( (write->tilew & 0xf) != 0 || 
			(write->tileh & 0xf) != 0 ) {
			vips_error( "vips2tiff", 
				"%s", _( "tile size not a multiple of 16" ) );
			return( NULL );
		}
	}

	/* We can only pyramid LABQ and non-complex images. 
	 */
	if( write->pyramid ) {
		if( im->Coding == VIPS_CODING_NONE && 
			vips_band_format_iscomplex( im->BandFmt ) ) {
			vips_error( "vips2tiff", 
				"%s", _( "can only pyramid LABQ and "
				"non-complex images" ) );
			return( NULL );
		}
	}

	/* Only 1-bit-ize 8 bit mono images.
	 */
	if( write->onebit &&
		(im->Coding != VIPS_CODING_NONE || 
			im->BandFmt != VIPS_FORMAT_UCHAR ||
			im->Bands != 1) ) {
		vips_warn( "vips2tiff", 
			"%s", _( "can only squash 1 band uchar images -- "
				"disabling squash" ) );
		write->onebit = 0;
	}

	if( write->onebit && 
		write->compression == COMPRESSION_JPEG ) {
		vips_warn( "vips2tiff", 
			"%s", _( "can't have 1-bit JPEG -- disabling JPEG" ) );
		write->compression = COMPRESSION_NONE;
	}
 
	/* We can only MINISWHITE non-complex images of 1 or 2 bands.
	 */
	if( write->miniswhite &&
		(im->Coding != VIPS_CODING_NONE || 
			vips_band_format_iscomplex( im->BandFmt ) ||
			im->Bands > 2) ) {
		vips_warn( "vips2tiff", 
			"%s", _( "can only save non-complex greyscale images "
				"as miniswhite -- disabling miniswhite" ) );
		write->miniswhite = FALSE;
	}

	/* Sizeof a line of bytes in the TIFF tile.
	 */
	if( im->Coding == VIPS_CODING_LABQ )
		write->tls = write->tilew * 3;
	else if( write->onebit )
		write->tls = VIPS_ROUND_UP( write->tilew, 8 ) / 8;
	else
		write->tls = VIPS_IMAGE_SIZEOF_PEL( im ) * write->tilew;

	/* Build the pyramid framework.
	 */
	write->layer = pyramid_new( write, NULL, im->Xsize, im->Ysize );

	/* Fill all the layers.
	 */
	if( pyramid_fill( write ) ) {
		write_free( write );
		return( NULL );
	}

	if( tile ) 
		write->tbuf = vips_malloc( NULL, 
			TIFFTileSize( write->layer->tif ) );
	else
		write->tbuf = vips_malloc( NULL, 
			TIFFScanlineSize( write->layer->tif ) );
	if( !write->tbuf ) {
		write_free( write );
		return( NULL );
	}

	return( write );
}
/* Write a TIFF header. width and height are the size of the VipsImage we are
 * writing (it may have been shrunk).
 */
static int
write_tiff_header( Write *write, Layer *layer )
{
	TIFF *tif = layer->tif;

	int format; 
	int orientation; 

	/* Output base header fields.
	 */
	TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, layer->width );
	TIFFSetField( tif, TIFFTAG_IMAGELENGTH, layer->height );
	TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
	TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
	TIFFSetField( tif, TIFFTAG_COMPRESSION, write->compression );

	if( write->compression == COMPRESSION_JPEG ) 
		TIFFSetField( tif, TIFFTAG_JPEGQUALITY, write->jpqual );

	if( write->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) 
		TIFFSetField( tif, TIFFTAG_PREDICTOR, write->predictor );

	/* Don't write mad resolutions (eg. zero), it confuses some programs.
	 */
	TIFFSetField( tif, TIFFTAG_RESOLUTIONUNIT, write->resunit );
	TIFFSetField( tif, TIFFTAG_XRESOLUTION, 
		VIPS_FCLIP( 0.01, write->xres, 1000000 ) );
	TIFFSetField( tif, TIFFTAG_YRESOLUTION, 
		VIPS_FCLIP( 0.01, write->yres, 1000000 ) );

	if( !write->strip ) 
		if( write_embed_profile( write, tif ) ||
			write_embed_xmp( write, tif ) ||
			write_embed_ipct( write, tif ) ||
			write_embed_photoshop( write, tif ) ||
			write_embed_imagedescription( write, tif ) )
			return( -1 ); 

	if( vips_image_get_typeof( write->im, VIPS_META_ORIENTATION ) &&
		!vips_image_get_int( write->im, 
			VIPS_META_ORIENTATION, &orientation ) )
		TIFFSetField( tif, TIFFTAG_ORIENTATION, orientation );

	/* And colour fields.
	 */
	if( write->im->Coding == VIPS_CODING_LABQ ) {
		TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, 3 );
		TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 8 );
		TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB );
	}
	else if( write->onebit ) {
		TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, 1 );
		TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 1 );
		TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, 
			write->miniswhite ? 
				PHOTOMETRIC_MINISWHITE :  
				PHOTOMETRIC_MINISBLACK ); 
	}
	else {
		int photometric;

		/* Number of bands that have colour in .. other bands are saved
		 * as alpha.
		 */
		int colour_bands;

		int alpha_bands;

		TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, write->im->Bands );
		TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 
			vips_format_sizeof( write->im->BandFmt ) << 3 );

		if( write->im->Bands < 3 ) {
			/* Mono or mono + alpha.
			 */
			photometric = write->miniswhite ? 
				PHOTOMETRIC_MINISWHITE :  
				PHOTOMETRIC_MINISBLACK;
			colour_bands = 1;
		}
		else {
			/* Could be: RGB, CMYK, LAB, perhaps with extra alpha.
			 */
			if( write->im->Type == VIPS_INTERPRETATION_LAB || 
				write->im->Type == VIPS_INTERPRETATION_LABS ) {
				photometric = PHOTOMETRIC_CIELAB;
				colour_bands = 3;
			}
			else if( write->im->Type == VIPS_INTERPRETATION_CMYK &&
				write->im->Bands >= 4 ) {
				photometric = PHOTOMETRIC_SEPARATED;
				TIFFSetField( tif, 
					TIFFTAG_INKSET, INKSET_CMYK );
				colour_bands = 4;
			}
			else if( write->compression == COMPRESSION_JPEG &&
				write->im->Bands == 3 &&
				write->im->BandFmt == VIPS_FORMAT_UCHAR &&
				(!write->rgbjpeg && write->jpqual < 90) ) { 
				/* This signals to libjpeg that it can do
				 * YCbCr chrominance subsampling from RGB, not
				 * that we will supply the image as YCbCr.
				 */
				photometric = PHOTOMETRIC_YCBCR;
				TIFFSetField( tif, TIFFTAG_JPEGCOLORMODE, 
					JPEGCOLORMODE_RGB );
				colour_bands = 3;
			}
			else {
				/* Some kind of generic multi-band image ..
				 * save the first three bands as RGB, the rest
				 * as alpha.
				 */
				photometric = PHOTOMETRIC_RGB;
				colour_bands = 3;
			}
		}

		alpha_bands = VIPS_CLIP( 0, 
			write->im->Bands - colour_bands, MAX_ALPHA );
		if( alpha_bands > 0 ) { 
			uint16 v[MAX_ALPHA];
			int i;

			/* EXTRASAMPLE_UNASSALPHA means generic extra
			 * alpha-like channels. ASSOCALPHA means pre-multipled
			 * alpha only. 
			 */
			for( i = 0; i < alpha_bands; i++ )
				v[i] = EXTRASAMPLE_UNASSALPHA;
			TIFFSetField( tif, 
				TIFFTAG_EXTRASAMPLES, alpha_bands, v );
		}

		TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );
	}

	/* Layout.
	 */
	if( write->tile ) {
		TIFFSetField( tif, TIFFTAG_TILEWIDTH, write->tilew );
		TIFFSetField( tif, TIFFTAG_TILELENGTH, write->tileh );
	}
	else
		TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, write->tileh );

	if( layer->above ) 
		/* Pyramid layer.
		 */
		TIFFSetField( tif, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );

	/* Sample format.
	 */
	format = SAMPLEFORMAT_UINT;
	if( vips_band_format_isuint( write->im->BandFmt ) )
		format = SAMPLEFORMAT_UINT;
	else if( vips_band_format_isint( write->im->BandFmt ) )
		format = SAMPLEFORMAT_INT;
	else if( vips_band_format_isfloat( write->im->BandFmt ) )
		format = SAMPLEFORMAT_IEEEFP;
	else if( vips_band_format_iscomplex( write->im->BandFmt ) )
		format = SAMPLEFORMAT_COMPLEXIEEEFP;
	TIFFSetField( tif, TIFFTAG_SAMPLEFORMAT, format );

	return( 0 );
}
Exemple #6
0
/**
 * vips_image_guess_interpretation:
 * @image: image to guess for
 *
 * Return the #VipsInterpretation for an image, guessing a sane value if
 * the set value looks crazy.
 *
 * Returns: a sensible #VipsInterpretation for the image.
 */
VipsInterpretation
vips_image_guess_interpretation( const VipsImage *image )
{
	gboolean sane;

	sane = TRUE;

	/* Coding overrides interpretation.
	 */
	switch( image->Coding ) {
	case VIPS_CODING_LABQ:
		if( image->Type != VIPS_INTERPRETATION_LABQ )
			sane = FALSE;
		break;

	case VIPS_CODING_RAD:
		if( image->Type != VIPS_INTERPRETATION_RGB )
			sane = FALSE;
		break;

	default:
		break;
	}

	switch( image->Type ) {
	case VIPS_INTERPRETATION_MULTIBAND: 
		if( image->Bands == 1 )
			sane = FALSE;
		break;

	case VIPS_INTERPRETATION_B_W: 
		/* Don't test bands, we allow bands after the first to be
		 * unused extras, like alpha.
		 */
		break;

	case VIPS_INTERPRETATION_HISTOGRAM: 
		if( image->Xsize > 1 && image->Ysize > 1 )
			sane = FALSE;
		break;

	case VIPS_INTERPRETATION_FOURIER: 
		if( !vips_band_format_iscomplex( image->BandFmt ) )
			sane = FALSE;
		break;

	case VIPS_INTERPRETATION_XYZ: 
	case VIPS_INTERPRETATION_LAB: 
	case VIPS_INTERPRETATION_RGB: 
	case VIPS_INTERPRETATION_CMC: 
	case VIPS_INTERPRETATION_LCH: 
	case VIPS_INTERPRETATION_sRGB: 
	case VIPS_INTERPRETATION_HSV: 
	case VIPS_INTERPRETATION_scRGB: 
	case VIPS_INTERPRETATION_YXY: 
		if( image->Bands < 3 )
			sane = FALSE;
		break;

	case VIPS_INTERPRETATION_CMYK: 
		if( image->Bands < 4 )
			sane = FALSE;
		break;

	case  VIPS_INTERPRETATION_LABQ:
		if( image->Coding != VIPS_CODING_LABQ )
			sane = FALSE;
		break;

	case  VIPS_INTERPRETATION_LABS:
		if( image->BandFmt != VIPS_FORMAT_SHORT )
			sane = FALSE;
		break;

	case  VIPS_INTERPRETATION_RGB16:
		if( image->BandFmt == VIPS_FORMAT_CHAR ||
			image->BandFmt == VIPS_FORMAT_UCHAR ||
			image->Bands < 3 )
			sane = FALSE;
		break;

	case  VIPS_INTERPRETATION_GREY16:
		if( image->BandFmt == VIPS_FORMAT_CHAR ||
			image->BandFmt == VIPS_FORMAT_UCHAR )
			sane = FALSE;
		break;

	case  VIPS_INTERPRETATION_MATRIX:
		if( image->Bands != 1 )
			sane = FALSE;
		break;

	default:
		g_assert_not_reached();
	}

	if( sane )
		return( vips_image_get_interpretation( image ) );
	else
		return( vips_image_default_interpretation( image ) );
}