/** * a_geotag_get_exif_date_from_file: * @filename: The image file to process * @has_GPS_info: Returns whether the file has existing GPS information * * Returns: An allocated string with the date and time in EXIF_DATE_FORMAT, otherwise NULL if some kind of failure * * Here EXIF processing is used to get time information * */ gchar* a_geotag_get_exif_date_from_file ( const gchar *filename, gboolean *has_GPS_info ) { gchar* datetime = NULL; ExifData *ed = exif_data_new_from_file ( filename ); // Detect EXIF load failure if ( !ed ) return datetime; gchar str[128]; ExifEntry *ee; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); datetime = g_strdup ( str ); } // Check GPS Info *has_GPS_info = FALSE; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_VERSION_ID); // Confirm this has a GPS Id - normally "2.0.0.0" or "2.2.0.0" if ( ee && ee->components == 4 ) *has_GPS_info = TRUE; exif_data_free ( ed ); return datetime; }
/** * Updates the sensor by reading the current value into it */ static void update(CAMERA_STATE *camera, struct sensor *sensor) { if (!sensor->enabled) return; struct state *state = (struct state *) sensor; if (!state->loader) state->loader = exif_loader_new(); exif_loader_reset(state->loader); exif_loader_write(state->loader, camera->imagedata.buffer, camera->imagedata.pos); ExifData *data = exif_loader_get_data(state->loader); ExifByteOrder bo = exif_data_get_byte_order(data); int valid = get_shutter_speed(data, bo, &state->shutter_speed); if (valid) valid = get_aperture(data, bo, &state->aperture); if (valid) valid = getDouble(data, bo, EXIF_TAG_ISO_SPEED_RATINGS, &state->iso); exif_data_free(data); if (valid) { // Calculate the light level state->light_level = (2.0 * log(state->aperture) - log(state->shutter_speed) - log(state->iso / 100.0)) / log(2.0); // Update the sensor sensor_log(camera, &state->sensor, (int) (state->light_level * 1000), "Lvl %.1f", state->light_level); } }
///@todo create a dedicated EXIF class QString ImageImporter::getExifData(const QString& filename, ExifTag tag) { ExifData* ed = exif_data_new_from_file(filename.ascii()); ExifContent* c0, * c1, * cExif; c0 = ed->ifd[EXIF_IFD_0]; c1 = ed->ifd[EXIF_IFD_1]; cExif = ed->ifd[EXIF_IFD_EXIF]; switch (tag) { case EXIF_TAG_MAKE: case EXIF_TAG_MODEL: case EXIF_TAG_SOFTWARE: return getEntry(c0, tag); break; case EXIF_TAG_EXPOSURE_TIME: case EXIF_TAG_FNUMBER: case EXIF_TAG_PIXEL_X_DIMENSION: case EXIF_TAG_PIXEL_Y_DIMENSION: case EXIF_TAG_FLASH: case EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM: case EXIF_TAG_ISO_SPEED_RATINGS: case EXIF_TAG_DATE_TIME_ORIGINAL: return getEntry(cExif, tag); break; default: return ""; break; } exif_data_free(ed); }
long GalleryUtil::GetNaturalRotation(const unsigned char *buffer, int size) { long rotateAngle = 0; #ifdef EXIF_SUPPORT try { ExifData *data = exif_data_new_from_data(buffer, size); if (data) { rotateAngle = GetNaturalRotation(data); exif_data_free(data); } else { LOG(VB_FILE, LOG_ERR, LOC + "Could not load exif data from buffer"); } } catch (...) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to extract EXIF headers from buffer"); } #else // Shut the compiler up about the unused argument (void)buffer; (void)size; #endif return rotateAngle; }
void imFileFormatJPEG::iWriteExifAttrib(imAttribTable* attrib_table) { ExifData* exif = exif_data_new(); ExifByteOrder byte_order; if (imBinCPUByteOrder() == IM_LITTLEENDIAN) byte_order = EXIF_BYTE_ORDER_INTEL; else byte_order = EXIF_BYTE_ORDER_MOTOROLA; exif_data_set_byte_order(exif, byte_order); attrib_table->ForEach(exif, (imAttribTableCallback)iExifWriteTag); imbyte* data = NULL; unsigned int data_size = 0; exif_data_save_data(exif, &data, &data_size); if (data) { jpeg_write_marker(&this->cinfo, JPEG_APP0+1, data, data_size); free(data); } exif_data_free(exif); }
long GalleryUtil::GetNaturalRotation(const QString &filePathString) { long rotateAngle = 0; #ifdef EXIF_SUPPORT QByteArray filePathBA = filePathString.toLocal8Bit(); const char *filePath = filePathBA.constData(); try { ExifData *data = exif_data_new_from_file(filePath); if (data) { rotateAngle = GetNaturalRotation(data); exif_data_free(data); } else { LOG(VB_FILE, LOG_ERR, LOC + QString("Could not load exif data from '%1'") .arg(filePath)); } } catch (...) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to extract EXIF headers from '%1'") .arg(filePath)); } #else // Shut the compiler up about the unused argument (void)filePathString; #endif return rotateAngle; }
/** * a_geotag_create_waypoint_positioned: * @filename: The image file to process * @coord: The location for positioning the Waypoint * @name: Returns a name for the Waypoint (can be NULL) * * Returns: An allocated Waypoint or NULL if Waypoint could not be generated * * Here EXIF processing is used to get non position related information (i.e. just the comment) * */ VikWaypoint* a_geotag_create_waypoint_positioned ( const gchar *filename, VikCoord coord, gdouble alt, gchar **name ) { *name = NULL; VikWaypoint *wp = vik_waypoint_new(); wp->visible = TRUE; wp->coord = coord; wp->altitude = alt; ExifData *ed = exif_data_new_from_file ( filename ); // Set info from exif values if ( ed ) { wp->comment = geotag_get_exif_comment ( ed ); gchar str[128]; ExifEntry *ee; // Name ee = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_XP_TITLE); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); *name = g_strdup ( str ); } // Finished with EXIF exif_data_free ( ed ); } vik_waypoint_set_image ( wp, filename ); return wp; }
// Implementation using libexif void ImageResolution::readexif(char const *fn) { ExifData *ed; ed = exif_data_new_from_file(fn); if (!ed) return; ExifByteOrder byte_order = exif_data_get_byte_order(ed); ExifEntry *xres = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_X_RESOLUTION); ExifEntry *yres = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_Y_RESOLUTION); ExifEntry *unit = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_RESOLUTION_UNIT); if (xres && yres) { x_ = exifDouble(xres, byte_order); y_ = exifDouble(yres, byte_order); if (unit) { double u = exifDouble(unit, byte_order); if (u==3) { x_ *= 2.54; y_ *= 2.54; } } ok_ = true; } exif_data_free(ed); }
QPixmap ExifPixmap::createPixmap(QString path) { ExifData *exifData = exif_data_new_from_file(path.toStdString().c_str()); int orientation = 0; if(exifData) { ExifByteOrder byteOrder = exif_data_get_byte_order(exifData); ExifEntry *exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION); if(exifEntry) { orientation = exif_get_short(exifEntry->data, byteOrder); } exif_data_free(exifData); } QPixmap pic(path); /* 0th Row 0th Column 1 top left side 2 top right side 3 bottom right side 4 bottom left side 5 left side top 6 right side top 7 right side bottom 8 left side bottom */ QTransform t; switch(orientation) { // TODO : test flips case 1: break; case 2: t.scale(-1,1); break; case 3: t.rotate(180); break; case 4: t.rotate(180); t.scale(-1,1); break; case 5: t.rotate(90); t.scale(-1,1); break; case 6: t.rotate(90); break; case 7: t.rotate(-90); t.scale(-1,1); break; case 8: t.rotate(-90); break; default: break; } return pic.transformed(t); }
/** * a_geotag_get_exif_date_from_file: * @filename: The image file to process * @has_GPS_info: Returns whether the file has existing GPS information * * Returns: An allocated string with the date and time in EXIF_DATE_FORMAT, otherwise NULL if some kind of failure * * Here EXIF processing is used to get time information * */ gchar* a_geotag_get_exif_date_from_file ( const gchar *filename, gboolean *has_GPS_info ) { gchar* datetime = NULL; *has_GPS_info = FALSE; #ifdef HAVE_LIBGEXIV2 GExiv2Metadata *gemd = gexiv2_metadata_new (); if ( gexiv2_metadata_open_path ( gemd, filename, NULL ) ) { gdouble lat, lon; *has_GPS_info = ( gexiv2_metadata_get_gps_longitude(gemd,&lon) && gexiv2_metadata_get_gps_latitude(gemd,&lat) ); // Prefer 'Photo' version over 'Image' if ( gexiv2_metadata_has_tag ( gemd, "Exif.Photo.DateTimeOriginal" ) ) datetime = g_strdup ( gexiv2_metadata_get_tag_interpreted_string ( gemd, "Exif.Photo.DateTimeOriginal" ) ); else datetime = g_strdup ( gexiv2_metadata_get_tag_interpreted_string ( gemd, "Exif.Image.DateTimeOriginal" ) ); } metadata_free ( gemd ); #else #ifdef HAVE_LIBEXIF ExifData *ed = exif_data_new_from_file ( filename ); // Detect EXIF load failure if ( !ed ) return datetime; gchar str[128]; ExifEntry *ee; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); datetime = g_strdup ( str ); } // Check GPS Info ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_VERSION_ID); // Confirm this has a GPS Id - normally "2.0.0.0" or "2.2.0.0" if ( ee && ee->components == 4 ) *has_GPS_info = TRUE; // Check other basic GPS fields exist too // I have encountered some images which have just the EXIF_TAG_GPS_VERSION_ID but nothing else // So to confirm check more EXIF GPS TAGS: ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE); if ( !ee ) *has_GPS_info = FALSE; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE); if ( !ee ) *has_GPS_info = FALSE; exif_data_free ( ed ); #endif #endif return datetime; }
void exif_data_unref (ExifData *data) { if (!data) return; data->priv->ref_count--; if (!data->priv->ref_count) exif_data_free (data); }
/** * a_geotag_waypoint_positioned: * @filename: The image file to process * @coord: The location for positioning the Waypoint * @name: Returns a name for the Waypoint (can be NULL) * @waypoint: An existing waypoint to update (can be NULL to generate a new waypoint) * * Returns: An allocated waypoint if the input waypoint is NULL, * otherwise the passed in waypoint is updated * * Here EXIF processing is used to get non position related information (i.e. just the comment) * */ VikWaypoint* a_geotag_waypoint_positioned ( const gchar *filename, VikCoord coord, gdouble alt, gchar **name, VikWaypoint *wp ) { *name = NULL; if ( wp == NULL ) { // Need to create waypoint wp = vik_waypoint_new(); wp->visible = TRUE; } wp->coord = coord; wp->altitude = alt; #ifdef HAVE_LIBGEXIV2 GExiv2Metadata *gemd = gexiv2_metadata_new (); if ( gexiv2_metadata_open_path ( gemd, filename, NULL ) ) { wp->comment = geotag_get_exif_comment ( gemd ); if ( gexiv2_metadata_has_tag ( gemd, "Exif.Image.XPTitle" ) ) *name = g_strdup ( gexiv2_metadata_get_tag_interpreted_string ( gemd, "Exif.Image.XPTitle" ) ); } metadata_free ( gemd ); #else #ifdef HAVE_LIBEXIF ExifData *ed = exif_data_new_from_file ( filename ); // Set info from exif values if ( ed ) { wp->comment = geotag_get_exif_comment ( ed ); gchar str[128]; ExifEntry *ee; // Name ee = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_XP_TITLE); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); *name = g_strdup ( str ); } // Finished with EXIF exif_data_free ( ed ); } #endif #endif vik_waypoint_set_image ( wp, filename ); return wp; }
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); }
static int parse_exif( VipsImage *im, void *data, int data_length ) { #ifdef HAVE_EXIF { ExifData *ed; VipsExif ve; if( !(ed = exif_data_new_from_data( data, data_length )) ) return( -1 ); #ifdef DEBUG_VERBOSE show_tags( ed ); show_values( ed ); #endif /*DEBUG_VERBOSE*/ /* Attach informational fields for what we find. FIXME ... better to have this in the UI layer? Or we could attach non-human-readable tags here (int, double etc) and then move the human stuff to the UI layer? */ ve.image = im; ve.ed = ed; exif_data_foreach_content( ed, (ExifDataForeachContentFunc) attach_exif_content, &ve ); /* Look for resolution fields and use them to set the VIPS * xres/yres fields. */ res_from_exif( im, ed ); attach_thumbnail( im, ed ); exif_data_free( ed ); } #endif /*HAVE_EXIF*/ return( 0 ); }
/** * a_geotag_get_position: * * @filename: The (JPG) file with EXIF information in it * * Returns: The position in LatLon format. * It will be 0,0 if some kind of failure occurs. */ struct LatLon a_geotag_get_position ( const gchar *filename ) { struct LatLon ll = { 0.0, 0.0 }; #ifdef HAVE_LIBGEXIV2 GExiv2Metadata *gemd = gexiv2_metadata_new (); if ( gexiv2_metadata_open_path ( gemd, filename, NULL ) ) { gdouble lat; gdouble lon; gdouble alt; if ( gexiv2_metadata_get_gps_info ( gemd, &lon, &lat, &alt ) ) { ll.lat = lat; ll.lon = lon; } } metadata_free ( gemd ); #else #ifdef HAVE_LIBEXIF // open image with libexif ExifData *ed = exif_data_new_from_file ( filename ); // Detect EXIF load failure if ( !ed ) return ll; ExifEntry *ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_VERSION_ID); // Confirm this has a GPS Id - normally "2.0.0.0" or "2.2.0.0" if ( ! ( ee && ee->components == 4 ) ) goto MyReturn0; ll = get_latlon ( ed ); MyReturn0: // Finished with EXIF exif_data_free ( ed ); #endif #endif return ll; }
void psd_image_resource_free(psd_context * context) { psd_int i; psd_alpha_channel_free(context); psd_freeif(context->layer_group_id); psd_freeif(context->thumbnail_resource.jfif_data); psd_freeif(context->thumbnail_resource.thumbnail_data); psd_freeif(context->version_info.writer_name); psd_freeif(context->version_info.reader_name); psd_freeif(context->grid_guides.guide_coordinate); psd_freeif(context->grid_guides.guide_direction); psd_freeif(context->slices_resource.slices_resource_block); psd_freeif(context->color_samplers.resource); for (i = 0; i < context->url_list.number_of_urls; i ++) psd_freeif(context->url_list.items[i].name); psd_freeif(context->url_list.items); #ifdef PSD_INCLUDDE_LIBEXIF exif_data_free((ExifData *)context->exif_data); #else psd_freeif(context->exif_data); #endif #ifdef PSD_INCLUDE_LIBXML xmlFreeDoc((xmlDocPtr)context->XMP_metadata); #else psd_freeif(context->XMP_metadata); #endif #ifdef PSD_GET_PATH_RESOURCE psd_path_free(context); #endif }
void freeExifData(ExifData* exifData) { exif_data_free(exifData); }
void imFileFormatJPEG::iReadExifAttrib(unsigned char* data, int data_length, imAttribTable* attrib_table) { ExifData* exif = exif_data_new_from_data(data, data_length); if (!exif) return; void* value = NULL; int c, value_size = 0; ExifByteOrder byte_order = exif_data_get_byte_order(exif); for (int ifd = 0; ifd < EXIF_IFD_COUNT; ifd++) { if (ifd == EXIF_IFD_1 || ifd == EXIF_IFD_INTEROPERABILITY) // Skip thumbnail and interoperability continue; ExifContent *content = exif->ifd[ifd]; if (content && content->count) { for (int j = 0; j < (int)content->count; j++) { ExifEntry *entry = content->entries[j]; int type = 0; const char* name = exif_tag_get_name_in_ifd(entry->tag, (ExifIfd)ifd); if (!name) continue; if (value_size < (int)entry->size) { value = realloc(value, entry->size); value_size = entry->size; } int format_size = exif_format_get_size(entry->format); if (entry->tag == EXIF_TAG_RESOLUTION_UNIT) { int res_unit = (int)exif_get_short (entry->data, byte_order); if (res_unit == 2) attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPI"); else if (res_unit == 3) attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPC"); continue; } switch (entry->format) { case EXIF_FORMAT_UNDEFINED: case EXIF_FORMAT_ASCII: case EXIF_FORMAT_SBYTE: case EXIF_FORMAT_BYTE: { type = IM_BYTE; imbyte *bvalue = (imbyte*)value; for (c = 0; c < (int)entry->components; c++) bvalue[c] = entry->data[c]; } break; case EXIF_FORMAT_SSHORT: { type = IM_SHORT; short *svalue = (short*)value; for (c = 0; c < (int)entry->components; c++) svalue[c] = exif_get_short(entry->data + format_size * c, byte_order); } break; case EXIF_FORMAT_SHORT: { type = IM_USHORT; imushort *usvalue = (imushort*)value; for (c = 0; c < (int)entry->components; c++) usvalue[c] = exif_get_short(entry->data + format_size * c, byte_order); } break; case EXIF_FORMAT_LONG: { type = IM_INT; int *ivalue = (int*)value; for (c = 0; c < (int)entry->components; c++) ivalue[c] = (int)exif_get_long(entry->data + format_size * c, byte_order); } break; case EXIF_FORMAT_SLONG: { type = IM_INT; int *ivalue = (int*)value; for (c = 0; c < (int)entry->components; c++) ivalue[c] = (int)exif_get_slong(entry->data + format_size * c, byte_order); } break; case EXIF_FORMAT_RATIONAL: { ExifRational v_rat; type = IM_FLOAT; float *fvalue = (float*)value; for (c = 0; c < (int)entry->components; c++) { v_rat = exif_get_rational(entry->data + format_size * c, byte_order); fvalue[c] = (float)v_rat.numerator / (float)v_rat.denominator; } } break; case EXIF_FORMAT_SRATIONAL: { ExifSRational v_srat; type = IM_FLOAT; float *fvalue = (float*)value; for (c = 0; c < (int)entry->components; c++) { v_srat = exif_get_srational(entry->data + format_size * c, byte_order); fvalue[c] = (float)v_srat.numerator / (float)v_srat.denominator; } } break; case EXIF_FORMAT_FLOAT: // defined but unsupported in libEXIF case EXIF_FORMAT_DOUBLE: // defined but unsupported in libEXIF break; } attrib_table->Set(name, type, entry->components, value); } } } if (value) free(value); exif_data_free(exif); }
long GalleryUtil::GetNaturalRotation(const QString &filePathString) { long rotateAngle = 0; #ifdef EXIF_SUPPORT QByteArray filePathBA = filePathString.toLocal8Bit(); const char *filePath = filePathBA.constData(); try { char *exifvalue = new char[1024]; ExifData *data = exif_data_new_from_file (filePath); if (data) { for (int i = 0; i < EXIF_IFD_COUNT; i++) { ExifEntry *entry = exif_content_get_entry (data->ifd[i], EXIF_TAG_ORIENTATION); ExifByteOrder byteorder = exif_data_get_byte_order (data); if (entry) { ExifShort v_short = exif_get_short (entry->data, byteorder); VERBOSE(VB_GENERAL|VB_EXTRA, QString("Exif entry=%1").arg(v_short)); /* See http://sylvana.net/jpegcrop/exif_orientation.html*/ if (v_short == 8) { rotateAngle = -90; } else if (v_short == 6) { rotateAngle = 90; } break; } } exif_data_free(data); } else { VERBOSE(VB_FILE, LOC_ERR + QString("Could not load exif data from '%1'") .arg(filePath)); } delete [] exifvalue; #if 0 Exiv2::ExifData exifData; int rc = exifData.read(filePath); if (!rc) { Exiv2::ExifKey key = Exiv2::ExifKey("Exif.Image.Orientation"); Exiv2::ExifData::iterator pos = exifData.findKey(key); if (pos != exifData.end()) { long orientation = pos->toLong(); switch (orientation) { case 6: rotateAngle = 90; break; case 8: rotateAngle = -90; break; default: rotateAngle = 0; break; } } } #endif } catch (...) { VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Failed to extract EXIF headers from '%1'") .arg(filePathString)); } #else // Shut the compiler up about the unused argument (void)filePathString; #endif // EXIF_SUPPORT return rotateAngle; }
QDateTime GalleryUtil::GetTimestamp(const QString &filePath) { QDateTime timestamp; try { #ifdef EXIF_SUPPORT #if NEW_LIB_EXIF char *exifvalue = new char[20]; #endif ExifData *data = exif_data_new_from_file( filePath.toLocal8Bit().constData()); if (data) { for (int i = 0; i < EXIF_IFD_COUNT; i++) { ExifEntry *entry = exif_content_get_entry (data->ifd[i], EXIF_TAG_DATE_TIME_ORIGINAL); if (entry) { #if NEW_LIB_EXIF exif_entry_get_value(entry, exifvalue, 20); QString formatted = exifvalue; #else QString formatted = exif_entry_get_value(entry); #endif timestamp = QDateTime::fromString(formatted, "yyyy:MM:dd hh:mm:ss"); if (timestamp.isValid()) { // Found one, done break; } else { LOG(VB_FILE, LOG_ERR, LOC + QString("Could not parse exif timestamp from '%1'") .arg(filePath)); } } } exif_data_free(data); } else { LOG(VB_FILE, LOG_ERR, LOC + QString("Could not load exif data from '%1'") .arg(filePath)); } #if NEW_LIB_EXIF delete [] exifvalue; #endif #endif // EXIF_SUPPORT } catch (...) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to extract EXIF headers from '%1'") .arg(filePath)); } return timestamp; }
QString GalleryUtil::GetCaption(const QString &filePath) { QString caption(""); try { #ifdef EXIF_SUPPORT #if NEW_LIB_EXIF char *exifvalue = new char[1024]; #endif ExifData *data = exif_data_new_from_file( filePath.toLocal8Bit().constData()); if (data) { for (int i = 0; i < EXIF_IFD_COUNT; i++) { ExifEntry *entry = exif_content_get_entry (data->ifd[i], EXIF_TAG_USER_COMMENT); if (entry) { #if NEW_LIB_EXIF exif_entry_get_value(entry, exifvalue, 1024); caption = exifvalue; #else caption = exif_entry_get_value(entry); #endif // Found one, done if(!caption.trimmed().isEmpty()) break; } entry = exif_content_get_entry (data->ifd[i], EXIF_TAG_IMAGE_DESCRIPTION); if (entry) { #if NEW_LIB_EXIF exif_entry_get_value(entry, exifvalue, 1024); caption = exifvalue; #else caption = exif_entry_get_value(entry); #endif // Found one, done if(!caption.trimmed().isEmpty()) break; } } exif_data_free(data); } else { LOG(VB_FILE, LOG_ERR, LOC + QString("Could not load exif data from '%1'") .arg(filePath)); } #if NEW_LIB_EXIF delete [] exifvalue; #endif #endif // EXIF_SUPPORT } catch (...) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to extract EXIF headers from '%1'") .arg(filePath)); } return caption; }
static int write_exif( Write *write ) { unsigned char *data; size_t data_length; unsigned int idl; #ifdef HAVE_EXIF ExifData *ed; /* Either parse from the embedded EXIF, or if there's none, make * some fresh EXIF we can write the resolution to. */ if( im_header_get_typeof( write->in, IM_META_EXIF_NAME ) ) { if( im_meta_get_blob( write->in, IM_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(); /* Update EXIF resolution from VIPS. */ if( set_exif_resolution( 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 ) { im_error( "im_jpeg2vips", "%s", _( "error saving EXIF" ) ); exif_data_free( ed ); return( -1 ); } data_length = idl; #ifdef DEBUG printf( "im_vips2jpeg: 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( im_header_get_typeof( write->in, IM_META_EXIF_NAME ) ) { if( im_meta_get_blob( write->in, IM_META_EXIF_NAME, (void *) &data, &data_length ) ) return( -1 ); #ifdef DEBUG printf( "im_vips2jpeg: attaching %d bytes of EXIF\n", data_length ); #endif /*DEBUG*/ jpeg_write_marker( &write->cinfo, JPEG_APP0 + 1, data, data_length ); } #endif /*!HAVE_EXIF*/ return( 0 ); }
GstTagList * gst_droidcamsrc_exif_tags_from_jpeg_data (void *data, size_t size) { GstTagList *tags = NULL; ExifMem *mem = exif_mem_new (g_malloc0, g_realloc, g_free); ExifData *exif = exif_data_new_mem (mem); unsigned char *exif_data = NULL; void *_exif_data = NULL; unsigned int exif_data_size = 0; GstBuffer *buffer; ExifEntry *iso; int x, i; exif_data_load_data (exif, data, size); exif_data_set_data_type (exif, EXIF_DATA_TYPE_COMPRESSED); exif_data_save_data (exif, &exif_data, &exif_data_size); if (!exif_data_size) { goto out; } if (exif_data_size <= 6) { goto out; } /* dump the data. based on libexif code */ for (x = 0; x < EXIF_IFD_COUNT; x++) { if (exif->ifd[x] && exif->ifd[x]->count) { for (i = 0; i < exif->ifd[x]->count; i++) { char val[1024]; ExifEntry *e = exif->ifd[x]->entries[i]; GST_LOG ("Exif IFD: %s. Tag 0x%x (%s) = %s", exif_ifd_get_name (x), e->tag, exif_tag_get_name_in_ifd (e->tag, exif_entry_get_ifd (e)), exif_entry_get_value (e, val, sizeof (val))); } } } _exif_data = exif_data; exif_data += 6; exif_data_size -= 6; buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, exif_data, exif_data_size, 0, exif_data_size, NULL, NULL); tags = gst_tag_list_from_exif_buffer_with_tiff_header (buffer); gst_buffer_unref (buffer); /* We don't want these tags */ gst_tag_list_remove_tag (tags, GST_TAG_DEVICE_MANUFACTURER); gst_tag_list_remove_tag (tags, GST_TAG_DEVICE_MODEL); gst_tag_list_remove_tag (tags, GST_TAG_APPLICATION_NAME); gst_tag_list_remove_tag (tags, GST_TAG_DATE_TIME); /* we have a mess with ISO so we will just behave as N9 */ iso = exif_content_get_entry (exif->ifd[EXIF_IFD_EXIF], EXIF_TAG_ISO_SPEED_RATINGS); if (iso) { #ifdef __arm__ guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_MOTOROLA); #else guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_INTEL); #endif gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CAPTURING_ISO_SPEED, val, NULL); } /* TODO: the following are being dropped * * 0x213 EXIF_TAG_YCBCR_POSITIONING * 0x9004 EXIF_TAG_DATE_TIME_DIGITIZED * 0x9101 EXIF_TAG_COMPONENTS_CONFIGURATION * 0xa001 EXIF_TAG_COLOR_SPACE * 0xa002 EXIF_TAG_PIXEL_X_DIMENSION * 0xa003 EXIF_TAG_PIXEL_Y_DIMENSION * 0xa005 EXIF_TAG_INTEROPERABILITY_IFD_POINTER * thumbnail. * 0x100 EXIF_TAG_IMAGE_WIDTH * 0x101 EXIF_TAG_IMAGE_LENGTH * 0x9203 EXIF_TAG_BRIGHTNESS_VALUE * 0x9205 EXIF_TAG_MAX_APERTURE_VALUE * 0x9206 EXIF_TAG_SUBJECT_DISTANCE * 0x9208 EXIF_TAG_LIGHT_SOURCE * 0x9286 EXIF_TAG_USER_COMMENT */ out: if (_exif_data) { exif_mem_free (mem, _exif_data); } if (exif) { exif_data_free (exif); } exif_mem_unref (mem); return tags; }
LocImageContainer ImageProcessor::process (QString filename) { QImage image (m_data); if (!image.isNull()) { image = image.scaled(720, 500, Qt::KeepAspectRatioByExpanding); } LocImageContainer locImageContainer(image); locImageContainer.setAltitude(3000.00); //get exif data ExifData *ed = exif_data_new_from_file (filename.toLocal8Bit().constData()); if (!ed) { locImageContainer.setLocationAvailable(false); locImageContainer.setExifDataAvailable(false); return locImageContainer; } locImageContainer.setExifDataAvailable(true); //save temp char value[256]={0,}; // Retrieve make QString make; ExifEntry *ee = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE); if (!ee) { make = ""; } else { exif_entry_get_value(ee, value, sizeof(value)); locImageContainer.setMake (QString(value)); } // Retrieve model ee = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL); if (!ee) { locImageContainer.setCameraModel (""); } else { exif_entry_get_value(ee, value, sizeof(value)); locImageContainer.setCameraModel ("Taken with the "+QString(value)); } // Retrieve time ee = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL); if (!ee) { locImageContainer.setDateTaken (""); } else { exif_entry_get_value(ee, value, sizeof(value)); QString dateTime(value); QDateTime dateTaken = QDateTime::fromString (dateTime, "yyyy:MM:dd HH:mm:ss"); locImageContainer.setDateTaken (dateTaken.toString("'on 'dddd d, MMMM yyyy 'at' HH:mm")); } // Retrieve LATITUDE ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LATITUDE); if (!ee) { locImageContainer.setLocationAvailable(false); locImageContainer.setLatitude(-9999.99); } else { if ( ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) { double lat = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LATITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, value, 128 ); if ( value[0] == 'S' ) lat = -lat; } locImageContainer.setLocationAvailable(true); locImageContainer.setLatitude (lat); } } ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LONGITUDE); if (!ee) { locImageContainer.setLocationAvailable(false); locImageContainer.setLongitude(-9999.99); } else { if ( ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) { double lon = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LONGITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, value, 128 ); if ( value[0] == 'W' ) lon = -lon; } locImageContainer.setLocationAvailable(true); locImageContainer.setLongitude (lon); } } exif_data_free(ed); return locImageContainer; }
void ThumbGenerator::loadFile(QImage& image, const QFileInfo& fi) { static int sequence = 0; if (GalleryUtil::IsMovie(fi.filePath())) { bool thumbnailCreated = false; QDir tmpDir("/tmp/mythgallery"); if (!tmpDir.exists()) { if (!tmpDir.mkdir(tmpDir.absolutePath())) { LOG(VB_GENERAL, LOG_ERR, "Unable to create temp dir for movie thumbnail creation: " + tmpDir.absolutePath()); } } if (tmpDir.exists()) { QString thumbFile = QString("%1.png") .arg(++sequence,8,10,QChar('0')); QString cmd = "mythpreviewgen"; QStringList args; args << logPropagateArgs.split(" ", QString::SkipEmptyParts); args << "--infile" << '"' + fi.absoluteFilePath() + '"'; args << "--outfile" << '"' + tmpDir.filePath(thumbFile) + '"'; MythSystemLegacy ms(cmd, args, kMSRunShell); ms.SetDirectory(tmpDir.absolutePath()); ms.Run(); if (ms.Wait() == GENERIC_EXIT_OK) { QFileInfo thumb(tmpDir.filePath(thumbFile)); if (thumb.exists()) { QImage img(thumb.absoluteFilePath()); image = img; thumbnailCreated = true; } } } if (!thumbnailCreated) { QImage *img = GetMythUI()->LoadScaleImage("gallery-moviethumb.png"); if (img) { image = *img; } } } else { #ifdef EXIF_SUPPORT // Try to get thumbnail from exif data ExifData *ed = exif_data_new_from_file(fi.absoluteFilePath() .toLocal8Bit().constData()); if (ed && ed->data) { image.loadFromData(ed->data, ed->size); } if (ed) exif_data_free(ed); if (image.width() > m_width && image.height() > m_height) return; #endif #ifdef DCRAW_SUPPORT QString extension = fi.suffix(); QSet<QString> dcrawFormats = DcrawFormats::getFormats(); int rotateAngle; if (dcrawFormats.contains(extension) && (rotateAngle = DcrawHandler::loadThumbnail(&image, fi.absoluteFilePath())) != -1 && image.width() > m_width && image.height() > m_height) { if (rotateAngle != 0) { QMatrix matrix; matrix.rotate(rotateAngle); image = image.transformed(matrix); } return; } #endif image.load(fi.absoluteFilePath()); } }
void FileSystemScanner::readEXIF(File* file) { static QString EXIFIFD_NAME_EXIF = exif_ifd_get_name(EXIF_IFD_EXIF); int maxDataLength = 255; char* charData = new char[maxDataLength]; ExifData* exifData = exif_data_new_from_file(file->fileInfo()->absFilePath().ascii()); // exif_data_dump(exifData); for (int i = 0; i < EXIF_IFD_COUNT; i++) { ExifContent* content = exifData->ifd[i]; QString group = QString(exif_ifd_get_name((ExifIfd) i)); if (group == EXIFIFD_NAME_EXIF) { for (unsigned int e = 0; e < content->count; e++) { ExifEntry* entry = content->entries[e]; ExifTag exifTagType = entry->tag; QString title = QString(exif_tag_get_title(entry->tag)); QString name = QString(exif_tag_get_name(entry->tag)); exif_entry_get_value(entry, charData, maxDataLength); QString data = QString(charData); QString description = QString(exif_tag_get_description(entry->tag)); // tracer->sdebug(__func__) << " - " << title << " / " << name << " = " << data << " (" << description << ")" << endl; // get the exif tagnode title and the tagnode representing this tag from the engine TagNode* exifTagNodeTitle = m_engine->exifTagNodeTitle(); TagNode* exifTagNodeEntry = exifTagNodeTitle->child(title); switch (exifTagType) { case EXIF_TAG_DATE_TIME_ORIGINAL: case EXIF_TAG_DATE_TIME_DIGITIZED: { QDateTime dateTime = readExifDateTime(data); TagNodeDateTime* exifTagNodeEntryDateTime = dynamic_cast<TagNodeDateTime*>(exifTagNodeEntry); if (exifTagNodeEntryDateTime == 0) { // tagnode for this EXIF entry does not exist --> create it exifTagNodeEntryDateTime = dynamic_cast<TagNodeDateTime*>(m_engine->createTag(exifTagNodeTitle, TagNode::TYPE_DATETIME, title, description, QString::null)); exifTagNodeEntryDateTime->setReadonly(true); } if (dateTime.isValid()) { // create new assoc new FileTagNodeAssocDateTime(file, exifTagNodeEntryDateTime, dateTime); } break; } default: { TagNodeString* exifTagNodeEntryString = dynamic_cast<TagNodeString*>(exifTagNodeEntry); if (exifTagNodeEntryString == 0) { // tagnode for this EXIF entry does not exist --> create it exifTagNodeEntryString = dynamic_cast<TagNodeString*>(m_engine->createTag(exifTagNodeTitle, TagNode::TYPE_STRING, title, description, QString::null)); exifTagNodeEntryString->setReadonly(true); } // create new assoc new FileTagNodeAssocString(file, exifTagNodeEntryString, data); } } } } } exif_data_free(exifData); delete charData; }
/* 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 ); }
static int read_exif( IMAGE *im, void *data, int data_length ) { char *data_copy; /* Horrifyingly, some JPEGs have several APP1 sections. We must only * use the first one that starts "Exif.." */ if( ((char *) data)[0] != 'E' || ((char *) data)[1] != 'x' || ((char *) data)[2] != 'i' || ((char *) data)[3] != 'f' ) return( 0 ); if( im_header_get_typeof( im, IM_META_EXIF_NAME ) ) return( 0 ); /* Always attach a copy of the unparsed exif data. */ if( !(data_copy = im_malloc( NULL, data_length )) ) return( -1 ); memcpy( data_copy, data, data_length ); if( im_meta_set_blob( im, IM_META_EXIF_NAME, (im_callback_fn) im_free, data_copy, data_length ) ) { im_free( data_copy ); return( -1 ); } #ifdef HAVE_EXIF { ExifData *ed; if( !(ed = exif_data_new_from_data( data, data_length )) ) return( -1 ); if( ed->size > 0 ) { #ifdef DEBUG_VERBOSE show_tags( ed ); show_values( ed ); #endif /*DEBUG_VERBOSE*/ /* Attach informational fields for what we find. FIXME ... better to have this in the UI layer? Or we could attach non-human-readable tags here (int, double etc) and then move the human stuff to the UI layer? */ exif_data_foreach_content( ed, (ExifDataForeachContentFunc) attach_exif_content, im ); /* Look for resolution fields and use them to set the VIPS * xres/yres fields. */ set_vips_resolution( im, ed ); attach_thumbnail( im, ed ); } exif_data_free( ed ); } #endif /*HAVE_EXIF*/ return( 0 ); }
/* Scan the exif block on the image, if any, and make a set of vips metadata * tags for what we find. */ int vips__exif_parse( VipsImage *image ) { void *data; size_t length; ExifData *ed; VipsExifParams params; const char *str; if( !vips_image_get_typeof( image, VIPS_META_EXIF_NAME ) ) return( 0 ); if( vips_image_get_blob( image, VIPS_META_EXIF_NAME, &data, &length ) ) return( -1 ); if( !(ed = vips_exif_load_data_without_fix( data, length )) ) return( -1 ); #ifdef DEBUG_VERBOSE show_tags( ed ); show_values( ed ); #endif /*DEBUG_VERBOSE*/ /* Look for resolution fields and use them to set the VIPS xres/yres * fields. * * If the fields are missing, set them from the image, which will have * previously had them set from something like JFIF. */ if( vips_image_resolution_from_exif( image, ed ) && vips_exif_resolution_from_image( ed, image ) ) { exif_data_free( ed ); return( -1 ); } /* Make sure all required fields are there before we attach the vips * metadata. */ exif_data_fix( ed ); /* Attach informational fields for what we find. */ params.image = image; params.ed = ed; exif_data_foreach_content( ed, (ExifDataForeachContentFunc) vips_exif_get_content, ¶ms ); vips_exif_get_thumbnail( image, ed ); exif_data_free( ed ); /* Orientation handling. ifd0 has the Orientation tag for the main * image. */ if( vips_image_get_typeof( image, "exif-ifd0-Orientation" ) != 0 && !vips_image_get_string( image, "exif-ifd0-Orientation", &str ) ) { int orientation; orientation = atoi( str ); orientation = VIPS_CLIP( 1, orientation, 8 ); vips_image_set_int( image, VIPS_META_ORIENTATION, orientation ); } return( 0 ); }
/** * a_geotag_create_waypoint_from_file: * @filename: The image file to process * @vcmode: The current location mode to use in the positioning of Waypoint * @name: Returns a name for the Waypoint (can be NULL) * * Returns: An allocated Waypoint or NULL if Waypoint could not be generated (e.g. no EXIF info) * */ VikWaypoint* a_geotag_create_waypoint_from_file ( const gchar *filename, VikCoordMode vcmode, gchar **name ) { // Default return values (for failures) *name = NULL; VikWaypoint *wp = NULL; // TODO use log? //ExifLog *log = NULL; // open image with libexif ExifData *ed = exif_data_new_from_file ( filename ); // Detect EXIF load failure if ( !ed ) // return with no Waypoint return wp; struct LatLon ll; gchar str[128]; ExifEntry *ee; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_VERSION_ID); // Confirm this has a GPS Id - normally "2.0.0.0" or "2.2.0.0" if ( ! ( ee && ee->components == 4 ) ) goto MyReturn; // Could test for these versions explicitly but may have byte order issues... //if ( ! ( ee->data[0] == 2 && ee->data[2] == 0 && ee->data[3] == 0 ) ) // goto MyReturn; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_MAP_DATUM); if ( ! ( ee && ee->components > 0 && ee->format == EXIF_FORMAT_ASCII ) ) goto MyReturn; // If map datum specified - only deal in WGS-84 - the defacto standard if ( ee && ee->components > 0 ) { exif_entry_get_value ( ee, str, 128 ); if ( strncmp (str, "WGS-84", 6) ) goto MyReturn; } // // Lat & Long is necessary to form a waypoint. // ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE); if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) goto MyReturn; ll.lat = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); if ( str[0] == 'S' ) ll.lat = -ll.lat; } ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE); if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) ) goto MyReturn; ll.lon = Rational2Double ( ee->data, exif_format_get_size(ee->format), exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE_REF); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); if ( str[0] == 'W' ) ll.lon = -ll.lon; } // // Not worried if none of the other fields exist, as can default the values to something // gdouble alt = VIK_DEFAULT_ALTITUDE; ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE); if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_RATIONAL ) { alt = Rational2Double ( ee->data, 0, exif_data_get_byte_order(ed) ); ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE_REF); if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_BYTE && ee->data[0] == 1 ) alt = -alt; } // Name ee = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_XP_TITLE); if ( ee ) { exif_entry_get_value ( ee, str, 128 ); *name = g_strdup ( str ); } // // Now create Waypoint with acquired information // wp = vik_waypoint_new(); wp->visible = TRUE; // Set info from exif values // Location vik_coord_load_from_latlon ( &(wp->coord), vcmode, &ll ); // Altitude wp->altitude = alt; wp->comment = geotag_get_exif_comment ( ed ); vik_waypoint_set_image ( wp, filename ); MyReturn: // Finished with EXIF exif_data_free ( ed ); return wp; }