gthumb r2239 - in trunk: . data/glade libgthumb src
- From: mjc svn gnome org
- To: svn-commits-list gnome org
- Subject: gthumb r2239 - in trunk: . data/glade libgthumb src
- Date: Thu, 31 Jan 2008 19:30:57 +0000 (GMT)
Author: mjc
Date: Thu Jan 31 19:30:57 2008
New Revision: 2239
URL: http://svn.gnome.org/viewvc/gthumb?rev=2239&view=rev
Log:
2008-01-31 Michael J. Chudobiak <mjc svn gnome org>
* libgthumb/gth-exif-utils.c:
* libgthumb/gth-exif-utils.h:
Purged gth_minimal_exif_tag_write, gth_minimal_exif_tag_action.
Use exiv2-based routines now.
* data/glade/gthumb_tools.glade:
* src/dlg-change-date.c: (ok_clicked), (update_sensitivity),
(dlg_change_date):
Added the ability to change DateTimeOriginal and DateTimeDigitized,
in addition to the existing DateTime-changing function.
Modified:
trunk/ChangeLog
trunk/data/glade/gthumb_tools.glade
trunk/libgthumb/gth-exif-utils.c
trunk/libgthumb/gth-exif-utils.h
trunk/src/dlg-change-date.c
Modified: trunk/data/glade/gthumb_tools.glade
==============================================================================
--- trunk/data/glade/gthumb_tools.glade (original)
+++ trunk/data/glade/gthumb_tools.glade Thu Jan 31 19:30:57 2008
@@ -2205,7 +2205,45 @@
<widget class="GtkCheckButton" id="cd_exif_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="label" translatable="yes">EXIF date</property>
+ <property name="label" translatable="yes">Exif DateTime tag</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="cd_exif_orig_checkbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Exif DateTimeOriginal tag</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="cd_exif_dig_checkbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Exif DateTimeDigitized tag</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
Modified: trunk/libgthumb/gth-exif-utils.c
==============================================================================
--- trunk/libgthumb/gth-exif-utils.c (original)
+++ trunk/libgthumb/gth-exif-utils.c Thu Jan 31 19:30:57 2008
@@ -319,308 +319,6 @@
}
-const char leth[] = {0x49, 0x49, 0x2a, 0x00}; // Little endian TIFF header
-const char beth[] = {0x4d, 0x4d, 0x00, 0x2a}; // Big endian TIFF header
-const char types[] = {0x00, 0x01, 0x01, 0x02, 0x04, 0x08, 0x00, 0x08, 0x00, 0x04, 0x08}; // size in bytes for EXIF types
-
-#define DE_ENDIAN16(val) endian == G_BIG_ENDIAN ? GUINT16_FROM_BE(val) : GUINT16_FROM_LE(val)
-#define DE_ENDIAN32(val) endian == G_BIG_ENDIAN ? GUINT32_FROM_BE(val) : GUINT32_FROM_LE(val)
-
-#define ENDIAN16_IT(val) endian == G_BIG_ENDIAN ? GUINT16_TO_BE(val) : GUINT16_TO_LE(val)
-#define ENDIAN32_IT(val) endian == G_BIG_ENDIAN ? GUINT32_TO_BE(val) : GUINT32_TO_LE(val)
-
-#define IFD_OFFSET_PUSH(val) if (oi < sizeof(offsets) - 1) offsets[oi++] = val; else return PATCH_EXIF_TOO_MANY_IFDS;
-#define IFD_OFFSET_PULL() offsets[--oi]
-
-#define IFD_NAME_PUSH(val) names[ni++] = val;
-#define IFD_NAME_PULL() names[--ni]
-
-static unsigned short de_get16(void *ptr, guint endian)
-{
- unsigned short val;
-
- memcpy(&val, ptr, sizeof(val));
- val = DE_ENDIAN16(val);
-
- return val;
-}
-
-static unsigned int de_get32(void *ptr, guint endian)
-{
- unsigned int val;
-
- memcpy(&val, ptr, sizeof(val));
- val = DE_ENDIAN32(val);
-
- return val;
-}
-
-int static
-gth_minimal_exif_tag_action (const char *local_file,
- ExifTag etag,
- void *data,
- int size,
- int access)
-{
- /* This function updates/reads ONLY the affected tag. Unlike libexif, it does
- not attempt to correct or re-format other data. This helps preserve
- the integrity of certain MakerNote entries, by avoiding re-positioning
- of the data whenever possible. Some MakerNotes incorporate absolute
- offsets and others use relative offsets. The offset issue is
- avoided if tags are not moved or resized if not required. */
-
- FILE *jf; // File descriptor to file to patch
- char buf[1024 * 64]; // Working buffer
- int i; // index into working buffer
- int tag; // endianed version of 'etag' in call
- int gpsifd; // endianed gps ifd pointer tag
- int exififd; // endianed exif ifd pointer tag
- int offset; // de-endianed offset in various situations
- int tags; // number of tags in current ifd
- int type; // de-endianed type of tag used as index into types[]
- int count; // de-endianed count of elements in a tag
- int stitch; // offset in data buffer in type size increments
- int tiff = 0; // offset to active tiff header
- int endian = 0; // detected endian of data
- int readsize = 0; // number of read bytes from file into buffer
- int writesize = 0; // number of written bytes from buffer to file
- int patches = 0; // number of values changed
-
- // IFD stack variables
- unsigned long offsets[32]; // Offsets in working buffer to start of IFDs
- char *names[32]; // Printable names of IFD:s (for debug mostly)
- int oi = 0; // index into offsets
- int ni = 0; // iundex into names
- int cifdi = 0; // curret ifd index
-
- debug (DEBUG_INFO, "gth_minimal_exif_tag_access (%s, %04x, %08x, %d)\n", local_file, etag, data, size);
-
- // local files only
- g_assert (uri_has_scheme (local_file) == FALSE);
-
- // Init IFD stack
- IFD_OFFSET_PUSH(0);
- IFD_NAME_PUSH("START");
-
- // open file r (read (r))
- if ((jf = fopen (local_file, "r")) == NULL)
- return PATCH_EXIF_FILE_ERROR;
-
- // Fill buffer
- readsize = fread (buf, 1, sizeof (buf), jf);
-
- // close file during prcessing
- fclose (jf);
-
- // Check for TIFF header and catch endianess
- i = 0;
- while (i < readsize) {
-
- // Little endian TIFF header
- if (bcmp (&buf[i], leth, 4) == 0) {
- endian = G_LITTLE_ENDIAN;
- }
-
- // Big endian TIFF header
- else if (bcmp (&buf[i], beth, 4) == 0) {
- endian = G_BIG_ENDIAN;
- }
-
- // Keep looking through buffer
- else {
- i++;
- continue;
- }
- // We have found either big or little endian TIFF header
- tiff = i;
- break;
- }
-
- // So did we find a TIFF header or did we just hit end of buffer?
- if (tiff == 0) return PATCH_EXIF_NO_TIFF;
-
- // Endian some tag values that we will look for
- exififd = ENDIAN16_IT(0x8769);
- gpsifd = ENDIAN16_IT(0x8825);
- tag = ENDIAN16_IT(etag);
-
- // Read out the offset
- offset = de_get32(&buf[i] + 4, endian);
- i = i + offset;
-
- // Start out with IFD0 (and add more IFDs while we go)
- IFD_OFFSET_PUSH(i);
- IFD_NAME_PUSH("IFD0");
-
- // As long as we find more IFDs check out the tags in each
- while ((oi >=0 && (i = IFD_OFFSET_PULL()) != 0 && i < readsize - 2)) {
-
- cifdi = oi; // remember which ifd we are at
-
- debug (DEBUG_INFO, "%s:\n", IFD_NAME_PULL());
- tags = de_get16(&buf[i], endian);
- i = i + 2;
-
- // Check this IFD for tags of interest
- while (tags-- && i < readsize - 12) {
- type = de_get16(&buf[i + 2], endian);
- count = de_get32(&buf[i + 4], endian);
- offset = de_get32(&buf[i + 8], endian);
-
- debug (DEBUG_INFO, "TAG: %04x type:%02d count:%02d offset:%04lx ",
- de_get16(&buf[i], endian), type, count, offset);
-
- // Our tag?
- if (bcmp (&buf[i], (char *)&tag, 2) == 0) {
-
- // Write TAG value
- if (access == 1) {
-
- // Local value that can be patched directly in TAG table
- if ((types[type] * count) <= 4) {
-
- // Fake TIFF offset
- offset = i + 8 - tiff;
- patches++;
- }
- // Offseted value of same or larger size that we can patch
- else if (types[type] * count >= size) {
-
- // Adjust count to new length
- count = size / types[type];
- *((unsigned short*)(&buf[i + 4])) = ENDIAN32_IT(count);
- patches++;
- }
- // Otherwise we are not able to patch the new value, at least not here
- else {
- fprintf (stderr, "gth_minimal_exif_tag_write: New TAG value does not fit, no patch applied\n");
- i = i + 12;
- continue;
- }
-
- if (offset + tiff + count * types[type] > sizeof (buf)) return PATCH_EXIF_TRASHED_IFD;
-
- // Copy the data
- stitch = 0;
- while (stitch < count) {
- switch (types[type]) {
- case 1:
- buf[tiff + offset + stitch] = *(char *) (data + stitch);
- break;
- case 2:
- *((unsigned short*)(&buf[tiff + offset + stitch * 2])) =
- ENDIAN16_IT(*(guint16 *) (data + stitch * 2));
- break;
- case 4:
- *((unsigned long*) (&buf[tiff + offset + stitch * 4])) =
- ENDIAN32_IT(*(guint32 *) (data + stitch * 4));
- break;
- default:
- fprintf(stderr, "gth_minimal_exif_tag_write:unsupported element size\n");
- return PATCH_EXIF_UNSUPPORTED_TYPE;
- }
- stitch++;
- }
- }
- // Read a TAG value
- else{
- int ret = PATCH_EXIF_OK;
-
- // Local value that can be read directly in TAG table
- if ((types[type] * count) <= 4 && size >= (types[type] * count)) {
-
- // Fake TIFF offset
- offset = i + 8 - tiff;
- patches++;
- }
- // Offseted value of less or equal size than buffer
- else if (types[type] * count <= size) {
- patches++;
- }
- // Otherwise we are not able to read the value
- else {
- fprintf(stderr, "gth_minimal_exif_tag_read: TAG value does not fit, Can't read full value\n");
- // Adjust count and warn for partial data
- count = size / types[type];
- ret = PATCH_EXIF_TAGVAL_OVERFLOW;
- }
-
- stitch = 0;
- while (stitch < count) {
- switch (types[type]) {
- case 1:
- *(char *) (data + stitch) = buf[tiff + offset + stitch];
- break;
- case 2:
- *(guint16 *) (data + stitch * 2) =
- de_get16(&buf[tiff + offset + stitch * 2], endian);
-
- break;
- case 4:
- *(guint32 *) (data + stitch * 4) =
- de_get32(&buf[tiff + offset + stitch * 4], endian);
-
- break;
- default:
- fprintf(stderr, "gth_minimal_exif_tag_read:unsupported element size\n");
- return PATCH_EXIF_UNSUPPORTED_TYPE;
- }
- stitch++;
- }
- return ret;
- }
- }
- // EXIF pointer tag?
- else if (bcmp (&buf[i], (char *) &exififd, 2) == 0) {
- IFD_OFFSET_PUSH(offset + tiff);
- IFD_NAME_PUSH("EXIF");
- }
- // GPS pointer tag?
- else if (bcmp (&buf[i], (char *) &gpsifd, 2) == 0) {
- IFD_OFFSET_PUSH(offset + tiff);
- IFD_NAME_PUSH("GPS");
- }
-
- debug (DEBUG_INFO, "\n");
-
- i = i + 12;
- }
-
- // Check for a valid next pointer and assume that to be IFD1 if we just checked IFD0
- if (cifdi == 1 && i < readsize - tiff && (i = de_get32(&buf[i], endian)) != 0) {
- i = i + tiff;
- IFD_OFFSET_PUSH(i);
- IFD_NAME_PUSH("IFD1");
- }
- }
-
- // Check if we need to save
- if (patches == 0)
- return PATCH_EXIF_NO_TAGS;
-
- // open file rb+ (read (r) and modify (+), b indicates binary file accces on non-Unix systems
- if ((jf = fopen (local_file, "rb+")) == NULL)
- return PATCH_EXIF_FILE_ERROR;
-
- // Save changes
- writesize = fwrite (buf, 1, readsize, jf);
- fclose (jf);
-
- return (readsize == writesize) ? PATCH_EXIF_OK : PATCH_EXIF_FILE_ERROR;
-}
-
-
-int
-gth_minimal_exif_tag_write (const char *local_file,
- ExifTag etag,
- void *data,
- int size)
-{
- debug (DEBUG_INFO, "gth_minimal_exif_tag_write(%s, %04x, %08x, %d)\n", local_file, etag, data, size);
- return gth_minimal_exif_tag_action (local_file, etag, data, size, 1);
-}
-
-
void
write_orientation_field (const char *local_file,
GthTransform transform)
Modified: trunk/libgthumb/gth-exif-utils.h
==============================================================================
--- trunk/libgthumb/gth-exif-utils.h (original)
+++ trunk/libgthumb/gth-exif-utils.h Thu Jan 31 19:30:57 2008
@@ -105,10 +105,6 @@
const char *uri_dest,
const char *tag_name,
const char *tag_value);
-int gth_minimal_exif_tag_write (const char *filename,
- ExifTag etag,
- void *data,
- int size);
void write_orientation_field (const char *filename,
GthTransform transform);
GList * gth_read_exiv2 (const char *filename,
Modified: trunk/src/dlg-change-date.c
==============================================================================
--- trunk/src/dlg-change-date.c (original)
+++ trunk/src/dlg-change-date.c Thu Jan 31 19:30:57 2008
@@ -51,6 +51,8 @@
GtkWidget *cd_last_modified_checkbutton;
GtkWidget *cd_comment_checkbutton;
GtkWidget *cd_exif_checkbutton;
+ GtkWidget *cd_exif_orig_checkbutton;
+ GtkWidget *cd_exif_dig_checkbutton;
GtkWidget *cd_following_date_radiobutton;
GtkWidget *cd_created_radiobutton;
@@ -157,7 +159,9 @@
comment_data_free (cdata);
}
- if (is_active (data->cd_exif_checkbutton)) {
+ if (is_active (data->cd_exif_checkbutton) ||
+ is_active (data->cd_exif_orig_checkbutton) ||
+ is_active (data->cd_exif_dig_checkbutton)) {
char buf[32];
struct tm tm;
int res;
@@ -184,16 +188,22 @@
gnome_vfs_get_file_info (fdata->path, info, GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS|GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
localtime_r(&mtime, &tm);
- snprintf(buf, 32, "%04d:%02d:%02d %02d:%02d:%02d ",
+ snprintf (buf, 32, "%04d:%02d:%02d %02d:%02d:%02d ",
tm.tm_year + 1900,
tm.tm_mon + 1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec );
- if ((res = gth_minimal_exif_tag_write (local_file_to_modify, EXIF_TAG_DATE_TIME, buf, 20)) != PATCH_EXIF_OK)
- _gtk_error_dialog_run (GTK_WINDOW (data->dialog),
- _("Could not write Exif DataTime tag. Error %d."), res);
+
+ if (is_active (data->cd_exif_checkbutton))
+ update_and_save_metadata (local_file_to_modify, local_file_to_modify, "Exif.Image.DateTime", buf);
+
+ if (is_active (data->cd_exif_orig_checkbutton))
+ update_and_save_metadata (local_file_to_modify, local_file_to_modify, "Exif.Photo.DateTimeOriginal", buf);
+
+ if (is_active (data->cd_exif_dig_checkbutton))
+ update_and_save_metadata (local_file_to_modify, local_file_to_modify, "Exif.Photo.DateTimeDigitized", buf);
mtime++; // Step the time to enable sorting of pictures according to EXIF time
@@ -230,7 +240,9 @@
gtk_widget_set_sensitive (data->ok_button,
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_last_modified_checkbutton))
|| gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_comment_checkbutton))
- || gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_exif_checkbutton)));
+ || gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_exif_checkbutton))
+ || gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_exif_orig_checkbutton))
+ || gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_exif_dig_checkbutton)));
gtk_widget_set_sensitive (data->cd_dateedit, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_following_date_radiobutton)));
gtk_widget_set_sensitive (data->cd_timezone_box, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->cd_adjust_timezone_radiobutton)));
@@ -292,6 +304,8 @@
data->cd_last_modified_checkbutton = glade_xml_get_widget (data->gui, "cd_last_modified_checkbutton");
data->cd_comment_checkbutton = glade_xml_get_widget (data->gui, "cd_comment_checkbutton");
data->cd_exif_checkbutton = glade_xml_get_widget (data->gui, "cd_exif_checkbutton");
+ data->cd_exif_orig_checkbutton = glade_xml_get_widget (data->gui, "cd_exif_orig_checkbutton");
+ data->cd_exif_dig_checkbutton = glade_xml_get_widget (data->gui, "cd_exif_dig_checkbutton");
data->cd_following_date_radiobutton = glade_xml_get_widget (data->gui, "cd_following_date_radiobutton");
data->cd_created_radiobutton = glade_xml_get_widget (data->gui, "cd_created_radiobutton");
@@ -347,6 +361,14 @@
"clicked",
G_CALLBACK (radio_button_clicked),
data);
+ g_signal_connect (G_OBJECT (data->cd_exif_orig_checkbutton),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (G_OBJECT (data->cd_exif_dig_checkbutton),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
g_signal_connect (G_OBJECT (data->cd_following_date_radiobutton),
"clicked",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]