Exif::Exif(QString path) { ExifLoader *loader; loader = exif_loader_new(); exif_loader_write_file(loader, path.toStdString().c_str()); m_data = exif_loader_get_data(loader); exif_loader_unref(loader); }
int main(int argc, char **argv) { int rc = 1; ExifLoader *l; if (argc < 2) { printf("Usage: %s image.jpg\n", argv[0]); printf("Extracts a thumbnail from the given EXIF image.\n"); return rc; } /* Create an ExifLoader object to manage the EXIF loading process */ l = exif_loader_new(); if (l) { ExifData *ed; /* Load the EXIF data from the image file */ exif_loader_write_file(l, argv[1]); /* Get a pointer to the EXIF data */ ed = exif_loader_get_data(l); /* The loader is no longer needed--free it */ exif_loader_unref(l); l = NULL; if (ed) { /* Make sure the image had a thumbnail before trying to write it */ if (ed->data && ed->size) { FILE *thumb; char thumb_name[1024]; /* Try to create a unique name for the thumbnail file */ snprintf(thumb_name, sizeof(thumb_name), "%s_thumb.jpg", argv[1]); thumb = fopen(thumb_name, "wb"); if (thumb) { /* Write the thumbnail image to the file */ fwrite(ed->data, 1, ed->size, thumb); fclose(thumb); printf("Wrote thumbnail to %s\n", thumb_name); rc = 0; } else { printf("Could not create file %s\n", thumb_name); rc = 2; } } else { printf("No EXIF thumbnail in file %s\n", argv[1]); rc = 1; } /* Free the EXIF data */ exif_data_unref(ed); } } return rc; }
ExifData * exif_data_new_from_file (const char *path) { ExifData *edata; ExifLoader *loader; loader = exif_loader_new (); exif_loader_write_file (loader, path); edata = exif_loader_get_data (loader); exif_loader_unref (loader); return (edata); }
void free_ListExifLoaderItem(ListExifLoader *item) { if (item->prev != NULL && item->next != NULL) { item->prev->next = item->next; item->next->prev = item->prev; } else if (item->prev != NULL) { item->prev->next = NULL; } else if (item->next != NULL) { item->next->prev = NULL; } exif_loader_unref (item->exif_loader); free(item); }
static void load_finished (NemoImagePropertiesPage *page) { GtkWidget *label; label = gtk_grid_get_child_at (GTK_GRID (page->details->grid), 0, 0); gtk_container_remove (GTK_CONTAINER (page->details->grid), label); if (page->details->loader != NULL) { gdk_pixbuf_loader_close (page->details->loader, NULL); } if (page->details->got_size) { append_basic_info (page); append_options_info (page); append_exif_info (page); append_xmp_info (page); } else { append_item (page, _("Failed to load image information"), NULL); } if (page->details->loader != NULL) { g_object_unref (page->details->loader); page->details->loader = NULL; } #ifdef HAVE_EXIF if (page->details->exifldr != NULL) { exif_loader_unref (page->details->exifldr); page->details->exifldr = NULL; } #endif /*HAVE_EXIF*/ #ifdef HAVE_EXEMPI if (page->details->xmp != NULL) { xmp_free (page->details->xmp); page->details->xmp = NULL; } #endif }
static void load_finished (CajaImagePropertiesPage *page) { GdkPixbufFormat *format; char *name, *desc; gtk_widget_destroy (page->details->loading_label); if (page->details->loader != NULL) { gdk_pixbuf_loader_close (page->details->loader, NULL); } if (page->details->got_size) { #ifdef HAVE_EXIF ExifData *exif_data; #endif /*HAVE_EXIF*/ format = gdk_pixbuf_loader_get_format (page->details->loader); name = gdk_pixbuf_format_get_name (format); desc = gdk_pixbuf_format_get_description (format); append_label_take_str (page->details->vbox, g_strdup_printf ("<b>%s</b> %s (%s)", _("Image Type:"), name, desc)); append_label_take_str (page->details->vbox, g_strdup_printf (ngettext ("<b>Width:</b> %d pixel", "<b>Width:</b> %d pixels", page->details->width), page->details->width)); append_label_take_str (page->details->vbox, g_strdup_printf (ngettext ("<b>Height:</b> %d pixel", "<b>Height:</b> %d pixels", page->details->height), page->details->height)); g_free (name); g_free (desc); #ifdef HAVE_EXIF exif_data = exif_loader_get_data (page->details->exifldr); append_exifdata_string (exif_data, page); exif_data_unref (exif_data); #endif /*HAVE_EXIF*/ #ifdef HAVE_EXEMPI append_xmpdata_string (page->details->xmp, page); #endif /*HAVE_EXEMPI*/ } else { append_label (page->details->vbox, _("Failed to load image information")); } if (page->details->loader != NULL) { g_object_unref (page->details->loader); page->details->loader = NULL; } #ifdef HAVE_EXIF if (page->details->exifldr != NULL) { exif_loader_unref (page->details->exifldr); page->details->exifldr = NULL; } #endif /*HAVE_EXIF*/ #ifdef HAVE_EXEMPI if (page->details->xmp != NULL) { xmp_free(page->details->xmp); page->details->xmp = NULL; } #endif /*HAVE_EXEMPI*/ }
int64_t GetImageMetadata(const char *path, char *name) { ExifData *ed; ExifEntry *e = NULL; ExifLoader *l; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; FILE *infile; int width=0, height=0, thumb=0; char make[32], model[64] = {'\0'}; char b[1024]; struct stat file; int64_t ret; image_s *imsrc; metadata_t m; uint32_t free_flags = 0xFFFFFFFF; memset(&m, '\0', sizeof(metadata_t)); //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path); if ( stat(path, &file) != 0 ) return 0; strip_ext(name); //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size); /* MIME hard-coded to JPEG for now, until we add PNG support */ m.mime = strdup("image/jpeg"); l = exif_loader_new(); exif_loader_write_file(l, path); ed = exif_loader_get_data(l); exif_loader_unref(l); if( !ed ) goto no_exifdata; e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL); if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) ) { m.date = strdup(exif_entry_get_value(e, b, sizeof(b))); if( strlen(m.date) > 10 ) { m.date[4] = '-'; m.date[7] = '-'; m.date[10] = 'T'; } else { free(m.date); m.date = NULL; } } else { /* One last effort to get the date from XMP */ image_get_jpeg_date_xmp(path, &m.date); } //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", m.date); e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE); if( e ) { strncpyt(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make)); e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL); if( e ) { strncpyt(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model)); if( !strcasestr(model, make) ) snprintf(model, sizeof(model), "%s %s", make, exif_entry_get_value(e, b, sizeof(b))); m.creator = escape_tag(trim(model), 1); } } //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model); e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION); if( e ) { int rotate; switch( exif_get_short(e->data, exif_data_get_byte_order(ed)) ) { case 3: rotate = 180; break; case 6: rotate = 90; break; case 8: rotate = 270; break; default: rotate = 0; break; } if( rotate ) xasprintf(&m.rotation, "%d", rotate); } if( ed->size ) { /* We might need to verify that the thumbnail is 160x160 or smaller */ if( ed->size > 12000 ) { imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size, 1, ROTATE_NONE); if( imsrc ) { if( (imsrc->width <= 160) && (imsrc->height <= 160) ) thumb = 1; image_free(imsrc); } } else { thumb = 1; //- 20130708 Sungmin add if(ed->data && ed->size) { char* art_file; if( !thumb_cache_exists(path, &art_file) ) { char cache_dir[MAXPATHLEN]; strncpyt(cache_dir, art_file, sizeof(cache_dir)); make_dir(dirname(cache_dir), S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); FILE *thumb = fopen(art_file, "wb"); //DPRINTF(E_WARN, L_METADATA, " * cache_dir: %s\n", cache_dir); //DPRINTF(E_WARN, L_METADATA, " * thumbnail: %s\n", art_file); if(thumb) { fwrite(ed->data, 1, ed->size, thumb); fclose(thumb); } } free(art_file); } } } //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * thumbnail: %d\n", thumb); exif_data_unref(ed); no_exifdata: /* If SOF parsing fails, then fall through to reading the JPEG data with libjpeg to get the resolution */ if( image_get_jpeg_resolution(path, &width, &height) != 0 || !width || !height ) { infile = fopen(path, "r"); if( infile ) { cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = libjpeg_error_handler; jpeg_create_decompress(&cinfo); if( setjmp(setjmp_buffer) ) goto error; jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); width = cinfo.output_width; height = cinfo.output_height; error: jpeg_destroy_decompress(&cinfo); fclose(infile); } } //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * resolution: %dx%d\n", width, height); if( !width || !height ) { free_metadata(&m, free_flags); return 0; } if( width <= 640 && height <= 480 ) m.dlna_pn = strdup("JPEG_SM"); else if( width <= 1024 && height <= 768 ) m.dlna_pn = strdup("JPEG_MED"); else if( (width <= 4096 && height <= 4096) || !GETFLAG(DLNA_STRICT_MASK) ) m.dlna_pn = strdup("JPEG_LRG"); xasprintf(&m.resolution, "%dx%d", width, height); ret = sql_exec(db, "INSERT into DETAILS" " (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION," " ROTATION, THUMBNAIL, CREATOR, DLNA_PN, MIME) " "VALUES" " (%Q, '%q', %lld, %ld, %Q, %Q, %Q, %d, %Q, %Q, %Q);", path, name, (long long)file.st_size, file.st_mtime, m.date, m.resolution, m.rotation, thumb, m.creator, m.dlna_pn, m.mime); if( ret != SQLITE_OK ) { fprintf(stderr, "Error inserting details for '%s'!\n", path); ret = 0; } else { ret = sqlite3_last_insert_rowid(db); } free_metadata(&m, free_flags); return ret; }
/*------------------------------------------------------------------* * MODIFICATIONS: * * Date Description Author * *============ ================================== =============== * * * *------------------------------------------------------------------*/ void ZImageThread::run() { ZRequestList::iterator vIt; ZImageThreadEvent *vEvt; #ifdef ZULU_EXIF ExifData *vEd; #endif bool vExifHasThumb; qDebug("%s::Thread started", __FILE__); for(;;) { qDebug("%s::Loop entered", __FILE__); /* * Wait until we are notified to begin processing */ mThreadWait.wait(); if (mShutdown) break; /* * We've got data */ qDebug("%s::Data to process", __FILE__); vIt = mRequests.begin(); QPixmap *vPix; while (vIt != mRequests.end()) { vExifHasThumb = false; vPix = NULL; #ifdef ZULU_EXIF /* * try to obtain thumbnail from exif */ ExifLoader *vLoader = exif_loader_new(); exif_loader_write_file(vLoader, (*vIt).GetURI().latin1()); vEd = exif_loader_get_data(vLoader); exif_loader_unref(vLoader); if (vEd == NULL) { qDebug("%s::%s does not contain EXIF data!", __FILE__, (*vIt).GetURI().latin1()); } else { qDebug("%s::%s has EXIF data!", __FILE__, (*vIt).GetURI().latin1()); if (vEd->data != NULL) { QImage vTemp; if (vTemp.loadFromData(vEd->data, vEd->size) == false) qDebug("%s::Unable to load pixmap", __FILE__); else { vPix = new QPixmap(vTemp.smoothScale((*vIt).GetWidth(), (*vIt).GetHeight(), QImage::ScaleMin)); if (vPix == NULL) qDebug("%s::Unable to create pixmap", __FILE__); else vExifHasThumb = true; } } } #endif /* * Create the thumbnail */ if (vExifHasThumb == false) { QString vURI = (*vIt).GetURI(); qDebug("%s::Image format => [%s]", __FILE__, QImage::imageFormat(vURI)); qDebug("%s::Loading image %s", __FILE__, (*vIt).GetURI().latin1()); QImageIO vImgIO; vImgIO.setFileName(vURI); if (vImgIO.read() == false) { qDebug("%s::Unable to read image", __FILE__); continue; } vPix = new QPixmap(vImgIO.image().scale((*vIt).GetWidth() , (*vIt).GetHeight(), QImage::ScaleMin)); if (vPix == NULL) qDebug("%s::Unable to create pixmap from image", __FILE__); } /* * Create and send the notification event */ vEvt = new ZImageThreadEvent((*vIt).GetKey(), vPix); delete vPix; vPix = NULL; QApplication::postEvent(mParent, vEvt); /* * Now remove this request from the queue */ mListLock.lock(); vIt = mRequests.erase(vIt); mListLock.unlock(); } } qDebug("%s::Thread exiting", __FILE__); }
/** * Module execution function. Receives a pointer to a file the module is to * process. The file is represented by a TskFile interface which is used * to read the contents of the file and post extracted EXIF data to the * database. * * @param pFile A pointer to a file. * @returns TskModule::OK on success, TskModule::FAIL on error. */ TskModule::Status TSK_MODULE_EXPORT run(TskFile * pFile) { if (pFile == NULL) { LOGERROR(L"ExifExtractModule: passed NULL file pointer."); return TskModule::FAIL; } try { char buffer[FILE_BUFFER_SIZE]; int bytesRead = 0; memset(buffer, 0, FILE_BUFFER_SIZE); bytesRead = pFile->read(buffer, FILE_BUFFER_SIZE); if (bytesRead < 4) return TskModule::OK; // Check the first 4 bytes to see if this is a JPEG file. // We check for both the JFIF and EXIF signatures. if (memcmp(buffer, jfifSig, sizeof(jfifSig)) != 0 && memcmp(buffer, exifSig, sizeof(exifSig)) != 0) { // It's not a JPEG file so we skip it. return TskModule::OK; } ExifLoader * exifLoader = exif_loader_new(); if (exifLoader == NULL) { LOGERROR(L"ExifExtractModule - Received NULL ExifLoader pointer"); return TskModule::FAIL; } // Feed the file content into libexif while (bytesRead > 0) { exif_loader_write(exifLoader, reinterpret_cast<unsigned char *>(buffer), bytesRead); memset(buffer, 0, FILE_BUFFER_SIZE); bytesRead = pFile->read(buffer, FILE_BUFFER_SIZE); } ExifData * exifData = exif_loader_get_data(exifLoader); // exifData will be NULL if there is no EXIF data in the image if (exifData != NULL) { // For debugging, exif_data_dump writes all exif data to stdout //exif_data_dump(exifData); extractExifData(exifData, pFile); exif_data_unref(exifData); } // Free the loader exif_loader_unref(exifLoader); } catch (TskException& tskEx) { std::wstringstream msg; msg << L"ExifExtractModule - Error processing file id " << pFile->getId() << L": " << tskEx.what(); LOGERROR(msg.str()); return TskModule::FAIL; } catch (std::exception& ex) { std::wstringstream msg; msg << L"ExifExtractModule - Error processing file id " << pFile->getId() << L": " << ex.what(); LOGERROR(msg.str()); return TskModule::FAIL; } return TskModule::OK; }
static void append_xmp_value_pair (GString *string, XmpPtr xmp, const char *ns, const char *propname, char *descr) { uint32_t options; XmpStringPtr value; value = xmp_string_new(); #ifdef HAVE_EXEMPI_NEW_API if (xmp_get_property (xmp, ns, propname, value, &options)) { #else if (xmp_get_property_and_bits (xmp, ns, propname, value, &options)) { #endif if (XMP_IS_PROP_SIMPLE (options)) { g_string_append_printf (string, "<b>%s:</b> %s\n", descr, xmp_string_cstr (value)); } else if (XMP_IS_PROP_ARRAY (options)) { XmpIteratorPtr iter; iter = xmp_iterator_new (xmp, ns, propname, XMP_ITER_JUSTLEAFNODES); if (iter) { gboolean first = TRUE; g_string_append_printf (string, "<b>%s:</b> ", descr); while (xmp_iterator_next (iter, NULL, NULL, value, &options) && !XMP_IS_PROP_QUALIFIER(options)) { if (!first) { g_string_append_printf (string, ", "); } else { first = FALSE; } g_string_append_printf (string, "%s", xmp_string_cstr(value)); } xmp_iterator_free(iter); g_string_append_printf(string, "\n"); } } } xmp_string_free(value); } static void append_xmpdata_string(XmpPtr xmp, GString *string) { if(xmp != NULL) { append_xmp_value_pair(string, xmp, NS_IPTC4XMP, "Location", _("Location")); append_xmp_value_pair(string, xmp, NS_DC, "description", _("Description")); append_xmp_value_pair(string, xmp, NS_DC, "subject", _("Keywords")); append_xmp_value_pair(string, xmp, NS_DC, "creator", _("Creator")); append_xmp_value_pair(string, xmp, NS_DC, "rights", _("Copyright")); append_xmp_value_pair(string, xmp, NS_XAP,"Rating", _("Rating")); /* TODO add CC licenses */ } } #endif static void load_finished (NautilusImagePropertiesPage *page) { GdkPixbufFormat *format; char *name, *desc; GString *str; if (page->details->got_size) { #ifdef HAVE_EXIF ExifData *exif_data; #endif str = g_string_new (NULL); format = gdk_pixbuf_loader_get_format (page->details->loader); name = gdk_pixbuf_format_get_name (format); desc = gdk_pixbuf_format_get_description (format); g_string_append_printf (str, "<b>%s</b> %s (%s)\n", _("Image Type:"), name, desc); g_string_append_printf (str, ngettext ("<b>Width:</b> %d pixel\n", "<b>Width:</b> %d pixels\n", page->details->width), page->details->width); g_string_append_printf (str, ngettext ("<b>Height:</b> %d pixel\n", "<b>Height:</b> %d pixels\n", page->details->height), page->details->height); g_free (name); g_free (desc); #ifdef HAVE_EXIF exif_data = exif_loader_get_data (page->details->exifldr); append_exifdata_string (exif_data, str); exif_data_unref (exif_data); #endif /*HAVE_EXIF*/ #ifdef HAVE_EXEMPI append_xmpdata_string(page->details->xmp, str); #endif /*HAVE EXEMPI*/ gtk_label_set_markup (GTK_LABEL (page->details->resolution), str->str); gtk_label_set_selectable (GTK_LABEL (page->details->resolution), TRUE); g_string_free (str, TRUE); } else { gtk_label_set_text (GTK_LABEL (page->details->resolution), _("Failed to load image information")); } if (page->details->loader != NULL) { gdk_pixbuf_loader_close (page->details->loader, NULL); g_object_unref (page->details->loader); page->details->loader = NULL; } #ifdef HAVE_EXIF if (page->details->exifldr != NULL) { exif_loader_unref (page->details->exifldr); page->details->exifldr = NULL; } #endif /*HAVE_EXIF*/ #ifdef HAVE_EXEMPI if (page->details->xmp != NULL) { xmp_free(page->details->xmp); page->details->xmp = NULL; } #endif }