示例#1
0
static VipsAngle 
get_angle( VipsImage *im )
{
	VipsAngle angle;
	const char *orientation;

	angle = VIPS_ANGLE_0;

	if( vips_image_get_typeof( im, ORIENTATION ) && 
		!vips_image_get_string( im, ORIENTATION, &orientation ) ) {
		if( vips_isprefix( "6", orientation ) )
			angle = VIPS_ANGLE_90;
		else if( vips_isprefix( "8", orientation ) )
			angle = VIPS_ANGLE_270;
		else if( vips_isprefix( "3", orientation ) )
			angle = VIPS_ANGLE_180;

		/* Other values do rotate + mirror, don't bother handling them
		 * though, how common can mirroring be. 
		 *
		 * See:
		 *
		 * http://www.80sidea.com/archives/2316
		 */
	}

	return( angle );
}
示例#2
0
文件: exif.c 项目: jcupitt/libvips
/* Set the EXIF resolution from the vips xres/yres tags.
 */
static int
vips_exif_resolution_from_image( ExifData *ed, VipsImage *image )
{
	double xres, yres;
	const char *p;
	int unit;

	VIPS_DEBUG_MSG( "vips_exif_resolution_from_image: vips res of %g, %g\n",
		image->Xres, image->Yres );

	/* Default to inches, more progs support it.
	 */
	unit = 2;
	if( vips_image_get_typeof( image, VIPS_META_RESOLUTION_UNIT ) &&
		!vips_image_get_string( image, 
			VIPS_META_RESOLUTION_UNIT, &p ) ) {
		if( vips_isprefix( "cm", p ) ) 
			unit = 3;
		else if( vips_isprefix( "none", p ) ) 
			unit = 1;
	}

	switch( unit ) {
	case 1:
		xres = image->Xres;
		yres = image->Yres;
		break;

	case 2:
		xres = image->Xres * 25.4;
		yres = image->Yres * 25.4;
		break;

	case 3:
		xres = image->Xres * 10.0;
		yres = image->Yres * 10.0;
		break;

	default:
		g_warning( "%s", _( "unknown EXIF resolution unit" ) );
		return( 0 );
	}

	/* Main image xres/yres/unit are in ifd0. ifd1 has the thumbnail
	 * xres/yres/unit.
	 */
	vips_exif_set_tag( ed, 0, EXIF_TAG_X_RESOLUTION, 
		vips_exif_set_double, (void *) &xres );
	vips_exif_set_tag( ed, 0, EXIF_TAG_Y_RESOLUTION, 
		vips_exif_set_double, (void *) &yres );
	vips_exif_set_tag( ed, 0, EXIF_TAG_RESOLUTION_UNIT, 
		vips_exif_set_int, (void *) &unit );

	return( 0 );
}
示例#3
0
static void *
vips_fits_write_meta( VipsImage *image, 
	const char *field, GValue *value, void *a )
{
	VipsFits *fits = (VipsFits *) a;

	int status;
	const char *value_str;

	status = 0;

	/* We want fields which start "fits-".
	 */
	if( !vips_isprefix( "fits-", field ) )
		return( NULL );

	/* The value should be a refstring, since we wrote it in fits2vips 
	 * above ^^.
	 */
	value_str = vips_value_get_ref_string( value, NULL );

	VIPS_DEBUG_MSG( "vips_fits_write_meta: setting meta on fits image:\n" );
	VIPS_DEBUG_MSG( " value == \"%s\"\n", value_str );

	if( fits_write_record( fits->fptr, value_str, &status ) ) {
		vips_fits_error( status );
		return( a );
	}

	return( NULL );
}
示例#4
0
文件: vipspng.c 项目: jcupitt/libvips
static void *
write_png_comment( VipsImage *image, 
	const char *field, GValue *value, void *data )
{
	Write *write = (Write *) data;

	if( vips_isprefix( "png-comment-", field ) ) { 
		const char *str;
		int i;
		char key[80];

		if( vips_image_get_string( write->in, field, &str ) )
			return( image );

		if( sscanf( field, "png-comment-%d-%80s", &i, key ) != 2 ) {
			vips_error( "vips2png", 
				"%s", _( "bad png comment key" ) );
			return( image );
		}

		vips__png_set_text( write->pPng, write->pInfo, key, str );
	}

	return( NULL );
}
示例#5
0
/* Find the prefix part of a dir ... name is the name of this prog from argv0.
 *
 * dir					name		guess prefix
 *
 * /home/john/vips-7.6.4/bin/vips-7.6	vips-7.6	/home/john/vips-7.6.4
 * /usr/local/bin/ip			ip		/usr/local
 *
 * all other forms ... return NULL.
 */
