|
# This is a script to import face tags from Picasa into Digikam's SQLite database. |
|
# First you need to export Picasa database into XML using this tool: |
|
# https://sourceforge.net/projects/exportpicasa/ |
|
# Later you need to adjust this script to fit your needs and then just run it. |
|
|
|
import xml.etree.ElementTree as ET |
|
import sqlite3 |
|
|
|
# Adjust the values below: |
|
XML_FILE_PATH = '/path/to/file.xml' |
|
SQLITE_DB_PATH = '/path/to/sqlite.db' |
|
# In order to find out what is the parent tag ID in your database, just tag some person in Digikam, open the database using any SQLite client and see what is the pid value in Tags table for the tag you've just created. |
|
PARENT_TAG_ID = 30 |
|
|
|
tree = ET.parse(XML_FILE_PATH) |
|
root = tree.getroot() |
|
|
|
conn = sqlite3.connect(SQLITE_DB_PATH) |
|
cur = conn.cursor() |
|
|
|
for folder in root: |
|
folderName = folder.get('name') |
|
|
|
cur.execute("SELECT a.id FROM AlbumRoots r INNER JOIN Albums a ON r.id = a.albumRoot WHERE r.specificPath || a.relativePath = :folderName", {'folderName': folderName}) |
|
row = cur.fetchone() |
|
|
|
if not row: |
|
continue |
|
|
|
albumId = row[0] |
|
|
|
for file in folder: |
|
fileName = file.get('name') |
|
cur.execute("SELECT i.id FROM Images i WHERE i.name = :name AND i.album = :albumId", {'name': fileName, 'albumId': albumId}) |
|
row = cur.fetchone() |
|
imageId = row[0] |
|
|
|
for face in file: |
|
personName = face.get('contact_name') |
|
rectLeft = float(face.get('rect_left')) |
|
rectRight = float(face.get('rect_right')) |
|
rectTop = float(face.get('rect_top')) |
|
rectBottom = float(face.get('rect_bottom')) |
|
|
|
if not personName: |
|
continue |
|
|
|
cur.execute("SELECT i.width, i.height FROM ImageInformation i WHERE i.imageId = :imageId", {'imageId': imageId}) |
|
row = cur.fetchone() |
|
|
|
imageWidth = row[0] |
|
imageHeight = row[1] |
|
|
|
x = int(imageWidth * rectLeft) |
|
y = int(imageHeight * rectTop) |
|
width = int(imageWidth * (rectRight - rectLeft)) |
|
height = int(imageWidth * (rectBottom - rectTop)) |
|
|
|
rectValue = '<rect x="' + str(x) + '" y="' + str(y) + '" width="' + str(width) + '" height="' + str(height) + '"/>' |
|
|
|
cur.execute("SELECT t.id FROM Tags t WHERE t.name = :name AND t.pid = :tagId", {'name': personName, 'tagId': PARENT_TAG_ID}) |
|
row = cur.fetchone() |
|
|
|
if row: |
|
tagId = row[0] |
|
else: |
|
cur.execute("INSERT INTO Tags (pid, name, icon) VALUES (:tagId, :name, 0)", {'tagId': PARENT_TAG_ID, 'name': personName}) |
|
tagId = cur.lastrowid |
|
|
|
cur.execute("INSERT INTO TagProperties (tagid, property, value) VALUES (:tagId, 'person', :value)", {'tagId': tagId, 'value': personName}) |
|
cur.execute("INSERT INTO TagProperties (tagid, property, value) VALUES (:tagId, 'kfaceId', :value)", {'tagId': tagId, 'value': personName}) |
|
|
|
try: |
|
cur.execute("INSERT INTO ImageTags (imageid, tagid) VALUES (:imageId, :tagId)", {'imageId': imageId, 'tagId': tagId}) |
|
except sqlite3.IntegrityError as ex: |
|
print 'WARNING: ' + str(ex) + '. Image: ' + folderName + '/' + fileName + ', person: ' + personName |
|
|
|
cur.execute("INSERT INTO ImageTagProperties (imageid, tagid, property, value) VALUES (:imageId, :tagId, 'tagRegion', :rectValue)", {'imageId': imageId, 'tagId': tagId, 'rectValue': rectValue}) |
|
|
|
conn.commit() |
|
conn.close() |
So why wasn't this a problem in Picasa? Does Picasa use a different date (e.g. file creation vs. file modification vs. photography date)? Or did you manually reorder the photos in Picasa (and it stores the order in its internal database)?
In other words, my question is: Where does the order "come from" that you want?