Answers:
我是Shotwell的制造商Yorba的创始人。感谢您的提问。
导出时,Shotwell 0.7将元数据(例如标签和标题)写入照片。元数据以EXIF,IPTC和/或XMP格式编写(取决于照片中开头的是哪种)。大多数其他照片程序都可以读取这些格式,因此,如果从Shotwell导出照片,则其他程序应该可以毫无问题地读取其标签。
即将发布的Shotwell 0.8可以即时将元数据写入照片文件- 要启用此功能,请在首选项对话框中选择“ 将标签,标题和其他元数据写入照片文件 ”选项。选择此项后,Shotwell将在您标记照片文件后立即更新它们。要使用此功能,请从源代码构建Shotwell中继(请参阅http://yorba.org/shotwell/install/#source),或仅等待Shotwell 0.8(我们计划在12月下旬发布)。
不幸的是,Shotwell似乎确实将标签保留在自己的数据库中,而不是将它们作为exif,IPTC或XMP嵌入图片中。您可以使用exiftool进行检查,可以通过安装存储库中提供的软件包libimage-exiftool-perl进行安装。
使用命令;exiftool testpicture.jpg
检查您之前用Shotwell标记过的一张名为testpicture.jpg的照片。您将看到exiftool输出中不包含Shotwell标签。
exiftool实用程序可以为您的照片加标签,将标签嵌入照片中,这样做的好处是大多数照片管理器都会使用它们,其中包括Shotwell。例如:
exiftool -keywords=favourite -keywords=family testpicture.jpg
用两个新关键字(收藏夹和家族)替换现有的关键字列表。
将testpicture.jpg导入Shotwell时,该图片将被标记为“最爱和家人”
知道Shotwell数据库是位于您所在位置的sqlite数据库可能会有所帮助。~/.shotwell/data
目录,通常称为photo.db,您可以将其复制到计算机上的其他位置,并使用sqlite访问。
sqlite有一些GUI前端,firefox这里有一个,或者您可以使用sqliteman。这两个前端都导出到csv功能。将标签导出到csv(逗号分隔值)时,可以检查是否有任何其他照片管理软件将标签导入并映射到其各自数据库中的相应字段。我相信Digikam可以做到。Digikam还可以在照片本身中嵌入exif数据。
希望随着Shotwell获得更多功能,这种情况将会改变。
更新:虽然确实在创建这些标签时Shotwell 0.7不会将其标签存储在图片中,但是如果您选择导出标签,则可以将这些标签嵌入图片中,这要感谢亚当(Adam)明确指出。希望此输出在处理jpeg时无损。我怀疑是这样,如果在导出对话框中为“缩放”选项选择了原始大小。
快速(肮脏的?)Python代码无需升级Shotwell就可以做到这一点(我认为从0.8.x开始Shotwell可以写出标签,但是您不能在Lucid上升级到该标签)。这东西会以标签的形式写出星级(显然,如果您不想要的话,注释会有点漏掉)。
需要exiftool。它将复制Shotwell数据库和图像中的所有标签(即Shotwell导入图像时导入的标签),因此请当心。此外,花大量时间收集大量照片。
import os
conn = sqlite3.connect("/home/ username /.shotwell/data/photo.db")
def get_tags():
return [ x[0] for x in conn.execute("SELECT name FROM TagTable").fetchall()]
def tag_query(tag):
return conn.execute("SELECT photo_id_list FROM TagTable WHERE name=?", (tag,)).fetchone()[0].split(",")
def get_tagged_photos(tag):
for id in tag_query(tag):
result = conn.execute("select filename from PhotoTable where id=?", (id,) ).fetchone()
if result:
yield result[0]
def get_photos_by_rating(rating):
return [photo[0] for photo in conn.execute("select filename from PhotoTable where rating=?",(rating,)).fetchall()]
def get_tagging_commands():
commands = []
for rating in range(1,5):
for photo in get_photos_by_rating(rating):
commands.append("exiftool -overwrite_original_in_place -preserve -keywords+=rating%d \"%s\""% (rating,photo))
for tag in [tag for tag in get_tags() if tag != "keep"]:
for photo in get_tagged_photos(tag):
commands.append("exiftool -overwrite_original_in_place -preserve -keywords+=%s \"%s\"" % (tag,photo))
return commands
commands = get_tagging_commands()
for command in commands:
print command
os.system(command)
如果您想要一个非常好的GUI工具/浏览器,使您可以使用Exif标记来标记图像(因此在Shotwell中也可用),我建议使用jBrout。
要安装它,请转到Synaptic,选择设置/存储库,单击“其他软件”选项卡,然后单击“添加”按钮并粘贴在此行:
deb http://jbrout.free.fr/download/debian二进制文件/
然后重新加载并搜索jBrout。
我尝试使用user38122的脚本来解析Shotwell数据库,但是它没有用。显然,该架构在最新版本中已更改。相反,我编写了以下脚本,该脚本使用pandas(我个人更喜欢编写SQL)来进行标记交叉。在下面的示例中,我显示了同时具有标签“ cat”和标签“ sleeping”的所有图像。
#!/usr/bin/python
# An example of how to query the shotwell database with pandas
import sqlite3, pandas, os, time, datetime
con = sqlite3.connect('/home/dov/.local/share/shotwell/data/photo.db')
photo_df = pandas.read_sql("SELECT * from PhotoTable", con)
for c in ['exposure_time','timestamp','time_created']:
photo_df[c] = photo_df[c].map(datetime.datetime.fromtimestamp)
tag_df = pandas.read_sql('SELECT * from TagTable', con)
def get_image_ids(tag):
"""The image ids are stored morphed in the database as %016x"""
global tag_df
return set([int(s.replace('thumb',''),16)
for s in tag_df[tag_df.name==tag].photo_id_list.iloc[0].split(',')
if len(s)])
def get_photos(ids):
"""Get the photos for a list of ids"""
global photo_df
return photo_df[photo_df.id.isin(ids)].sort(['exposure_time'])
def view_pix(rows):
cmd = ('eog ' + ' '.join(['"%s"'%row.filename
for idx,row in rows.iterrows()]))
# print cmd
os.system(cmd)
print 'querying...'
# An example of how to create an intersection of two tags
ids1 = get_image_ids('cat')
ids2 = get_image_ids('sleeping')
rows = get_photos(ids1.intersection(ids2))
# An example of how to filter the rows by timestamp
time_low,time_high = datetime.datetime(2006,8,1),datetime.datetime(2009,1,1)
rows = rows[(rows.exposure_time > time_low)
& (rows.exposure_time < time_high)]
print '\n'.join([str(ts) for ts in rows['exposure_time']])
view_pix(rows)
print 'done'