static char *
extract_prefix( const char *dir, const char *name )
{
	char edir[PATH_MAX];
	char vname[PATH_MAX];
	int i;

#ifdef DEBUG
	printf( "extract_prefix: trying for dir = \"%s\", name = \"%s\"\n", 
		dir, name );
#endif /*DEBUG*/

	/* Is dir relative? Prefix with cwd.
	 */
	if( !g_path_is_absolute( dir ) ) {
		vips_snprintf( edir, PATH_MAX, "%s" G_DIR_SEPARATOR_S "%s",
			get_current_dir(), dir );
	}
	else {
		vips_strncpy( edir, dir, PATH_MAX );
	}

	/* Chop off the trailing prog name, plus the trailing
	 * G_DIR_SEPARATOR_S.
	 */
	if( !vips_ispostfix( edir, name ) ) 
		return( NULL );
	vips_strncpy( vname, edir, PATH_MAX );
	vname[strlen( edir ) - strlen( name ) - 1] = '\0';

	/* Remove any "/./", any trailing "/.", any trailing "/".
	 */
	for( i = 0; i < (int) strlen( vname ); i++ ) 
		if( vips_isprefix( G_DIR_SEPARATOR_S "." G_DIR_SEPARATOR_S, 
			vname + i ) )
			memcpy( vname + i, vname + i + 2, 
				strlen( vname + i + 2 ) + 1 );
	if( vips_ispostfix( vname, G_DIR_SEPARATOR_S "." ) )
		vname[strlen( vname ) - 2] = '\0';
	if( vips_ispostfix( vname, G_DIR_SEPARATOR_S ) )
		vname[strlen( vname ) - 1] = '\0';

#ifdef DEBUG
	printf( "extract_prefix: canonicalised path = \"%s\"\n", vname );
#endif /*DEBUG*/

	/* Ought to be a "/bin" at the end now.
	 */
	if( !vips_ispostfix( vname, G_DIR_SEPARATOR_S "bin" ) ) 
		return( NULL );
	vname[strlen( vname ) - strlen( G_DIR_SEPARATOR_S "bin" )] = '\0';

#ifdef DEBUG
	printf( "extract_prefix: found \"%s\"\n", vname );
#endif /*DEBUG*/

	return( vips_strdup( NULL, vname ) );
}
示例#6
0
文件: tiffsave.c 项目: DINKIN/libvips
static int
vips_foreign_save_tiff_build( VipsObject *object )
{
	VipsForeignSave *save = (VipsForeignSave *) object;
	VipsForeignSaveTiff *tiff = (VipsForeignSaveTiff *) object;

	const char *p;

	if( VIPS_OBJECT_CLASS( vips_foreign_save_tiff_parent_class )->
		build( object ) )
		return( -1 );

	/* Default xres/yres to the values from the image.
	 */
	if( !vips_object_argument_isset( object, "xres" ) )
		tiff->xres = save->ready->Xres * 10.0;
	if( !vips_object_argument_isset( object, "yres" ) )
		tiff->yres = save->ready->Yres * 10.0;

	/* resunit param overrides resunit metadata.
	 */
	if( !vips_object_argument_isset( object, "resunit" ) &&
		vips_image_get_typeof( save->ready, 
			VIPS_META_RESOLUTION_UNIT ) &&
		!vips_image_get_string( save->ready, 
			VIPS_META_RESOLUTION_UNIT, &p ) &&
		vips_isprefix( "in", p ) ) 
		tiff->resunit = VIPS_FOREIGN_TIFF_RESUNIT_INCH;

	if( tiff->resunit == VIPS_FOREIGN_TIFF_RESUNIT_INCH ) {
		tiff->xres *= 2.54;
		tiff->yres *= 2.54;
	}

	if( vips__tiff_write( save->ready, tiff->filename,
		tiff->compression, tiff->Q, tiff->predictor,
		tiff->profile,
		tiff->tile, tiff->tile_width, tiff->tile_height,
		tiff->pyramid,
		tiff->squash,
		tiff->miniswhite,
		tiff->resunit, tiff->xres, tiff->yres,
		tiff->bigtiff,
		tiff->rgbjpeg,
		tiff->properties ) )
		return( -1 );

	return( 0 );
}
示例#7
0
文件: exif.c 项目: jcupitt/libvips
static void *
vips_exif_image_field( VipsImage *image, 
	const char *field, GValue *value, void *data )
{
	ExifData *ed = (ExifData *) data;

	const char *string;
	int ifd;
	const char *p;
	ExifTag tag;

	if( !vips_isprefix( "exif-ifd", field ) ) 
		return( NULL );

	/* value must be a string.
	 */
	if( vips_image_get_string( image, field, &string ) ) {
		g_warning( _( "bad exif meta \"%s\"" ), field );
		return( NULL ); 
	}

	p = field + strlen( "exif-ifd" );
	ifd = atoi( p ); 

	for( ; isdigit( *p ); p++ )
		;
	if( *p != '-' ) {
		g_warning( _( "bad exif meta \"%s\"" ), field );
		return( NULL ); 
	}

	if( !(tag = exif_tag_from_name( p + 1 )) ) {
		g_warning( _( "bad exif meta \"%s\"" ), field );
		return( NULL ); 
	}

	vips_exif_set_tag( ed, ifd, tag, vips_exif_set_entry, (void *) string );

	return( NULL ); 
}
示例#8
0
文件: jpeg2vips.c 项目: jieah/libvips
/* Read a cinfo to a VIPS image. Set invert_pels if the pixel reader needs to
 * do 255-pel.
 */
