mirror of
https://github.com/gryf/pygtktalog.git
synced 2025-12-17 11:30:19 +01:00
* Added EXIF support - parse, write to db, show in apropriate tab.
This commit is contained in:
2
README
2
README
@@ -61,7 +61,7 @@ For version 1.0 following aims have to be done:
|
|||||||
- files properties
|
- files properties
|
||||||
x thumbnail
|
x thumbnail
|
||||||
x description
|
x description
|
||||||
- exif information
|
x exif information
|
||||||
- keywords (tags)
|
- keywords (tags)
|
||||||
- gthumb integration
|
- gthumb integration
|
||||||
x adding images
|
x adding images
|
||||||
|
|||||||
@@ -722,62 +722,22 @@
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkVBox" id="vbox4">
|
<widget class="GtkScrolledWindow" id="exifinfo">
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkHPaned" id="movieinfo">
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkScrolledWindow" id="scrolledwindow5">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||||
<child>
|
|
||||||
<widget class="GtkTreeView" id="treeview1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
|
||||||
<property name="headers_clickable">True</property>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="resize">False</property>
|
|
||||||
<property name="shrink">True</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkScrolledWindow" id="exifinfo">
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
|
||||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
|
||||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkTreeView" id="exif_tree">
|
<widget class="GtkTreeView" id="exif_tree">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="headers_clickable">True</property>
|
<property name="headers_clickable">True</property>
|
||||||
|
<property name="rules_hint">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
<packing>
|
||||||
<property name="position">2</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
@@ -786,7 +746,7 @@
|
|||||||
<widget class="GtkLabel" id="label4">
|
<widget class="GtkLabel" id="label4">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label" translatable="yes">page 3</property>
|
<property name="label" translatable="yes">EXIF</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="type">tab</property>
|
<property name="type">tab</property>
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ class MainController(Controller):
|
|||||||
# initialize treeviews
|
# initialize treeviews
|
||||||
self.__setup_disc_treeview()
|
self.__setup_disc_treeview()
|
||||||
self.__setup_files_treeview()
|
self.__setup_files_treeview()
|
||||||
|
self.__setup_exif_treeview()
|
||||||
|
|
||||||
# in case passing catalog filename in command line, unlock gui
|
# in case passing catalog filename in command line, unlock gui
|
||||||
if self.model.filename != None:
|
if self.model.filename != None:
|
||||||
@@ -167,11 +168,9 @@ class MainController(Controller):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
path, column = self.view['discs'].get_cursor()
|
path, column = self.view['discs'].get_cursor()
|
||||||
print path
|
|
||||||
iter = model.get_iter(path)
|
iter = model.get_iter(path)
|
||||||
self.model.get_root_entries(model.get_value(iter, 0))
|
self.model.get_root_entries(model.get_value(iter, 0))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
print "zuo"
|
|
||||||
self.model.get_root_entries(1)
|
self.model.get_root_entries(1)
|
||||||
return
|
return
|
||||||
return
|
return
|
||||||
@@ -351,21 +350,6 @@ class MainController(Controller):
|
|||||||
self.view['update1'].set_sensitive(False)
|
self.view['update1'].set_sensitive(False)
|
||||||
self.__popup_menu(event)
|
self.__popup_menu(event)
|
||||||
|
|
||||||
# elif event.button == 1: # Left click
|
|
||||||
# """Show files on right treeview, after clicking the left disc treeview."""
|
|
||||||
# model = self.view['discs'].get_model()
|
|
||||||
# selected_item = self.model.discs_tree.get_value(self.model.discs_tree.get_iter(path),0)
|
|
||||||
# if __debug__:
|
|
||||||
# print "c_main.py, on_discs_cursor_changed()",selected_item
|
|
||||||
# self.model.get_root_entries(selected_item)
|
|
||||||
#
|
|
||||||
# self.view['details'].show()
|
|
||||||
# txt = self.model.get_file_info(selected_item)
|
|
||||||
# buf = self.view['details'].get_buffer()
|
|
||||||
# buf.set_text(txt)
|
|
||||||
# self.view['details'].set_buffer(buf)
|
|
||||||
# return
|
|
||||||
|
|
||||||
def on_expand_all1_activate(self, menuitem):
|
def on_expand_all1_activate(self, menuitem):
|
||||||
self.view['discs'].expand_all()
|
self.view['discs'].expand_all()
|
||||||
return
|
return
|
||||||
@@ -402,19 +386,10 @@ class MainController(Controller):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def on_files_cursor_changed(self, treeview):
|
def on_files_cursor_changed(self, treeview):
|
||||||
"""Show details of selected file"""
|
"""Show details of selected file/directory"""
|
||||||
model, paths = treeview.get_selection().get_selected_rows()
|
model, paths = treeview.get_selection().get_selected_rows()
|
||||||
try:
|
try:
|
||||||
itera = model.get_iter(paths[0])
|
itera = model.get_iter(paths[0])
|
||||||
#if model.get_value(itera,4) == 1:
|
|
||||||
# #directory, do nothin', just turn off view
|
|
||||||
# '''self.view['details'].hide()
|
|
||||||
# buf = self.view['details'].get_buffer()
|
|
||||||
# buf.set_text('')
|
|
||||||
# self.view['details'].set_buffer(buf)'''
|
|
||||||
#else:
|
|
||||||
#file, show what you got.
|
|
||||||
#self.details.get_top_widget()
|
|
||||||
iter = model.get_iter(treeview.get_cursor()[0])
|
iter = model.get_iter(treeview.get_cursor()[0])
|
||||||
selected_item = self.model.files_list.get_value(iter, 0)
|
selected_item = self.model.files_list.get_value(iter, 0)
|
||||||
self.__get_item_info(selected_item)
|
self.__get_item_info(selected_item)
|
||||||
@@ -535,8 +510,6 @@ class MainController(Controller):
|
|||||||
|
|
||||||
def on_delete2_activate(self, menu_item):
|
def on_delete2_activate(self, menu_item):
|
||||||
try:
|
try:
|
||||||
#path, column = self.view['discs'].get_cursor()
|
|
||||||
#selected_iter = model.get_iter(path)
|
|
||||||
selection = self.view['discs'].get_selection()
|
selection = self.view['discs'].get_selection()
|
||||||
model, selected_iter = selection.get_selected()
|
model, selected_iter = selection.get_selected()
|
||||||
except:
|
except:
|
||||||
@@ -562,7 +535,6 @@ class MainController(Controller):
|
|||||||
path = (row, )
|
path = (row, )
|
||||||
|
|
||||||
# delete from db
|
# delete from db
|
||||||
print current_id
|
|
||||||
self.model.delete(current_id)
|
self.model.delete(current_id)
|
||||||
|
|
||||||
# refresh files treeview
|
# refresh files treeview
|
||||||
@@ -819,26 +791,6 @@ class MainController(Controller):
|
|||||||
self.view['images'].set_pixbuf_column(1)
|
self.view['images'].set_pixbuf_column(1)
|
||||||
return
|
return
|
||||||
|
|
||||||
def __setup_tags_treeview(self):
|
|
||||||
"""Setup TreeView discs widget as tree."""
|
|
||||||
self.view['tags'].set_model(self.model.tagsTree)
|
|
||||||
|
|
||||||
c = gtk.TreeViewColumn('Filename')
|
|
||||||
|
|
||||||
# one row contains image and text
|
|
||||||
cellpb = gtk.CellRendererPixbuf()
|
|
||||||
cell = gtk.CellRendererText()
|
|
||||||
c.pack_start(cellpb, False)
|
|
||||||
c.pack_start(cell, True)
|
|
||||||
c.set_attributes(cellpb, stock_id=2)
|
|
||||||
c.set_attributes(cell, text=1)
|
|
||||||
|
|
||||||
self.view['discs'].append_column(c)
|
|
||||||
|
|
||||||
# registration of treeview signals:
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def __setup_files_treeview(self):
|
def __setup_files_treeview(self):
|
||||||
"""Setup TreeView files widget, as columned list."""
|
"""Setup TreeView files widget, as columned list."""
|
||||||
self.view['files'].set_model(self.model.files_list)
|
self.view['files'].set_model(self.model.files_list)
|
||||||
@@ -866,14 +818,20 @@ class MainController(Controller):
|
|||||||
c.set_sort_column_id(3)
|
c.set_sort_column_id(3)
|
||||||
c.set_resizable(True)
|
c.set_resizable(True)
|
||||||
self.view['files'].append_column(c)
|
self.view['files'].append_column(c)
|
||||||
|
return
|
||||||
|
|
||||||
#c = gtk.TreeViewColumn('Category',gtk.CellRendererText(), text=5)
|
def __setup_exif_treeview(self):
|
||||||
#c.set_sort_column_id(5)
|
self.view['exif_tree'].set_model(self.model.exif_list)
|
||||||
#c.set_resizable(True)
|
|
||||||
#self.view['files'].append_column(c)
|
|
||||||
|
|
||||||
# registration of treeview signals:
|
c = gtk.TreeViewColumn('EXIF key',gtk.CellRendererText(), text=0)
|
||||||
|
c.set_sort_column_id(0)
|
||||||
|
c.set_resizable(True)
|
||||||
|
self.view['exif_tree'].append_column(c)
|
||||||
|
|
||||||
|
c = gtk.TreeViewColumn('EXIF value',gtk.CellRendererText(), text=1)
|
||||||
|
c.set_sort_column_id(1)
|
||||||
|
c.set_resizable(True)
|
||||||
|
self.view['exif_tree'].append_column(c)
|
||||||
return
|
return
|
||||||
|
|
||||||
def __abort(self):
|
def __abort(self):
|
||||||
@@ -962,6 +920,12 @@ class MainController(Controller):
|
|||||||
else:
|
else:
|
||||||
self.view['img_container'].hide()
|
self.view['img_container'].hide()
|
||||||
|
|
||||||
|
if set.has_key('exif'):
|
||||||
|
self.view['exif_tree'].set_model(self.model.exif_list)
|
||||||
|
self.view['exifinfo'].show()
|
||||||
|
else:
|
||||||
|
self.view['exifinfo'].hide()
|
||||||
|
|
||||||
if set.has_key('thumbnail'):
|
if set.has_key('thumbnail'):
|
||||||
self.view['thumb'].set_from_file(set['thumbnail'])
|
self.view['thumb'].set_from_file(set['thumbnail'])
|
||||||
self.view['thumb'].show()
|
self.view['thumb'].show()
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ from m_config import ConfigModel
|
|||||||
from m_details import DetailsModel
|
from m_details import DetailsModel
|
||||||
from utils.thumbnail import Thumbnail
|
from utils.thumbnail import Thumbnail
|
||||||
from utils.img import Img
|
from utils.img import Img
|
||||||
|
from utils.parse_exif import ParseExif
|
||||||
|
|
||||||
class MainModel(ModelMT):
|
class MainModel(ModelMT):
|
||||||
"""Create, load, save, manipulate db file which is container for data"""
|
"""Create, load, save, manipulate db file which is container for data"""
|
||||||
@@ -63,6 +64,20 @@ class MainModel(ModelMT):
|
|||||||
CD = 1 # sorce: cd/dvd
|
CD = 1 # sorce: cd/dvd
|
||||||
DR = 2 # source: filesystem
|
DR = 2 # source: filesystem
|
||||||
|
|
||||||
|
EXIF_DICT= {0: 'Camera',
|
||||||
|
1: 'Date',
|
||||||
|
2: 'Aperture',
|
||||||
|
3: 'Exposure program',
|
||||||
|
4: 'Exposure bias',
|
||||||
|
5: 'ISO',
|
||||||
|
6: 'Focal length',
|
||||||
|
7: 'Subject distance',
|
||||||
|
8: 'Metering mode',
|
||||||
|
9: 'Flash',
|
||||||
|
10: 'Light source',
|
||||||
|
11: 'Resolution',
|
||||||
|
12: 'Orientation'}
|
||||||
|
|
||||||
# images extensions - only for PIL and EXIF
|
# images extensions - only for PIL and EXIF
|
||||||
IMG = ['jpg', 'jpeg', 'gif', 'png', 'tif', 'tiff', 'tga', 'pcx', 'bmp',
|
IMG = ['jpg', 'jpeg', 'gif', 'png', 'tif', 'tiff', 'tga', 'pcx', 'bmp',
|
||||||
'xbm', 'xpm', 'jp2', 'jpx', 'pnm']
|
'xbm', 'xpm', 'jp2', 'jpx', 'pnm']
|
||||||
@@ -89,9 +104,13 @@ class MainModel(ModelMT):
|
|||||||
gobject.TYPE_UINT64,
|
gobject.TYPE_UINT64,
|
||||||
gobject.TYPE_STRING, gobject.TYPE_INT,
|
gobject.TYPE_STRING, gobject.TYPE_INT,
|
||||||
gobject.TYPE_STRING, str)
|
gobject.TYPE_STRING, str)
|
||||||
# iconview store - image id, pixbuffer
|
# iconview store - id, pixbuffer
|
||||||
self.images_store = gtk.ListStore(gobject.TYPE_INT, gtk.gdk.Pixbuf)
|
self.images_store = gtk.ListStore(gobject.TYPE_INT, gtk.gdk.Pixbuf)
|
||||||
|
|
||||||
|
# exif liststore - id, exif key, exif value
|
||||||
|
self.exif_list = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_STRING)
|
||||||
|
|
||||||
# tag cloud array element is a dict with 4 keys:
|
# tag cloud array element is a dict with 4 keys:
|
||||||
# elem = {'id': str(id), 'name': tagname, 'size': size, 'color': color}
|
# elem = {'id': str(id), 'name': tagname, 'size': size, 'color': color}
|
||||||
# where color is in one of format:
|
# where color is in one of format:
|
||||||
@@ -334,6 +353,24 @@ class MainModel(ModelMT):
|
|||||||
pix = gtk.gdk.pixbuf_new_from_file(im)
|
pix = gtk.gdk.pixbuf_new_from_file(im)
|
||||||
self.images_store.append([id, pix])
|
self.images_store.append([id, pix])
|
||||||
retval['images'] = True
|
retval['images'] = True
|
||||||
|
|
||||||
|
sql = """SELECT camera, date, aperture, exposure_program,
|
||||||
|
exposure_bias, iso, focal_length, subject_distance, metering_mode,
|
||||||
|
flash, light_source, resolution, orientation
|
||||||
|
from exif
|
||||||
|
WHERE file_id = ?"""
|
||||||
|
|
||||||
|
self.db_cursor.execute(sql, (id,))
|
||||||
|
set = self.db_cursor.fetchone()
|
||||||
|
if set:
|
||||||
|
self.exif_list = gtk.ListStore(gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_STRING)
|
||||||
|
for key in self.EXIF_DICT:
|
||||||
|
myiter = self.exif_list.insert_before(None, None)
|
||||||
|
self.exif_list.set_value(myiter, 0, self.EXIF_DICT[key])
|
||||||
|
self.exif_list.set_value(myiter, 1, set[key])
|
||||||
|
|
||||||
|
retval['exif'] = True
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
def get_source(self, path):
|
def get_source(self, path):
|
||||||
@@ -638,6 +675,22 @@ class MainModel(ModelMT):
|
|||||||
file_id INTEGER,
|
file_id INTEGER,
|
||||||
thumbnail TEXT,
|
thumbnail TEXT,
|
||||||
filename TEXT);""")
|
filename TEXT);""")
|
||||||
|
self.db_cursor.execute("""create table
|
||||||
|
exif(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
file_id INTEGER,
|
||||||
|
camera TEXT,
|
||||||
|
date TEXT,
|
||||||
|
aperture TEXT,
|
||||||
|
exposure_program TEXT,
|
||||||
|
exposure_bias TEXT,
|
||||||
|
iso TEXT,
|
||||||
|
focal_length TEXT,
|
||||||
|
subject_distance TEXT,
|
||||||
|
metering_mode TEXT,
|
||||||
|
flash TEXT,
|
||||||
|
light_source TEXT,
|
||||||
|
resolution TEXT,
|
||||||
|
orientation TEXT);""")
|
||||||
self.db_cursor.execute("insert into files values(1, 1, 'root', null, 0, 0, 0, 0, null, null);")
|
self.db_cursor.execute("insert into files values(1, 1, 'root', null, 0, 0, 0, 0, null, null);")
|
||||||
self.db_cursor.execute("insert into groups values(1, 'default', 'black');")
|
self.db_cursor.execute("insert into groups values(1, 'default', 'black');")
|
||||||
|
|
||||||
@@ -802,6 +855,8 @@ class MainModel(ModelMT):
|
|||||||
# fetch details about files
|
# fetch details about files
|
||||||
if self.config.confd['retrive']:
|
if self.config.confd['retrive']:
|
||||||
update = True
|
update = True
|
||||||
|
exif = None
|
||||||
|
|
||||||
sql = """select seq FROM sqlite_sequence WHERE name='files'"""
|
sql = """select seq FROM sqlite_sequence WHERE name='files'"""
|
||||||
db_cursor.execute(sql)
|
db_cursor.execute(sql)
|
||||||
fileid = db_cursor.fetchone()[0]
|
fileid = db_cursor.fetchone()[0]
|
||||||
@@ -816,9 +871,36 @@ class MainModel(ModelMT):
|
|||||||
db_cursor.execute(sql, (fileid,
|
db_cursor.execute(sql, (fileid,
|
||||||
tpath.split(self.internal_dirname)[1][1:]))
|
tpath.split(self.internal_dirname)[1][1:]))
|
||||||
|
|
||||||
if self.config.confd['exif']:
|
# exif - stroe data in exif table
|
||||||
# TODO: exif implementation
|
if self.config.confd['exif'] and ext in ['jpg', 'jpeg']:
|
||||||
pass
|
p = None
|
||||||
|
if self.config.confd['thumbs'] and exif:
|
||||||
|
p = ParseExif(exif_dict=exif)
|
||||||
|
else:
|
||||||
|
p = ParseExif(exif_file=current_file)
|
||||||
|
if not p.exif_dict:
|
||||||
|
p = None
|
||||||
|
if p:
|
||||||
|
p = p.parse()
|
||||||
|
p = list(p)
|
||||||
|
p.insert(0, fileid)
|
||||||
|
sql = """INSERT INTO exif (file_id,
|
||||||
|
camera,
|
||||||
|
date,
|
||||||
|
aperture,
|
||||||
|
exposure_program,
|
||||||
|
exposure_bias,
|
||||||
|
iso,
|
||||||
|
focal_length,
|
||||||
|
subject_distance,
|
||||||
|
metering_mode,
|
||||||
|
flash,
|
||||||
|
light_source,
|
||||||
|
resolution,
|
||||||
|
orientation)
|
||||||
|
values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"""
|
||||||
|
db_cursor.execute(sql, (tuple(p)))
|
||||||
|
|
||||||
|
|
||||||
# Extensions - user defined actions
|
# Extensions - user defined actions
|
||||||
if ext in self.config.confd['extensions'].keys():
|
if ext in self.config.confd['extensions'].keys():
|
||||||
|
|||||||
107
src/utils/parse_exif.py
Normal file
107
src/utils/parse_exif.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import re
|
||||||
|
import EXIF
|
||||||
|
class ParseExif(object):
|
||||||
|
def __init__(self, exif_dict=None, exif_file=None):
|
||||||
|
self.camera = None
|
||||||
|
self.date = None
|
||||||
|
self.aperture = None
|
||||||
|
self.exposure_program = None
|
||||||
|
self.exposure_bias = None
|
||||||
|
self.iso = None
|
||||||
|
self.focal_length = None
|
||||||
|
self.subject_distance = None
|
||||||
|
self.metering_mode = None
|
||||||
|
self.flash = None
|
||||||
|
self.light_source = None
|
||||||
|
self.resolution = None
|
||||||
|
self.orientation = None
|
||||||
|
self.exif_dict = exif_dict
|
||||||
|
if not self.exif_dict:
|
||||||
|
try:
|
||||||
|
f = open(exif_file, 'rb')
|
||||||
|
e = EXIF.process_file(f)
|
||||||
|
if len(e.keys()) >0:
|
||||||
|
self.exif_dict = e
|
||||||
|
f.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
def parse(self):
|
||||||
|
try:
|
||||||
|
self.camera = "%s" % self.exif_dict['Image Make']
|
||||||
|
self.camera = self.camera.strip()
|
||||||
|
except: pass
|
||||||
|
try:
|
||||||
|
model = "%s" % self.exif_dict['Image Model']
|
||||||
|
self.camera += ", " + model.strip()
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.date = "%s" % self.exif_dict['EXIF DateTimeOriginal']
|
||||||
|
p = re.compile('[\d,:]+')
|
||||||
|
if not p.match(self.date):
|
||||||
|
self.date = None
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.aperture = "%s" % self.exif_dict['EXIF FNumber']
|
||||||
|
if len(self.aperture.split("/")) == 2:
|
||||||
|
self.aperture += '.'
|
||||||
|
self.aperture = "%.1f" % eval(self.aperture)
|
||||||
|
self.aperture = "f/%.1f" % float(self.aperture)
|
||||||
|
self.aperture = self.aperture.replace('.',',')
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try: self.exposure_program = "%s" % self.exif_dict['EXIF ExposureProgram']
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.exposure_bias = "%s" % self.exif_dict['EXIF ExposureBiasValue']
|
||||||
|
if len(self.exposure_bias.split("/")) == 2:
|
||||||
|
self.exposure_bias += '.'
|
||||||
|
self.exposure_bias = "%.1f" % eval(self.exposure_bias)
|
||||||
|
self.exposure_bias = "%.1f" % float(self.exposure_bias)
|
||||||
|
self.exposure_bias = self.exposure_bias.replace('.',',')
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try: self.iso = "%s" % self.exif_dict['EXIF ISOSpeedRatings']
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.focal_length = "%s" % self.exif_dict['EXIF FocalLength']
|
||||||
|
if len(self.focal_length.split("/")) == 2:
|
||||||
|
self.focal_length += '.'
|
||||||
|
self.focal_length = "%.2f" % eval(self.focal_length)
|
||||||
|
self.focal_length = "%.2f mm" % float(self.focal_length)
|
||||||
|
self.focal_length = self.focal_length.replace('.',',')
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.subject_distance = "%s" % self.exif_dict['EXIF SubjectDistance']
|
||||||
|
if len(self.subject_distance.split("/")) == 2:
|
||||||
|
self.subject_distance += '.'
|
||||||
|
self.subject_distance = "%.3f" % eval(self.subject_distance)
|
||||||
|
self.subject_distance = "%.3f m" % float(self.subject_distance)
|
||||||
|
self.subject_distance = self.subject_distance.replace('.',',')
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try: self.metering_mode = "%s" % self.exif_dict['EXIF MeteringMode']
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try: self.flash = "%s" % self.exif_dict['EXIF Flash']
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try: self.light_source = "%s" % self.exif_dict['EXIF LightSource']
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try: self.resolution = "%s" % self.exif_dict['Image XResolution']
|
||||||
|
except: pass
|
||||||
|
try: self.resolution = self.resolution + " x %s" % self.exif_dict['Image YResolution']
|
||||||
|
except: pass
|
||||||
|
try: self.resolution = self.resolution + " (%s)" % self.exif_dict['Image ResolutionUnit']
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
try: self.orientation = "%s" % self.exif_dict['Image Orientation']
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
return (self.camera, self.date, self.aperture, self.exposure_program, self.exposure_bias, self.iso, self.focal_length, self.subject_distance, self.metering_mode, self.flash, self.light_source, self.resolution, self.orientation)
|
||||||
|
#print self.date #self.camera, self.date, self.aperture, self.exposure_program, self.exposure_bias, self.iso, self.focal_length, self.subject_distance, self.metering_mode, self.flash, self.light_source, self.resolution, self.flash, self.orientation
|
||||||
Reference in New Issue
Block a user