static gboolean get_coordinates (EogImage *image, gdouble *latitude, gdouble *longitude) { ExifData *exif_data; gchar buffer[32]; gdouble lon, lat; exif_data = (ExifData *) eog_image_get_exif_info (image); if (exif_data) { ExifEntry *entry; ExifByteOrder byte_order; byte_order = exif_data_get_byte_order (exif_data); entry = exif_data_get_entry (exif_data, EXIF_TAG_GPS_LONGITUDE); if (!parse_exif_gps_coordinate (entry, &lon, byte_order) || (lon > 180.0)) { exif_data_unref (exif_data); return FALSE; } eog_exif_data_get_value (exif_data, EXIF_TAG_GPS_LONGITUDE_REF, buffer, 32); if (strcmp (buffer, "W") == 0) lon *= -1; entry = exif_data_get_entry (exif_data, EXIF_TAG_GPS_LATITUDE); if (!parse_exif_gps_coordinate (entry, &lat, byte_order) || (lat > 90.0)) { exif_data_unref (exif_data); return FALSE; } eog_exif_data_get_value (exif_data, EXIF_TAG_GPS_LATITUDE_REF, buffer, 32); if (strcmp (buffer, "S") == 0) lat *= -1; *longitude = lon; *latitude = lat; exif_data_unref (exif_data); return TRUE; } return FALSE; }
static ExifDataTypeMakerNote exif_data_get_type_maker_note (ExifData *d) { ExifEntry *e, *em; char value[1024]; if (!d) return EXIF_DATA_TYPE_MAKER_NOTE_NONE; e = exif_data_get_entry (d, EXIF_TAG_MAKER_NOTE); if (!e) return EXIF_DATA_TYPE_MAKER_NOTE_NONE; /* Olympus & Nikon & Sanyo */ if ((e->size >= 8) && ( !memcmp (e->data, "OLYMP", 6) || !memcmp (e->data, "OLYMPUS", 8) || !memcmp (e->data, "SANYO", 6) || !memcmp (e->data, "Nikon", 6))) return EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS; em = exif_data_get_entry (d, EXIF_TAG_MAKE); if (!em) return EXIF_DATA_TYPE_MAKER_NOTE_NONE; /* Canon */ if (!strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon")) return EXIF_DATA_TYPE_MAKER_NOTE_CANON; /* Pentax & some variant of Nikon */ if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b)) { if (!strncasecmp ( exif_entry_get_value (em, value, sizeof(value)), "Nikon", 5)) return EXIF_DATA_TYPE_MAKER_NOTE_NIKON; else return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX; } if ((e->size >= 8) && !memcmp (e->data, "AOC", 4)) { return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX; } if ((e->size >= 8) && !memcmp (e->data, "QVC", 4)) { return EXIF_DATA_TYPE_MAKER_NOTE_CASIO; } if ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8)) { return EXIF_DATA_TYPE_MAKER_NOTE_FUJI; } return EXIF_DATA_TYPE_MAKER_NOTE_NONE; }
qint64 ImageSlideInfo::readExifIntValue(ExifData* pExifData, ExifTag exifTag) { qint64 exifValue = 0; if (!pExifData) return exifValue; ExifByteOrder exifByteOrder = exif_data_get_byte_order(pExifData); ExifEntry* pExifEntry = exif_data_get_entry(pExifData, exifTag); if (pExifEntry) { // paranoic a bit if (pExifEntry->size <= sizeof(qint64)) { if (pExifEntry->format == EXIF_FORMAT_SBYTE) exifValue = static_cast<qint64>(*pExifEntry->data); if (pExifEntry->format == EXIF_FORMAT_SSHORT) exifValue = static_cast<qint64>(exif_get_sshort(pExifEntry->data, exifByteOrder)); if (pExifEntry->format == EXIF_FORMAT_SLONG) exifValue = static_cast<qint64>(exif_get_slong(pExifEntry->data, exifByteOrder)); } } return exifValue; }
void JP4::readMakerNote() { if (_raw_app1) _ed = exif_data_new_from_data(_raw_app1, _raw_app1_length); if (!_ed) return; ExifEntry* makerNoteEntry = exif_data_get_entry(_ed, EXIF_TAG_MAKER_NOTE); if (!makerNoteEntry) { _makerNote.gain[0] = _makerNote.gain[1] = _makerNote.gain[2] = _makerNote.gain[3] = 2.0; _makerNote.gamma[0] = _makerNote.gamma[1] = _makerNote.gamma[2] = _makerNote.gamma[3] = 0.57; _makerNote.gamma_scale[0] = _makerNote.gamma_scale[1] = _makerNote.gamma_scale[2] = _makerNote.gamma_scale[3] = 0xffff; _makerNote.black[0] = _makerNote.black[1] = _makerNote.black[2] = _makerNote.black[3] = 10/256.0; _makerNote.decim_hor = 1; _makerNote.decim_ver = 1; _makerNote.bin_hor = 1; _makerNote.bin_ver = 1; return; } int makerNoteLength = makerNoteEntry->size/4; long makerNote[makerNoteLength]; for (int i = 0; i < makerNoteLength; i++) { makerNote[i] = get_long(makerNoteEntry->data + i*4); } for (int i = 0; i < 4; i++) { // channel gain 8.16 (0x10000 - 1.0). Combines both analog gain and digital scaling _makerNote.gain[i] = makerNote[i] / 65536.0; // (P_PIXEL_LOW<<24) | (P_GAMMA <<16) and 16-bit (6.10) scale for gamma tables, _makerNote.gamma_scale[i] = (makerNote[i+4] & 0xffff); _makerNote.gamma[i] = ((makerNote[i+4]>>16) & 0xff) / 100.0; _makerNote.black[i] = (makerNote[i+4]>>24) / 256.0; } if (makerNoteLength >= 12) { _makerNote.woi_left = (makerNote[8] & 0xffff); _makerNote.woi_width = (makerNote[8]>>16) & 0xffff; _makerNote.woi_top = (makerNote[9] & 0xffff); _makerNote.woi_height = (makerNote[9]>>16); _makerNote.flip_hor = (makerNote[10] & 0x1); _makerNote.flip_ver = (makerNote[10]>>1) & 0x1; _makerNote.bayer_mode = (makerNote[10]>>2) & 0x3; _makerNote.color_mode = (makerNote[10]>>4) & 0x0f; _makerNote.decim_hor = (makerNote[10]>> 8) & 0x0f; _makerNote.decim_ver = (makerNote[10]>>12) & 0x0f; _makerNote.bin_hor = (makerNote[10]>>16) & 0x0f; _makerNote.bin_ver = (makerNote[10]>>20) & 0x0f; }
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); }
int exif_mnote_data_canon_identify (const ExifData *ed, const ExifEntry *e) { char value[8]; ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE); if (!em) return 0; return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon"); }
std::string Exif::value(std::string tag_name) const { ExifEntry *entry; ExifTag tag; std::string value; char raw_value[1024]; tag = exif_tag_from_name(tag_name.c_str()); entry = exif_data_get_entry(m_data, tag); value = exif_entry_get_value(entry, raw_value, sizeof(raw_value)); return value; }
/** * eog_exif_data_get_value: * @exif_data: pointer to an <structname>ExifData</structname> struct * @tag_id: the requested tag's id. See <filename>exif-tag.h</filename> * from the libexif package for possible values (e.g. %EXIF_TAG_EXPOSURE_MODE). * @buffer: a pre-allocated output buffer * @buf_size: size of @buffer * * Convenience function to extract a string representation of an Exif tag * directly from an <structname>ExifData</structname> struct. The string is * written into @buffer as far as @buf_size permits. * * Returns: a pointer to @buffer. */ const gchar * eog_exif_data_get_value (EogExifData *exif_data, gint tag_id, gchar *buffer, guint buf_size) { ExifEntry *exif_entry; const gchar *exif_value; exif_entry = exif_data_get_entry (exif_data, tag_id); buffer[0] = 0; exif_value = exif_entry_get_value (exif_entry, buffer, buf_size); return exif_value; }
/*! If MakerNote is recognized, load it. * * \param[in,out] data #ExifData * \param[in] d pointer to raw EXIF data * \param[in] ds length of data at d */ static void interpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds) { int mnoteid; ExifEntry* e = exif_data_get_entry (data, EXIF_TAG_MAKER_NOTE); if (!e) return; if ((mnoteid = exif_mnote_data_olympus_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Olympus MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_olympus_new (data->priv->mem); } else if ((mnoteid = exif_mnote_data_canon_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Canon MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options); } else if ((mnoteid = exif_mnote_data_fuji_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Fuji MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_fuji_new (data->priv->mem); /* NOTE: Must do Pentax detection last because some of the * heuristics are pretty general. */ } else if ((mnoteid = exif_mnote_data_pentax_identify (data, e)) != 0) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Pentax MakerNote variant type %d", mnoteid); data->priv->md = exif_mnote_data_pentax_new (data->priv->mem); } /* * If we are able to interpret the maker note, do so. */ if (data->priv->md) { exif_mnote_data_log (data->priv->md, data->priv->log); exif_mnote_data_set_byte_order (data->priv->md, data->priv->order); exif_mnote_data_set_offset (data->priv->md, data->priv->offset_mnote); exif_mnote_data_load (data->priv->md, d, ds); } }
static int getDouble(ExifData *ed, ExifByteOrder bo, ExifTag t, double *d) { ExifEntry * e = exif_data_get_entry(ed, t); if (!e) return 0; char *b = e->data; switch (e->format) { case EXIF_FORMAT_SHORT: *d = (double) exif_get_short(b, bo); return 1; case EXIF_FORMAT_SSHORT: *d = (double) exif_get_sshort(b, bo); return 1; case EXIF_FORMAT_LONG: *d = (double) exif_get_long(b, bo); return 1; case EXIF_FORMAT_SLONG: *d = (double) exif_get_slong(b, bo); return 1; case EXIF_FORMAT_RATIONAL: { ExifRational r = exif_get_rational(b, bo); *d = (double) r.numerator / (double) r.denominator; return 1; } case EXIF_FORMAT_SRATIONAL: { ExifSRational r = exif_get_srational(b, bo); *d = (double) r.numerator / (double) r.denominator; return 1; } default: return 0; } }
ExifEntry * rstto_file_get_exif ( RsttoFile *r_file, ExifTag id ) { /* If there is no exif-data object, try to create it */ if ( NULL == r_file->priv->exif_data ) { r_file->priv->exif_data = exif_data_new_from_file ( rstto_file_get_path (r_file) ); } if ( NULL != r_file->priv->exif_data ) { return exif_data_get_entry ( r_file->priv->exif_data, id ); } /* If there is no exif-data, return NULL */ return NULL; }
QString ImageSlideInfo::readExifStringValue(ExifData* pExifData, ExifTag exifTag) { QString exifValueStr; if (!pExifData) return exifValueStr; ExifEntry* pExifEntry = exif_data_get_entry(pExifData, exifTag); if (pExifEntry) { if (pExifEntry->format == EXIF_FORMAT_ASCII) { char* pBuffer = new char[pExifEntry->size]; memset(pBuffer, '\0', pExifEntry->size); exif_entry_get_value(pExifEntry, pBuffer, pExifEntry->size); if (strlen(pBuffer) > 0) exifValueStr = pBuffer; delete[] pBuffer; } } return exifValueStr; }
int exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e) { int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size); if (variant == nikonV0) { /* This variant needs some extra checking with the Make */ char value[5]; ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE); variant = unrecognized; if (em) { const char *v = exif_entry_get_value (em, value, sizeof(value)); if (v && (!strncmp (v, "Nikon", sizeof(value)) || !strncmp (v, "NIKON", sizeof(value)) )) /* When saved, this variant will be written out like the * alternative nikonV2 form above instead */ variant = nikonV0; } } return variant; }
bool getCalibrationFromEXIF(char const * fileName, int& width, int& height, double& focalLengthX, double& focalLengthY, double const defaultWidth, double const defaultHeight) { width = defaultWidth; height = defaultHeight; focalLengthX = focalLengthY = -1; double fNative = -1, f35mm = -1; double fResX = -1, fResY = -1, fResUnits = -1; ExifData * ed = exif_data_new_from_file(fileName); if (!ed) return false; ExifByteOrder const byteOrder = exif_data_get_byte_order(ed); ExifEntry * entry; entry = exif_data_get_entry(ed, EXIF_TAG_PIXEL_X_DIMENSION); if (entry) width = getEXIF_DoubleVal(entry, byteOrder); entry = exif_data_get_entry(ed, EXIF_TAG_PIXEL_Y_DIMENSION); if (entry) height = getEXIF_DoubleVal(entry, byteOrder); entry = exif_data_get_entry(ed, EXIF_TAG_FOCAL_LENGTH); if (entry) fNative = getEXIF_DoubleVal(entry, byteOrder); entry = exif_data_get_entry(ed, EXIF_TAG_FOCAL_PLANE_X_RESOLUTION); if (entry) fResX = getEXIF_DoubleVal(entry, byteOrder); entry = exif_data_get_entry(ed, EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION); if (entry) fResY = getEXIF_DoubleVal(entry, byteOrder); entry = exif_data_get_entry(ed, EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT); if (entry) fResUnits = getEXIF_DoubleVal(entry, byteOrder); if (fResUnits == 1 || fResUnits == 2) fResUnits = 25.4; else if (fResUnits == 3) fResUnits = 10.0; else if (fResUnits == 4) fResUnits = 1.0; else if (fResUnits == 5) fResUnits = 0.001; else fResUnits = 25.4; if (fNative > 0 && fResX > 0 && fResY > 0 && fResUnits > 0) { focalLengthX = fNative * fResX / fResUnits; focalLengthY = fNative * fResY / fResUnits; } else { entry = exif_data_get_entry(ed, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM); if (entry) f35mm = getEXIF_DoubleVal(entry, byteOrder); if (f35mm > 0) focalLengthX = focalLengthY = f35mm*width / 35.0; } // end if return focalLengthX > 0; } // getCalibrationFromEXIF()
void eog_exif_util_set_focal_length_label_text (GtkLabel *label, EogExifData *exif_data) { ExifEntry *entry = NULL, *entry35mm = NULL; ExifByteOrder byte_order; gfloat f_val = 0.0; gchar *fl_text = NULL,*fl35_text = NULL; /* If no ExifData is supplied the label will be * cleared later as fl35_text is NULL. */ if (exif_data != NULL) { entry = exif_data_get_entry (exif_data, EXIF_TAG_FOCAL_LENGTH); entry35mm = exif_data_get_entry (exif_data, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM); byte_order = exif_data_get_byte_order (exif_data); } if (entry && G_LIKELY (entry->format == EXIF_FORMAT_RATIONAL)) { ExifRational value; /* Decode value by hand as libexif is not necessarily returning * it in the format we want it to be. */ value = exif_get_rational (entry->data, byte_order); /* Guard against div by zero */ if (G_LIKELY(value.denominator != 0)) f_val = (gfloat)value.numerator/ (gfloat)value.denominator; /* TRANSLATORS: This is the actual focal length used when the image was taken.*/ fl_text = g_strdup_printf (_("%.1f (lens)"), f_val); } if (entry35mm && G_LIKELY (entry35mm->format == EXIF_FORMAT_SHORT)) { ExifShort s_val; s_val = exif_get_short (entry35mm->data, byte_order); /* Print as float to get a similar look as above. */ /* TRANSLATORS: This is the equivalent focal length assuming a 35mm film camera. */ fl35_text = g_strdup_printf(_("%.1f (35mm film)"),(float)s_val); } if (fl_text) { if (fl35_text) { gchar *merged_txt; merged_txt = g_strconcat (fl35_text,", ", fl_text, NULL); gtk_label_set_text (label, merged_txt); g_free (merged_txt); } else { gtk_label_set_text (label, fl_text); } } else { /* This will also clear the label if no ExifData was supplied */ gtk_label_set_text (label, fl35_text); } g_free (fl35_text); g_free (fl_text); }
static void metadatamux_exif_for_each_tag_in_list (const GstTagList * list, const gchar * tag, gpointer user_data) { ExifData *ed = (ExifData *) user_data; ExifTag exif_tag; GType type = G_TYPE_INVALID; ExifEntry *entry = NULL; ExifIfd ifd = EXIF_IFD_COUNT; const ExifByteOrder byte_order = exif_data_get_byte_order (ed); exif_tag = metadatamux_exif_get_exif_from_tag (tag, &type, &ifd); if (!exif_tag) goto done; entry = exif_data_get_entry (ed, exif_tag); if (entry) exif_entry_ref (entry); else { entry = exif_entry_new (); exif_content_add_entry (ed->ifd[ifd], entry); exif_entry_initialize (entry, exif_tag); } if (entry->data == NULL) { if (entry->tag == EXIF_TAG_GPS_ALTITUDE) { entry->format = EXIF_FORMAT_RATIONAL; entry->components = 1; entry->size = exif_format_get_size (entry->format) * entry->components; entry->data = g_malloc (entry->size); } else if (entry->tag == EXIF_TAG_GPS_LATITUDE || entry->tag == EXIF_TAG_GPS_LONGITUDE) { entry->format = EXIF_FORMAT_RATIONAL; entry->components = 3; entry->size = exif_format_get_size (entry->format) * entry->components; entry->data = g_malloc (entry->size); } } if (type == GST_TYPE_FRACTION) { const GValue *gvalue = gst_tag_list_get_value_index (list, tag, 0); gint numerator = gst_value_get_fraction_numerator (gvalue); gint denominator = gst_value_get_fraction_denominator (gvalue); switch (entry->format) { case EXIF_FORMAT_SRATIONAL: { ExifSRational sr = { numerator, denominator }; exif_set_srational (entry->data, byte_order, sr); } break; case EXIF_FORMAT_RATIONAL: { ExifRational r; if (entry->tag == EXIF_TAG_X_RESOLUTION || entry->tag == EXIF_TAG_Y_RESOLUTION) { ExifEntry *unit_entry = NULL; unit_entry = exif_data_get_entry (ed, EXIF_TAG_RESOLUTION_UNIT); if (unit_entry) { ExifShort vsh = exif_get_short (unit_entry->data, byte_order); if (vsh != 2) /* inches */ exif_set_short (unit_entry->data, byte_order, 2); } } r.numerator = numerator; r.denominator = denominator; if (numerator < 0) r.numerator = -numerator; if (denominator < 0) r.denominator = -denominator; exif_set_rational (entry->data, byte_order, r); } break; default: break; } } else if (type == GST_TYPE_BUFFER) { const GValue *val = NULL; GstBuffer *buf; val = gst_tag_list_get_value_index (list, tag, 0); buf = gst_value_get_buffer (val); entry->components = GST_BUFFER_SIZE (buf); entry->size = GST_BUFFER_SIZE (buf); entry->data = g_malloc (entry->size); memcpy (entry->data, GST_BUFFER_DATA (buf), entry->size); } else { switch (type) { case G_TYPE_STRING: { gchar *value = NULL; if (gst_tag_list_get_string (list, tag, &value)) { if (entry->tag == EXIF_TAG_DATE_TIME_DIGITIZED || entry->tag == EXIF_TAG_DATE_TIME || entry->tag == EXIF_TAG_DATE_TIME_ORIGINAL) { GString *datetime = g_string_new_len (value, 20); /* enough memory to hold "YYYY:MM:DD HH:MM:SS" */ if (metadatamux_exif_convert_from_datetime (datetime)) { } else { GST_ERROR ("Unexpected date & time format for %s", tag); } g_free (value); value = datetime->str; g_string_free (datetime, FALSE); } else if (value) { entry->components = strlen (value) + 1; entry->size = exif_format_get_size (entry->format) * entry->components; entry->data = (guint8 *) value; value = NULL; } } } break; case G_TYPE_UINT: case G_TYPE_INT: { gint value; ExifShort v_short; if (G_TYPE_UINT == type) { gst_tag_list_get_uint (list, tag, (guint *) & value); } else { gst_tag_list_get_int (list, tag, &value); } switch (entry->format) { case EXIF_FORMAT_SHORT: if (entry->tag == EXIF_TAG_CONTRAST || entry->tag == EXIF_TAG_SATURATION) { if (value < -33) value = 1; /* low */ else if (value < 34) value = 0; /* normal */ else value = 2; /* high */ } v_short = value; exif_set_short (entry->data, byte_order, v_short); break; case EXIF_FORMAT_LONG: exif_set_long (entry->data, byte_order, value); break; default: break; } } break; case G_TYPE_DOUBLE: { gdouble value; gst_tag_list_get_double (list, tag, &value); if (entry->tag == EXIF_TAG_GPS_LATITUDE || entry->tag == EXIF_TAG_GPS_LONGITUDE) { ExifRational *rt = (ExifRational *) entry->data; gdouble v = fabs (value); ExifEntry *ref_entry = NULL; char ref; const ExifTag ref_tag = entry->tag == EXIF_TAG_GPS_LATITUDE ? EXIF_TAG_GPS_LATITUDE_REF : EXIF_TAG_GPS_LONGITUDE_REF; /* DDD - degrees */ rt->numerator = (gulong) v; rt->denominator = 1; GST_DEBUG ("deg: %lf : %lu / %lu", v, (gulong) rt->numerator, (gulong) rt->denominator); v -= rt->numerator; rt++; /* MM - minutes */ rt->numerator = (gulong) (v * 60.0); rt->denominator = 1; GST_DEBUG ("min: %lf : %lu / %lu", v, (gulong) rt->numerator, (gulong) rt->denominator); v -= ((gdouble) rt->numerator / 60.0); rt++; /* SS - seconds */ rt->numerator = (gulong) (0.5 + v * 3600.0); rt->denominator = 1; GST_DEBUG ("sec: %lf : %lu / %lu", v, (gulong) rt->numerator, (gulong) rt->denominator); if (entry->tag == EXIF_TAG_GPS_LONGITUDE) { GST_DEBUG ("longitude : %lf", value); ref = (value < 0.0) ? 'W' : 'E'; } else { GST_DEBUG ("latitude : %lf", value); ref = (value < 0.0) ? 'S' : 'N'; } ref_entry = exif_data_get_entry (ed, ref_tag); if (ref_entry) { exif_entry_ref (ref_entry); } else { ref_entry = exif_entry_new (); exif_content_add_entry (ed->ifd[EXIF_IFD_GPS], ref_entry); exif_entry_initialize (ref_entry, ref_tag); } if (ref_entry->data == NULL) { ref_entry->format = EXIF_FORMAT_ASCII; ref_entry->components = 2; ref_entry->size = 2; ref_entry->data = g_malloc (2); } ref_entry->data[0] = ref; ref_entry->data[1] = 0; exif_entry_unref (ref_entry); } else if (entry->tag == EXIF_TAG_GPS_ALTITUDE) { ExifEntry *ref_entry = NULL; ExifRational *rt = (ExifRational *) entry->data; rt->numerator = (gulong) fabs (10.0 * value); rt->denominator = 10; GST_DEBUG ("altitude : %lf", value); ref_entry = exif_data_get_entry (ed, EXIF_TAG_GPS_ALTITUDE_REF); if (ref_entry) { exif_entry_ref (ref_entry); } else { ref_entry = exif_entry_new (); exif_content_add_entry (ed->ifd[EXIF_IFD_GPS], ref_entry); exif_entry_initialize (ref_entry, EXIF_TAG_GPS_ALTITUDE_REF); } if (ref_entry->data == NULL) { ref_entry->format = EXIF_FORMAT_BYTE; ref_entry->components = 1; ref_entry->size = 1; ref_entry->data = g_malloc (1); } if (value > 0.0) { ref_entry->data[0] = 0; } else { ref_entry->data[0] = 1; } exif_entry_unref (ref_entry); } } break; default: break; } } done: if (entry) exif_entry_unref (entry); }
static time_t duf_exif_get_time( ExifData * edata, int *pdate_changed, char *stime_original, size_t stime_original_size, int *pr ) { int lr = 0; time_t timeepoch = 0; ExifEntry *entry = NULL; int changed = 0; #if 0 if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL ) ) /* || ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED ) ) */ || ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME ) ) ) #else if ( ( entry = exif_data_get_entry( edata, EXIF_TAG_DATE_TIME_ORIGINAL ) ) || ( entry = exif_data_get_entry( edata, EXIF_TAG_DATE_TIME ) ) ) #endif { memset( stime_original, stime_original_size, 0 ); /* Get the contents of the tag in human-readable form */ if ( lr >= 0 && !exif_entry_get_value( entry, stime_original, stime_original_size ) ) DUF_MAKE_ERROR( lr, DUF_ERROR_EXIF ); { char *corrected_time = NULL; for ( int i = 0; i < strlen( stime_original ); i++ ) { char c; c = stime_original[i]; if ( ( c < ' ' || c > 'z' ) && c != '?' && c != ':' && c != ' ' ) { DUF_TRACE( exif, 0, ">>>>>>>>>>>>>> %s <<<<<<<<<<<<<", stime_original ); DUF_MAKE_ERROR( lr, DUF_ERROR_EXIF_BROKEN_DATE ); break; } } if ( lr >= 0 ) corrected_time = mas_strdup( stime_original ); /* DUF_SHOW_ERROR( "@@@@@@@@@@@@@@ %s", stime_original ); */ DUF_TRACE( exif, 3, "stime_original:%s", stime_original ); /* 2008:06:21 13:18:19 */ /* 0123:56:89 12:45:78 */ if ( lr >= 0 ) { char *pq; while ( ( pq = strchr( corrected_time, '?' ) ) ) { int n; n = pq - corrected_time; if ( n < 4 ) { if ( n > 1 ) *pq = '9'; } else if ( n == 5 || n == 6 ) { corrected_time[5] = '1'; corrected_time[6] = '2'; } else if ( n == 8 || n == 9 ) { corrected_time[8] = '3'; corrected_time[9] = '1'; } else if ( n == 11 || n == 12 || n == 14 || n == 15 || n == 17 || n == 18 ) { corrected_time[n] = '0'; } changed++; } } if ( lr >= 0 && !*corrected_time ) DUF_MAKE_ERROR( lr, DUF_ERROR_EXIF_NO_DATE ); else if ( lr >= 0 && strchr( corrected_time, '?' ) ) { DUF_SHOW_ERROR( "broken date %s", corrected_time ); DUF_MAKE_ERROR( lr, DUF_ERROR_EXIF_BROKEN_DATE ); } if ( lr >= 0 || lr == DUF_ERROR_EXIF_BROKEN_DATE ) { if ( corrected_time && *corrected_time ) { struct tm times = { 0 }; strptime( corrected_time, "%Y:%m:%d %H:%M:%S", × ); /* timeepoch = mktime( × ); */ /* timeepoch = timelocal( × ); */ timeepoch = timegm( × ); /* strftime( buf1, sizeof( buf1 ), "%Y-%m-%d %H:%M:%S", × ); */ /* DUF_SHOW_ERROR( "!!!!! %lu : %lu", timeepoch, time(NULL) ); */ /* Don't bother printing it if it's entirely blank */ /* trim_spaces( corrected_time ); */ } } mas_free( corrected_time ); } /* ??? exif_entry_free( entry ); */ } else if ( 0 ) { #if 0 # define exif_data_get_entry(d, t) ( exif_content_get_entry( d->ifd[EXIF_IFD_0], t ) ? exif_content_get_entry( d->ifd[EXIF_IFD_0], t ) : exif_content_get_entry( d->ifd[EXIF_IFD_1], t ) ? exif_content_get_entry( d->ifd[EXIF_IFD_1], t ) : exif_content_get_entry( d->ifd[EXIF_IFD_EXIF], t ) ? exif_content_get_entry( d->ifd[EXIF_IFD_EXIF], t ) : exif_content_get_entry( d->ifd[EXIF_IFD_GPS], t ) ? exif_content_get_entry( d->ifd[EXIF_IFD_GPS], t ) : exif_content_get_entry( d->ifd[EXIF_IFD_INTEROPERABILITY], t ) ? exif_content_get_entry( d->ifd[EXIF_IFD_INTEROPERABILITY], t ) : NULL ) #endif DUF_MAKE_ERROR( lr, DUF_ERROR_EXIF_NO_DATE ); #if 0 if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME_ORIGINAL ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +1" ); else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_1], EXIF_TAG_DATE_TIME_ORIGINAL ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +2" ); else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +3" ); #else if ( ( entry = exif_data_get_entry( edata, EXIF_TAG_DATE_TIME_ORIGINAL ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +123" ); #endif #if 0 else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME_DIGITIZED ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +4" ); else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_1], EXIF_TAG_DATE_TIME_DIGITIZED ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +5" ); else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +6" ); #else else if ( ( entry = exif_data_get_entry( edata, EXIF_TAG_DATE_TIME_DIGITIZED ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +456" ); #endif #if 0 else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +7" ); else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_1], EXIF_TAG_DATE_TIME ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +8" ); else if ( ( entry = exif_content_get_entry( edata->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +9" ); #else else if ( ( entry = exif_data_get_entry( edata, EXIF_TAG_DATE_TIME ) ) ) DUF_SHOW_ERROR( "NO DATE - HAS +789" ); #endif else DUF_SHOW_ERROR( "NO DATE" ); /* ??? exif_entry_free( entry ); */ }
/* Function to populate TSK Blackboard exif related attributes */ void extractExifData(ExifData * exifData, TskFile * pFile) { std::map<ExifTag, TSK_ATTRIBUTE_TYPE>::iterator it; std::vector<TskBlackboardAttribute> attrs; std::string datetime = ""; int timezone = 0; for (it = tagMap.begin(); it != tagMap.end(); ++it) { ExifEntry * exifEntry = exif_data_get_entry(exifData, it->first); char tag_data[256]; if (exifEntry == NULL) continue; if (it->first == EXIF_TAG_GPS_LATITUDE || it->first == EXIF_TAG_GPS_LONGITUDE) { // Check for the EXIF_IFD_GPS image file directory to avoid interoperability value ExifIfd ifd = exif_entry_get_ifd(exifEntry); if (ifd != EXIF_IFD_GPS) continue; exif_entry_get_value(exifEntry, tag_data, 256); float decDegrees = getDecimalDegrees(tag_data); char refValue[2]; if (it->first == EXIF_TAG_GPS_LATITUDE) { // Get the latitude reference value; used to determine if positive or negative decimal value ExifEntry * latitudeRef = exif_data_get_entry(exifData, it->first); exif_entry_get_value(latitudeRef, refValue,2); if (strcmp(refValue, "S") == 0) decDegrees *= -1; } else { // Get the longitude reference value; used to determine if positive or negative decimal value ExifEntry * longitudeRef = exif_data_get_entry(exifData, it->first); exif_entry_get_value(longitudeRef, refValue,2); if (strcmp(refValue, "W") == 0) decDegrees *= -1; } TskBlackboardAttribute attr(it->second, name(), "", decDegrees); attrs.push_back(attr); } else if (it->first == EXIF_TAG_GPS_SPEED) { // Check for the EXIF_IFD_GPS image file directory to avoid interoperability value ExifIfd ifd = exif_entry_get_ifd(exifEntry); if (ifd != EXIF_IFD_GPS) continue; //Get the GPS speed value exif_entry_get_value(exifEntry, tag_data, 256); float speed = getGPSSpeed(tag_data); char refValue[2]; //Get the GPS speed reference value ExifEntry * speedRef = exif_data_get_entry(exifData, it->first); exif_entry_get_value(speedRef, refValue,2); //Convert Kilometers per hour to meters per second if (strcmp(refValue, "K") == 0) { speed *= 0.277778; } //Convert Miles per hour to meters per second if (strcmp(refValue, "M") == 0) { speed *= 0.44704; } //Convert Knots to meters per second if (strcmp(refValue, "N") == 0) { speed *= 0.514444; } TskBlackboardAttribute attr(it->second, name(), "", speed); attrs.push_back(attr); } else if (it->first == EXIF_TAG_DATE_TIME_ORIGINAL) { exif_entry_get_value(exifEntry, tag_data, 256); datetime = std::string(tag_data); } else if(it->first == EXIF_TAG_TIME_ZONE_OFFSET){ exif_entry_get_value(exifEntry, tag_data, 256); timezone = atoi(tag_data); } else { // Get the tag's data exif_entry_get_value(exifEntry, tag_data, 256); // Add tag data to blackboard TskBlackboardAttribute attr(it->second, name(), "", tag_data); attrs.push_back(attr); } } if(!datetime.empty()){ Poco::DateTime parsedDT; int tzd; Poco::DateTimeParser::tryParse(datetime, parsedDT, tzd); if(timezone) parsedDT.makeUTC(timezone); else parsedDT.makeUTC(tzd); TskBlackboardAttribute attr(TSK_DATETIME, name(), "", (uint64_t)parsedDT.utcTime()); attrs.push_back(attr); } if(attrs.size() > 0){ TskBlackboardArtifact art = pFile->createArtifact(TSK_METADATA_EXIF); for(size_t i = 0; i < attrs.size(); i++){ art.addAttribute(attrs[i]); } } }