ExifData *
exif_data_new_mem (ExifMem *mem)
{
	ExifData *data;
	unsigned int i;

	if (!mem) 
		return NULL;

	data = exif_mem_alloc (mem, sizeof (ExifData));
	if (!data) 
		return (NULL);
	data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate));
	if (!data->priv) { 
	  	exif_mem_free (mem, data); 
		return (NULL); 
	}
	data->priv->ref_count = 1;

	data->priv->mem = mem;
	exif_mem_ref (mem);

	for (i = 0; i < EXIF_IFD_COUNT; i++) {
		data->ifd[i] = exif_content_new_mem (data->priv->mem);
		if (!data->ifd[i]) {
			exif_data_free (data);
			return (NULL);
		}
		data->ifd[i]->parent = data;
	}

	/* Default options */
#ifndef NO_VERBOSE_TAG_STRINGS
	/*
	 * When the tag list is compiled away, setting this option prevents
	 * any tags from being loaded
	 */
	exif_data_set_option (data, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
#endif
	exif_data_set_option (data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);

	/* Default data type: none */
	exif_data_set_data_type (data, EXIF_DATA_TYPE_COUNT);

	return (data);
}
Ejemplo n.º 2
0
ExifData* load_file (file_t* file)
{
  ExifData* ed = exif_data_new ();
  exif_data_unset_option (ed, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
  exif_data_set_option (ed, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS);
  exif_data_load_data (ed, file->addr, file->st.st_size);
  return ed;
}
Ejemplo n.º 3
0
static void load_exif_tags( ExifData * ed , JSON::Object & tags )
{
	tplog2( "  LOADING EXIF TAGS" );

	exif_data_set_option( ed , EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS );
	exif_data_set_option( ed , EXIF_DATA_OPTION_FOLLOW_SPECIFICATION );

	exif_data_fix( ed );

	ExifClosure closure;

	closure.exif_data = ed;
	closure.tags = & tags;

	for ( int i = 0; i < EXIF_IFD_COUNT; ++i )
	{
		if ( ExifContent * c = ed->ifd[i] )
		{
			exif_content_foreach_entry( c , foreach_exif_entry , & closure );
		}
	}

	tplog2( "  LOADED EXIF TAGS" );
}
Ejemplo n.º 4
0
/* Examine the metadata tags on the image and update the EXIF block.
 */
int
vips__exif_update( VipsImage *image )
{
	unsigned char *data;
	size_t length;
	unsigned int idl;
	ExifData *ed;

	/* Either parse from the embedded EXIF, or if there's none, make
	 * some fresh EXIF we can write the resolution to.
	 */
	if( vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) ) {
		if( vips_image_get_blob( image, VIPS_META_EXIF_NAME, 
			(void *) &data, &length ) )
			return( -1 );

		if( !(ed = exif_data_new_from_data( data, length )) )
			return( -1 );
	}
	else  {
		ed = exif_data_new();

		exif_data_set_option( ed, 
			EXIF_DATA_OPTION_FOLLOW_SPECIFICATION );
		exif_data_set_data_type( ed, EXIF_DATA_TYPE_COMPRESSED );
		exif_data_set_byte_order( ed, EXIF_BYTE_ORDER_INTEL );
	
		/* Create the mandatory EXIF fields with default data.
		 */
		exif_data_fix( ed );
	}

	/* Update EXIF tags from the image metadata.
	 */
	vips_exif_update( ed, image );

	/* Update EXIF resolution from the vips image header.
	 */
	if( vips_exif_resolution_from_image( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF image dimensions from the vips image header.
	 */
	if( vips_exif_set_dimensions( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF orientation from the vips image header.
	 */
	if( vips_exif_set_orientation( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update the thumbnail.
	 */
	if( vips_exif_set_thumbnail( ed, image ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Reserialise and write. exif_data_save_data() returns an int for some
	 * reason.
	 */
	exif_data_save_data( ed, &data, &idl );
	if( !idl ) {
		vips_error( "exif", "%s", _( "error saving EXIF" ) );
		exif_data_free( ed );
		return( -1 );
	}
	length = idl;

#ifdef DEBUG
	printf( "vips__exif_update: generated %zd bytes of EXIF\n", length  );
#endif /*DEBUG*/

	vips_image_set_blob( image, VIPS_META_EXIF_NAME, 
		(VipsCallbackFn) vips_free, data, length );

	exif_data_free( ed );

	return( 0 );
}
Ejemplo n.º 5
0
ExifData* createExifData(const CameraParameters& params) {
    ExifData* exifData = exif_data_new();

    exif_data_set_option(exifData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
    exif_data_set_data_type(exifData, EXIF_DATA_TYPE_COMPRESSED);
    exif_data_set_byte_order(exifData, EXIF_BYTE_ORDER_INTEL);

    // Create mandatory exif fields and set their default values
    exif_data_fix(exifData);

    float triplet[3];
    float floatValue = 0.0f;
    const char* stringValue;
    int64_t degrees;

    // Datetime, creating and initializing a datetime tag will automatically
    // set the current date and time in the tag so just do that.
    createEntry(exifData, EXIF_IFD_0, EXIF_TAG_DATE_TIME);

    // Make and model
    createEntry(exifData, EXIF_IFD_0, EXIF_TAG_MAKE, "Emulator-Goldfish");
    createEntry(exifData, EXIF_IFD_0, EXIF_TAG_MODEL, "Emulator-Goldfish");

    // Picture size
    int width = -1, height = -1;
    params.getPictureSize(&width, &height);
    if (width >= 0 && height >= 0) {
        createEntry(exifData, EXIF_IFD_EXIF,
                    EXIF_TAG_PIXEL_X_DIMENSION, width);
        createEntry(exifData, EXIF_IFD_EXIF,
                    EXIF_TAG_PIXEL_Y_DIMENSION, height);
    }
    // Orientation
    if (getCameraParam(params,
                       CameraParameters::KEY_ROTATION,
                       &degrees)) {
        // Exif orientation values, please refer to
        // http://www.exif.org/Exif2-2.PDF, Section 4.6.4-A-Orientation
        // Or these websites:
        // http://sylvana.net/jpegcrop/exif_orientation.html
        // http://www.impulseadventure.com/photo/exif-orientation.html
        enum {
            EXIF_ROTATE_CAMERA_CW0 = 1,
            EXIF_ROTATE_CAMERA_CW90 = 6,
            EXIF_ROTATE_CAMERA_CW180 = 3,
            EXIF_ROTATE_CAMERA_CW270 = 8,
        };
        uint16_t exifOrien = 1;
        switch (degrees) {
            case 0:
                exifOrien = EXIF_ROTATE_CAMERA_CW0;
                break;
            case 90:
                exifOrien = EXIF_ROTATE_CAMERA_CW90;
                break;
            case 180:
                exifOrien = EXIF_ROTATE_CAMERA_CW180;
                break;
            case 270:
                exifOrien = EXIF_ROTATE_CAMERA_CW270;
                break;
        }
        createEntry(exifData, EXIF_IFD_0, EXIF_TAG_ORIENTATION, exifOrien);
    }
    // Focal length
    if (getCameraParam(params,
                       CameraParameters::KEY_FOCAL_LENGTH,
                       &floatValue)) {
        createEntry(exifData, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH, floatValue);
    }
    // GPS latitude and reference, reference indicates sign, store unsigned
    if (getCameraParam(params,
                       CameraParameters::KEY_GPS_LATITUDE,
                       &floatValue)) {
        convertGpsCoordinate(floatValue, &triplet);
        createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, triplet);

        const char* ref = floatValue < 0.0f ? "S" : "N";
        createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, ref);
    }
    // GPS longitude and reference, reference indicates sign, store unsigned
    if (getCameraParam(params,
                       CameraParameters::KEY_GPS_LONGITUDE,
                       &floatValue)) {
        convertGpsCoordinate(floatValue, &triplet);
        createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, triplet);

        const char* ref = floatValue < 0.0f ? "W" : "E";
        createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, ref);
    }
    // GPS altitude and reference, reference indicates sign, store unsigned
    if (getCameraParam(params,
                       CameraParameters::KEY_GPS_ALTITUDE,
                       &floatValue)) {
        createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE,
                    static_cast<float>(fabs(floatValue)));

        // 1 indicated below sea level, 0 indicates above sea level
        uint8_t ref = floatValue < 0.0f ? 1 : 0;
        createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE_REF, ref);
    }
    // GPS timestamp and datestamp
    int64_t timestamp = 0;
    if (getCameraParam(params,
                       CameraParameters::KEY_GPS_TIMESTAMP,
                       &timestamp)) {
        std::string date;
        if (convertTimestampToTimeAndDate(timestamp, &triplet, &date)) {
            createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_TIME_STAMP,
                        triplet, 1.0f);
            createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_DATE_STAMP,
                        date.c_str());
        }
    }

    // GPS processing method
    if (getCameraParam(params,
                       CameraParameters::KEY_GPS_PROCESSING_METHOD,
                       &stringValue)) {
        std::vector<unsigned char> data;
        // Because this is a tag with an undefined format it has to be prefixed
        // with the encoding type. Insert an ASCII prefix first, then the
        // actual string. Undefined tags do not have to be null terminated.
        data.insert(data.end(),
                    std::begin(kAsciiPrefix),
                    std::end(kAsciiPrefix));
        data.insert(data.end(), stringValue, stringValue + strlen(stringValue));
        createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_PROCESSING_METHOD,
                    &data[0], data.size());
    }

    return exifData;
}
Ejemplo n.º 6
0
static int
write_exif( Write *write )
{
#ifdef HAVE_EXIF
	unsigned char *data;
	size_t data_length;
	unsigned int idl;
	ExifData *ed;

	/* Either parse from the embedded EXIF, or if there's none, make
	 * some fresh EXIF we can write the resolution to.
	 */
	if( vips_image_get_typeof( write->in, VIPS_META_EXIF_NAME ) ) {
		if( vips_image_get_blob( write->in, VIPS_META_EXIF_NAME, 
			(void *) &data, &data_length ) )
			return( -1 );

		if( !(ed = exif_data_new_from_data( data, data_length )) )
			return( -1 );
	}
	else  {
		ed = exif_data_new();

		exif_data_set_option( ed, 
			EXIF_DATA_OPTION_FOLLOW_SPECIFICATION );
		exif_data_set_data_type( ed, EXIF_DATA_TYPE_COMPRESSED );
		exif_data_set_byte_order( ed, EXIF_BYTE_ORDER_INTEL );
	
		/* Create the mandatory EXIF fields with default data.
		 */
		exif_data_fix( ed );
	}

	/* Update EXIF tags from the image metadata.
	 */
	vips_exif_update( ed, write->in );

	/* Update EXIF resolution from the vips image header.
	 */
	if( vips__set_exif_resolution( ed, write->in ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF image dimensions from the vips image header.
	 */
	if( set_exif_dimensions( ed, write->in ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Update EXIF orientation from the vips image header.
	 */
	if( set_exif_orientation( ed, write->in ) ) {
		exif_data_free( ed );
		return( -1 );
	}

	/* Reserialise and write. exif_data_save_data() returns an int for some
	 * reason.
	 */
	exif_data_save_data( ed, &data, &idl );
	if( !idl ) {
		vips_error( "VipsJpeg", "%s", _( "error saving EXIF" ) );
		exif_data_free( ed );
		return( -1 );
	}
	data_length = idl;

#ifdef DEBUG
	printf( "write_exif: attaching %zd bytes of EXIF\n", data_length  );
#endif /*DEBUG*/

	exif_data_free( ed );
	jpeg_write_marker( &write->cinfo, JPEG_APP0 + 1, data, data_length );
	free( data );
#else /*!HAVE_EXIF*/
	/* No libexif ... just copy the embedded EXIF over.
	 */
	if( write_blob( write, VIPS_META_EXIF_NAME, JPEG_APP0 + 1 ) )
		return( -1 );
#endif /*!HAVE_EXIF*/

	return( 0 );
}