static int
read_jpeg_header( ReadJpeg *jpeg, VipsImage *out )
{
    struct jpeg_decompress_struct *cinfo = &jpeg->cinfo;

    jpeg_saved_marker_ptr p;
    VipsInterpretation interpretation;
    double xres, yres;

    /* Capture app2 sections here for assembly.
     */
    void *app2_data[MAX_APP2_SECTIONS] = { 0 };
    size_t app2_data_length[MAX_APP2_SECTIONS] = { 0 };
    size_t 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 = jpeg->shrink;
    cinfo->scale_num = 1;
    jpeg_calc_output_dimensions( cinfo );

    jpeg->invert_pels = FALSE;
    switch( cinfo->out_color_space ) {
    case JCS_GRAYSCALE:
        interpretation = VIPS_INTERPRETATION_B_W;
        break;

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

    case JCS_RGB:
    default:
        interpretation = VIPS_INTERPRETATION_sRGB;
        break;
    }

    /* Get the jfif resolution. exif may overwrite this later.
     */
    xres = 1.0;
    yres = 1.0;
    if( cinfo->saw_JFIF_marker &&
            cinfo->X_density != 1U &&
            cinfo->Y_density != 1U ) {
#ifdef DEBUG
        printf( "read_jpeg_header: seen jfif _density %d, %d\n",
                cinfo->X_density, cinfo->Y_density );
#endif /*DEBUG*/

        switch( cinfo->density_unit ) {
        case 1:
            /* Pixels per inch.
             */
            xres = cinfo->X_density / 25.4;
            yres = cinfo->Y_density / 25.4;
            break;

        case 2:
            /* Pixels per cm.
             */
            xres = cinfo->X_density / 10.0;
            yres = cinfo->Y_density / 10.0;
            break;

        default:
            vips_warn( "VipsJpeg",
                       "%s", _( "unknown JFIF resolution unit" ) );
            break;
        }

#ifdef DEBUG
        printf( "read_jpeg_header: seen jfif resolution %g, %g p/mm\n",
                xres, yres );
#endif /*DEBUG*/
    }

    /* Set VIPS header.
     */
    vips_image_init_fields( out,
                            cinfo->output_width, cinfo->output_height,
                            cinfo->output_components,
                            VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
                            interpretation,
                            xres, yres );

    vips_demand_hint( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );

    /* Interlaced jpegs need lots of memory to read, so our caller needs
     * to know.
     */
    (void) vips_image_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 ) {
#ifdef DEBUG
        {
            printf( "read_jpeg_header: seen %d bytes of APP%d\n",
            p->data_length,
            p->marker - JPEG_APP0 );

            for( i = 0; i < 10; i++ )
                printf( "\t%d) '%c' (%d)\n",
                i, p->data[i], p->data[i] );
        }
#endif /*DEBUG*/

        switch( p->marker ) {
        case JPEG_APP0 + 1:
            /* Possible EXIF or XMP data.
             */
            if( p->data_length > 4 &&
                    vips_isprefix( "Exif", (char *) p->data ) ) {
                if( parse_exif( out,
                                p->data, p->data_length ) ||
                        attach_blob( out, VIPS_META_EXIF_NAME,
                                     p->data, p->data_length ) )
                    return( -1 );
            }

            if( p->data_length > 4 &&
                    vips_isprefix( "http", (char *) p->data ) &&
                    attach_blob( out, VIPS_META_XMP_NAME,
                                 p->data, p->data_length ) )
                return( -1 );

            break;

        case JPEG_APP0 + 2:
            /* Possible ICC profile.
             */
            if( p->data_length > 14 &&
                    vips_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;

        case JPEG_APP0 + 13:
            /* Possible IPCT data block.
             */
            if( p->data_length > 5 &&
                    vips_isprefix( "Photo", (char *) p->data ) &&
                    attach_blob( out, VIPS_META_IPCT_NAME,
                                 p->data, p->data_length ) )
                return( -1 );
            break;

        default:
            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 %zd byte ICC profile\n",
                data_length );
#endif /*DEBUG*/

        if( !(data = vips_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];
        }

        vips_image_set_blob( out, VIPS_META_ICC_NAME,
                             (VipsCallbackFn) vips_free, data, data_length );
    }

    return( 0 );
}